@observertc/observer-js 1.0.1-c3edea3.0 → 1.0.1-cda37f7.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 (140) hide show
  1. package/lib/ObservedCall.d.ts +43 -7
  2. package/lib/ObservedCall.d.ts.map +1 -1
  3. package/lib/ObservedCall.js +129 -13
  4. package/lib/ObservedCallEventMonitor.d.ts +104 -0
  5. package/lib/ObservedCallEventMonitor.d.ts.map +1 -0
  6. package/lib/ObservedCallEventMonitor.js +314 -0
  7. package/lib/ObservedCallSummary.d.ts +18 -0
  8. package/lib/ObservedCallSummary.d.ts.map +1 -0
  9. package/lib/ObservedClient.d.ts +70 -11
  10. package/lib/ObservedClient.d.ts.map +1 -1
  11. package/lib/ObservedClient.js +392 -72
  12. package/lib/ObservedClientEventMonitor.d.ts +89 -0
  13. package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
  14. package/lib/ObservedClientEventMonitor.js +247 -0
  15. package/lib/ObservedClientSummary.d.ts +23 -0
  16. package/lib/ObservedClientSummary.d.ts.map +1 -0
  17. package/lib/ObservedClientSummary.js +2 -0
  18. package/lib/ObservedDataChannel.d.ts +6 -0
  19. package/lib/ObservedDataChannel.d.ts.map +1 -1
  20. package/lib/ObservedDataChannel.js +30 -0
  21. package/lib/ObservedIceCandidatePair.d.ts +6 -1
  22. package/lib/ObservedIceCandidatePair.d.ts.map +1 -1
  23. package/lib/ObservedIceCandidatePair.js +45 -1
  24. package/lib/ObservedIceTransport.d.ts +4 -0
  25. package/lib/ObservedIceTransport.d.ts.map +1 -1
  26. package/lib/ObservedIceTransport.js +28 -0
  27. package/lib/ObservedInboundTrack.d.ts +2 -0
  28. package/lib/ObservedInboundTrack.d.ts.map +1 -1
  29. package/lib/ObservedInboundTrack.js +2 -0
  30. package/lib/ObservedOutboundTrack.d.ts +2 -0
  31. package/lib/ObservedOutboundTrack.d.ts.map +1 -1
  32. package/lib/ObservedOutboundTrack.js +2 -0
  33. package/lib/ObservedPeerConnection.d.ts +29 -2
  34. package/lib/ObservedPeerConnection.d.ts.map +1 -1
  35. package/lib/ObservedPeerConnection.js +181 -29
  36. package/lib/ObservedTURN.d.ts +31 -0
  37. package/lib/ObservedTURN.d.ts.map +1 -0
  38. package/lib/ObservedTURN.js +58 -0
  39. package/lib/ObservedTurnServer.d.ts +25 -0
  40. package/lib/ObservedTurnServer.d.ts.map +1 -0
  41. package/lib/ObservedTurnServer.js +59 -0
  42. package/lib/Observer.d.ts +43 -22
  43. package/lib/Observer.d.ts.map +1 -1
  44. package/lib/Observer.js +126 -40
  45. package/lib/ObserverEventMonitor.d.ts +130 -0
  46. package/lib/ObserverEventMonitor.d.ts.map +1 -0
  47. package/lib/ObserverEventMonitor.js +404 -0
  48. package/lib/ObserverSummary.d.ts +13 -0
  49. package/lib/ObserverSummary.d.ts.map +1 -0
  50. package/lib/ObserverSummary.js +2 -0
  51. package/lib/common/utils.d.ts +2 -1
  52. package/lib/common/utils.d.ts.map +1 -1
  53. package/lib/common/utils.js +11 -3
  54. package/lib/index.d.ts +6 -0
  55. package/lib/index.d.ts.map +1 -1
  56. package/lib/index.js +9 -1
  57. package/lib/schema/ClientEventTypes.d.ts +160 -0
  58. package/lib/schema/ClientEventTypes.d.ts.map +1 -0
  59. package/lib/schema/ClientEventTypes.js +38 -0
  60. package/lib/schema/{metaTypes.d.ts → ClientMetaTypes.d.ts} +2 -2
  61. package/lib/schema/ClientMetaTypes.d.ts.map +1 -0
  62. package/lib/schema/ClientMetaTypes.js +16 -0
  63. package/lib/schema/ClientSample.d.ts +1 -1
  64. package/lib/schema/ClientSample.d.ts.map +1 -1
  65. package/lib/updaters/CallUpdater.d.ts.map +1 -0
  66. package/lib/updaters/CallUpdater.js +2 -0
  67. package/lib/updaters/ObserverUpdater.d.ts +5 -0
  68. package/lib/updaters/ObserverUpdater.d.ts.map +1 -0
  69. package/lib/updaters/ObserverUpdater.js +2 -0
  70. package/lib/updaters/OnAllCallObserverUpdater.d.ts +15 -0
  71. package/lib/updaters/OnAllCallObserverUpdater.d.ts.map +1 -0
  72. package/lib/updaters/OnAllCallObserverUpdater.js +50 -0
  73. package/lib/updaters/OnAllClientCallUpdater.d.ts +15 -0
  74. package/lib/updaters/OnAllClientCallUpdater.d.ts.map +1 -0
  75. package/lib/updaters/OnAllClientCallUpdater.js +53 -0
  76. package/lib/updaters/OnAnyCallObserverUpdater.d.ts +12 -0
  77. package/lib/updaters/OnAnyCallObserverUpdater.d.ts.map +1 -0
  78. package/lib/updaters/OnAnyCallObserverUpdater.js +37 -0
  79. package/lib/updaters/OnAnyClientCallUpdater.d.ts +12 -0
  80. package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +1 -0
  81. package/lib/updaters/OnAnyClientCallUpdater.js +36 -0
  82. package/lib/updaters/OnIntervalUpdater.d.ts +10 -0
  83. package/lib/updaters/OnIntervalUpdater.d.ts.map +1 -0
  84. package/lib/updaters/OnIntervalUpdater.js +17 -0
  85. package/lib/updaters/Updater.d.ts +6 -0
  86. package/lib/updaters/Updater.d.ts.map +1 -0
  87. package/lib/updaters/Updater.js +2 -0
  88. package/lib/utils/MediasoupRemoteTrackResolver.d.ts +25 -0
  89. package/lib/utils/MediasoupRemoteTrackResolver.d.ts.map +1 -0
  90. package/lib/utils/MediasoupRemoteTrackResolver.js +110 -0
  91. package/package.json +1 -1
  92. package/src/ObservedCall.ts +210 -16
  93. package/src/ObservedCallEventMonitor.ts +392 -0
  94. package/src/ObservedCallSummary.ts +22 -0
  95. package/src/ObservedClient.ts +490 -79
  96. package/src/ObservedClientEventMonitor.ts +301 -0
  97. package/src/ObservedClientSummary.ts +24 -0
  98. package/src/ObservedDataChannel.ts +32 -0
  99. package/src/ObservedIceCandidatePair.ts +44 -2
  100. package/src/ObservedIceTransport.ts +29 -0
  101. package/src/ObservedInboundTrack.ts +3 -0
  102. package/src/ObservedOutboundTrack.ts +3 -0
  103. package/src/ObservedPeerConnection.ts +210 -46
  104. package/src/ObservedTURN.ts +86 -0
  105. package/src/ObservedTurnServer.ts +72 -0
  106. package/src/Observer.ts +179 -64
  107. package/src/ObserverEventMonitor.ts +518 -0
  108. package/src/ObserverSummary.ts +15 -0
  109. package/src/common/utils.ts +12 -2
  110. package/src/index.ts +6 -0
  111. package/src/schema/ClientEventTypes.ts +176 -0
  112. package/src/schema/{metaTypes.ts → ClientMetaTypes.ts} +1 -1
  113. package/src/schema/ClientSample.ts +1 -1
  114. package/src/updaters/ObserverUpdater.ts +5 -0
  115. package/src/updaters/OnAllCallObserverUpdater.ts +59 -0
  116. package/src/updaters/OnAllClientCallUpdater.ts +61 -0
  117. package/src/updaters/OnAnyCallObserverUpdater.ts +41 -0
  118. package/src/updaters/OnAnyClientCallUpdater.ts +39 -0
  119. package/src/updaters/OnIntervalUpdater.ts +19 -0
  120. package/src/updaters/Updater.ts +5 -0
  121. package/src/utils/MediasoupRemoteTrackResolver.ts +155 -0
  122. package/tsconfig.json +1 -1
  123. package/lib/schema/eventTypes.d.ts +0 -33
  124. package/lib/schema/eventTypes.d.ts.map +0 -1
  125. package/lib/schema/eventTypes.js +0 -38
  126. package/lib/schema/metaTypes.d.ts.map +0 -1
  127. package/lib/schema/metaTypes.js +0 -16
  128. package/lib/utils/CallUpdater.d.ts.map +0 -1
  129. package/lib/utils/OnAllClientCallUpdater.d.ts +0 -16
  130. package/lib/utils/OnAllClientCallUpdater.d.ts.map +0 -1
  131. package/lib/utils/OnAllClientCallUpdater.js +0 -58
  132. package/lib/utils/onAnyClientCallUpdater.d.ts +0 -14
  133. package/lib/utils/onAnyClientCallUpdater.d.ts.map +0 -1
  134. package/lib/utils/onAnyClientCallUpdater.js +0 -51
  135. package/src/schema/eventTypes.ts +0 -36
  136. package/src/utils/OnAllClientCallUpdater.ts +0 -68
  137. package/src/utils/onAnyClientCallUpdater.ts +0 -59
  138. /package/lib/{utils/CallUpdater.js → ObservedCallSummary.js} +0 -0
  139. /package/lib/{utils → updaters}/CallUpdater.d.ts +0 -0
  140. /package/src/{utils → updaters}/CallUpdater.ts +0 -0
@@ -4,8 +4,8 @@ exports.ObservedClient = void 0;
4
4
  const events_1 = require("events");
5
5
  const ObservedPeerConnection_1 = require("./ObservedPeerConnection");
6
6
  const logger_1 = require("./common/logger");
7
- const eventTypes_1 = require("./schema/eventTypes");
8
- const metaTypes_1 = require("./schema/metaTypes");
7
+ const ClientEventTypes_1 = require("./schema/ClientEventTypes");
8
+ const ClientMetaTypes_1 = require("./schema/ClientMetaTypes");
9
9
  const utils_1 = require("./common/utils");
10
10
  const Detectors_1 = require("./detectors/Detectors");
11
11
  const logger = (0, logger_1.createLogger)('ObservedClient');
@@ -25,6 +25,7 @@ class ObservedClient extends events_1.EventEmitter {
25
25
  closed = false;
26
26
  joinedAt;
27
27
  leftAt;
28
+ closedAt;
28
29
  // the timestamp of the CLIENT_JOINED event
29
30
  operationSystem;
30
31
  engine;
@@ -32,43 +33,73 @@ class ObservedClient extends events_1.EventEmitter {
32
33
  browser;
33
34
  mediaConstraints = [];
34
35
  usingTURN = false;
36
+ usingTCP = false;
35
37
  availableOutgoingBitrate = 0;
36
38
  availableIncomingBitrate = 0;
37
- // public totalInboundPacketsLost = 0;
38
- // public totalInboundPacketsReceived = 0;
39
- // public totalOutboundPacketsSent = 0;
40
- // public totalDataChannelBytesSent = 0;
41
- // public totalDataChannelBytesReceived = 0;
42
- // public totalSentBytes = 0;
43
- // public totalReceivedBytes = 0;
44
- // public totalReceivedAudioBytes = 0;
45
- // public totalReceivedVideoBytes = 0;
46
- // public totalSentAudioBytes = 0;
47
- // public totalSentVideoBytes = 0;
48
- // public deltaReceivedAudioBytes = 0;
49
- // public deltaReceivedVideoBytes = 0;
50
- // public deltaSentAudioBytes = 0;
51
- // public deltaSentVideoBytes = 0;
52
- // public deltaDataChannelBytesSent = 0;
53
- // public deltaDataChannelBytesReceived = 0;
54
- // public deltaInboundPacketsLost = 0;
55
- // public deltaInboundPacketsReceived = 0;
56
- // public deltaOutboundPacketsSent = 0;
57
- avgRttInMs;
58
- outboundAudioBitrate;
59
- outboundVideoBitrate;
60
- inboundAudioBitrate;
61
- inboundVideoBitrate;
39
+ totalInboundPacketsLost = 0;
40
+ totalInboundPacketsReceived = 0;
41
+ totalOutboundPacketsSent = 0;
42
+ totalDataChannelBytesSent = 0;
43
+ totalDataChannelBytesReceived = 0;
44
+ totalDataChannelMessagesSent = 0;
45
+ totalDataChannelMessagesReceived = 0;
46
+ totalReceivedAudioBytes = 0;
47
+ totalReceivedVideoBytes = 0;
48
+ totalSentAudioBytes = 0;
49
+ totalSentVideoBytes = 0;
50
+ totalSentBytes = 0;
51
+ totalReceivedBytes = 0;
52
+ deltaReceivedAudioBytes = 0;
53
+ deltaReceivedVideoBytes = 0;
54
+ deltaSentAudioBytes = 0;
55
+ deltaSentVideoBytes = 0;
56
+ deltaDataChannelBytesSent = 0;
57
+ deltaDataChannelBytesReceived = 0;
58
+ deltaDataChannelMessagesSent = 0;
59
+ deltaDataChannelMessagesReceived = 0;
60
+ deltaInboundPacketsLost = 0;
61
+ deltaInboundPacketsReceived = 0;
62
+ deltaOutboundPacketsSent = 0;
63
+ deltaTransportSentBytes = 0;
64
+ deltaTransportReceivedBytes = 0;
65
+ deltaRttLt50Measurements = 0;
66
+ deltaRttLt150Measurements = 0;
67
+ deltaRttLt300Measurements = 0;
68
+ deltaRttGtOrEq300Measurements = 0;
69
+ currentMaxRttInMs;
70
+ currentMinRttInMs;
71
+ currentAvgRttInMs;
72
+ sendingAudioBitrate = 0;
73
+ sendingVideoBitrate = 0;
74
+ receivingAudioBitrate = 0;
75
+ receivingVideoBitrate = 0;
76
+ numberOfInboundRtpStreams = 0;
77
+ numberOfInbundTracks = 0;
78
+ numberOfOutboundRtpStreams = 0;
79
+ numberOfOutboundTracks = 0;
80
+ numberOfDataChannels = 0;
81
+ totalRttLt50Measurements = 0;
82
+ totalRttLt150Measurements = 0;
83
+ totalRttLt300Measurements = 0;
84
+ totalRttGtOrEq300Measurements = 0;
85
+ deltaNumberOfIssues = 0;
86
+ totalScoreSum = 0;
87
+ numberOfScoreMeasurements = 0;
88
+ totalNumberOfIssues = 0;
62
89
  mediaDevices = [];
63
90
  issues = [];
91
+ _injections = {};
64
92
  constructor(settings, call) {
65
93
  super();
66
94
  this.call = call;
67
95
  this.setMaxListeners(Infinity);
68
96
  this.clientId = settings.clientId;
69
- this.appData = settings.appData;
97
+ this.appData = settings.appData ?? {};
70
98
  this.detectors = new Detectors_1.Detectors();
71
99
  }
100
+ get numberOfPeerConnections() {
101
+ return this.observedPeerConnections.size;
102
+ }
72
103
  get score() {
73
104
  return this.calculatedScore.value;
74
105
  }
@@ -77,19 +108,144 @@ class ObservedClient extends events_1.EventEmitter {
77
108
  return;
78
109
  this.closed = true;
79
110
  Array.from(this.observedPeerConnections.values()).forEach((peerConnection) => peerConnection.close());
111
+ this.closedAt = Date.now();
80
112
  this.emit('close');
81
113
  }
82
114
  accept(sample) {
83
115
  if (this.closed)
84
116
  throw new Error(`Client ${this.clientId} is closed`);
85
117
  const now = Date.now();
86
- sample.clientEvents?.forEach(this._processClientEvent.bind(this));
87
- sample.clientMetaItems?.forEach(this.processMetadata.bind(this));
88
- sample.clientIssues?.forEach(this.processIssue.bind(this));
89
- sample.peerConnections?.forEach(this._updatePeerConnection.bind(this));
90
- sample.extensionStats?.forEach(this.processExtensionStats.bind(this));
118
+ const elapsedInMs = now - this.updated;
119
+ const elapsedInSeconds = elapsedInMs / 1000;
120
+ let sumOfRtts = 0;
121
+ let numberOfRttMeasurements = 0;
122
+ ++this.acceptedSamples;
123
+ this.availableIncomingBitrate = 0;
124
+ this.availableOutgoingBitrate = 0;
125
+ this.deltaDataChannelBytesReceived = 0;
126
+ this.deltaDataChannelBytesSent = 0;
127
+ this.deltaDataChannelMessagesReceived = 0;
128
+ this.deltaDataChannelMessagesSent = 0;
129
+ this.deltaInboundPacketsLost = 0;
130
+ this.deltaInboundPacketsReceived = 0;
131
+ this.deltaOutboundPacketsSent = 0;
132
+ this.deltaReceivedAudioBytes = 0;
133
+ this.deltaReceivedVideoBytes = 0;
134
+ this.deltaSentAudioBytes = 0;
135
+ this.deltaSentVideoBytes = 0;
136
+ this.deltaTransportReceivedBytes = 0;
137
+ this.deltaTransportSentBytes = 0;
138
+ this.deltaRttLt50Measurements = 0;
139
+ this.deltaRttLt150Measurements = 0;
140
+ this.deltaRttLt300Measurements = 0;
141
+ this.deltaRttGtOrEq300Measurements = 0;
142
+ this.deltaNumberOfIssues = 0;
143
+ this.numberOfDataChannels = 0;
144
+ this.numberOfInboundRtpStreams = 0;
145
+ this.numberOfInbundTracks = 0;
146
+ this.numberOfOutboundRtpStreams = 0;
147
+ this.numberOfOutboundTracks = 0;
148
+ this.usingTURN = false;
149
+ this.usingTCP = false;
150
+ this.currentMinRttInMs = undefined;
151
+ this.currentMaxRttInMs = undefined;
152
+ this._mergeInjections(sample);
153
+ const clientEventsPostBuffer = [];
154
+ for (const clientEvent of sample.clientEvents ?? []) {
155
+ this._processClientEvent(clientEvent, clientEventsPostBuffer);
156
+ this.call.observer.emit('client-event', this, clientEvent);
157
+ }
158
+ for (const metaData of sample.clientMetaItems ?? []) {
159
+ this.addMetadata(metaData);
160
+ }
161
+ for (const issue of sample.clientIssues ?? []) {
162
+ this.addIssue(issue);
163
+ ++this.deltaNumberOfIssues;
164
+ }
165
+ for (const extensionStat of sample.extensionStats ?? []) {
166
+ this.addExtensionStats(extensionStat);
167
+ }
168
+ for (const pcSample of sample.peerConnections ?? []) {
169
+ const observedPeerConnection = this._updatePeerConnection(pcSample);
170
+ if (!observedPeerConnection)
171
+ continue;
172
+ this.deltaDataChannelBytesReceived += observedPeerConnection.deltaDataChannelBytesReceived;
173
+ this.deltaDataChannelBytesSent += observedPeerConnection.deltaDataChannelBytesSent;
174
+ this.deltaDataChannelMessagesReceived += observedPeerConnection.deltaDataChannelMessagesReceived;
175
+ this.deltaDataChannelMessagesSent += observedPeerConnection.deltaDataChannelMessagesSent;
176
+ this.deltaInboundPacketsLost += observedPeerConnection.deltaInboundPacketsLost;
177
+ this.deltaInboundPacketsReceived += observedPeerConnection.deltaInboundPacketsReceived;
178
+ this.deltaOutboundPacketsSent += observedPeerConnection.deltaOutboundPacketsSent;
179
+ this.deltaReceivedAudioBytes += observedPeerConnection.deltaReceivedAudioBytes;
180
+ this.deltaReceivedVideoBytes += observedPeerConnection.deltaReceivedVideoBytes;
181
+ this.deltaSentAudioBytes += observedPeerConnection.deltaSentAudioBytes;
182
+ this.deltaSentVideoBytes += observedPeerConnection.deltaSentVideoBytes;
183
+ this.deltaTransportReceivedBytes += observedPeerConnection.deltaTransportReceivedBytes;
184
+ this.deltaTransportSentBytes += observedPeerConnection.deltaTransportSentBytes;
185
+ this.availableIncomingBitrate += observedPeerConnection.availableIncomingBitrate;
186
+ this.availableOutgoingBitrate += observedPeerConnection.availableOutgoingBitrate;
187
+ this.numberOfDataChannels += observedPeerConnection.observedDataChannels.size;
188
+ this.numberOfInbundTracks += observedPeerConnection.observedInboundTracks.size;
189
+ this.numberOfOutboundRtpStreams += observedPeerConnection.observedOutboundRtps.size;
190
+ this.numberOfOutboundTracks += observedPeerConnection.observedOutboundTracks.size;
191
+ this.numberOfInboundRtpStreams += observedPeerConnection.observedInboundRtps.size;
192
+ if (observedPeerConnection.usingTURN) {
193
+ this.usingTURN = true;
194
+ }
195
+ if (observedPeerConnection.usingTCP) {
196
+ this.usingTCP = true;
197
+ }
198
+ if (observedPeerConnection.currentRttInMs) {
199
+ if (this.currentMinRttInMs === undefined || observedPeerConnection.currentRttInMs < this.currentMinRttInMs) {
200
+ this.currentMinRttInMs = observedPeerConnection.currentRttInMs;
201
+ }
202
+ if (this.currentMaxRttInMs === undefined || observedPeerConnection.currentRttInMs > this.currentMaxRttInMs) {
203
+ this.currentMaxRttInMs = observedPeerConnection.currentRttInMs;
204
+ }
205
+ if (observedPeerConnection.currentRttInMs < 50) {
206
+ this.deltaRttLt50Measurements += 1;
207
+ }
208
+ else if (observedPeerConnection.currentRttInMs < 150) {
209
+ this.deltaRttLt150Measurements += 1;
210
+ }
211
+ else if (observedPeerConnection.currentRttInMs < 300) {
212
+ this.deltaRttLt300Measurements += 1;
213
+ }
214
+ else if (300 <= observedPeerConnection.currentRttInMs) {
215
+ this.deltaRttGtOrEq300Measurements += 1;
216
+ }
217
+ sumOfRtts += observedPeerConnection.currentRttInMs;
218
+ ++numberOfRttMeasurements;
219
+ }
220
+ }
221
+ for (const clientEvent of clientEventsPostBuffer) {
222
+ this._processClientEvent(clientEvent);
223
+ }
91
224
  // emit new attachments?
92
225
  this.attachments = sample.attachments;
226
+ this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
227
+ this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
228
+ this.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
229
+ this.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
230
+ this.totalInboundPacketsLost += this.deltaInboundPacketsLost;
231
+ this.totalInboundPacketsReceived += this.deltaInboundPacketsReceived;
232
+ this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
233
+ this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
234
+ this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
235
+ this.totalSentAudioBytes += this.deltaSentAudioBytes;
236
+ this.totalSentVideoBytes += this.deltaSentVideoBytes;
237
+ this.totalReceivedBytes += this.deltaTransportReceivedBytes;
238
+ this.totalSentBytes += this.deltaTransportSentBytes;
239
+ this.totalRttLt50Measurements += this.deltaRttLt50Measurements;
240
+ this.totalRttLt150Measurements += this.deltaRttLt150Measurements;
241
+ this.totalRttLt300Measurements += this.deltaRttLt300Measurements;
242
+ this.totalRttGtOrEq300Measurements += this.deltaRttGtOrEq300Measurements;
243
+ this.totalNumberOfIssues += this.deltaNumberOfIssues;
244
+ this.receivingAudioBitrate = (this.deltaReceivedAudioBytes * 8) / (elapsedInSeconds);
245
+ this.receivingVideoBitrate = (this.totalReceivedVideoBytes * 8) / (elapsedInSeconds);
246
+ this.sendingAudioBitrate = (this.deltaSentAudioBytes * 8) / (elapsedInSeconds);
247
+ this.sendingVideoBitrate = (this.deltaSentVideoBytes * 8) / (elapsedInSeconds);
248
+ this.currentAvgRttInMs = 0 < numberOfRttMeasurements ? sumOfRtts / numberOfRttMeasurements : undefined;
93
249
  this.calculatedScore.value = sample.score;
94
250
  this.detectors.update();
95
251
  // emit update
@@ -98,18 +254,17 @@ class ObservedClient extends events_1.EventEmitter {
98
254
  elapsedTimeInMs: now - this.updated,
99
255
  });
100
256
  this.updated = now;
257
+ // if result changed after update
258
+ if (this.calculatedScore.value) {
259
+ this.totalScoreSum += this.calculatedScore.value;
260
+ ++this.numberOfScoreMeasurements;
261
+ }
101
262
  }
102
- _processClientEvent(event) {
263
+ _processClientEvent(event, postBuffer) {
264
+ // eslint-disable-next-line no-console
265
+ // console.warn('ClientEvent', event);
103
266
  switch (event.type) {
104
- case eventTypes_1.ClientEventType.CALL_STARTED: {
105
- // update call timestamp if it's the first time
106
- break;
107
- }
108
- case eventTypes_1.ClientEventType.CALL_ENDED: {
109
- // update call timestamp if it's the first time
110
- break;
111
- }
112
- case eventTypes_1.ClientEventType.CLIENT_JOINED: {
267
+ case ClientEventTypes_1.ClientEventTypes.CLIENT_JOINED: {
113
268
  if (event.timestamp) {
114
269
  if (!this.joinedAt) {
115
270
  this.joinedAt = event.timestamp;
@@ -125,74 +280,239 @@ class ObservedClient extends events_1.EventEmitter {
125
280
  }
126
281
  break;
127
282
  }
128
- case eventTypes_1.ClientEventType.CLIENT_LEFT: {
283
+ case ClientEventTypes_1.ClientEventTypes.CLIENT_LEFT: {
129
284
  if (event.timestamp) {
130
285
  if (!this.leftAt) {
131
286
  this.leftAt = event.timestamp;
132
287
  this.emit('left');
133
288
  }
289
+ else {
290
+ logger.warn(`Client ${this.clientId} leftAt timestamp was already set`);
291
+ }
292
+ }
293
+ break;
294
+ }
295
+ case ClientEventTypes_1.ClientEventTypes.PEER_CONNECTION_OPENED: {
296
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
297
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
298
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
299
+ if (observedPeerConnection) {
300
+ observedPeerConnection.openedAt = event.timestamp;
301
+ }
302
+ else if (postBuffer) {
303
+ postBuffer.push(event);
304
+ }
305
+ else {
306
+ logger.warn('Received PEER_CONNECTION_OPENED event without a corresponding observedPeerConnection', event);
307
+ }
308
+ }
309
+ break;
310
+ }
311
+ case ClientEventTypes_1.ClientEventTypes.PEER_CONNECTION_CLOSED: {
312
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
313
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
314
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
315
+ if (observedPeerConnection) {
316
+ observedPeerConnection.closedAt = event.timestamp;
317
+ }
318
+ else if (postBuffer) {
319
+ postBuffer.push(event);
320
+ }
321
+ else {
322
+ logger.warn('Received PEER_CONNECTION_CLOSED event without a corresponding observedPeerConnection', event);
323
+ }
324
+ }
325
+ break;
326
+ }
327
+ case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_ADDED: {
328
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
329
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
330
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
331
+ const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
332
+ if (observedTrack) {
333
+ observedTrack.addedAt = event.timestamp;
334
+ }
335
+ else if (postBuffer) {
336
+ postBuffer.push(event);
337
+ }
338
+ else {
339
+ logger.warn('Received MEDIA_TRACK_ADDED event without a corresponding observedPeerConnection or observedTrack', event);
340
+ }
341
+ }
342
+ break;
343
+ }
344
+ case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_REMOVED: {
345
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
346
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
347
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
348
+ const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
349
+ if (observedTrack) {
350
+ observedTrack.removedAt = event.timestamp;
351
+ }
352
+ else if (postBuffer) {
353
+ postBuffer.push(event);
354
+ }
355
+ else {
356
+ logger.warn('Received MEDIA_TRACK_REMOVED event without a corresponding observedPeerConnection or observedTrack', event);
357
+ }
358
+ }
359
+ break;
360
+ }
361
+ case ClientEventTypes_1.ClientEventTypes.DATA_CHANNEL_OPEN: {
362
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
363
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
364
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
365
+ const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
366
+ if (observedDataChannel) {
367
+ observedDataChannel.addedAt = event.timestamp;
368
+ }
369
+ else if (postBuffer) {
370
+ postBuffer.push(event);
371
+ }
372
+ else {
373
+ logger.warn('Received DATA_CHANNEL_OPENED event without a corresponding observedPeerConnection or observedDataChannel', event);
374
+ }
375
+ }
376
+ break;
377
+ }
378
+ case ClientEventTypes_1.ClientEventTypes.DATA_CHANNEL_CLOSED: {
379
+ const payload = (0, utils_1.parseJsonAs)(event.payload);
380
+ if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
381
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
382
+ const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
383
+ if (observedDataChannel) {
384
+ observedDataChannel.removedAt = event.timestamp;
385
+ }
386
+ else if (postBuffer) {
387
+ postBuffer.push(event);
388
+ }
389
+ else {
390
+ logger.warn('Received DATA_CHANNEL_CLOSE event without a corresponding observedPeerConnection or observedDataChannel', event);
391
+ }
134
392
  }
135
393
  break;
136
394
  }
137
395
  }
138
- this.call.observer.processors.events.process({
139
- call: this.call,
140
- client: this,
141
- data: event,
142
- });
396
+ this.emit('clientEvent', event);
397
+ }
398
+ injectMetaData(metaData) {
399
+ if (this.closed)
400
+ return;
401
+ if (!this._injections.clientMetaItems)
402
+ this._injections.clientMetaItems = [];
403
+ this._injections.clientMetaItems.push(metaData);
404
+ }
405
+ injectEvent(event) {
406
+ if (this.closed)
407
+ return;
408
+ if (!this._injections.clientEvents)
409
+ this._injections.clientEvents = [];
410
+ this._injections.clientEvents.push(event);
143
411
  }
144
- processMetadata(metadata) {
412
+ injectIssue(issue) {
413
+ if (this.closed)
414
+ return;
415
+ if (!this._injections.clientIssues)
416
+ this._injections.clientIssues = [];
417
+ this._injections.clientIssues.push(issue);
418
+ }
419
+ injectExtensionStat(stat) {
420
+ if (this.closed)
421
+ return;
422
+ if (!this._injections.extensionStats)
423
+ this._injections.extensionStats = [];
424
+ this._injections.extensionStats.push(stat);
425
+ }
426
+ injectAttachment(key, value) {
427
+ if (this.closed)
428
+ return;
429
+ if (!this._injections.attachments)
430
+ this._injections.attachments = {};
431
+ this._injections.attachments[key] = value;
432
+ }
433
+ addMetadata(metadata) {
434
+ if (this.closed)
435
+ return;
145
436
  switch (metadata.type) {
146
- case metaTypes_1.ClientMetaType.BROWSER: {
437
+ case ClientMetaTypes_1.ClientMetaTypes.BROWSER: {
147
438
  this.browser = (0, utils_1.parseJsonAs)(metadata.payload);
148
439
  break;
149
440
  }
150
- case metaTypes_1.ClientMetaType.ENGINE: {
441
+ case ClientMetaTypes_1.ClientMetaTypes.ENGINE: {
151
442
  this.engine = (0, utils_1.parseJsonAs)(metadata.payload);
152
443
  break;
153
444
  }
154
- case metaTypes_1.ClientMetaType.PLATFORM: {
445
+ case ClientMetaTypes_1.ClientMetaTypes.PLATFORM: {
155
446
  this.platform = (0, utils_1.parseJsonAs)(metadata.payload);
156
447
  break;
157
448
  }
158
- case metaTypes_1.ClientMetaType.OPERATION_SYSTEM: {
449
+ case ClientMetaTypes_1.ClientMetaTypes.OPERATION_SYSTEM: {
159
450
  this.operationSystem = (0, utils_1.parseJsonAs)(metadata.payload);
160
451
  break;
161
452
  }
162
453
  }
163
- this.call.observer.processors.metaData.process({
164
- call: this.call,
165
- client: this,
166
- data: metadata,
167
- });
454
+ this.call.observer.emit('client-metadata', this, metadata);
168
455
  }
169
- processIssue(issue) {
170
- this.call.observer.processors.issues.process({
171
- call: this.call,
172
- client: this,
173
- data: issue,
174
- });
456
+ addIssue(issue) {
457
+ if (this.closed)
458
+ return;
459
+ this.emit('issue', issue);
460
+ this.call.observer.emit('client-issue', this, issue);
175
461
  }
176
- processExtensionStats(stats) {
177
- this.call.observer.processors.extensionStats.process({
178
- call: this.call,
179
- client: this,
180
- data: stats,
181
- });
462
+ addExtensionStats(stats) {
463
+ this.call.observer.emit('client-extension-stats', this, stats);
464
+ this.emit('extensionStats', stats);
182
465
  }
183
466
  _updatePeerConnection(sample) {
184
467
  let observedPeerConnection = this.observedPeerConnections.get(sample.peerConnectionId);
185
468
  if (!observedPeerConnection) {
186
469
  if (!sample.peerConnectionId) {
187
- return logger.warn(`ObservedClient received an invalid PeerConnectionSample (missing peerConnectionId field). ClientId: ${this.clientId}, CallId: ${this.call.callId}`, sample);
470
+ return (logger.warn(`ObservedClient received an invalid PeerConnectionSample (missing peerConnectionId field). ClientId: ${this.clientId}, CallId: ${this.call.callId}`, sample), void 0);
188
471
  }
189
472
  observedPeerConnection = new ObservedPeerConnection_1.ObservedPeerConnection(sample.peerConnectionId, this);
190
473
  observedPeerConnection.once('close', () => {
191
474
  this.observedPeerConnections.delete(sample.peerConnectionId);
192
475
  });
193
476
  this.observedPeerConnections.set(sample.peerConnectionId, observedPeerConnection);
477
+ this.emit('newpeerconnection', observedPeerConnection);
194
478
  }
195
479
  observedPeerConnection.accept(sample);
480
+ return observedPeerConnection;
481
+ }
482
+ _mergeInjections(sample) {
483
+ if (this.closed)
484
+ return sample;
485
+ if (this._injections.clientEvents) {
486
+ if (!sample.clientEvents)
487
+ sample.clientEvents = [];
488
+ sample.clientEvents.push(...this._injections.clientEvents);
489
+ this._injections.clientEvents = undefined;
490
+ }
491
+ if (this._injections.clientIssues) {
492
+ if (!sample.clientIssues)
493
+ sample.clientIssues = [];
494
+ sample.clientIssues.push(...this._injections.clientIssues);
495
+ this._injections.clientIssues = undefined;
496
+ }
497
+ if (this._injections.extensionStats) {
498
+ if (!sample.extensionStats)
499
+ sample.extensionStats = [];
500
+ sample.extensionStats.push(...this._injections.extensionStats);
501
+ this._injections.extensionStats = undefined;
502
+ }
503
+ if (this._injections.attachments) {
504
+ if (!sample.attachments)
505
+ sample.attachments = {};
506
+ Object.assign(sample.attachments, this._injections.attachments);
507
+ this._injections.attachments = undefined;
508
+ }
509
+ if (this._injections.clientMetaItems) {
510
+ if (!sample.clientMetaItems)
511
+ sample.clientMetaItems = [];
512
+ sample.clientMetaItems.push(...this._injections.clientMetaItems);
513
+ this._injections.clientMetaItems = undefined;
514
+ }
515
+ return sample;
196
516
  }
197
517
  }
198
518
  exports.ObservedClient = ObservedClient;
@@ -0,0 +1,89 @@
1
+ import { ObservedCertificate } from './ObservedCertificate';
2
+ import { ObservedClient } from './ObservedClient';
3
+ import { ObservedCodec } from './ObservedCodec';
4
+ import { ObservedDataChannel } from './ObservedDataChannel';
5
+ import { ObservedIceCandidate } from './ObservedIceCandidate';
6
+ import { ObservedIceCandidatePair } from './ObservedIceCandidatePair';
7
+ import { ObservedIceTransport } from './ObservedIceTransport';
8
+ import { ObservedInboundRtp } from './ObservedInboundRtp';
9
+ import { ObservedInboundTrack } from './ObservedInboundTrack';
10
+ import { ObservedMediaPlayout } from './ObservedMediaPlayout';
11
+ import { ObservedMediaSource } from './ObservedMediaSource';
12
+ import { ObservedOutboundRtp } from './ObservedOutboundRtp';
13
+ import { ObservedOutboundTrack } from './ObservedOutboundTrack';
14
+ import { ObservedPeerConnection } from './ObservedPeerConnection';
15
+ import { ClientIssue, ClientMetaData, ExtensionStat } from './schema/ClientSample';
16
+ export declare class ObservedClientEventMonitor<Context> {
17
+ readonly observedClient: ObservedClient;
18
+ readonly context: Context;
19
+ constructor(observedClient: ObservedClient, context: Context);
20
+ onClientClosed?: (client: ObservedClient, ctx: Context) => void;
21
+ private _onClientClosed;
22
+ onPeerConnectionAdded?: (peerConnection: ObservedPeerConnection, ctx: Context) => void;
23
+ private _onPeerConnconnectionAdded;
24
+ onPeerConnectionRemoved?: (peerConnection: ObservedPeerConnection, ctx: Context) => void;
25
+ private _onPeerConnectionRemoved;
26
+ onCertificateAdded?: (certificate: ObservedCertificate, ctx: Context) => void;
27
+ private _onCertificateAdded;
28
+ onCertificateRemoved?: (certificate: ObservedCertificate, ctx: Context) => void;
29
+ private _onCertificateRemoved;
30
+ onInboundTrackAdded?: (inboundTrack: ObservedInboundTrack, ctx: Context) => void;
31
+ private _onInboundTrackAdded;
32
+ onInboundTrackRemoved?: (inboundTrack: ObservedInboundTrack, ctx: Context) => void;
33
+ private _onInboundTrackRemoved;
34
+ onOutboundTrackAdded?: (outboundTrack: ObservedOutboundTrack, ctx: Context) => void;
35
+ private _onOutboundTrackAdded;
36
+ onOutboundTrackRemoved?: (outboundTrack: ObservedOutboundTrack, ctx: Context) => void;
37
+ private _onOutboundTrackRemoved;
38
+ onInboundRtpAdded?: (inboundRtp: ObservedInboundRtp, ctx: Context) => void;
39
+ private _onInboundRtpAdded;
40
+ onInboundRtpRemoved?: (inboundRtp: ObservedInboundRtp, ctx: Context) => void;
41
+ private _onInboundRtpRemoved;
42
+ onOutboundRtpAdded?: (outboundRtp: ObservedOutboundRtp, ctx: Context) => void;
43
+ private _onOutboundRtpAdded;
44
+ onOutboundRtpRemoved?: (outboundRtp: ObservedOutboundRtp, ctx: Context) => void;
45
+ private _onOutboundRtpRemoved;
46
+ onDataChannelAdded?: (dataChannel: ObservedDataChannel, ctx: Context) => void;
47
+ private _onDataChannelAdded;
48
+ onDataChannelRemoved?: (dataChannel: ObservedDataChannel, ctx: Context) => void;
49
+ private _onDataChannelRemoved;
50
+ onAddedIceTransport?: (iceTransport: ObservedIceTransport, ctx: Context) => void;
51
+ private _onAddedIceTransport;
52
+ onRemovedIceTransport?: (iceTransport: ObservedIceTransport, ctx: Context) => void;
53
+ private _onRemovedIceTransport;
54
+ onIceCandidateAdded?: (iceCandidate: ObservedIceCandidate, ctx: Context) => void;
55
+ private _onIceCandidateAdded;
56
+ onIceCandidateRemoved?: (iceCandidate: ObservedIceCandidate, ctx: Context) => void;
57
+ private _onIceCandidateRemoved;
58
+ onAddedIceCandidatePair?: (candidatePair: ObservedIceCandidatePair, ctx: Context) => void;
59
+ private _onAddedIceCandidatePair;
60
+ onRemovedIceCandidatePair?: (candidatePair: ObservedIceCandidatePair, ctx: Context) => void;
61
+ private _onRemovedIceCandidatePair;
62
+ onAddedMediaCodec?: (codec: ObservedCodec, ctx: Context) => void;
63
+ private _onAddedMediaCodec;
64
+ onRemovedMediaCodec?: (codec: ObservedCodec, ctx: Context) => void;
65
+ private _onRemovedMediaCodec;
66
+ onAddedMediaPlayout?: (mediaPlayout: ObservedMediaPlayout, ctx: Context) => void;
67
+ private _onAddedMediaPlayout;
68
+ onRemovedMediaPlayout?: (mediaPlayout: ObservedMediaPlayout, ctx: Context) => void;
69
+ private _onRemovedMediaPlayout;
70
+ onMediaSourceAdded?: (mediaSource: ObservedMediaSource, ctx: Context) => void;
71
+ private _onMediaSourceAdded;
72
+ onMediaSourceRemoved?: (mediaSource: ObservedMediaSource, ctx: Context) => void;
73
+ private _onMediaSourceRemoved;
74
+ onClientIssue?: (issue: ClientIssue, ctx: Context) => void;
75
+ private _onClientIssue;
76
+ onClientMetadata?: (metadata: ClientMetaData, ctx: Context) => void;
77
+ private _onClientMetadata;
78
+ onClientExtensionStats?: (extensionStats: ExtensionStat, ctx: Context) => void;
79
+ private _onClientExtensionStats;
80
+ onClientJoined?: (client: ObservedClient, ctx: Context) => void;
81
+ private _onClientJoined;
82
+ onClientLeft?: (client: ObservedClient, ctx: Context) => void;
83
+ private _onClientLeft;
84
+ onUserMediaError?: (error: string, observedClient: ObservedClient, ctx: Context) => void;
85
+ private _onUserMediaError;
86
+ onUsingTurn?: (client: ObservedClient, ctx: Context) => void;
87
+ private _onUsingTurn;
88
+ }
89
+ //# sourceMappingURL=ObservedClientEventMonitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObservedClientEventMonitor.d.ts","sourceRoot":"","sources":["../src/ObservedClientEventMonitor.ts"],"names":[],"mappings":"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"}