@flashphoner/websdk 2.0.262 → 2.0.264

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,14 +13348,16 @@ 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
- if (!statCollector.metricsBatch) {
13340
- statCollector.metricsBatch = [];
13341
- }
13357
+ statCollector.startNewBatch();
13342
13358
 
13343
13359
  let metrics = [];
13360
+ let lostMetrics = [];
13344
13361
  statCollector.headers.split(",").forEach((header) => {
13345
13362
  let components = header.split(".");
13346
13363
  let descriptor = {
@@ -13348,7 +13365,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13348
13365
  id: components[1],
13349
13366
  name: components[2]
13350
13367
  }
13351
- let value = "undefined";
13368
+ let value = null;
13352
13369
 
13353
13370
  if (stats[descriptor.type]) {
13354
13371
  for (const report of stats[descriptor.type]) {
@@ -13358,13 +13375,32 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13358
13375
  }
13359
13376
  }
13360
13377
  }
13361
- metrics.push(value);
13378
+ if (value === null) {
13379
+ lostMetrics.push(descriptor);
13380
+ } else {
13381
+ metrics.push(value);
13382
+ }
13362
13383
  });
13363
- statCollector.metricsBatch.push(metrics);
13364
- statCollector.batchCount--;
13365
- if (statCollector.batchCount === 0) {
13384
+ // Metrics list may change if some metrics are added or some metrics are lost #WCS-4627
13385
+ let headersUpdated = await statCollector.updateHeaders(stats);
13386
+ if (lostMetrics.length) {
13387
+ statCollector.logger.info(LOG_PREFIX + "-" + statCollector.id, "Missing metrics: " + JSON.stringify(lostMetrics));
13388
+ // Send metrics already collected and start a new batch with current metrics array to send them later #WCS-4627
13366
13389
  await statCollector.sendMetrics();
13390
+ statCollector.startNewBatch(metrics);
13391
+ } else {
13392
+ statCollector.metricsBatch.push(metrics);
13393
+ statCollector.batchCount--;
13394
+ if (statCollector.batchCount === 0 || headersUpdated) {
13395
+ await statCollector.sendMetrics();
13396
+ }
13397
+ }
13398
+ // Check if metrics list changed and send a new headers if needed #WCS-4619
13399
+ if (headersUpdated) {
13400
+ statCollector.logger.info(LOG_PREFIX + "-" + statCollector.id, "RTC metrics list has changed, sending a new metrics description");
13401
+ statCollector.sendHeaders();
13367
13402
  }
13403
+ statCollector.timerBusy = false;
13368
13404
  }
13369
13405
  },
13370
13406
  sendMetrics: async function() {
@@ -13372,7 +13408,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13372
13408
  let metricsToSend = [];
13373
13409
  let metricsData;
13374
13410
 
13375
- for (let i = 0; i < statCollector.metricsBatch.length; i++) {
13411
+ for (let i = 0; statCollector.metricsBatch && i < statCollector.metricsBatch.length; i++) {
13376
13412
  let metricsString = "";
13377
13413
  for (let j = 0; j < statCollector.metricsBatch[i].length; j++) {
13378
13414
  let valueString = valueToString(statCollector.metricsBatch[i][j]);
@@ -13396,7 +13432,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13396
13432
  try {
13397
13433
  metricsData = await util.compress(statCollector.compression, JSON.stringify(metricsToSend), true);
13398
13434
  } catch(e) {
13399
- statCollector.logger.warn(LOG_PREFIX, "Can't send metrics data using" + statCollector.compression + ": " + e);
13435
+ statCollector.logger.warn(LOG_PREFIX + "-" + statCollector.id, "Can't send metrics data using" + statCollector.compression + ": " + e);
13400
13436
  metricsData = null;
13401
13437
  }
13402
13438
  } else {
@@ -13409,8 +13445,21 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13409
13445
  };
13410
13446
  statCollector.send("webRTCMetricsBatch", data);
13411
13447
  }
13412
- statCollector.metricsBatch = null;
13413
- statCollector.batchCount = statCollector.description.batchSize;
13448
+ statCollector.cleanBatch();
13449
+ },
13450
+ startNewBatch: function(metrics) {
13451
+ if (!statCollector.metricsBatch) {
13452
+ statCollector.metricsBatch = [];
13453
+ if (metrics) {
13454
+ statCollector.metricsBatch.push(metrics);
13455
+ }
13456
+ }
13457
+ },
13458
+ cleanBatch: function() {
13459
+ if (statCollector.metricsBatch) {
13460
+ statCollector.metricsBatch = null;
13461
+ statCollector.batchCount = statCollector.description.batchSize;
13462
+ }
13414
13463
  }
13415
13464
  }
13416
13465
  return statCollector;