@observertc/observer-js 0.42.9 → 1.0.0-5f150eb.0

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.
Files changed (303) hide show
  1. package/.prettierrc +6 -6
  2. package/README.md +493 -63
  3. package/lib/ObservedCall.d.ts +48 -43
  4. package/lib/ObservedCall.d.ts.map +1 -1
  5. package/lib/ObservedCall.js +164 -107
  6. package/lib/ObservedCallEventMonitor.d.ts +107 -0
  7. package/lib/ObservedCallEventMonitor.d.ts.map +1 -0
  8. package/lib/ObservedCallEventMonitor.js +321 -0
  9. package/lib/ObservedCallSummary.d.ts +18 -0
  10. package/lib/ObservedCallSummary.d.ts.map +1 -0
  11. package/lib/ObservedCertificate.d.ts +19 -0
  12. package/lib/ObservedCertificate.d.ts.map +1 -0
  13. package/lib/ObservedCertificate.js +38 -0
  14. package/lib/ObservedClient.d.ts +78 -145
  15. package/lib/ObservedClient.d.ts.map +1 -1
  16. package/lib/ObservedClient.js +661 -746
  17. package/lib/ObservedClientEventMonitor.d.ts +91 -0
  18. package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
  19. package/lib/ObservedClientEventMonitor.js +254 -0
  20. package/lib/ObservedClientSummary.d.ts +23 -0
  21. package/lib/ObservedClientSummary.d.ts.map +1 -0
  22. package/lib/ObservedClientSummary.js +2 -0
  23. package/lib/ObservedCodec.d.ts +22 -0
  24. package/lib/ObservedCodec.d.ts.map +1 -0
  25. package/lib/ObservedCodec.js +45 -0
  26. package/lib/ObservedDataChannel.d.ts +25 -69
  27. package/lib/ObservedDataChannel.d.ts.map +1 -1
  28. package/lib/ObservedDataChannel.js +69 -109
  29. package/lib/ObservedIceCandidate.d.ts +29 -0
  30. package/lib/ObservedIceCandidate.d.ts.map +1 -0
  31. package/lib/ObservedIceCandidate.js +59 -0
  32. package/lib/ObservedIceCandidatePair.d.ts +45 -0
  33. package/lib/ObservedIceCandidatePair.d.ts.map +1 -0
  34. package/lib/ObservedIceCandidatePair.js +127 -0
  35. package/lib/ObservedIceTransport.d.ts +36 -0
  36. package/lib/ObservedIceTransport.d.ts.map +1 -0
  37. package/lib/ObservedIceTransport.js +93 -0
  38. package/lib/ObservedInboundRtp.d.ts +92 -0
  39. package/lib/ObservedInboundRtp.d.ts.map +1 -0
  40. package/lib/ObservedInboundRtp.js +193 -0
  41. package/lib/ObservedInboundTrack.d.ts +34 -0
  42. package/lib/ObservedInboundTrack.d.ts.map +1 -0
  43. package/lib/ObservedInboundTrack.js +92 -0
  44. package/lib/ObservedMediaPlayout.d.ts +22 -0
  45. package/lib/ObservedMediaPlayout.d.ts.map +1 -0
  46. package/lib/ObservedMediaPlayout.js +42 -0
  47. package/lib/ObservedMediaSource.d.ts +28 -0
  48. package/lib/ObservedMediaSource.d.ts.map +1 -0
  49. package/lib/ObservedMediaSource.js +55 -0
  50. package/lib/ObservedOutboundRtp.d.ts +62 -0
  51. package/lib/ObservedOutboundRtp.d.ts.map +1 -0
  52. package/lib/ObservedOutboundRtp.js +144 -0
  53. package/lib/ObservedOutboundTrack.d.ts +34 -0
  54. package/lib/ObservedOutboundTrack.d.ts.map +1 -0
  55. package/lib/ObservedOutboundTrack.js +65 -0
  56. package/lib/ObservedPeerConnection.d.ts +154 -80
  57. package/lib/ObservedPeerConnection.d.ts.map +1 -1
  58. package/lib/ObservedPeerConnection.js +724 -357
  59. package/lib/ObservedPeerConnectionTransport.d.ts +17 -0
  60. package/lib/ObservedPeerConnectionTransport.d.ts.map +1 -0
  61. package/lib/ObservedPeerConnectionTransport.js +34 -0
  62. package/lib/ObservedRemoteInboundRtp.d.ts +30 -0
  63. package/lib/ObservedRemoteInboundRtp.d.ts.map +1 -0
  64. package/lib/ObservedRemoteInboundRtp.js +60 -0
  65. package/lib/ObservedRemoteOutboundRtp.d.ts +30 -0
  66. package/lib/ObservedRemoteOutboundRtp.d.ts.map +1 -0
  67. package/lib/ObservedRemoteOutboundRtp.js +60 -0
  68. package/lib/ObservedTURN.d.ts +31 -0
  69. package/lib/ObservedTURN.d.ts.map +1 -0
  70. package/lib/ObservedTURN.js +58 -0
  71. package/lib/ObservedTurnServer.d.ts +25 -0
  72. package/lib/ObservedTurnServer.d.ts.map +1 -0
  73. package/lib/ObservedTurnServer.js +59 -0
  74. package/lib/Observer.d.ts +46 -54
  75. package/lib/Observer.d.ts.map +1 -1
  76. package/lib/Observer.js +131 -226
  77. package/lib/ObserverEventMonitor.d.ts +141 -0
  78. package/lib/ObserverEventMonitor.d.ts.map +1 -0
  79. package/lib/ObserverEventMonitor.js +440 -0
  80. package/lib/ObserverSummary.d.ts +13 -0
  81. package/lib/ObserverSummary.d.ts.map +1 -0
  82. package/lib/ObserverSummary.js +2 -0
  83. package/lib/Reports.d.ts +85 -0
  84. package/lib/Reports.d.ts.map +1 -0
  85. package/lib/Reports.js +2 -0
  86. package/lib/common/Middleware.d.ts +10 -1
  87. package/lib/common/Middleware.d.ts.map +1 -1
  88. package/lib/common/Middleware.js +55 -36
  89. package/lib/common/logger.d.ts +8 -4
  90. package/lib/common/logger.d.ts.map +1 -1
  91. package/lib/common/logger.js +44 -68
  92. package/lib/common/types.d.ts +0 -21
  93. package/lib/common/types.d.ts.map +1 -1
  94. package/lib/common/types.js +1 -0
  95. package/lib/common/utils.d.ts +3 -1
  96. package/lib/common/utils.d.ts.map +1 -1
  97. package/lib/common/utils.js +23 -3
  98. package/lib/detectors/Detector.d.ts +5 -0
  99. package/lib/detectors/Detector.d.ts.map +1 -0
  100. package/lib/detectors/Detector.js +3 -0
  101. package/lib/detectors/Detectors.d.ts +11 -0
  102. package/lib/detectors/Detectors.d.ts.map +1 -0
  103. package/lib/detectors/Detectors.js +34 -0
  104. package/lib/index.d.ts +27 -25
  105. package/lib/index.d.ts.map +1 -1
  106. package/lib/index.js +45 -41
  107. package/lib/mediasoup/ObservedMediaRouter.d.ts +10 -0
  108. package/lib/mediasoup/ObservedMediaRouter.d.ts.map +1 -0
  109. package/lib/mediasoup/ObservedMediaRouter.js +6 -0
  110. package/lib/monitors/TurnUsageMonitor.d.ts +0 -52
  111. package/lib/monitors/TurnUsageMonitor.d.ts.map +1 -1
  112. package/lib/monitors/TurnUsageMonitor.js +145 -120
  113. package/lib/schema/ClientEventTypes.d.ts +228 -0
  114. package/lib/schema/ClientEventTypes.d.ts.map +1 -0
  115. package/lib/schema/ClientEventTypes.js +41 -0
  116. package/lib/schema/ClientMetaTypes.d.ts +34 -0
  117. package/lib/schema/ClientMetaTypes.d.ts.map +1 -0
  118. package/lib/schema/ClientMetaTypes.js +16 -0
  119. package/lib/schema/ClientSample.d.ts +1333 -0
  120. package/lib/schema/ClientSample.d.ts.map +1 -0
  121. package/lib/schema/ClientSample.js +4 -0
  122. package/lib/scores/CalculatedScore.d.ts +6 -0
  123. package/lib/scores/CalculatedScore.d.ts.map +1 -0
  124. package/lib/scores/CalculatedScore.js +2 -0
  125. package/lib/scores/DefaultCallScoreCalculator.d.ts +7 -0
  126. package/lib/scores/DefaultCallScoreCalculator.d.ts.map +1 -0
  127. package/lib/scores/DefaultCallScoreCalculator.js +21 -0
  128. package/lib/scores/ScoreCalculator.d.ts +4 -0
  129. package/lib/scores/ScoreCalculator.d.ts.map +1 -0
  130. package/lib/scores/ScoreCalculator.js +2 -0
  131. package/lib/updaters/CallUpdater.d.ts +5 -0
  132. package/lib/updaters/CallUpdater.d.ts.map +1 -0
  133. package/lib/updaters/CallUpdater.js +2 -0
  134. package/lib/updaters/ObserverUpdater.d.ts +5 -0
  135. package/lib/updaters/ObserverUpdater.d.ts.map +1 -0
  136. package/lib/updaters/ObserverUpdater.js +2 -0
  137. package/lib/updaters/OnAllCallObserverUpdater.d.ts +15 -0
  138. package/lib/updaters/OnAllCallObserverUpdater.d.ts.map +1 -0
  139. package/lib/updaters/OnAllCallObserverUpdater.js +50 -0
  140. package/lib/updaters/OnAllClientCallUpdater.d.ts +15 -0
  141. package/lib/updaters/OnAllClientCallUpdater.d.ts.map +1 -0
  142. package/lib/updaters/OnAllClientCallUpdater.js +53 -0
  143. package/lib/updaters/OnAnyCallObserverUpdater.d.ts +12 -0
  144. package/lib/updaters/OnAnyCallObserverUpdater.d.ts.map +1 -0
  145. package/lib/updaters/OnAnyCallObserverUpdater.js +37 -0
  146. package/lib/updaters/OnAnyClientCallUpdater.d.ts +12 -0
  147. package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +1 -0
  148. package/lib/updaters/OnAnyClientCallUpdater.js +36 -0
  149. package/lib/updaters/OnIntervalUpdater.d.ts +10 -0
  150. package/lib/updaters/OnIntervalUpdater.d.ts.map +1 -0
  151. package/lib/updaters/OnIntervalUpdater.js +17 -0
  152. package/lib/updaters/Updater.d.ts +6 -0
  153. package/lib/updaters/Updater.d.ts.map +1 -0
  154. package/lib/updaters/Updater.js +2 -0
  155. package/lib/utils/MediasoupRemoteTrackResolver.d.ts +25 -0
  156. package/lib/utils/MediasoupRemoteTrackResolver.d.ts.map +1 -0
  157. package/lib/utils/MediasoupRemoteTrackResolver.js +110 -0
  158. package/lib/utils/RemoteTrackResolver.d.ts +7 -0
  159. package/lib/utils/RemoteTrackResolver.d.ts.map +1 -0
  160. package/lib/utils/RemoteTrackResolver.js +2 -0
  161. package/package.json +4 -4
  162. package/src/ObservedCall.ts +243 -161
  163. package/src/ObservedCallEventMonitor.ts +402 -0
  164. package/src/ObservedCallSummary.ts +22 -0
  165. package/src/ObservedCertificate.ts +43 -0
  166. package/src/ObservedClient.ts +715 -1003
  167. package/src/ObservedClientEventMonitor.ts +309 -0
  168. package/src/ObservedClientSummary.ts +24 -0
  169. package/src/ObservedCodec.ts +49 -0
  170. package/src/ObservedDataChannel.ts +71 -181
  171. package/src/ObservedIceCandidate.ts +64 -0
  172. package/src/ObservedIceCandidatePair.ts +134 -0
  173. package/src/ObservedIceTransport.ts +99 -0
  174. package/src/ObservedInboundRtp.ts +205 -0
  175. package/src/ObservedInboundTrack.ts +105 -0
  176. package/src/ObservedMediaPlayout.ts +49 -0
  177. package/src/ObservedMediaSource.ts +60 -0
  178. package/src/ObservedOutboundRtp.ts +156 -0
  179. package/src/ObservedOutboundTrack.ts +82 -0
  180. package/src/ObservedPeerConnection.ts +933 -402
  181. package/src/ObservedPeerConnectionTransport.ts +38 -0
  182. package/src/ObservedRemoteInboundRtp.ts +64 -0
  183. package/src/ObservedRemoteOutboundRtp.ts +65 -0
  184. package/src/ObservedTURN.ts +86 -0
  185. package/src/ObservedTurnServer.ts +72 -0
  186. package/src/Observer.ts +183 -298
  187. package/src/ObserverEventMonitor.ts +561 -0
  188. package/src/ObserverSummary.ts +15 -0
  189. package/src/Reports.ts +87 -0
  190. package/src/common/Middleware.ts +70 -42
  191. package/src/common/logger.ts +60 -69
  192. package/src/common/types.ts +0 -42
  193. package/src/common/utils.ts +24 -2
  194. package/src/detectors/Detector.ts +6 -0
  195. package/src/detectors/Detectors.ts +38 -0
  196. package/src/index.ts +30 -91
  197. package/src/mediasoup/ObservedMediaRouter.ts +10 -0
  198. package/src/monitors/TurnUsageMonitor.ts +164 -164
  199. package/src/schema/ClientEventTypes.ts +280 -0
  200. package/src/schema/ClientMetaTypes.ts +41 -0
  201. package/src/schema/ClientSample.ts +1682 -0
  202. package/src/scores/CalculatedScore.ts +6 -0
  203. package/src/scores/DefaultCallScoreCalculator.ts +23 -0
  204. package/src/scores/ScoreCalculator.ts +3 -0
  205. package/src/updaters/CallUpdater.ts +5 -0
  206. package/src/updaters/ObserverUpdater.ts +5 -0
  207. package/src/updaters/OnAllCallObserverUpdater.ts +59 -0
  208. package/src/updaters/OnAllClientCallUpdater.ts +61 -0
  209. package/src/updaters/OnAnyCallObserverUpdater.ts +41 -0
  210. package/src/updaters/OnAnyClientCallUpdater.ts +39 -0
  211. package/src/updaters/OnIntervalUpdater.ts +19 -0
  212. package/src/updaters/Updater.ts +5 -0
  213. package/src/utils/MediasoupRemoteTrackResolver.ts +155 -0
  214. package/src/utils/RemoteTrackResolver.ts +12 -0
  215. package/tsconfig.json +3 -3
  216. package/lib/ObservedICE.d.ts +0 -64
  217. package/lib/ObservedICE.d.ts.map +0 -1
  218. package/lib/ObservedICE.js +0 -141
  219. package/lib/ObservedInboundAudioTrack.d.ts +0 -96
  220. package/lib/ObservedInboundAudioTrack.d.ts.map +0 -1
  221. package/lib/ObservedInboundAudioTrack.js +0 -217
  222. package/lib/ObservedInboundVideoTrack.d.ts +0 -101
  223. package/lib/ObservedInboundVideoTrack.d.ts.map +0 -1
  224. package/lib/ObservedInboundVideoTrack.js +0 -232
  225. package/lib/ObservedOutboundAudioTrack.d.ts +0 -87
  226. package/lib/ObservedOutboundAudioTrack.d.ts.map +0 -1
  227. package/lib/ObservedOutboundAudioTrack.js +0 -186
  228. package/lib/ObservedOutboundVideoTrack.d.ts +0 -91
  229. package/lib/ObservedOutboundVideoTrack.d.ts.map +0 -1
  230. package/lib/ObservedOutboundVideoTrack.js +0 -193
  231. package/lib/ObservedSfu.d.ts +0 -59
  232. package/lib/ObservedSfu.d.ts.map +0 -1
  233. package/lib/ObservedSfu.js +0 -157
  234. package/lib/ObservedSfuInboundRtpPad.d.ts +0 -42
  235. package/lib/ObservedSfuInboundRtpPad.d.ts.map +0 -1
  236. package/lib/ObservedSfuInboundRtpPad.js +0 -71
  237. package/lib/ObservedSfuOutboundRtpPad.d.ts +0 -42
  238. package/lib/ObservedSfuOutboundRtpPad.d.ts.map +0 -1
  239. package/lib/ObservedSfuOutboundRtpPad.js +0 -72
  240. package/lib/ObservedSfuSctpChannel.d.ts +0 -42
  241. package/lib/ObservedSfuSctpChannel.d.ts.map +0 -1
  242. package/lib/ObservedSfuSctpChannel.js +0 -57
  243. package/lib/ObservedSfuTransport.d.ts +0 -58
  244. package/lib/ObservedSfuTransport.d.ts.map +0 -1
  245. package/lib/ObservedSfuTransport.js +0 -120
  246. package/lib/RemoteTrackAssigner.d.ts +0 -14
  247. package/lib/RemoteTrackAssigner.d.ts.map +0 -1
  248. package/lib/RemoteTrackAssigner.js +0 -52
  249. package/lib/ReportsCollector.d.ts +0 -109
  250. package/lib/ReportsCollector.d.ts.map +0 -1
  251. package/lib/ReportsCollector.js +0 -207
  252. package/lib/common/CalculatedScore.d.ts +0 -80
  253. package/lib/common/CalculatedScore.d.ts.map +0 -1
  254. package/lib/common/CalculatedScore.js +0 -162
  255. package/lib/common/CallEventType.d.ts +0 -63
  256. package/lib/common/CallEventType.d.ts.map +0 -1
  257. package/lib/common/CallEventType.js +0 -39
  258. package/lib/common/CallMetaReports.d.ts +0 -42
  259. package/lib/common/CallMetaReports.d.ts.map +0 -1
  260. package/lib/common/CallMetaReports.js +0 -36
  261. package/lib/common/QualityScoreUtils.d.ts +0 -1
  262. package/lib/common/QualityScoreUtils.d.ts.map +0 -1
  263. package/lib/common/QualityScoreUtils.js +0 -1
  264. package/lib/common/TypedEventEmitter.d.ts +0 -22
  265. package/lib/common/TypedEventEmitter.d.ts.map +0 -1
  266. package/lib/common/TypedEventEmitter.js +0 -11
  267. package/lib/common/callEventReports.d.ts +0 -10
  268. package/lib/common/callEventReports.d.ts.map +0 -1
  269. package/lib/common/callEventReports.js +0 -112
  270. package/lib/monitors/CallSummary.d.ts +0 -37
  271. package/lib/monitors/CallSummary.d.ts.map +0 -1
  272. package/lib/monitors/CallSummaryMonitor.d.ts +0 -32
  273. package/lib/monitors/CallSummaryMonitor.d.ts.map +0 -1
  274. package/lib/monitors/CallSummaryMonitor.js +0 -152
  275. package/lib/monitors/ClientIssueMonitor.d.ts +0 -32
  276. package/lib/monitors/ClientIssueMonitor.d.ts.map +0 -1
  277. package/lib/monitors/ClientIssueMonitor.js +0 -49
  278. package/lib/monitors/SfuServerMonitor.d.ts +0 -79
  279. package/lib/monitors/SfuServerMonitor.d.ts.map +0 -1
  280. package/lib/monitors/SfuServerMonitor.js +0 -198
  281. package/src/ObservedICE.ts +0 -237
  282. package/src/ObservedInboundAudioTrack.ts +0 -344
  283. package/src/ObservedInboundVideoTrack.ts +0 -361
  284. package/src/ObservedOutboundAudioTrack.ts +0 -307
  285. package/src/ObservedOutboundVideoTrack.ts +0 -319
  286. package/src/ObservedSfu.ts +0 -231
  287. package/src/ObservedSfuInboundRtpPad.ts +0 -106
  288. package/src/ObservedSfuOutboundRtpPad.ts +0 -107
  289. package/src/ObservedSfuSctpChannel.ts +0 -103
  290. package/src/ObservedSfuTransport.ts +0 -185
  291. package/src/RemoteTrackAssigner.ts +0 -68
  292. package/src/ReportsCollector.ts +0 -336
  293. package/src/common/CalculatedScore.ts +0 -188
  294. package/src/common/CallEventType.ts +0 -69
  295. package/src/common/CallMetaReports.ts +0 -82
  296. package/src/common/QualityScoreUtils.ts +0 -0
  297. package/src/common/TypedEventEmitter.ts +0 -32
  298. package/src/common/callEventReports.ts +0 -178
  299. package/src/monitors/CallSummary.ts +0 -38
  300. package/src/monitors/CallSummaryMonitor.ts +0 -192
  301. package/src/monitors/ClientIssueMonitor.ts +0 -88
  302. package/src/monitors/SfuServerMonitor.ts +0 -285
  303. /package/lib/{monitors/CallSummary.js → ObservedCallSummary.js} +0 -0
@@ -1,799 +1,714 @@
1
1
  "use strict";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
2
  Object.defineProperty(exports, "__esModule", { value: true });
14
3
  exports.ObservedClient = void 0;
15
4
  const events_1 = require("events");
16
5
  const ObservedPeerConnection_1 = require("./ObservedPeerConnection");
17
6
  const logger_1 = require("./common/logger");
18
- const CallMetaReports_1 = require("./common/CallMetaReports");
19
- // eslint-disable-next-line camelcase
7
+ const ClientEventTypes_1 = require("./schema/ClientEventTypes");
8
+ const ClientMetaTypes_1 = require("./schema/ClientMetaTypes");
20
9
  const utils_1 = require("./common/utils");
21
- const CallEventType_1 = require("./common/CallEventType");
10
+ const Detectors_1 = require("./detectors/Detectors");
22
11
  const logger = (0, logger_1.createLogger)('ObservedClient');
23
12
  class ObservedClient extends events_1.EventEmitter {
24
- constructor(_model, call, appData) {
13
+ call;
14
+ detectors;
15
+ clientId;
16
+ observedPeerConnections = new Map();
17
+ calculatedScore = {
18
+ weight: 1,
19
+ value: undefined,
20
+ };
21
+ settings;
22
+ appData;
23
+ attachments;
24
+ updated = Date.now();
25
+ acceptedSamples = 0;
26
+ closed = false;
27
+ joinedAt;
28
+ leftAt;
29
+ closedAt;
30
+ lastSampleTimestamp;
31
+ // the timestamp of the CLIENT_JOINED event
32
+ operationSystem;
33
+ engine;
34
+ platform;
35
+ browser;
36
+ mediaConstraints = [];
37
+ usingTURN = false;
38
+ usingTCP = false;
39
+ availableOutgoingBitrate = 0;
40
+ availableIncomingBitrate = 0;
41
+ // public totalInboundPacketsLost = 0;
42
+ // public totalInboundPacketsReceived = 0;
43
+ // public totalOutboundPacketsSent = 0;
44
+ // public totalDataChannelBytesSent = 0;
45
+ // public totalDataChannelBytesReceived = 0;
46
+ // public totalDataChannelMessagesSent = 0;
47
+ // public totalDataChannelMessagesReceived = 0;
48
+ // public totalReceivedAudioBytes = 0;
49
+ // public totalReceivedVideoBytes = 0;
50
+ // public totalSentAudioBytes = 0;
51
+ // public totalSentVideoBytes = 0;
52
+ // public totalSentBytes = 0;
53
+ // public totalReceivedBytes = 0;
54
+ // public totalRttLt50Measurements = 0;
55
+ // public totalRttLt150Measurements = 0;
56
+ // public totalRttLt300Measurements = 0;
57
+ // public totalRttGtOrEq300Measurements = 0;
58
+ deltaReceivedAudioBytes = 0;
59
+ deltaReceivedVideoBytes = 0;
60
+ deltaSentAudioBytes = 0;
61
+ deltaSentVideoBytes = 0;
62
+ deltaDataChannelBytesSent = 0;
63
+ deltaDataChannelBytesReceived = 0;
64
+ deltaDataChannelMessagesSent = 0;
65
+ deltaDataChannelMessagesReceived = 0;
66
+ deltaInboundPacketsLost = 0;
67
+ deltaInboundPacketsReceived = 0;
68
+ deltaOutboundPacketsSent = 0;
69
+ deltaTransportSentBytes = 0;
70
+ deltaTransportReceivedBytes = 0;
71
+ deltaRttLt50Measurements = 0;
72
+ deltaRttLt150Measurements = 0;
73
+ deltaRttLt300Measurements = 0;
74
+ deltaRttGtOrEq300Measurements = 0;
75
+ currentMaxRttInMs;
76
+ currentMinRttInMs;
77
+ currentAvgRttInMs;
78
+ sendingAudioBitrate = 0;
79
+ sendingVideoBitrate = 0;
80
+ receivingAudioBitrate = 0;
81
+ receivingVideoBitrate = 0;
82
+ numberOfInboundRtpStreams = 0;
83
+ numberOfInbundTracks = 0;
84
+ numberOfOutboundRtpStreams = 0;
85
+ numberOfOutboundTracks = 0;
86
+ numberOfDataChannels = 0;
87
+ deltaNumberOfIssues = 0;
88
+ totalScoreSum = 0;
89
+ numberOfScoreMeasurements = 0;
90
+ // public totalNumberOfIssues = 0;
91
+ report;
92
+ mediaDevices = [];
93
+ issues = [];
94
+ _injections = {};
95
+ closeTimer;
96
+ constructor(settings, call) {
25
97
  super();
26
- this._model = _model;
27
98
  this.call = call;
28
- this.appData = appData;
29
- this.created = Date.now();
30
- this.updated = Date.now();
31
- this._peerConnections = new Map();
32
- this._closed = false;
33
- this._acceptedSamples = 0;
34
- this.usingTURN = false;
35
- this.availableOutgoingBitrate = 0;
36
- this.availableIncomingBitrate = 0;
37
- this.totalInboundPacketsLost = 0;
38
- this.totalInboundPacketsReceived = 0;
39
- this.totalOutboundPacketsSent = 0;
40
- this.totalDataChannelBytesSent = 0;
41
- this.totalDataChannelBytesReceived = 0;
42
- this.totalSentBytes = 0;
43
- this.totalReceivedBytes = 0;
44
- this.totalReceivedAudioBytes = 0;
45
- this.totalReceivedVideoBytes = 0;
46
- this.totalSentAudioBytes = 0;
47
- this.totalSentVideoBytes = 0;
48
- this.deltaReceivedAudioBytes = 0;
49
- this.deltaReceivedVideoBytes = 0;
50
- this.deltaSentAudioBytes = 0;
51
- this.deltaSentVideoBytes = 0;
52
- this.deltaDataChannelBytesSent = 0;
53
- this.deltaDataChannelBytesReceived = 0;
54
- this.deltaInboundPacketsLost = 0;
55
- this.deltaInboundPacketsReceived = 0;
56
- this.deltaOutboundPacketsSent = 0;
57
- this.mediaConstraints = [];
58
- this.mediaDevices = [];
59
- this.mediaCodecs = [];
60
- this.userMediaErrors = [];
61
- this.issues = [];
62
- this.ωpendingPeerConnectionTimestamps = [];
63
- this.ωpendingMediaTrackTimestamps = [];
64
99
  this.setMaxListeners(Infinity);
100
+ this.clientId = settings.clientId;
101
+ this.appData = settings.appData ?? {};
102
+ this.detectors = new Detectors_1.Detectors();
103
+ this.settings = {
104
+ closeClientIfIdleForMs: settings.closeClientIfIdleForMs,
105
+ };
106
+ this.report = {
107
+ callId: this.call.callId,
108
+ clientId: this.clientId,
109
+ rttDistribution: {
110
+ gtOrEq300ms: 0,
111
+ lt50ms: 0,
112
+ lt150ms: 0,
113
+ lt300ms: 0,
114
+ count: 0,
115
+ sum: 0,
116
+ },
117
+ scoreDistribution: {
118
+ '0': 0,
119
+ '1': 0,
120
+ '2': 0,
121
+ '3': 0,
122
+ '4': 0,
123
+ '5': 0,
124
+ count: 0,
125
+ sum: 0,
126
+ },
127
+ issues: {},
128
+ totalAudioBytesReceived: 0,
129
+ totalVideoBytesReceived: 0,
130
+ totalAudioBytesSent: 0,
131
+ totalVideoBytesSent: 0,
132
+ totalDataChannelBytesReceived: 0,
133
+ totalDataChannelBytesSent: 0,
134
+ totalDataChannelMessagesReceived: 0,
135
+ totalDataChannelMessagesSent: 0,
136
+ totalInboundRtpBytesReceived: 0,
137
+ totalInboundRtpPacketsLost: 0,
138
+ totalInboundRtpPacketsReceived: 0,
139
+ totalOutboundRtpBytesSent: 0,
140
+ totalOutboundRtpPacketsSent: 0,
141
+ totalNumberOfIssues: 0,
142
+ };
65
143
  }
66
- getSfu() {
67
- var _a;
68
- const sfu = this.call.observer.observedSfus.get((_a = this.sfuId) !== null && _a !== void 0 ? _a : '');
69
- if (!sfu)
70
- return;
71
- return sfu;
72
- }
73
- get joined() {
74
- return this._joined;
75
- }
76
- set joined(value) {
77
- this._joined = value;
78
- if (this._joined) {
79
- this.emit('joined');
80
- }
81
- }
82
- get left() {
83
- return this._left;
84
- }
85
- set left(value) {
86
- this._left = value;
87
- if (this._left) {
88
- this.emit('left');
89
- }
90
- }
91
- get sfu() {
92
- if (!this.sfuId)
93
- return;
94
- return this.call.observer.observedSfus.get(this.sfuId);
95
- }
96
- get coordinates() {
97
- return this._model.coordinates;
98
- }
99
- set coordinates(value) {
100
- this._model.coordinates = value;
101
- }
102
- get clientId() {
103
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
104
- return this._model.clientId;
105
- }
106
- get roomId() {
107
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
108
- return this.call.roomId;
109
- }
110
- get serviceId() {
111
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
112
- return this.call.serviceId;
113
- }
114
- get callId() {
115
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
116
- return this.call.callId;
117
- }
118
- get mediaUnitId() {
119
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
120
- return this._model.mediaUnitId;
121
- }
122
- get reports() {
123
- return this.call.reports;
124
- }
125
- get userId() {
126
- return this._model.userId;
127
- }
128
- set userId(userId) {
129
- this._model.userId = userId;
130
- }
131
- get timeZoneOffsetInHours() {
132
- return this._timeZoneOffsetInHours;
133
- }
134
- get marker() {
135
- return this._model.marker;
136
- }
137
- get browser() {
138
- return this._model.browser;
139
- }
140
- get engine() {
141
- return this._model.engine;
142
- }
143
- get operationSystem() {
144
- return this._model.operationSystem;
145
- }
146
- get platform() {
147
- return this._model.platform;
148
- }
149
- get acceptedSamples() {
150
- return this._acceptedSamples;
151
- }
152
- get closed() {
153
- return this._closed;
144
+ get numberOfPeerConnections() {
145
+ return this.observedPeerConnections.size;
154
146
  }
155
- get peerConnections() {
156
- return this._peerConnections;
147
+ get score() {
148
+ return this.calculatedScore.value;
157
149
  }
158
150
  close() {
159
- if (this._closed)
151
+ if (this.closed)
160
152
  return;
161
- this._closed = true;
162
- Array.from(this._peerConnections.values()).forEach((peerConnection) => peerConnection.close());
153
+ this.closed = true;
154
+ this._injections.clientEvents?.forEach((clientEvent) => this._processClientEvent(clientEvent));
155
+ this._injections.clientIssues?.forEach((clientIssue) => this.addIssue(clientIssue));
156
+ this._injections.extensionStats?.forEach((extensionStat) => this.addExtensionStats(extensionStat));
157
+ this._injections.clientMetaItems?.forEach((clientMetaItem) => this.addMetadata(clientMetaItem));
158
+ Array.from(this.observedPeerConnections.values()).forEach((peerConnection) => peerConnection.close());
159
+ if (!this.leftAt) {
160
+ this.leftAt = this.lastSampleTimestamp;
161
+ if (this.leftAt) {
162
+ this.emit('left');
163
+ }
164
+ }
165
+ this.closedAt = Date.now();
163
166
  this.emit('close');
164
167
  }
165
- addEventReport(params) {
166
- var _a;
167
- const { attachments } = params, fields = __rest(params, ["attachments"]);
168
- this.reports.addCallEventReport(Object.assign(Object.assign({}, fields), { serviceId: this.serviceId, mediaUnitId: this.mediaUnitId, roomId: this.roomId, callId: this.callId, clientId: this.clientId, userId: this.userId, timestamp: (_a = params.timestamp) !== null && _a !== void 0 ? _a : Date.now(), marker: this.marker, attachments: attachments ? JSON.stringify(attachments) : undefined }));
169
- }
170
- addExtensionStatsReport(extensionType, payload) {
171
- this.reports.addClientExtensionReport({
172
- serviceId: this.serviceId,
173
- mediaUnitId: this.mediaUnitId,
174
- roomId: this.roomId,
175
- callId: this.callId,
176
- clientId: this.clientId,
177
- userId: this.userId,
178
- timestamp: Date.now(),
179
- extensionType,
180
- payload: JSON.stringify(payload),
181
- marker: this.marker,
182
- });
183
- }
184
- addIssue(issue) {
185
- var _a;
186
- try {
187
- this.reports.addCallEventReport({
188
- serviceId: this.serviceId,
189
- mediaUnitId: this.mediaUnitId,
190
- roomId: this.roomId,
191
- callId: this.callId,
192
- clientId: this.clientId,
193
- userId: this.userId,
194
- name: CallEventType_1.CallEventType.CLIENT_ISSUE,
195
- value: issue.severity,
196
- peerConnectionId: issue.peerConnectionId,
197
- mediaTrackId: issue.trackId,
198
- message: issue.description,
199
- timestamp: (_a = issue.timestamp) !== null && _a !== void 0 ? _a : Date.now(),
200
- attachments: issue.attachments ? JSON.stringify(issue.attachments) : undefined,
201
- });
202
- }
203
- catch (err) {
204
- logger.warn(`Error adding client issue: ${err === null || err === void 0 ? void 0 : err.message}`);
205
- }
206
- this._addAndEmitIssue(issue);
207
- }
208
168
  accept(sample) {
209
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25;
210
- if (this._closed)
169
+ if (this.closed)
211
170
  throw new Error(`Client ${this.clientId} is closed`);
212
- if (sample.clientId && sample.clientId !== 'NULL' && sample.clientId !== this.clientId) {
213
- throw new Error(`Sample client id (${sample.clientId}) does not match the client id of the observed client (${this.clientId})`);
171
+ if (this.closeTimer) {
172
+ clearTimeout(this.closeTimer);
173
+ this.closeTimer = undefined;
214
174
  }
215
175
  const now = Date.now();
216
- ++this._acceptedSamples;
217
- if (0 < this.issues.length) {
218
- // we reset the issues every time we accept a new sample
219
- this.issues = [];
220
- }
221
- for (const peerConnection of this._peerConnections.values()) {
222
- if (peerConnection.closed)
176
+ const elapsedInMs = now - this.updated;
177
+ const elapsedInSeconds = elapsedInMs / 1000;
178
+ let sumOfRtts = 0;
179
+ let numberOfRttMeasurements = 0;
180
+ ++this.acceptedSamples;
181
+ this.availableIncomingBitrate = 0;
182
+ this.availableOutgoingBitrate = 0;
183
+ this.deltaDataChannelBytesReceived = 0;
184
+ this.deltaDataChannelBytesSent = 0;
185
+ this.deltaDataChannelMessagesReceived = 0;
186
+ this.deltaDataChannelMessagesSent = 0;
187
+ this.deltaInboundPacketsLost = 0;
188
+ this.deltaInboundPacketsReceived = 0;
189
+ this.deltaOutboundPacketsSent = 0;
190
+ this.deltaReceivedAudioBytes = 0;
191
+ this.deltaReceivedVideoBytes = 0;
192
+ this.deltaSentAudioBytes = 0;
193
+ this.deltaSentVideoBytes = 0;
194
+ this.deltaTransportReceivedBytes = 0;
195
+ this.deltaTransportSentBytes = 0;
196
+ this.deltaRttLt50Measurements = 0;
197
+ this.deltaRttLt150Measurements = 0;
198
+ this.deltaRttLt300Measurements = 0;
199
+ this.deltaRttGtOrEq300Measurements = 0;
200
+ this.deltaNumberOfIssues = 0;
201
+ this.numberOfDataChannels = 0;
202
+ this.numberOfInboundRtpStreams = 0;
203
+ this.numberOfInbundTracks = 0;
204
+ this.numberOfOutboundRtpStreams = 0;
205
+ this.numberOfOutboundTracks = 0;
206
+ this.usingTURN = false;
207
+ this.usingTCP = false;
208
+ this.currentMinRttInMs = undefined;
209
+ this.currentMaxRttInMs = undefined;
210
+ this._mergeInjections(sample);
211
+ const clientEventsPostBuffer = [];
212
+ for (const clientEvent of sample.clientEvents ?? []) {
213
+ this._processClientEvent(clientEvent, clientEventsPostBuffer);
214
+ this.call.observer.emit('client-event', this, clientEvent);
215
+ }
216
+ for (const metaData of sample.clientMetaItems ?? []) {
217
+ this.addMetadata(metaData);
218
+ }
219
+ for (const issue of sample.clientIssues ?? []) {
220
+ this.addIssue(issue);
221
+ ++this.deltaNumberOfIssues;
222
+ }
223
+ for (const extensionStat of sample.extensionStats ?? []) {
224
+ this.addExtensionStats(extensionStat);
225
+ }
226
+ for (const pcSample of sample.peerConnections ?? []) {
227
+ const observedPeerConnection = this._updatePeerConnection(pcSample);
228
+ if (!observedPeerConnection)
223
229
  continue;
224
- peerConnection.resetMetrics();
225
- }
226
- if (this._model.userId) {
227
- if (sample.userId && sample.userId !== 'NULL' && sample.userId !== this._model.userId) {
228
- this._model.userId = sample.userId;
229
- }
230
- }
231
- else if (sample.userId && sample.userId !== 'NULL') {
232
- this._model.userId = sample.userId;
233
- }
234
- if (this._model.marker !== sample.marker) {
235
- this._model.marker = sample.marker;
236
- this._peerConnections.forEach((peerConnection) => (peerConnection.marker = sample.marker));
237
- }
238
- if (this._timeZoneOffsetInHours !== sample.timeZoneOffsetInHours) {
239
- this._timeZoneOffsetInHours = sample.timeZoneOffsetInHours;
240
- }
241
- if (sample.os && (((_a = this._model.operationSystem) === null || _a === void 0 ? void 0 : _a.name) !== sample.os.name ||
242
- ((_b = this._model.operationSystem) === null || _b === void 0 ? void 0 : _b.version) !== sample.os.version ||
243
- ((_c = this._model.operationSystem) === null || _c === void 0 ? void 0 : _c.versionName) !== sample.os.versionName)) {
244
- this._model.operationSystem = sample.os;
245
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
246
- type: CallMetaReports_1.CallMetaType.OPERATION_SYSTEM,
247
- payload: sample.os,
248
- }, this.userId, undefined, sample.timestamp);
249
- this.reports.addCallMetaReport(callMetaReport);
250
- }
251
- if (sample.engine && (((_d = this._model.engine) === null || _d === void 0 ? void 0 : _d.name) !== sample.engine.name ||
252
- ((_e = this._model.engine) === null || _e === void 0 ? void 0 : _e.version) !== sample.engine.version)) {
253
- this._model.engine = sample.engine;
254
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
255
- type: CallMetaReports_1.CallMetaType.ENGINE,
256
- payload: sample.engine,
257
- }, this.userId, undefined, sample.timestamp);
258
- this.reports.addCallMetaReport(callMetaReport);
259
- }
260
- if (sample.platform && (((_f = this._model.platform) === null || _f === void 0 ? void 0 : _f.model) !== sample.platform.model ||
261
- ((_g = this._model.platform) === null || _g === void 0 ? void 0 : _g.type) !== sample.platform.type ||
262
- ((_h = this._model.platform) === null || _h === void 0 ? void 0 : _h.vendor) !== sample.platform.vendor)) {
263
- this._model.platform = sample.platform;
264
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
265
- type: CallMetaReports_1.CallMetaType.PLATFORM,
266
- payload: sample.platform,
267
- }, this.userId, undefined, sample.timestamp);
268
- this.reports.addCallMetaReport(callMetaReport);
269
- }
270
- if (sample.browser && (((_j = this._model.browser) === null || _j === void 0 ? void 0 : _j.name) !== sample.browser.name ||
271
- ((_k = this._model.browser) === null || _k === void 0 ? void 0 : _k.version) !== sample.browser.version)) {
272
- this._model.browser = sample.browser;
273
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
274
- type: CallMetaReports_1.CallMetaType.BROWSER,
275
- payload: sample.browser,
276
- }, this.userId, undefined, sample.timestamp);
277
- this.reports.addCallMetaReport(callMetaReport);
278
- }
279
- for (const mediaConstraint of (_l = sample.mediaConstraints) !== null && _l !== void 0 ? _l : []) {
280
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
281
- type: CallMetaReports_1.CallMetaType.MEDIA_CONSTRAINT,
282
- payload: mediaConstraint,
283
- }, this.userId, undefined, sample.timestamp);
284
- this.reports.addCallMetaReport(callMetaReport);
285
- this.mediaConstraints.push(mediaConstraint);
286
- }
287
- for (const localSDP of (_m = sample.localSDPs) !== null && _m !== void 0 ? _m : []) {
288
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
289
- type: CallMetaReports_1.CallMetaType.LOCAL_SDP,
290
- payload: localSDP,
291
- }, this.userId, undefined, sample.timestamp);
292
- this.reports.addCallMetaReport(callMetaReport);
293
- }
294
- for (const extensionStats of (_o = sample.extensionStats) !== null && _o !== void 0 ? _o : []) {
295
- this.reports.addClientExtensionReport({
296
- serviceId: this.serviceId,
297
- mediaUnitId: this.mediaUnitId,
298
- roomId: this.roomId,
299
- callId: this.callId,
300
- clientId: this.clientId,
301
- userId: this.userId,
302
- timestamp: now,
303
- payload: extensionStats.payload,
304
- extensionType: extensionStats.type,
305
- });
306
- }
307
- for (let _26 of (_p = sample.customCallEvents) !== null && _p !== void 0 ? _p : []) {
308
- const { timestamp } = _26, callEvent = __rest(_26, ["timestamp"]);
309
- switch (callEvent.name) {
310
- case CallEventType_1.CallEventType.CLIENT_JOINED: {
311
- const lastJoined = this.joined;
312
- this.joined = timestamp;
313
- // if it is joined before and it is joined again
314
- if (lastJoined && this.joined && lastJoined !== this.joined) {
315
- this.emit('rejoined', { lastJoined });
316
- }
317
- // in case we have a left event before the joined event
318
- if (this.left && this.joined && this.left < this.joined) {
319
- this.left = undefined;
320
- }
321
- break;
230
+ this.deltaDataChannelBytesReceived += observedPeerConnection.deltaDataChannelBytesReceived;
231
+ this.deltaDataChannelBytesSent += observedPeerConnection.deltaDataChannelBytesSent;
232
+ this.deltaDataChannelMessagesReceived += observedPeerConnection.deltaDataChannelMessagesReceived;
233
+ this.deltaDataChannelMessagesSent += observedPeerConnection.deltaDataChannelMessagesSent;
234
+ this.deltaInboundPacketsLost += observedPeerConnection.deltaInboundPacketsLost;
235
+ this.deltaInboundPacketsReceived += observedPeerConnection.deltaInboundPacketsReceived;
236
+ this.deltaOutboundPacketsSent += observedPeerConnection.deltaOutboundPacketsSent;
237
+ this.deltaReceivedAudioBytes += observedPeerConnection.deltaReceivedAudioBytes;
238
+ this.deltaReceivedVideoBytes += observedPeerConnection.deltaReceivedVideoBytes;
239
+ this.deltaSentAudioBytes += observedPeerConnection.deltaSentAudioBytes;
240
+ this.deltaSentVideoBytes += observedPeerConnection.deltaSentVideoBytes;
241
+ this.deltaTransportReceivedBytes += observedPeerConnection.deltaTransportReceivedBytes;
242
+ this.deltaTransportSentBytes += observedPeerConnection.deltaTransportSentBytes;
243
+ this.availableIncomingBitrate += observedPeerConnection.availableIncomingBitrate;
244
+ this.availableOutgoingBitrate += observedPeerConnection.availableOutgoingBitrate;
245
+ this.numberOfDataChannels += observedPeerConnection.observedDataChannels.size;
246
+ this.numberOfInbundTracks += observedPeerConnection.observedInboundTracks.size;
247
+ this.numberOfOutboundRtpStreams += observedPeerConnection.observedOutboundRtps.size;
248
+ this.numberOfOutboundTracks += observedPeerConnection.observedOutboundTracks.size;
249
+ this.numberOfInboundRtpStreams += observedPeerConnection.observedInboundRtps.size;
250
+ if (observedPeerConnection.usingTURN) {
251
+ this.usingTURN = true;
252
+ }
253
+ if (observedPeerConnection.usingTCP) {
254
+ this.usingTCP = true;
255
+ }
256
+ if (observedPeerConnection.currentRttInMs) {
257
+ if (this.currentMinRttInMs === undefined || observedPeerConnection.currentRttInMs < this.currentMinRttInMs) {
258
+ this.currentMinRttInMs = observedPeerConnection.currentRttInMs;
322
259
  }
323
- case CallEventType_1.CallEventType.CLIENT_LEFT: {
324
- this.left = timestamp;
325
- break;
260
+ if (this.currentMaxRttInMs === undefined || observedPeerConnection.currentRttInMs > this.currentMaxRttInMs) {
261
+ this.currentMaxRttInMs = observedPeerConnection.currentRttInMs;
326
262
  }
327
- case CallEventType_1.CallEventType.PEER_CONNECTION_OPENED: {
328
- callEvent.peerConnectionId && this.ωpendingPeerConnectionTimestamps.push({
329
- type: 'opened',
330
- peerConnectionId: callEvent.peerConnectionId,
331
- timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : sample.timestamp,
332
- });
333
- break;
263
+ if (observedPeerConnection.currentRttInMs < 50) {
264
+ this.deltaRttLt50Measurements += 1;
265
+ this.report.rttDistribution.lt50ms += 1;
334
266
  }
335
- case CallEventType_1.CallEventType.PEER_CONNECTION_CLOSED: {
336
- callEvent.peerConnectionId && this.ωpendingPeerConnectionTimestamps.push({
337
- type: 'closed',
338
- peerConnectionId: callEvent.peerConnectionId,
339
- timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : sample.timestamp,
340
- });
341
- break;
267
+ else if (observedPeerConnection.currentRttInMs < 150) {
268
+ this.deltaRttLt150Measurements += 1;
269
+ this.report.rttDistribution.lt150ms += 1;
342
270
  }
343
- case CallEventType_1.CallEventType.MEDIA_TRACK_ADDED: {
344
- callEvent.peerConnectionId && callEvent.mediaTrackId && this.ωpendingMediaTrackTimestamps.push({
345
- type: 'added',
346
- peerConnectionId: callEvent.peerConnectionId,
347
- mediaTrackId: callEvent.mediaTrackId,
348
- timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : sample.timestamp,
349
- });
350
- break;
271
+ else if (observedPeerConnection.currentRttInMs < 300) {
272
+ this.deltaRttLt300Measurements += 1;
273
+ this.report.rttDistribution.lt300ms += 1;
351
274
  }
352
- case CallEventType_1.CallEventType.MEDIA_TRACK_REMOVED: {
353
- callEvent.peerConnectionId && callEvent.mediaTrackId && this.ωpendingMediaTrackTimestamps.push({
354
- type: 'removed',
355
- peerConnectionId: callEvent.peerConnectionId,
356
- mediaTrackId: callEvent.mediaTrackId,
357
- timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : sample.timestamp,
358
- });
359
- break;
275
+ else if (300 <= observedPeerConnection.currentRttInMs) {
276
+ this.deltaRttGtOrEq300Measurements += 1;
277
+ this.report.rttDistribution.gtOrEq300ms += 1;
360
278
  }
361
- case CallEventType_1.CallEventType.CLIENT_ISSUE: {
362
- const severity = callEvent.value ? callEvent.value : 'minor';
363
- try {
364
- const issue = {
365
- severity,
366
- timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : Date.now(),
367
- description: callEvent.message,
368
- peerConnectionId: callEvent.peerConnectionId,
369
- trackId: callEvent.mediaTrackId,
370
- attachments: callEvent.attachments ? JSON.parse(callEvent.attachments) : undefined,
371
- };
372
- this._addAndEmitIssue(issue);
373
- }
374
- catch (err) {
375
- logger.warn(`Error parsing client issue: ${err === null || err === void 0 ? void 0 : err.message}`);
376
- }
377
- break;
279
+ this.report.rttDistribution.count += 1;
280
+ this.report.rttDistribution.sum += observedPeerConnection.currentRttInMs;
281
+ sumOfRtts += observedPeerConnection.currentRttInMs;
282
+ ++numberOfRttMeasurements;
283
+ }
284
+ }
285
+ for (const clientEvent of clientEventsPostBuffer) {
286
+ this._processClientEvent(clientEvent);
287
+ }
288
+ // emit new attachments?
289
+ this.attachments = sample.attachments;
290
+ this.report.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
291
+ this.report.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
292
+ this.report.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
293
+ this.report.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
294
+ this.report.totalInboundRtpPacketsLost += this.deltaInboundPacketsLost;
295
+ this.report.totalInboundRtpPacketsReceived += this.deltaInboundPacketsReceived;
296
+ this.report.totalOutboundRtpPacketsSent += this.deltaOutboundPacketsSent;
297
+ this.report.totalAudioBytesReceived += this.deltaReceivedAudioBytes;
298
+ this.report.totalVideoBytesReceived += this.deltaReceivedVideoBytes;
299
+ this.report.totalAudioBytesSent += this.deltaSentAudioBytes;
300
+ this.report.totalVideoBytesSent += this.deltaSentVideoBytes;
301
+ this.report.totalInboundRtpBytesReceived += this.deltaTransportReceivedBytes;
302
+ this.report.totalOutboundRtpBytesSent += this.deltaTransportSentBytes;
303
+ this.report.totalNumberOfIssues += this.deltaNumberOfIssues;
304
+ this.receivingAudioBitrate = (this.deltaReceivedAudioBytes * 8) / (elapsedInSeconds);
305
+ this.receivingVideoBitrate = (this.deltaReceivedVideoBytes * 8) / (elapsedInSeconds);
306
+ this.sendingAudioBitrate = (this.deltaSentAudioBytes * 8) / (elapsedInSeconds);
307
+ this.sendingVideoBitrate = (this.deltaSentVideoBytes * 8) / (elapsedInSeconds);
308
+ this.currentAvgRttInMs = 0 < numberOfRttMeasurements ? sumOfRtts / numberOfRttMeasurements : undefined;
309
+ this.calculatedScore.value = sample.score;
310
+ if (sample.score !== undefined) {
311
+ const bucket = Math.floor(sample.score).toString();
312
+ this.report.scoreDistribution[bucket] = (this.report.scoreDistribution[bucket] ?? 0) + 1;
313
+ this.report.scoreDistribution.count += 1;
314
+ this.report.scoreDistribution.sum += sample.score;
315
+ }
316
+ this.detectors.update();
317
+ this.lastSampleTimestamp = sample.timestamp;
318
+ // emit update
319
+ this.emit('update', sample, now - this.updated);
320
+ this.updated = now;
321
+ // if result changed after update
322
+ if (this.calculatedScore.value) {
323
+ this.totalScoreSum += this.calculatedScore.value;
324
+ ++this.numberOfScoreMeasurements;
325
+ }
326
+ if (this.settings.closeClientIfIdleForMs !== undefined) {
327
+ this.closeTimer = setTimeout(() => {
328
+ this.close();
329
+ }, this.settings.closeClientIfIdleForMs);
330
+ }
331
+ }
332
+ _processClientEvent(event, postBuffer) {
333
+ // eslint-disable-next-line no-console
334
+ // console.warn('ClientEvent', event);
335
+ switch (event.type) {
336
+ case ClientEventTypes_1.ClientEventTypes.CLIENT_JOINED: {
337
+ if (event.timestamp) {
338
+ if (!this.joinedAt) {
339
+ this.joinedAt = event.timestamp;
340
+ this.emit('joined');
341
+ }
342
+ else if (this.joinedAt < event.timestamp) {
343
+ this.emit('rejoined', event.timestamp);
344
+ }
345
+ else {
346
+ this.joinedAt = event.timestamp;
347
+ logger.warn(`Client ${this.clientId} joinedAt timestamp was updated to ${event.timestamp}. the joined event will not be emitted.`);
348
+ }
378
349
  }
379
- }
380
- this.reports.addCallEventReport(Object.assign({ serviceId: this.serviceId, mediaUnitId: this.mediaUnitId, roomId: this.roomId, callId: this.callId, clientId: this.clientId, userId: this.userId, timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : now }, callEvent));
381
- this.call.emit('callevent', Object.assign({ mediaUnitId: this.mediaUnitId, clientId: this.clientId, userId: this.userId, timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : now }, callEvent));
382
- }
383
- for (const userMediaError of (_q = sample.userMediaErrors) !== null && _q !== void 0 ? _q : []) {
384
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
385
- type: CallMetaReports_1.CallMetaType.USER_MEDIA_ERROR,
386
- payload: userMediaError,
387
- }, this.userId);
388
- this.reports.addCallMetaReport(callMetaReport);
389
- this.userMediaErrors.push(userMediaError);
390
- this.emit('usermediaerror', userMediaError);
391
- }
392
- for (const certificate of (_r = sample.certificates) !== null && _r !== void 0 ? _r : []) {
393
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
394
- type: CallMetaReports_1.CallMetaType.CERTIFICATE,
395
- payload: certificate,
396
- }, this.userId);
397
- this.reports.addCallMetaReport(callMetaReport);
398
- }
399
- for (const codec of (_s = sample.codecs) !== null && _s !== void 0 ? _s : []) {
400
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
401
- type: CallMetaReports_1.CallMetaType.CODEC,
402
- payload: codec,
403
- }, this.userId);
404
- this.reports.addCallMetaReport(callMetaReport);
405
- if (codec.mimeType && !this.mediaCodecs.find((c) => c.mimeType === codec.mimeType)) {
406
- this.mediaCodecs.push(codec);
407
- }
408
- }
409
- for (const iceServer of (_t = sample.iceServers) !== null && _t !== void 0 ? _t : []) {
410
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
411
- type: CallMetaReports_1.CallMetaType.ICE_SERVER,
412
- payload: iceServer,
413
- }, this.userId);
414
- this.reports.addCallMetaReport(callMetaReport);
415
- }
416
- for (const mediaDevice of (_u = sample.mediaDevices) !== null && _u !== void 0 ? _u : []) {
417
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
418
- type: CallMetaReports_1.CallMetaType.MEDIA_DEVICE,
419
- payload: mediaDevice,
420
- }, this.userId);
421
- this.reports.addCallMetaReport(callMetaReport);
422
- if (mediaDevice.id && !this.mediaDevices.find((d) => d.id === mediaDevice.id)) {
423
- this.mediaDevices.push(mediaDevice);
424
- }
425
- }
426
- for (const mediaSource of (_v = sample.mediaSources) !== null && _v !== void 0 ? _v : []) {
427
- const callMetaReport = (0, CallMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
428
- type: CallMetaReports_1.CallMetaType.MEDIA_SOURCE,
429
- payload: mediaSource,
430
- }, this.userId);
431
- this.reports.addCallMetaReport(callMetaReport);
432
- }
433
- for (const transport of (_w = sample.pcTransports) !== null && _w !== void 0 ? _w : []) {
434
- try {
435
- const peerConnection = (_x = this._peerConnections.get(transport.transportId)) !== null && _x !== void 0 ? _x : this._createPeerConnection(transport.peerConnectionId);
436
- !peerConnection.label && transport.label && (peerConnection.label = transport.label);
437
- peerConnection.update(transport, sample.timestamp);
438
- }
439
- catch (err) {
440
- logger.error(`Error creating peer connection: ${err === null || err === void 0 ? void 0 : err.message}`);
441
- }
442
- }
443
- for (const track of (_y = sample.inboundAudioTracks) !== null && _y !== void 0 ? _y : []) {
444
- if (!track.peerConnectionId || !track.trackId) {
445
- logger.warn(`InboundAudioTrack without peerConnectionId or trackId: ${JSON.stringify(track)}`);
446
- continue;
447
- }
448
- try {
449
- const peerConnection = (_z = this._peerConnections.get(track.peerConnectionId)) !== null && _z !== void 0 ? _z : this._createPeerConnection(track.peerConnectionId);
450
- if (!peerConnection)
451
- continue;
452
- const inboundAudioTrack = (_0 = peerConnection.inboundAudioTracks.get(track.trackId)) !== null && _0 !== void 0 ? _0 : peerConnection.createInboundAudioTrack({
453
- trackId: track.trackId,
454
- sfuStreamId: track.sfuStreamId,
455
- sfuSinkId: track.sfuSinkId,
456
- });
457
- inboundAudioTrack.update(track, sample.timestamp);
458
- if (!inboundAudioTrack.remoteOutboundTrack) {
459
- const remoteOutboundTrack = this.call.sfuStreamIdToOutboundAudioTrack.get((_1 = inboundAudioTrack.sfuStreamId) !== null && _1 !== void 0 ? _1 : '');
460
- if (remoteOutboundTrack) {
461
- inboundAudioTrack.remoteOutboundTrack = remoteOutboundTrack;
462
- inboundAudioTrack.once('close', () => {
463
- var _a;
464
- remoteOutboundTrack === null || remoteOutboundTrack === void 0 ? void 0 : remoteOutboundTrack.remoteInboundTracks.delete((_a = inboundAudioTrack.trackId) !== null && _a !== void 0 ? _a : '');
465
- });
466
- remoteOutboundTrack.remoteInboundTracks.set((_2 = inboundAudioTrack.trackId) !== null && _2 !== void 0 ? _2 : '', inboundAudioTrack);
350
+ logger.debug('Client %s joined at %o', this.clientId, event);
351
+ break;
352
+ }
353
+ case ClientEventTypes_1.ClientEventTypes.CLIENT_LEFT: {
354
+ if (event.timestamp) {
355
+ if (!this.leftAt) {
356
+ this.leftAt = event.timestamp;
357
+ this.emit('left');
358
+ }
359
+ else {
360
+ logger.warn(`Client ${this.clientId} leftAt timestamp was already set`);
467
361
  }
468
362
  }
469
- }
470
- catch (err) {
471
- logger.error(`Error creating inbound audio track: ${err === null || err === void 0 ? void 0 : err.message}`);
472
- }
473
- }
474
- for (const track of (_3 = sample.inboundVideoTracks) !== null && _3 !== void 0 ? _3 : []) {
475
- if (!track.peerConnectionId || !track.trackId) {
476
- logger.warn(`InboundVideoTrack without peerConnectionId or trackId: ${JSON.stringify(track)}`);
477
- continue;
478
- }
479
- if ((0, utils_1.isValidUuid)(track.trackId) === false) {
480
- // mediasoup-probator trackId is not a valid UUID, no need to warn about it
481
- if (track.trackId === 'probator')
482
- continue;
483
- logger.warn(`InboundVideoTrack with invalid trackId: ${track.trackId}`);
484
- continue;
485
- }
486
- try {
487
- const peerConnection = (_4 = this._peerConnections.get(track.peerConnectionId)) !== null && _4 !== void 0 ? _4 : this._createPeerConnection(track.peerConnectionId);
488
- if (!peerConnection)
489
- continue;
490
- const inboundVideoTrack = (_5 = peerConnection.inboundVideoTracks.get(track.trackId)) !== null && _5 !== void 0 ? _5 : peerConnection.createInboundVideoTrack({
491
- trackId: track.trackId,
492
- sfuStreamId: track.sfuStreamId,
493
- sfuSinkId: track.sfuSinkId,
494
- });
495
- inboundVideoTrack.update(track, sample.timestamp);
496
- if (!inboundVideoTrack.remoteOutboundTrack) {
497
- const remoteOutboundTrack = this.call.sfuStreamIdToOutboundVideoTrack.get((_6 = inboundVideoTrack.sfuStreamId) !== null && _6 !== void 0 ? _6 : '');
498
- if (remoteOutboundTrack) {
499
- inboundVideoTrack.remoteOutboundTrack = remoteOutboundTrack;
500
- inboundVideoTrack.once('close', () => {
501
- var _a;
502
- remoteOutboundTrack === null || remoteOutboundTrack === void 0 ? void 0 : remoteOutboundTrack.remoteInboundTracks.delete((_a = inboundVideoTrack.trackId) !== null && _a !== void 0 ? _a : '');
503
- });
504
- remoteOutboundTrack.remoteInboundTracks.set((_7 = inboundVideoTrack.trackId) !== null && _7 !== void 0 ? _7 : '', inboundVideoTrack);
363
+ logger.debug('Client %s left at %o', this.clientId, event);
364
+ break;
365
+ }
366
+ case ClientEventTypes_1.ClientEventTypes.PEER_CONNECTION_OPENED: {
367
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
368
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
369
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
370
+ if (observedPeerConnection) {
371
+ observedPeerConnection.openedAt = event.timestamp;
372
+ }
373
+ else if (postBuffer) {
374
+ postBuffer.push(event);
375
+ }
376
+ else {
377
+ logger.warn('Received PEER_CONNECTION_OPENED event without a corresponding observedPeerConnection: %o', event);
505
378
  }
506
379
  }
507
- }
508
- catch (err) {
509
- logger.error(`Error creating inbound video track: ${err === null || err === void 0 ? void 0 : err.message}`);
510
- }
511
- }
512
- for (const track of (_8 = sample.outboundAudioTracks) !== null && _8 !== void 0 ? _8 : []) {
513
- if (!track.peerConnectionId || !track.trackId) {
514
- logger.warn(`OutboundAudioTrack without peerConnectionId or trackId: ${JSON.stringify(track)}`);
515
- continue;
516
- }
517
- try {
518
- const peerConnection = (_9 = this._peerConnections.get(track.peerConnectionId)) !== null && _9 !== void 0 ? _9 : this._createPeerConnection(track.peerConnectionId);
519
- if (!peerConnection)
520
- continue;
521
- const outboundAudioTrack = (_10 = peerConnection.outboundAudioTracks.get(track.trackId)) !== null && _10 !== void 0 ? _10 : peerConnection.createOutboundAudioTrack({
522
- trackId: track.trackId,
523
- sfuStreamId: track.sfuStreamId,
524
- });
525
- outboundAudioTrack.update(track, sample.timestamp);
526
- if (outboundAudioTrack.sfuStreamId && !this.call.sfuStreamIdToOutboundAudioTrack.has(outboundAudioTrack.sfuStreamId)) {
527
- this.call.sfuStreamIdToOutboundAudioTrack.set(outboundAudioTrack.sfuStreamId, outboundAudioTrack);
380
+ break;
381
+ }
382
+ case ClientEventTypes_1.ClientEventTypes.PEER_CONNECTION_CLOSED: {
383
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
384
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
385
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
386
+ if (observedPeerConnection) {
387
+ observedPeerConnection.closedAt = event.timestamp;
388
+ }
389
+ else if (postBuffer) {
390
+ postBuffer.push(event);
391
+ }
392
+ else {
393
+ logger.warn('Received PEER_CONNECTION_CLOSED event without a corresponding observedPeerConnection: %o', event);
394
+ }
528
395
  }
529
- }
530
- catch (err) {
531
- logger.error(`Error creating outbound audio track: ${err === null || err === void 0 ? void 0 : err.message}`);
532
- }
533
- }
534
- for (const track of (_11 = sample.outboundVideoTracks) !== null && _11 !== void 0 ? _11 : []) {
535
- if (!track.peerConnectionId || !track.trackId) {
536
- logger.warn(`OutboundVideoTrack without peerConnectionId or trackId: ${JSON.stringify(track)}`);
537
- continue;
538
- }
539
- try {
540
- const peerConnection = (_12 = this._peerConnections.get(track.peerConnectionId)) !== null && _12 !== void 0 ? _12 : this._createPeerConnection(track.peerConnectionId);
541
- if (!peerConnection)
542
- continue;
543
- const outboundVideoTrack = (_13 = peerConnection.outboundVideoTracks.get(track.trackId)) !== null && _13 !== void 0 ? _13 : peerConnection.createOutboundVideoTrack({
544
- trackId: track.trackId,
545
- sfuStreamId: track.sfuStreamId,
546
- });
547
- outboundVideoTrack.update(track, sample.timestamp);
548
- if (outboundVideoTrack.sfuStreamId && !this.call.sfuStreamIdToOutboundVideoTrack.has(outboundVideoTrack.sfuStreamId)) {
549
- this.call.sfuStreamIdToOutboundVideoTrack.set(outboundVideoTrack.sfuStreamId, outboundVideoTrack);
396
+ break;
397
+ }
398
+ case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_ADDED: {
399
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
400
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
401
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
402
+ const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
403
+ if (observedTrack) {
404
+ observedTrack.addedAt = event.timestamp;
405
+ }
406
+ else if (postBuffer) {
407
+ postBuffer.push(event);
408
+ }
409
+ else {
410
+ logger.warn('Received MEDIA_TRACK_ADDED event without a corresponding observedPeerConnection or observedTrack: %o', event);
411
+ }
550
412
  }
551
- }
552
- catch (err) {
553
- logger.error(`Error creating outbound video track: ${err === null || err === void 0 ? void 0 : err.message}`);
554
- }
555
- }
556
- for (const iceLocalCandidate of (_14 = sample.iceLocalCandidates) !== null && _14 !== void 0 ? _14 : []) {
557
- if (!iceLocalCandidate.peerConnectionId) {
558
- logger.warn(`Local ice candidate without peerConnectionId: ${JSON.stringify(iceLocalCandidate)}`);
559
- continue;
560
- }
561
- const peerConnection = this._peerConnections.get(iceLocalCandidate.peerConnectionId);
562
- if (!peerConnection) {
563
- logger.debug(`Peer connection ${iceLocalCandidate.peerConnectionId} not found for ice local candidate ${iceLocalCandidate.id}`);
564
- continue;
565
- }
566
- peerConnection.ICE.addLocalCandidate(iceLocalCandidate, sample.timestamp);
567
- }
568
- for (const iceRemoteCandidate of (_15 = sample.iceRemoteCandidates) !== null && _15 !== void 0 ? _15 : []) {
569
- if (!iceRemoteCandidate.peerConnectionId) {
570
- logger.warn(`Remote ice candidate without peerConnectionId: ${JSON.stringify(iceRemoteCandidate)}`);
571
- continue;
572
- }
573
- const peerConnection = this._peerConnections.get(iceRemoteCandidate.peerConnectionId);
574
- if (!peerConnection) {
575
- logger.debug(`Peer connection ${iceRemoteCandidate.peerConnectionId} not found for ice remote candidate ${iceRemoteCandidate.id}`);
576
- continue;
577
- }
578
- peerConnection.ICE.addRemoteCandidate(iceRemoteCandidate, sample.timestamp);
579
- }
580
- for (const candidatePair of (_16 = sample.iceCandidatePairs) !== null && _16 !== void 0 ? _16 : []) {
581
- const peerConnection = this._peerConnections.get(candidatePair.peerConnectionId);
582
- if (!peerConnection) {
583
- logger.debug(`Peer connection ${candidatePair.peerConnectionId} not found for ice candidate pair ${candidatePair.localCandidateId}, ${candidatePair.remoteCandidateId}`);
584
- continue;
585
- }
586
- peerConnection.ICE.update(candidatePair, sample.timestamp);
587
- }
588
- for (const dataChannel of (_17 = sample.dataChannels) !== null && _17 !== void 0 ? _17 : []) {
589
- if (!dataChannel.peerConnectionId || !dataChannel.dataChannelIdentifier) {
590
- logger.warn(`DataChannel without peerConnectionId or dataChannelIdentifier: ${JSON.stringify(dataChannel)}`);
591
- continue;
592
- }
593
- try {
594
- const peerConnection = (_18 = this._peerConnections.get(dataChannel.peerConnectionId)) !== null && _18 !== void 0 ? _18 : this._createPeerConnection(dataChannel.peerConnectionId);
595
- if (!peerConnection)
596
- continue;
597
- const observedDataChannel = (_19 = peerConnection.dataChannels.get(dataChannel.dataChannelIdentifier)) !== null && _19 !== void 0 ? _19 : peerConnection.createDataChannel(dataChannel.dataChannelIdentifier);
598
- observedDataChannel.update(dataChannel, sample.timestamp);
599
- }
600
- catch (err) {
601
- logger.error(`Error creating data channel: ${err === null || err === void 0 ? void 0 : err.message}`);
602
- }
603
- }
604
- // try to set the timestamps of the peer connections
605
- if (0 < this.ωpendingPeerConnectionTimestamps.length) {
606
- const newPendingTimestamps = [];
607
- for (const pendingTimestamp of this.ωpendingPeerConnectionTimestamps) {
608
- const peerConnection = this._peerConnections.get(pendingTimestamp.peerConnectionId);
609
- if (!peerConnection) {
610
- newPendingTimestamps.push(pendingTimestamp);
611
- continue;
413
+ break;
414
+ }
415
+ case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_REMOVED: {
416
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
417
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
418
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
419
+ const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
420
+ if (observedTrack) {
421
+ observedTrack.removedAt = event.timestamp;
422
+ }
423
+ else if (postBuffer) {
424
+ postBuffer.push(event);
425
+ }
426
+ else {
427
+ logger.warn('Received MEDIA_TRACK_REMOVED event without a corresponding observedPeerConnection or observedTrack: %o', event);
428
+ }
612
429
  }
613
- if (pendingTimestamp.type === 'opened')
614
- peerConnection.opened = pendingTimestamp.timestamp;
615
- else if (pendingTimestamp.type === 'closed')
616
- peerConnection.closedTimestamp = pendingTimestamp.timestamp;
617
- }
618
- this.ωpendingPeerConnectionTimestamps = newPendingTimestamps;
619
- }
620
- // try to set the timestamps of the media tracks
621
- if (0 < this.ωpendingMediaTrackTimestamps.length) {
622
- const newPendingTimestamps = [];
623
- for (const pendingTimestamp of this.ωpendingMediaTrackTimestamps) {
624
- const peerConnection = this._peerConnections.get(pendingTimestamp.peerConnectionId);
625
- const mediaTrack = (_22 = (_21 = (_20 = peerConnection === null || peerConnection === void 0 ? void 0 : peerConnection.inboundAudioTracks.get(pendingTimestamp.mediaTrackId)) !== null && _20 !== void 0 ? _20 : peerConnection === null || peerConnection === void 0 ? void 0 : peerConnection.inboundVideoTracks.get(pendingTimestamp.mediaTrackId)) !== null && _21 !== void 0 ? _21 : peerConnection === null || peerConnection === void 0 ? void 0 : peerConnection.outboundAudioTracks.get(pendingTimestamp.mediaTrackId)) !== null && _22 !== void 0 ? _22 : peerConnection === null || peerConnection === void 0 ? void 0 : peerConnection.outboundVideoTracks.get(pendingTimestamp.mediaTrackId);
626
- if (!mediaTrack) {
627
- newPendingTimestamps.push(pendingTimestamp);
628
- continue;
430
+ break;
431
+ }
432
+ case ClientEventTypes_1.ClientEventTypes.DATA_CHANNEL_OPEN: {
433
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
434
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
435
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
436
+ const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
437
+ if (observedDataChannel) {
438
+ observedDataChannel.addedAt = event.timestamp;
439
+ }
440
+ else if (postBuffer) {
441
+ postBuffer.push(event);
442
+ }
443
+ else {
444
+ logger.warn('Received DATA_CHANNEL_OPENED event without a corresponding observedPeerConnection or observedDataChannel: %o', event);
445
+ }
629
446
  }
630
- if (pendingTimestamp.type === 'added')
631
- mediaTrack.added = pendingTimestamp.timestamp;
632
- else if (pendingTimestamp.type === 'removed')
633
- mediaTrack.removed = pendingTimestamp.timestamp;
634
- }
635
- this.ωpendingMediaTrackTimestamps = newPendingTimestamps;
636
- }
637
- // close resources that are not visited
638
- for (const peerConnection of this._peerConnections.values()) {
639
- if (!peerConnection.visited) {
640
- peerConnection.close();
641
- continue;
642
- }
643
- for (const track of peerConnection.inboundAudioTracks.values()) {
644
- if (!track.visited) {
645
- track.close();
646
- continue;
447
+ break;
448
+ }
449
+ case ClientEventTypes_1.ClientEventTypes.DATA_CHANNEL_CLOSED: {
450
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
451
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
452
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
453
+ const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
454
+ if (observedDataChannel) {
455
+ observedDataChannel.removedAt = event.timestamp;
456
+ }
457
+ else if (postBuffer) {
458
+ postBuffer.push(event);
459
+ }
460
+ else {
461
+ logger.warn('Received DATA_CHANNEL_CLOSE event without a corresponding observedPeerConnection or observedDataChannel: %o', event);
462
+ }
647
463
  }
648
- track.visited = false;
649
- }
650
- for (const track of peerConnection.inboundVideoTracks.values()) {
651
- if (!track.visited) {
652
- track.close();
653
- continue;
464
+ break;
465
+ }
466
+ case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_MUTED: {
467
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
468
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
469
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
470
+ const observedInboundTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId);
471
+ const observedOutboundTrack = observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
472
+ if (observedPeerConnection) {
473
+ if (observedInboundTrack) {
474
+ observedInboundTrack.muted = true;
475
+ observedPeerConnection?.emit('muted-inbound-track', observedInboundTrack);
476
+ }
477
+ else if (observedOutboundTrack) {
478
+ observedOutboundTrack.muted = true;
479
+ observedPeerConnection?.emit('muted-outbound-track', observedOutboundTrack);
480
+ }
481
+ }
482
+ else if (postBuffer) {
483
+ postBuffer.push(event);
484
+ }
485
+ else {
486
+ logger.warn('Received MEDIA_TRACK_MUTED event without a corresponding observedPeerConnection or observedTrack: %o', event);
487
+ }
654
488
  }
655
- track.visited = false;
656
- }
657
- for (const track of peerConnection.outboundAudioTracks.values()) {
658
- if (!track.visited) {
659
- track.close();
660
- continue;
489
+ break;
490
+ }
491
+ case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_UNMUTED: {
492
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
493
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
494
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
495
+ const observedInboundTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId);
496
+ const observedOutboundTrack = observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
497
+ if (observedPeerConnection) {
498
+ if (observedInboundTrack) {
499
+ observedInboundTrack.muted = false;
500
+ observedPeerConnection?.emit('unmuted-inbound-track', observedInboundTrack);
501
+ }
502
+ else if (observedOutboundTrack) {
503
+ observedOutboundTrack.muted = false;
504
+ observedPeerConnection?.emit('unmuted-outbound-track', observedOutboundTrack);
505
+ }
506
+ }
507
+ else if (postBuffer) {
508
+ postBuffer.push(event);
509
+ }
510
+ else {
511
+ logger.warn('Received MEDIA_TRACK_UNMUTED event without a corresponding observedPeerConnection or observedTrack: %o', event);
512
+ }
661
513
  }
662
- track.visited = false;
663
- }
664
- for (const dataChannel of peerConnection.dataChannels.values()) {
665
- if (!dataChannel.visited) {
666
- dataChannel.close();
667
- continue;
514
+ break;
515
+ }
516
+ case ClientEventTypes_1.ClientEventTypes.ICE_CONNECTION_STATE_CHANGED: {
517
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
518
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.iceConnectionState && typeof payload.iceConnectionState === 'string') {
519
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
520
+ if (observedPeerConnection) {
521
+ observedPeerConnection.iceConnectionState = payload.iceConnectionState;
522
+ observedPeerConnection.emit('iceconnectionstatechange', {
523
+ state: payload.iceConnectionState,
524
+ });
525
+ }
526
+ else if (postBuffer) {
527
+ postBuffer.push(event);
528
+ }
529
+ else {
530
+ logger.warn('Received ICE_CONNECTION_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
531
+ }
668
532
  }
669
- dataChannel.visited = false;
670
- }
671
- peerConnection.visited = false;
672
- }
673
- // update metrics
674
- const wasUsingTURN = this.usingTURN;
675
- const elapsedTimeInMs = now - this.updated;
676
- this.usingTURN = false;
677
- this.availableIncomingBitrate = 0;
678
- this.availableOutgoingBitrate = 0;
679
- this.deltaInboundPacketsLost = 0;
680
- this.deltaInboundPacketsReceived = 0;
681
- this.deltaOutboundPacketsSent = 0;
682
- this.deltaReceivedAudioBytes = 0;
683
- this.deltaReceivedVideoBytes = 0;
684
- this.deltaSentAudioBytes = 0;
685
- this.deltaSentVideoBytes = 0;
686
- this.deltaDataChannelBytesReceived = 0;
687
- this.deltaDataChannelBytesSent = 0;
688
- this.outboundAudioBitrate = 0;
689
- this.outboundVideoBitrate = 0;
690
- this.inboundAudioBitrate = 0;
691
- this.inboundVideoBitrate = 0;
692
- let sumRttInMs = 0;
693
- let anyPeerConnectionUsingTurn = false;
694
- let minPcScore;
695
- let maxPcScore;
696
- let numberOfScoredPeerConnections = 0;
697
- for (const peerConnection of this._peerConnections.values()) {
698
- if (peerConnection.closed)
699
- continue;
700
- peerConnection.updateMetrics();
701
- this.deltaInboundPacketsLost += peerConnection.deltaInboundPacketsLost;
702
- this.deltaInboundPacketsReceived += peerConnection.deltaInboundPacketsReceived;
703
- this.deltaOutboundPacketsSent += peerConnection.deltaOutboundPacketsSent;
704
- this.deltaReceivedAudioBytes += peerConnection.deltaReceivedAudioBytes;
705
- this.deltaReceivedVideoBytes += peerConnection.deltaReceivedVideoBytes;
706
- this.deltaSentAudioBytes += peerConnection.deltaSentAudioBytes;
707
- this.deltaSentVideoBytes += peerConnection.deltaSentVideoBytes;
708
- this.deltaDataChannelBytesReceived += peerConnection.deltaDataChannelBytesReceived;
709
- this.deltaDataChannelBytesSent += peerConnection.deltaDataChannelBytesSent;
710
- this.availableIncomingBitrate += (_23 = peerConnection.availableIncomingBitrate) !== null && _23 !== void 0 ? _23 : 0;
711
- this.availableOutgoingBitrate += (_24 = peerConnection.availableOutgoingBitrate) !== null && _24 !== void 0 ? _24 : 0;
712
- sumRttInMs += (_25 = peerConnection.avgRttInMs) !== null && _25 !== void 0 ? _25 : 0;
713
- anyPeerConnectionUsingTurn || (anyPeerConnectionUsingTurn = peerConnection.usingTURN);
714
- if (peerConnection.score) {
715
- if (minPcScore === undefined || peerConnection.score.score < minPcScore)
716
- minPcScore = peerConnection.score.score;
717
- if (maxPcScore === undefined || peerConnection.score.score > maxPcScore)
718
- maxPcScore = peerConnection.score.score;
719
- ++numberOfScoredPeerConnections;
533
+ break;
534
+ }
535
+ case ClientEventTypes_1.ClientEventTypes.ICE_GATHERING_STATE_CHANGED: {
536
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
537
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.iceGatheringState && typeof payload.iceGatheringState === 'string') {
538
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
539
+ if (observedPeerConnection) {
540
+ observedPeerConnection.iceGatheringState = payload.iceGatheringState;
541
+ observedPeerConnection.emit('icegatheringstatechange', {
542
+ state: payload.iceGatheringState,
543
+ });
544
+ }
545
+ else if (postBuffer) {
546
+ postBuffer.push(event);
547
+ }
548
+ else {
549
+ logger.warn('Received ICE_GATHERING_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
550
+ }
551
+ }
552
+ break;
553
+ }
554
+ case ClientEventTypes_1.ClientEventTypes.PEER_CONNECTION_STATE_CHANGED: {
555
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
556
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.peerConnectionState && typeof payload.peerConnectionState === 'string') {
557
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
558
+ if (observedPeerConnection) {
559
+ observedPeerConnection.connectionState = payload.peerConnectionState;
560
+ observedPeerConnection.emit('connectionstatechange', {
561
+ state: payload.peerConnectionState,
562
+ });
563
+ }
564
+ else if (postBuffer) {
565
+ postBuffer.push(event);
566
+ }
567
+ else {
568
+ logger.warn('Received PEER_CONNECTION_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
569
+ }
570
+ }
571
+ break;
720
572
  }
721
573
  }
722
- this.score = {
723
- score: minPcScore !== null && minPcScore !== void 0 ? minPcScore : -1,
724
- remarks: [{
725
- severity: 'none',
726
- text: `Min and max score of all peer connections: ${minPcScore}, ${maxPcScore}, number of PeerConnections with scores: ${numberOfScoredPeerConnections}`,
727
- }],
728
- timestamp: sample.timestamp,
729
- };
730
- this.emit('score', this.score);
731
- this.usingTURN = anyPeerConnectionUsingTurn === true;
732
- if (wasUsingTURN !== this.usingTURN)
733
- this.emit('usingturn', this.usingTURN);
734
- this.totalSentBytes += this.deltaSentAudioBytes + this.deltaSentVideoBytes;
735
- this.totalReceivedBytes += this.deltaReceivedAudioBytes + this.deltaReceivedVideoBytes;
736
- this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
737
- this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
738
- this.totalSentAudioBytes += this.deltaSentAudioBytes;
739
- this.totalSentVideoBytes += this.deltaSentVideoBytes;
740
- this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
741
- this.totalInboundPacketsReceived += this.deltaInboundPacketsReceived;
742
- this.totalInboundPacketsLost += this.deltaInboundPacketsLost;
743
- this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
744
- this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
745
- this.outboundAudioBitrate = (this.deltaSentAudioBytes * 8) / (Math.max(elapsedTimeInMs, 1) / 1000);
746
- this.outboundVideoBitrate = (this.deltaSentVideoBytes * 8) / (Math.max(elapsedTimeInMs, 1) / 1000);
747
- this.inboundAudioBitrate = (this.deltaReceivedAudioBytes * 8) / (Math.max(elapsedTimeInMs, 1) / 1000);
748
- this.inboundVideoBitrate = (this.deltaReceivedVideoBytes * 8) / (Math.max(elapsedTimeInMs, 1) / 1000);
749
- this.avgRttInMs = this._peerConnections.size ? sumRttInMs / this._peerConnections.size : undefined;
750
- // to make sure when sample is emitted it can be associated to this client
751
- sample.clientId = this.clientId;
752
- this.updated = now;
753
- this.lastStatsTimestamp = sample.timestamp;
754
- this.emit('update', {
755
- sample,
756
- elapsedTimeInMs,
757
- });
574
+ this.emit('clientEvent', event);
758
575
  }
759
- _addAndEmitIssue(issue) {
760
- var _a;
761
- this.issues.push(issue);
762
- if (issue.peerConnectionId) {
763
- const peerConnection = this._peerConnections.get(issue.peerConnectionId);
764
- if (peerConnection) {
765
- if (issue.trackId) {
766
- const track = (_a = peerConnection.inboundAudioTracks.get(issue.trackId)) !== null && _a !== void 0 ? _a : peerConnection.inboundVideoTracks.get(issue.trackId);
767
- if (track)
768
- track.ωpendingIssuesForScores.push(issue);
769
- }
770
- else {
771
- peerConnection.ωpendingIssuesForScores.push(issue);
772
- }
576
+ injectMetaData(metaData) {
577
+ if (this.closed)
578
+ return;
579
+ if (!this._injections.clientMetaItems)
580
+ this._injections.clientMetaItems = [];
581
+ this._injections.clientMetaItems.push(metaData);
582
+ }
583
+ injectEvent(event) {
584
+ if (this.closed)
585
+ return;
586
+ if (!this._injections.clientEvents)
587
+ this._injections.clientEvents = [];
588
+ this._injections.clientEvents.push(event);
589
+ }
590
+ injectIssue(issue) {
591
+ if (this.closed)
592
+ return;
593
+ if (!this._injections.clientIssues)
594
+ this._injections.clientIssues = [];
595
+ this._injections.clientIssues.push(issue);
596
+ }
597
+ injectExtensionStat(stat) {
598
+ if (this.closed)
599
+ return;
600
+ if (!this._injections.extensionStats)
601
+ this._injections.extensionStats = [];
602
+ this._injections.extensionStats.push(stat);
603
+ }
604
+ injectAttachment(key, value) {
605
+ if (this.closed)
606
+ return;
607
+ if (!this._injections.attachments)
608
+ this._injections.attachments = {};
609
+ this._injections.attachments[key] = value;
610
+ }
611
+ addMetadata(metadata) {
612
+ if (this.closed)
613
+ return;
614
+ switch (metadata.type) {
615
+ case ClientMetaTypes_1.ClientMetaTypes.BROWSER: {
616
+ this.browser = (0, utils_1.parseJsonAs)(metadata.payload);
617
+ break;
618
+ }
619
+ case ClientMetaTypes_1.ClientMetaTypes.ENGINE: {
620
+ this.engine = (0, utils_1.parseJsonAs)(metadata.payload);
621
+ break;
622
+ }
623
+ case ClientMetaTypes_1.ClientMetaTypes.PLATFORM: {
624
+ this.platform = (0, utils_1.parseJsonAs)(metadata.payload);
625
+ break;
626
+ }
627
+ case ClientMetaTypes_1.ClientMetaTypes.OPERATION_SYSTEM: {
628
+ this.operationSystem = (0, utils_1.parseJsonAs)(metadata.payload);
629
+ break;
773
630
  }
774
631
  }
775
- this.emit('issue', issue);
632
+ this.call.observer.emit('client-metadata', this, metadata);
776
633
  }
777
- _createPeerConnection(peerConnectionId, label) {
778
- const result = new ObservedPeerConnection_1.ObservedPeerConnection({
779
- peerConnectionId,
780
- label,
781
- }, this);
782
- const onNewSelectedCandidatePair = ({ localCandidate, remoteCandidate }) => {
783
- this.emit('selectedcandidatepair', {
784
- peerConnection: result,
785
- localCandidate,
786
- remoteCandidate,
634
+ addIssue(issue) {
635
+ if (this.closed)
636
+ return;
637
+ this.report.issues[issue.type] = (this.report.issues[issue.type] ?? 0) + 1;
638
+ this.emit('issue', issue);
639
+ this.call.observer.emit('client-issue', this, issue);
640
+ }
641
+ addExtensionStats(stats) {
642
+ this.call.observer.emit('client-extension-stats', this, stats);
643
+ this.emit('extensionStats', stats);
644
+ }
645
+ _updatePeerConnection(sample) {
646
+ let observedPeerConnection = this.observedPeerConnections.get(sample.peerConnectionId);
647
+ if (!observedPeerConnection) {
648
+ if (!sample.peerConnectionId) {
649
+ return (logger.warn(`ObservedClient received an invalid PeerConnectionSample (missing peerConnectionId field). ClientId: ${this.clientId}, CallId: ${this.call.callId}`, sample), void 0);
650
+ }
651
+ const newObservedPeerConnection = new ObservedPeerConnection_1.ObservedPeerConnection(sample.peerConnectionId, this);
652
+ const onInboundTrackRemoved = (track) => {
653
+ this.emit('trackreport', {
654
+ direction: 'inbound',
655
+ ...track.report,
656
+ });
657
+ };
658
+ const onOutboundTrackRemoved = (track) => {
659
+ this.emit('trackreport', {
660
+ direction: 'outbound',
661
+ ...track.report,
662
+ });
663
+ };
664
+ newObservedPeerConnection.once('close', () => {
665
+ newObservedPeerConnection?.off('removed-inbound-track', onInboundTrackRemoved);
666
+ newObservedPeerConnection?.off('removed-outbound-track', onOutboundTrackRemoved);
667
+ this.observedPeerConnections.delete(sample.peerConnectionId);
787
668
  });
788
- };
789
- result.once('close', () => {
790
- result.ICE.off('new-selected-candidate-pair', onNewSelectedCandidatePair);
791
- this._peerConnections.delete(peerConnectionId);
792
- });
793
- result.ICE.on('new-selected-candidate-pair', onNewSelectedCandidatePair);
794
- this._peerConnections.set(peerConnectionId, result);
795
- this.emit('newpeerconnection', result);
796
- return result;
669
+ newObservedPeerConnection.on('removed-inbound-track', onInboundTrackRemoved);
670
+ newObservedPeerConnection.on('removed-outbound-track', onOutboundTrackRemoved);
671
+ this.observedPeerConnections.set(sample.peerConnectionId, newObservedPeerConnection);
672
+ this.emit('newpeerconnection', newObservedPeerConnection);
673
+ observedPeerConnection = newObservedPeerConnection;
674
+ }
675
+ observedPeerConnection.accept(sample);
676
+ return observedPeerConnection;
677
+ }
678
+ _mergeInjections(sample) {
679
+ if (this.closed)
680
+ return sample;
681
+ if (this._injections.clientEvents) {
682
+ if (!sample.clientEvents)
683
+ sample.clientEvents = [];
684
+ sample.clientEvents.push(...this._injections.clientEvents);
685
+ this._injections.clientEvents = undefined;
686
+ }
687
+ if (this._injections.clientIssues) {
688
+ if (!sample.clientIssues)
689
+ sample.clientIssues = [];
690
+ sample.clientIssues.push(...this._injections.clientIssues);
691
+ this._injections.clientIssues = undefined;
692
+ }
693
+ if (this._injections.extensionStats) {
694
+ if (!sample.extensionStats)
695
+ sample.extensionStats = [];
696
+ sample.extensionStats.push(...this._injections.extensionStats);
697
+ this._injections.extensionStats = undefined;
698
+ }
699
+ if (this._injections.attachments) {
700
+ if (!sample.attachments)
701
+ sample.attachments = {};
702
+ Object.assign(sample.attachments, this._injections.attachments);
703
+ this._injections.attachments = undefined;
704
+ }
705
+ if (this._injections.clientMetaItems) {
706
+ if (!sample.clientMetaItems)
707
+ sample.clientMetaItems = [];
708
+ sample.clientMetaItems.push(...this._injections.clientMetaItems);
709
+ this._injections.clientMetaItems = undefined;
710
+ }
711
+ return sample;
797
712
  }
798
713
  }
799
714
  exports.ObservedClient = ObservedClient;