@flashphoner/websdk 2.0.261 → 2.0.263

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13145,6 +13145,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13145
13145
  metricsBatch: null,
13146
13146
  timer: null,
13147
13147
  batchCount: 0,
13148
+ timerBusy: false,
13148
13149
  start: async function() {
13149
13150
  let error = "Can't collect WebRTC stats to send: ";
13150
13151
  if (!statCollector.description.types) {
@@ -13184,7 +13185,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13184
13185
  update: async function(description) {
13185
13186
  if (!description) {
13186
13187
  if (statCollector.logger) {
13187
- statCollector.logger.error(LOG_PREFIX, "Can't update WebRTC metrics sending: no parameters passed");
13188
+ statCollector.logger.error(LOG_PREFIX + "-" + statCollector.id, "Can't update WebRTC metrics sending: no parameters passed");
13188
13189
  return;
13189
13190
  }
13190
13191
  }
@@ -13220,8 +13221,12 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13220
13221
  break;
13221
13222
  }
13222
13223
  },
13223
- updateHeaders: async function() {
13224
- let stats = await statCollector.mediaConnection.getWebRTCStats();
13224
+ updateHeaders: async function(stats = null) {
13225
+ let currentHeaders = "";
13226
+ let headersChanged = false;
13227
+ if (!stats) {
13228
+ stats = await statCollector.mediaConnection.getWebRTCStats();
13229
+ }
13225
13230
  Object.keys(statCollector.description.types).forEach((type) => {
13226
13231
  let typeDescriptor = statCollector.description.types[type];
13227
13232
  let metricsString = "";
@@ -13234,15 +13239,15 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13234
13239
  }
13235
13240
  if (stats[type]) {
13236
13241
  stats[type].forEach((report) => {
13237
- statCollector.logger.debug(LOG_PREFIX, type + " report: " + JSON.stringify(report));
13242
+ statCollector.logger.debug(LOG_PREFIX + "-" + statCollector.id, type + " report: " + JSON.stringify(report));
13238
13243
  if (contentFilters) {
13239
13244
  let filtersMatched = true;
13240
13245
  for (const filter in contentFilters) {
13241
- statCollector.logger.debug(LOG_PREFIX, type + " filter by " + filter + ": " + JSON.stringify(contentFilters[filter]));
13246
+ statCollector.logger.debug(LOG_PREFIX + "-" + statCollector.id, type + " filter by " + filter + ": " + JSON.stringify(contentFilters[filter]));
13242
13247
  let filterMatched = false;
13243
13248
  if (report[filter]) {
13244
13249
  for (const value of contentFilters[filter]) {
13245
- statCollector.logger.debug(LOG_PREFIX, filter + ": " + value + " <> " + report[filter]);
13250
+ statCollector.logger.debug(LOG_PREFIX + "-" + statCollector.id, filter + ": " + value + " <> " + report[filter]);
13246
13251
  if (report[filter] === value) {
13247
13252
  filterMatched = true;
13248
13253
  break;
@@ -13255,34 +13260,44 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13255
13260
  }
13256
13261
  }
13257
13262
  if (filtersMatched) {
13258
- statCollector.addHeaders(report, metricsString);
13263
+ currentHeaders = statCollector.addHeaders(currentHeaders, report, metricsString);
13259
13264
  }
13260
13265
  } else {
13261
- statCollector.addHeaders(report, metricsString);
13266
+ currentHeaders = statCollector.addHeaders(currentHeaders, report, metricsString);
13262
13267
  }
13263
13268
  });
13264
13269
  } else {
13265
- statCollector.logger.warn(LOG_PREFIX, "No report type found in RTC stats: '" + type + "'");
13270
+ statCollector.logger.debug(LOG_PREFIX + "-" + statCollector.id, "No report type found in RTC stats: '" + type + "'");
13266
13271
  }
13267
13272
  });
13273
+ if (currentHeaders !== statCollector.headers) {
13274
+ headersChanged = true;
13275
+ let newMetrics = [];
13276
+ currentHeaders.split(",").forEach((header) => {
13277
+ if (statCollector.headers.indexOf(header) === -1) {
13278
+ newMetrics.push(header);
13279
+ }
13280
+ });
13281
+ if (newMetrics.length) {
13282
+ statCollector.logger.info(LOG_PREFIX + "-" + statCollector.id, "RTC metrics to be collected: " + newMetrics.toString());
13283
+ }
13284
+ statCollector.headers = currentHeaders;
13285
+ }
13286
+ return headersChanged;
13268
13287
  },
13269
- addHeaders: function(report, metricsString) {
13288
+ addHeaders: function(currentHeaders, report, metricsString) {
13270
13289
  if (metricsString) {
13271
13290
  let metrics = metricsString.split(",");
13272
13291
  metrics.forEach((metric) => {
13273
- let metricFound = false;
13274
13292
  for (const key of Object.keys(report)) {
13275
13293
  if (metric === key) {
13276
- statCollector.headers = util.addFieldToCsvString(statCollector.headers, report.type + "." + report.id + "." + metric, ",");
13277
- metricFound = true;
13294
+ currentHeaders = util.addFieldToCsvString(currentHeaders, report.type + "." + report.id + "." + metric, ",");
13278
13295
  break;
13279
13296
  }
13280
13297
  }
13281
- if (!metricFound) {
13282
- statCollector.logger.warn(LOG_PREFIX, "No metric found in RTC stats report '" + report.type + "': '" + metric + "'");
13283
- }
13284
13298
  });
13285
13299
  }
13300
+ return currentHeaders;
13286
13301
  },
13287
13302
  updateCompression: async function() {
13288
13303
  if (statCollector.description.compression) {
@@ -13298,7 +13313,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13298
13313
  await util.compress(compression, "test", false);
13299
13314
  statCollector.compression = compression;
13300
13315
  } catch (e) {
13301
- statCollector.logger.warn(LOG_PREFIX, "Can't compress metrics data using " + compression + ": " + e);
13316
+ statCollector.logger.warn(LOG_PREFIX + "-" + statCollector.id, "Can't compress metrics data using " + compression + ": " + e);
13302
13317
  statCollector.compression = "none";
13303
13318
  }
13304
13319
  },
@@ -13311,7 +13326,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13311
13326
  statCollector.send("webRTCMetricsClientDescription", data);
13312
13327
  },
13313
13328
  send: function(message, data) {
13314
- statCollector.logger.debug(LOG_PREFIX, data);
13329
+ statCollector.logger.debug(LOG_PREFIX + "-" + statCollector.id, data);
13315
13330
  if (statCollector.wsConnection.readyState === WebSocket.OPEN) {
13316
13331
  statCollector.wsConnection.send(JSON.stringify({
13317
13332
  message: message,
@@ -13333,7 +13348,10 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13333
13348
  }
13334
13349
  },
13335
13350
  collectMetrics: async function() {
13336
- if (statCollector.timer) {
13351
+ if (statCollector.timer && !statCollector.timerBusy) {
13352
+ // Unfortunately there are no real atomics in JS unless SharedArrayBuffer is used
13353
+ // So we guard the timer callback with a dumb boolean
13354
+ statCollector.timerBusy = true;
13337
13355
  let stats = await statCollector.mediaConnection.getWebRTCStats();
13338
13356
 
13339
13357
  if (!statCollector.metricsBatch) {
@@ -13341,6 +13359,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13341
13359
  }
13342
13360
 
13343
13361
  let metrics = [];
13362
+ let lostMetrics = [];
13344
13363
  statCollector.headers.split(",").forEach((header) => {
13345
13364
  let components = header.split(".");
13346
13365
  let descriptor = {
@@ -13348,7 +13367,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13348
13367
  id: components[1],
13349
13368
  name: components[2]
13350
13369
  }
13351
- let value = "undefined";
13370
+ let value = "NO";
13352
13371
 
13353
13372
  if (stats[descriptor.type]) {
13354
13373
  for (const report of stats[descriptor.type]) {
@@ -13359,12 +13378,25 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13359
13378
  }
13360
13379
  }
13361
13380
  metrics.push(value);
13381
+ if (value == "NO") {
13382
+ lostMetrics.push(descriptor);
13383
+ }
13362
13384
  });
13385
+ if (lostMetrics.length) {
13386
+ statCollector.logger.info(LOG_PREFIX + "-" + statCollector.id, "Missing metrics: " + JSON.stringify(lostMetrics));
13387
+ }
13363
13388
  statCollector.metricsBatch.push(metrics);
13364
13389
  statCollector.batchCount--;
13365
13390
  if (statCollector.batchCount === 0) {
13366
13391
  await statCollector.sendMetrics();
13367
13392
  }
13393
+ // Check if metrics list changed and send a new headers if needed #WCS-4619
13394
+ if (await statCollector.updateHeaders(stats)) {
13395
+ statCollector.logger.info(LOG_PREFIX + "-" + statCollector.id, "RTC metrics list has changed, sending a new metrics description");
13396
+ await statCollector.sendMetrics();
13397
+ statCollector.sendHeaders();
13398
+ }
13399
+ statCollector.timerBusy = false;
13368
13400
  }
13369
13401
  },
13370
13402
  sendMetrics: async function() {
@@ -13377,14 +13409,17 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13377
13409
  for (let j = 0; j < statCollector.metricsBatch[i].length; j++) {
13378
13410
  let valueString = valueToString(statCollector.metricsBatch[i][j]);
13379
13411
  let previousString = "";
13380
- let separator = ";";
13412
+ let delimiter = ";";
13381
13413
  if (previous) {
13382
13414
  previousString = valueToString(previous[j]);
13383
13415
  }
13384
13416
  if (valueString === previousString) {
13385
13417
  valueString = "";
13386
13418
  }
13387
- metricsString = util.addFieldToCsvString(metricsString, valueString, separator);
13419
+ metricsString = util.addFieldToCsvString(metricsString, valueString, delimiter);
13420
+ if (j > 0 && metricsString === "") {
13421
+ metricsString = delimiter;
13422
+ }
13388
13423
  }
13389
13424
  previous = statCollector.metricsBatch[i];
13390
13425
  metricsToSend.push(metricsString);
@@ -13393,7 +13428,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13393
13428
  try {
13394
13429
  metricsData = await util.compress(statCollector.compression, JSON.stringify(metricsToSend), true);
13395
13430
  } catch(e) {
13396
- statCollector.logger.warn(LOG_PREFIX, "Can't send metrics data using" + statCollector.compression + ": " + e);
13431
+ statCollector.logger.warn(LOG_PREFIX + "-" + statCollector.id, "Can't send metrics data using" + statCollector.compression + ": " + e);
13397
13432
  metricsData = null;
13398
13433
  }
13399
13434
  } else {
@@ -14511,14 +14546,14 @@ const setPublishingBitrate = function(sdp, mediaConnection, minBitrate, maxBitra
14511
14546
  return sdp;
14512
14547
  };
14513
14548
 
14514
- const addFieldToCsvString = function(csvString, field, separator) {
14515
- if (field !== "" && field.indexOf(separator) >= 0 ) {
14549
+ const addFieldToCsvString = function(csvString, field, delimiter) {
14550
+ if (field !== "" && field.indexOf(delimiter) >= 0 ) {
14516
14551
  field = '"' + field + '"';
14517
14552
  }
14518
- if (csvString === "" && field !== "") {
14553
+ if (csvString === "") {
14519
14554
  csvString = field;
14520
14555
  } else {
14521
- csvString = csvString + separator + field;
14556
+ csvString = csvString + delimiter + field;
14522
14557
  }
14523
14558
  return csvString;
14524
14559
  }