diff --git a/compose/README.md b/compose/README.md index 53870123..e9a04f3e 100644 --- a/compose/README.md +++ b/compose/README.md @@ -18,4 +18,4 @@ Accessing endpoints: - Edumeet: https://127.0.0.1:8443/ - Prometheus: http://127.0.0.1:9090/ -- Grafana: http://127.0.0.1:9091/d/mediasoup/mediasoup (user:pass `admin`:`admin`) +- Grafana: http://127.0.0.1:9091/ (user:pass `admin`:`admin`) diff --git a/compose/config/edumeet-app-config.js b/compose/config/edumeet-app-config.js index c3eedc3f..3f556c68 100644 --- a/compose/config/edumeet-app-config.js +++ b/compose/config/edumeet-app-config.js @@ -68,15 +68,15 @@ var config = // Enable or disable simulcast for screen sharing video simulcastSharing : false, // Simulcast encoding layers and levels - simulcastEncodings : + /* simulcastEncodings : [ { scaleResolutionDownBy: 4 }, { scaleResolutionDownBy: 2 }, { scaleResolutionDownBy: 1 } - /* { maxBitRate: 50000 }, - { maxBitRate: 1000000 }, - { maxBitRate: 4800000 } */ - ], + // { maxBitRate: 50000 }, + // { maxBitRate: 1000000 }, + // { maxBitRate: 4800000 } + ], */ // The adaptive spatial layer selection scaling factor (in the range [0.5, 1.0]) // example: // with level width=640px, the minimum width required to trigger the diff --git a/compose/config/grafana-dashboards/mediasoup.json b/compose/config/grafana-dashboards/mediasoup.json index 44a51f7d..6954a6ac 100644 --- a/compose/config/grafana-dashboards/mediasoup.json +++ b/compose/config/grafana-dashboards/mediasoup.json @@ -15,6 +15,7 @@ "editable": true, "gnetId": null, "graphTooltip": 0, + "id": 2, "links": [], "panels": [ { @@ -35,7 +36,7 @@ "fillGradient": 0, "gridPos": { "h": 7, - "w": 4, + "w": 6, "x": 0, "y": 0 }, @@ -63,7 +64,6 @@ "renderer": "flot", "seriesOverrides": [ { - "$$hashKey": "object:254", "alias": "Workers", "fill": 0, "hideTooltip": true, @@ -110,7 +110,6 @@ }, "yaxes": [ { - "$$hashKey": "object:210", "format": "none", "label": null, "logBase": 1, @@ -119,7 +118,6 @@ "show": true }, { - "$$hashKey": "object:211", "decimals": 0, "format": "none", "label": "", @@ -152,8 +150,8 @@ "fillGradient": 0, "gridPos": { "h": 7, - "w": 4, - "x": 4, + "w": 6, + "x": 6, "y": 0 }, "hiddenSeries": false, @@ -178,13 +176,7 @@ "pointradius": 2, "points": false, "renderer": "flot", - "seriesOverrides": [ - { - "$$hashKey": "object:367", - "alias": "Memory", - "yaxis": 2 - } - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, @@ -216,16 +208,215 @@ }, "yaxes": [ { - "$$hashKey": "object:374", "format": "decmbytes", "label": null, "logBase": 1, "max": null, - "min": null, + "min": "0", + "show": true + }, + { + "decimals": 0, + "format": "decmbytes", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 0 + }, + "hiddenSeries": false, + "id": 45, + "legend": { + "avg": false, + "current": true, + "max": false, + "min": false, + "show": false, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(mediasoup_process_cpu_seconds_total[30s])", + "interval": "", + "legendFormat": "CPU", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Edumeet server CPU", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "decimals": 0, + "format": "decmbytes", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 0 + }, + "hiddenSeries": false, + "id": 77, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Memory", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "mediasoup_process_resident_memory_bytes / 1e6", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Edumeet server Memory", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decmbytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", "show": true }, { - "$$hashKey": "object:375", "decimals": 0, "format": "decmbytes", "label": "", @@ -258,8 +449,8 @@ "gridPos": { "h": 7, "w": 5, - "x": 8, - "y": 0 + "x": 0, + "y": 7 }, "hiddenSeries": false, "id": 34, @@ -289,13 +480,13 @@ "steppedLine": false, "targets": [ { - "expr": "sum(mediasoup_audio_in_count)", + "expr": "mediasoup_audio_in_count", "interval": "", "legendFormat": "Audio", "refId": "A" }, { - "expr": "sum(mediasoup_video_in_count)", + "expr": "mediasoup_video_in_count", "hide": false, "interval": "", "legendFormat": "Video", @@ -362,8 +553,8 @@ "gridPos": { "h": 7, "w": 5, - "x": 13, - "y": 0 + "x": 5, + "y": 7 }, "hiddenSeries": false, "id": 42, @@ -471,8 +662,8 @@ "gridPos": { "h": 7, "w": 5, - "x": 18, - "y": 0 + "x": 10, + "y": 7 }, "hiddenSeries": false, "id": 38, @@ -561,7 +752,6 @@ "dashLength": 10, "dashes": false, "datasource": null, - "description": "", "fieldConfig": { "defaults": { "custom": {}, @@ -569,122 +759,22 @@ }, "overrides": [] }, - "fill": 1, + "fill": 0, "fillGradient": 0, "gridPos": { "h": 7, "w": 4, - "x": 0, + "x": 15, "y": 7 }, "hiddenSeries": false, - "id": 45, - "legend": { - "avg": false, - "current": true, - "max": false, - "min": false, - "show": false, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.4.3", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(mediasoup_process_cpu_seconds_total[30s])", - "interval": "", - "legendFormat": "CPU", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Edumeet server CPU", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "$$hashKey": "object:94", - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "$$hashKey": "object:95", - "decimals": 0, - "format": "decmbytes", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "description": "", - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 4, - "x": 4, - "y": 7 - }, - "hiddenSeries": false, - "id": 77, + "id": 78, "legend": { "avg": false, "current": false, "max": false, "min": false, - "show": false, + "show": true, "total": false, "values": false }, @@ -701,9 +791,12 @@ "renderer": "flot", "seriesOverrides": [ { - "$$hashKey": "object:145", - "alias": "Memory", - "yaxis": 2 + "alias": "Lost", + "color": "#F2495C" + }, + { + "alias": "Retransmitted", + "color": "#FF9830" } ], "spaceLength": 10, @@ -711,17 +804,25 @@ "steppedLine": false, "targets": [ { - "expr": "mediasoup_process_resident_memory_bytes / 1e6", + "expr": "100 * mediasoup_packets_losts_in_sum / mediasoup_packets_counts_in_sum", + "format": "time_series", "interval": "", - "legendFormat": "", + "legendFormat": "Lost", "refId": "A" + }, + { + "expr": "100 * mediasoup_packets_retransmitted_in_sum / mediasoup_packets_counts_in_sum", + "hide": false, + "interval": "", + "legendFormat": "Retransmitted", + "refId": "B" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, - "title": "Edumeet server Memory", + "title": "Input packets", "tooltip": { "shared": true, "sort": 0, @@ -737,8 +838,8 @@ }, "yaxes": [ { - "$$hashKey": "object:152", - "format": "decmbytes", + "decimals": null, + "format": "percent", "label": null, "logBase": 1, "max": null, @@ -746,10 +847,8 @@ "show": true }, { - "$$hashKey": "object:153", - "decimals": 0, - "format": "decmbytes", - "label": "", + "format": "short", + "label": null, "logBase": 1, "max": null, "min": null, @@ -761,6 +860,117 @@ "alignLevel": null } }, + { + "datasource": null, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "links": [], + "mappings": [], + "max": 10, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0 + }, + { + "color": "orange", + "value": 5 + }, + { + "color": "green", + "value": 10 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 5, + "x": 19, + "y": 7 + }, + "id": 79, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "7.4.3", + "targets": [ + { + "expr": "mediasoup_audio_scores_in_mean", + "format": "time_series", + "interval": "", + "legendFormat": "Audio (average)", + "refId": "A" + }, + { + "expr": "mediasoup_audio_scores_in_min", + "hide": false, + "interval": "", + "legendFormat": "Audio (min)", + "refId": "B" + }, + { + "expr": "mediasoup_audio_scores_in_max", + "hide": false, + "interval": "", + "legendFormat": "Audio (max)", + "refId": "C" + }, + { + "expr": "mediasoup_video_scores_in_mean", + "format": "time_series", + "hide": false, + "interval": "", + "legendFormat": "Video (average)", + "refId": "D" + }, + { + "expr": "mediasoup_video_scores_in_min", + "hide": false, + "interval": "", + "legendFormat": "Video (min)", + "refId": "E" + }, + { + "expr": "mediasoup_video_scores_in_max", + "hide": false, + "interval": "", + "legendFormat": "Video (max)", + "refId": "F" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Scores", + "type": "stat" + }, { "aliasColors": {}, "bars": false, @@ -779,8 +989,8 @@ "gridPos": { "h": 7, "w": 5, - "x": 8, - "y": 7 + "x": 0, + "y": 14 }, "hiddenSeries": false, "id": 36, @@ -882,8 +1092,8 @@ "gridPos": { "h": 7, "w": 5, - "x": 13, - "y": 7 + "x": 5, + "y": 14 }, "hiddenSeries": false, "id": 43, @@ -997,8 +1207,8 @@ "gridPos": { "h": 7, "w": 5, - "x": 18, - "y": 7 + "x": 10, + "y": 14 }, "hiddenSeries": false, "id": 41, @@ -1100,8 +1310,8 @@ "gridPos": { "h": 7, "w": 5, - "x": 8, - "y": 14 + "x": 0, + "y": 21 }, "hiddenSeries": false, "id": 40, @@ -1216,8 +1426,8 @@ "gridPos": { "h": 7, "w": 5, - "x": 13, - "y": 14 + "x": 5, + "y": 21 }, "hiddenSeries": false, "id": 48, @@ -1332,8 +1542,8 @@ "gridPos": { "h": 7, "w": 5, - "x": 18, - "y": 14 + "x": 10, + "y": 21 }, "hiddenSeries": false, "id": 44, @@ -1455,7 +1665,7 @@ ] }, "timezone": "", - "title": "MediaSoup", - "uid": "mediasoup", - "version": 1 + "title": "MediaSoup (default)", + "uid": "mediasoup-default", + "version": 9 } \ No newline at end of file diff --git a/server/lib/metrics/aggregated.js b/server/lib/metrics/aggregated.js index c2b84876..4c4d7d41 100644 --- a/server/lib/metrics/aggregated.js +++ b/server/lib/metrics/aggregated.js @@ -34,16 +34,20 @@ module.exports = function(workers, config) let workers_cpu = new Stats(); let workers_memory = new Stats(); + // in let video_bitrates_in = new Stats(); - let video_bitrates_out = new Stats(); - let audio_bitrates_in = new Stats(); - let audio_bitrates_out = new Stats(); + let video_scores_in = new Stats(); + let audio_scores_in = new Stats(); let packets_counts_in = new Stats(); let packets_losts_in = new Stats(); let packets_retransmitted_in = new Stats(); + // out + let video_bitrates_out = new Stats(); + let audio_bitrates_out = new Stats(); + let round_trip_times_out = new Stats(); let packets_counts_out = new Stats(); let packets_losts_out = new Stats(); @@ -102,14 +106,15 @@ module.exports = function(workers, config) { continue; } - console.log(s); if (s.kind === 'video') { video_bitrates_in.push(s.bitrate); + video_scores_in.push(s.score); } else if (s.kind === 'audio') { audio_bitrates_in.push(s.bitrate); + audio_scores_in.push(s.score); } packets_counts_in.push(s.packetCount || 0); packets_losts_in.push(s.packetsLost || 0); @@ -163,7 +168,9 @@ module.exports = function(workers, config) workers_memory: formatStats(workers_memory), // in video_bitrates_in: formatStats(video_bitrates_in), + video_scores_in: formatStats(video_scores_in), audio_bitrates_in: formatStats(audio_bitrates_in), + audio_scores_in: formatStats(audio_scores_in), packets_counts_in: formatStats(packets_counts_in), packets_losts_in: formatStats(packets_losts_in), packets_retransmitted_in: formatStats(packets_retransmitted_in), @@ -183,77 +190,87 @@ module.exports = function(workers, config) logger.error('collectStats error:', err.message); } - setTimeout(collectStats, config.period * 1000); + setTimeout(collectStats, (config.period || 15) * 1000); } collectStats(); // mediasoup metrics [ - { name: 'workers_count', statName: 'workers_cpu', statValue: 'length' }, - { name: 'workers_cpu', statName: 'workers_cpu', statValue: 'sum' }, - - { name: 'workers_memory', statName: 'workers_memory', statValue: 'sum' }, - - // in - { name: 'audio_in_count', statName: 'audio_bitrates_in', statValue: 'length' }, - { name: 'audio_bitrates_in_sum', statName: 'audio_bitrates_in', statValue: 'sum' }, - { name: 'audio_bitrates_in_mean', statName: 'audio_bitrates_in', statValue: 'mean' }, - { name: 'audio_bitrates_in_min', statName: 'audio_bitrates_in', statValue: 'min' }, - { name: 'audio_bitrates_in_max', statName: 'audio_bitrates_in', statValue: 'max' }, - { name: 'audio_bitrates_in_p25', statName: 'audio_bitrates_in', statValue: 'p25' }, - - { name: 'video_in_count', statName: 'video_bitrates_in', statValue: 'length' }, - { name: 'video_bitrates_in_sum', statName: 'video_bitrates_in', statValue: 'sum' }, - { name: 'video_bitrates_in_mean', statName: 'video_bitrates_in', statValue: 'mean' }, - { name: 'video_bitrates_in_min', statName: 'video_bitrates_in', statValue: 'min' }, - { name: 'video_bitrates_in_max', statName: 'video_bitrates_in', statValue: 'max' }, - { name: 'video_bitrates_in_p25', statName: 'video_bitrates_in', statValue: 'p25' }, - - { name: 'packets_counts_in_mean', statName: 'packets_counts_in', statValue: 'mean' }, - { name: 'packets_counts_in_min', statName: 'packets_counts_in', statValue: 'min' }, - { name: 'packets_counts_in_max', statName: 'packets_counts_in', statValue: 'max' }, - { name: 'packets_counts_in_p25', statName: 'packets_counts_in', statValue: 'p25' }, - - { name: 'packets_losts_in_mean', statName: 'packets_losts_in', statValue: 'mean' }, - { name: 'packets_losts_in_min', statName: 'packets_losts_in', statValue: 'min' }, - { name: 'packets_losts_in_max', statName: 'packets_losts_in', statValue: 'max' }, - { name: 'packets_losts_in_p25', statName: 'packets_losts_in', statValue: 'p25' }, - + { name: 'workers_count', statName: 'workers_cpu', statValue: 'length' }, + { name: 'workers_cpu', statName: 'workers_cpu', statValue: 'sum' }, + { name: 'workers_memory', statName: 'workers_memory', statValue: 'sum' }, + // audio in + { name: 'audio_in_count', statName: 'audio_bitrates_in', statValue: 'length' }, + // audio in bitrates + { name: 'audio_bitrates_in_sum', statName: 'audio_bitrates_in', statValue: 'sum' }, + { name: 'audio_bitrates_in_mean', statName: 'audio_bitrates_in', statValue: 'mean' }, + { name: 'audio_bitrates_in_min', statName: 'audio_bitrates_in', statValue: 'min' }, + { name: 'audio_bitrates_in_max', statName: 'audio_bitrates_in', statValue: 'max' }, + { name: 'audio_bitrates_in_p25', statName: 'audio_bitrates_in', statValue: 'p25' }, + // audio in scores + { name: 'audio_scores_in_mean', statName: 'audio_scores_in', statValue: 'mean' }, + { name: 'audio_scores_in_min', statName: 'audio_scores_in', statValue: 'min' }, + { name: 'audio_scores_in_max', statName: 'audio_scores_in', statValue: 'max' }, + { name: 'audio_scores_in_p25', statName: 'audio_scores_in', statValue: 'p25' }, + // video in + { name: 'video_in_count', statName: 'video_bitrates_in', statValue: 'length' }, + // video in bitrates + { name: 'video_bitrates_in_sum', statName: 'video_bitrates_in', statValue: 'sum' }, + { name: 'video_bitrates_in_mean', statName: 'video_bitrates_in', statValue: 'mean' }, + { name: 'video_bitrates_in_min', statName: 'video_bitrates_in', statValue: 'min' }, + { name: 'video_bitrates_in_max', statName: 'video_bitrates_in', statValue: 'max' }, + { name: 'video_bitrates_in_p25', statName: 'video_bitrates_in', statValue: 'p25' }, + // video in scores + { name: 'video_scores_in_mean', statName: 'video_scores_in', statValue: 'mean' }, + { name: 'video_scores_in_min', statName: 'video_scores_in', statValue: 'min' }, + { name: 'video_scores_in_max', statName: 'video_scores_in', statValue: 'max' }, + { name: 'video_scores_in_p25', statName: 'video_scores_in', statValue: 'p25' }, + // packets in + { name: 'packets_counts_in_sum', statName: 'packets_counts_in', statValue: 'sum' }, + { name: 'packets_counts_in_mean', statName: 'packets_counts_in', statValue: 'mean' }, + { name: 'packets_counts_in_min', statName: 'packets_counts_in', statValue: 'min' }, + { name: 'packets_counts_in_max', statName: 'packets_counts_in', statValue: 'max' }, + { name: 'packets_counts_in_p25', statName: 'packets_counts_in', statValue: 'p25' }, + { name: 'packets_losts_in_sum', statName: 'packets_losts_in', statValue: 'sum' }, + { name: 'packets_losts_in_mean', statName: 'packets_losts_in', statValue: 'mean' }, + { name: 'packets_losts_in_min', statName: 'packets_losts_in', statValue: 'min' }, + { name: 'packets_losts_in_max', statName: 'packets_losts_in', statValue: 'max' }, + { name: 'packets_losts_in_p25', statName: 'packets_losts_in', statValue: 'p25' }, + { name: 'packets_retransmitted_in_sum', statName: 'packets_retransmitted_in', statValue: 'sum' }, { name: 'packets_retransmitted_in_mean', statName: 'packets_retransmitted_in', statValue: 'mean' }, { name: 'packets_retransmitted_in_min', statName: 'packets_retransmitted_in', statValue: 'min' }, { name: 'packets_retransmitted_in_max', statName: 'packets_retransmitted_in', statValue: 'max' }, { name: 'packets_retransmitted_in_p25', statName: 'packets_retransmitted_in', statValue: 'p25' }, - - // out - { name: 'audio_out_count', statName: 'audio_bitrates_out', statValue: 'length' }, - { name: 'audio_bitrates_out_sum', statName: 'audio_bitrates_out', statValue: 'sum' }, - { name: 'audio_bitrates_out_mean', statName: 'audio_bitrates_out', statValue: 'mean' }, - { name: 'audio_bitrates_out_min', statName: 'audio_bitrates_out', statValue: 'min' }, - { name: 'audio_bitrates_out_max', statName: 'audio_bitrates_out', statValue: 'max' }, - { name: 'audio_bitrates_out_p25', statName: 'audio_bitrates_out', statValue: 'p25' }, - - { name: 'video_out_count', statName: 'video_bitrates_out', statValue: 'length' }, - { name: 'video_bitrates_out_sum', statName: 'video_bitrates_out', statValue: 'sum' }, - { name: 'video_bitrates_out_mean', statName: 'video_bitrates_out', statValue: 'mean' }, - { name: 'video_bitrates_out_min', statName: 'video_bitrates_out', statValue: 'min' }, - { name: 'video_bitrates_out_max', statName: 'video_bitrates_out', statValue: 'max' }, - { name: 'video_bitrates_out_p25', statName: 'video_bitrates_out', statValue: 'p25' }, - - { name: 'spatial_layers_out_mean', statName: 'spatial_layers_out', statValue: 'mean' }, - { name: 'spatial_layers_out_min', statName: 'spatial_layers_out', statValue: 'min' }, - { name: 'spatial_layers_out_max', statName: 'spatial_layers_out', statValue: 'max' }, - { name: 'spatial_layers_out_p25', statName: 'spatial_layers_out', statValue: 'p25' }, - - { name: 'temporal_layers_out_mean', statName: 'temporal_layers_out', statValue: 'mean' }, - { name: 'temporal_layers_out_min', statName: 'temporal_layers_out', statValue: 'min' }, - { name: 'temporal_layers_out_max', statName: 'temporal_layers_out', statValue: 'max' }, - { name: 'temporal_layers_out_p25', statName: 'temporal_layers_out', statValue: 'p25' }, - - { name: 'round_trip_times_out_mean', statName: 'round_trip_times_out', statValue: 'mean' }, - { name: 'round_trip_times_out_min', statName: 'round_trip_times_out', statValue: 'min' }, - { name: 'round_trip_times_out_max', statName: 'round_trip_times_out', statValue: 'max' }, - { name: 'round_trip_times_out_p25', statName: 'round_trip_times_out', statValue: 'p25' }, + // audio out + { name: 'audio_out_count', statName: 'audio_bitrates_out', statValue: 'length' }, + { name: 'audio_bitrates_out_sum', statName: 'audio_bitrates_out', statValue: 'sum' }, + { name: 'audio_bitrates_out_mean', statName: 'audio_bitrates_out', statValue: 'mean' }, + { name: 'audio_bitrates_out_min', statName: 'audio_bitrates_out', statValue: 'min' }, + { name: 'audio_bitrates_out_max', statName: 'audio_bitrates_out', statValue: 'max' }, + { name: 'audio_bitrates_out_p25', statName: 'audio_bitrates_out', statValue: 'p25' }, + // video out + { name: 'video_out_count', statName: 'video_bitrates_out', statValue: 'length' }, + { name: 'video_bitrates_out_sum', statName: 'video_bitrates_out', statValue: 'sum' }, + { name: 'video_bitrates_out_mean', statName: 'video_bitrates_out', statValue: 'mean' }, + { name: 'video_bitrates_out_min', statName: 'video_bitrates_out', statValue: 'min' }, + { name: 'video_bitrates_out_max', statName: 'video_bitrates_out', statValue: 'max' }, + { name: 'video_bitrates_out_p25', statName: 'video_bitrates_out', statValue: 'p25' }, + // sl + { name: 'spatial_layers_out_mean', statName: 'spatial_layers_out', statValue: 'mean' }, + { name: 'spatial_layers_out_min', statName: 'spatial_layers_out', statValue: 'min' }, + { name: 'spatial_layers_out_max', statName: 'spatial_layers_out', statValue: 'max' }, + { name: 'spatial_layers_out_p25', statName: 'spatial_layers_out', statValue: 'p25' }, + // tl + { name: 'temporal_layers_out_mean', statName: 'temporal_layers_out', statValue: 'mean' }, + { name: 'temporal_layers_out_min', statName: 'temporal_layers_out', statValue: 'min' }, + { name: 'temporal_layers_out_max', statName: 'temporal_layers_out', statValue: 'max' }, + { name: 'temporal_layers_out_p25', statName: 'temporal_layers_out', statValue: 'p25' }, + // rtt out + { name: 'round_trip_times_out_mean', statName: 'round_trip_times_out', statValue: 'mean' }, + { name: 'round_trip_times_out_min', statName: 'round_trip_times_out', statValue: 'min' }, + { name: 'round_trip_times_out_max', statName: 'round_trip_times_out', statValue: 'max' }, + { name: 'round_trip_times_out_p25', statName: 'round_trip_times_out', statValue: 'p25' }, ].forEach(({ name, statName, statValue }) => { new promClient.Gauge({