@observertc/observer-js 1.0.1-72a904d.0 → 1.0.1-797e5af.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.
- package/lib/ObservedCall.d.ts +2 -8
- package/lib/ObservedCall.d.ts.map +1 -1
- package/lib/ObservedCall.js +12 -72
- package/lib/ObservedClient.d.ts +16 -8
- package/lib/ObservedClient.d.ts.map +1 -1
- package/lib/ObservedClient.js +258 -98
- package/lib/ObservedClientEventMonitor.d.ts +89 -0
- package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
- package/lib/ObservedClientEventMonitor.js +247 -0
- package/lib/ObservedDataChannel.d.ts +2 -0
- package/lib/ObservedDataChannel.d.ts.map +1 -1
- package/lib/ObservedDataChannel.js +2 -0
- package/lib/ObservedInboundTrack.d.ts +2 -0
- package/lib/ObservedInboundTrack.d.ts.map +1 -1
- package/lib/ObservedInboundTrack.js +2 -0
- package/lib/ObservedOutboundTrack.d.ts +2 -0
- package/lib/ObservedOutboundTrack.d.ts.map +1 -1
- package/lib/ObservedOutboundTrack.js +2 -0
- package/lib/ObservedPeerConnection.d.ts.map +1 -1
- package/lib/ObservedPeerConnection.js +22 -6
- package/lib/Observer.d.ts +1 -3
- package/lib/Observer.d.ts.map +1 -1
- package/lib/Observer.js +3 -21
- package/lib/ObserverSummary.d.ts +2 -0
- package/lib/ObserverSummary.d.ts.map +1 -1
- package/lib/common/utils.d.ts +1 -0
- package/lib/common/utils.d.ts.map +1 -1
- package/lib/common/utils.js +7 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -1
- package/lib/schema/ClientEventTypes.d.ts +43 -0
- package/lib/schema/ClientEventTypes.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ObservedCall.ts +51 -82
- package/src/ObservedClient.ts +336 -112
- package/src/ObservedClientEventMonitor.ts +301 -0
- package/src/ObservedDataChannel.ts +3 -0
- package/src/ObservedInboundTrack.ts +3 -0
- package/src/ObservedOutboundTrack.ts +3 -0
- package/src/ObservedPeerConnection.ts +25 -10
- package/src/Observer.ts +28 -25
- package/src/ObserverSummary.ts +3 -1
- package/src/common/utils.ts +6 -0
- package/src/index.ts +1 -0
- package/src/schema/ClientEventTypes.ts +46 -0
package/lib/ObservedClient.js
CHANGED
|
@@ -8,6 +8,7 @@ const ClientEventTypes_1 = require("./schema/ClientEventTypes");
|
|
|
8
8
|
const ClientMetaTypes_1 = require("./schema/ClientMetaTypes");
|
|
9
9
|
const utils_1 = require("./common/utils");
|
|
10
10
|
const Detectors_1 = require("./detectors/Detectors");
|
|
11
|
+
const ObservedClientEventMonitor_1 = require("./ObservedClientEventMonitor");
|
|
11
12
|
const logger = (0, logger_1.createLogger)('ObservedClient');
|
|
12
13
|
class ObservedClient extends events_1.EventEmitter {
|
|
13
14
|
call;
|
|
@@ -25,6 +26,7 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
25
26
|
closed = false;
|
|
26
27
|
joinedAt;
|
|
27
28
|
leftAt;
|
|
29
|
+
closedAt;
|
|
28
30
|
// the timestamp of the CLIENT_JOINED event
|
|
29
31
|
operationSystem;
|
|
30
32
|
engine;
|
|
@@ -32,6 +34,7 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
32
34
|
browser;
|
|
33
35
|
mediaConstraints = [];
|
|
34
36
|
usingTURN = false;
|
|
37
|
+
usingTCP = false;
|
|
35
38
|
availableOutgoingBitrate = 0;
|
|
36
39
|
availableIncomingBitrate = 0;
|
|
37
40
|
totalInboundPacketsLost = 0;
|
|
@@ -58,14 +61,15 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
58
61
|
deltaInboundPacketsLost = 0;
|
|
59
62
|
deltaInboundPacketsReceived = 0;
|
|
60
63
|
deltaOutboundPacketsSent = 0;
|
|
61
|
-
deltaRttInMsMeasurements = [];
|
|
62
64
|
deltaTransportSentBytes = 0;
|
|
63
65
|
deltaTransportReceivedBytes = 0;
|
|
64
66
|
deltaRttLt50Measurements = 0;
|
|
65
67
|
deltaRttLt150Measurements = 0;
|
|
66
68
|
deltaRttLt300Measurements = 0;
|
|
67
69
|
deltaRttGtOrEq300Measurements = 0;
|
|
68
|
-
|
|
70
|
+
currentMaxRttInMs;
|
|
71
|
+
currentMinRttInMs;
|
|
72
|
+
currentAvgRttInMs;
|
|
69
73
|
sendingAudioBitrate = 0;
|
|
70
74
|
sendingVideoBitrate = 0;
|
|
71
75
|
receivingAudioBitrate = 0;
|
|
@@ -82,9 +86,10 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
82
86
|
deltaNumberOfIssues = 0;
|
|
83
87
|
totalScoreSum = 0;
|
|
84
88
|
numberOfScoreMeasurements = 0;
|
|
85
|
-
|
|
89
|
+
totalNumberOfIssues = 0;
|
|
86
90
|
mediaDevices = [];
|
|
87
91
|
issues = [];
|
|
92
|
+
_injections = {};
|
|
88
93
|
constructor(settings, call) {
|
|
89
94
|
super();
|
|
90
95
|
this.call = call;
|
|
@@ -104,6 +109,7 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
104
109
|
return;
|
|
105
110
|
this.closed = true;
|
|
106
111
|
Array.from(this.observedPeerConnections.values()).forEach((peerConnection) => peerConnection.close());
|
|
112
|
+
this.closedAt = Date.now();
|
|
107
113
|
this.emit('close');
|
|
108
114
|
}
|
|
109
115
|
accept(sample) {
|
|
@@ -112,6 +118,8 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
112
118
|
const now = Date.now();
|
|
113
119
|
const elapsedInMs = now - this.updated;
|
|
114
120
|
const elapsedInSeconds = elapsedInMs / 1000;
|
|
121
|
+
let sumOfRtts = 0;
|
|
122
|
+
let numberOfRttMeasurements = 0;
|
|
115
123
|
++this.acceptedSamples;
|
|
116
124
|
this.availableIncomingBitrate = 0;
|
|
117
125
|
this.availableOutgoingBitrate = 0;
|
|
@@ -128,7 +136,6 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
128
136
|
this.deltaSentVideoBytes = 0;
|
|
129
137
|
this.deltaTransportReceivedBytes = 0;
|
|
130
138
|
this.deltaTransportSentBytes = 0;
|
|
131
|
-
this.deltaRttInMsMeasurements = [];
|
|
132
139
|
this.deltaRttLt50Measurements = 0;
|
|
133
140
|
this.deltaRttLt150Measurements = 0;
|
|
134
141
|
this.deltaRttLt300Measurements = 0;
|
|
@@ -139,12 +146,82 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
139
146
|
this.numberOfInbundTracks = 0;
|
|
140
147
|
this.numberOfOutboundRtpStreams = 0;
|
|
141
148
|
this.numberOfOutboundTracks = 0;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
this.usingTURN = false;
|
|
150
|
+
this.usingTCP = false;
|
|
151
|
+
this.currentMinRttInMs = undefined;
|
|
152
|
+
this.currentMaxRttInMs = undefined;
|
|
153
|
+
this._mergeInjections(sample);
|
|
154
|
+
const clientEventsPostBuffer = [];
|
|
155
|
+
for (const clientEvent of sample.clientEvents ?? []) {
|
|
156
|
+
this._processClientEvent(clientEvent, clientEventsPostBuffer);
|
|
157
|
+
this.call.observer.emit('client-event', this, clientEvent);
|
|
158
|
+
}
|
|
159
|
+
for (const metaData of sample.clientMetaItems ?? []) {
|
|
160
|
+
this.addMetadata(metaData);
|
|
161
|
+
}
|
|
162
|
+
for (const issue of sample.clientIssues ?? []) {
|
|
163
|
+
this.addIssue(issue);
|
|
164
|
+
++this.deltaNumberOfIssues;
|
|
165
|
+
}
|
|
166
|
+
for (const extensionStat of sample.extensionStats ?? []) {
|
|
167
|
+
this.addExtensionStats(extensionStat);
|
|
168
|
+
}
|
|
169
|
+
for (const pcSample of sample.peerConnections ?? []) {
|
|
170
|
+
const observedPeerConnection = this._updatePeerConnection(pcSample);
|
|
171
|
+
if (!observedPeerConnection)
|
|
172
|
+
continue;
|
|
173
|
+
this.deltaDataChannelBytesReceived += observedPeerConnection.deltaDataChannelBytesReceived;
|
|
174
|
+
this.deltaDataChannelBytesSent += observedPeerConnection.deltaDataChannelBytesSent;
|
|
175
|
+
this.deltaDataChannelMessagesReceived += observedPeerConnection.deltaDataChannelMessagesReceived;
|
|
176
|
+
this.deltaDataChannelMessagesSent += observedPeerConnection.deltaDataChannelMessagesSent;
|
|
177
|
+
this.deltaInboundPacketsLost += observedPeerConnection.deltaInboundPacketsLost;
|
|
178
|
+
this.deltaInboundPacketsReceived += observedPeerConnection.deltaInboundPacketsReceived;
|
|
179
|
+
this.deltaOutboundPacketsSent += observedPeerConnection.deltaOutboundPacketsSent;
|
|
180
|
+
this.deltaReceivedAudioBytes += observedPeerConnection.deltaReceivedAudioBytes;
|
|
181
|
+
this.deltaReceivedVideoBytes += observedPeerConnection.deltaReceivedVideoBytes;
|
|
182
|
+
this.deltaSentAudioBytes += observedPeerConnection.deltaSentAudioBytes;
|
|
183
|
+
this.deltaSentVideoBytes += observedPeerConnection.deltaSentVideoBytes;
|
|
184
|
+
this.deltaTransportReceivedBytes += observedPeerConnection.deltaTransportReceivedBytes;
|
|
185
|
+
this.deltaTransportSentBytes += observedPeerConnection.deltaTransportSentBytes;
|
|
186
|
+
this.availableIncomingBitrate += observedPeerConnection.availableIncomingBitrate;
|
|
187
|
+
this.availableOutgoingBitrate += observedPeerConnection.availableOutgoingBitrate;
|
|
188
|
+
this.numberOfDataChannels += observedPeerConnection.observedDataChannels.size;
|
|
189
|
+
this.numberOfInbundTracks += observedPeerConnection.observedInboundTracks.size;
|
|
190
|
+
this.numberOfOutboundRtpStreams += observedPeerConnection.observedOutboundRtps.size;
|
|
191
|
+
this.numberOfOutboundTracks += observedPeerConnection.observedOutboundTracks.size;
|
|
192
|
+
this.numberOfInboundRtpStreams += observedPeerConnection.observedInboundRtps.size;
|
|
193
|
+
if (observedPeerConnection.usingTURN) {
|
|
194
|
+
this.usingTURN = true;
|
|
195
|
+
}
|
|
196
|
+
if (observedPeerConnection.usingTCP) {
|
|
197
|
+
this.usingTCP = true;
|
|
198
|
+
}
|
|
199
|
+
if (observedPeerConnection.currentRttInMs) {
|
|
200
|
+
if (this.currentMinRttInMs === undefined || observedPeerConnection.currentRttInMs < this.currentMinRttInMs) {
|
|
201
|
+
this.currentMinRttInMs = observedPeerConnection.currentRttInMs;
|
|
202
|
+
}
|
|
203
|
+
if (this.currentMaxRttInMs === undefined || observedPeerConnection.currentRttInMs > this.currentMaxRttInMs) {
|
|
204
|
+
this.currentMaxRttInMs = observedPeerConnection.currentRttInMs;
|
|
205
|
+
}
|
|
206
|
+
if (observedPeerConnection.currentRttInMs < 50) {
|
|
207
|
+
this.deltaRttLt50Measurements += 1;
|
|
208
|
+
}
|
|
209
|
+
else if (observedPeerConnection.currentRttInMs < 150) {
|
|
210
|
+
this.deltaRttLt150Measurements += 1;
|
|
211
|
+
}
|
|
212
|
+
else if (observedPeerConnection.currentRttInMs < 300) {
|
|
213
|
+
this.deltaRttLt300Measurements += 1;
|
|
214
|
+
}
|
|
215
|
+
else if (300 <= observedPeerConnection.currentRttInMs) {
|
|
216
|
+
this.deltaRttGtOrEq300Measurements += 1;
|
|
217
|
+
}
|
|
218
|
+
sumOfRtts += observedPeerConnection.currentRttInMs;
|
|
219
|
+
++numberOfRttMeasurements;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
for (const clientEvent of clientEventsPostBuffer) {
|
|
223
|
+
this._processClientEvent(clientEvent);
|
|
224
|
+
}
|
|
148
225
|
// emit new attachments?
|
|
149
226
|
this.attachments = sample.attachments;
|
|
150
227
|
this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
|
|
@@ -164,11 +241,12 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
164
241
|
this.totalRttLt150Measurements += this.deltaRttLt150Measurements;
|
|
165
242
|
this.totalRttLt300Measurements += this.deltaRttLt300Measurements;
|
|
166
243
|
this.totalRttGtOrEq300Measurements += this.deltaRttGtOrEq300Measurements;
|
|
167
|
-
this.
|
|
244
|
+
this.totalNumberOfIssues += this.deltaNumberOfIssues;
|
|
168
245
|
this.receivingAudioBitrate = (this.deltaReceivedAudioBytes * 8) / (elapsedInSeconds);
|
|
169
246
|
this.receivingVideoBitrate = (this.totalReceivedVideoBytes * 8) / (elapsedInSeconds);
|
|
170
247
|
this.sendingAudioBitrate = (this.deltaSentAudioBytes * 8) / (elapsedInSeconds);
|
|
171
248
|
this.sendingVideoBitrate = (this.deltaSentVideoBytes * 8) / (elapsedInSeconds);
|
|
249
|
+
this.currentAvgRttInMs = 0 < numberOfRttMeasurements ? sumOfRtts / numberOfRttMeasurements : undefined;
|
|
172
250
|
this.calculatedScore.value = sample.score;
|
|
173
251
|
this.detectors.update();
|
|
174
252
|
// emit update
|
|
@@ -183,7 +261,7 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
183
261
|
++this.numberOfScoreMeasurements;
|
|
184
262
|
}
|
|
185
263
|
}
|
|
186
|
-
_processClientEvent(event) {
|
|
264
|
+
_processClientEvent(event, postBuffer) {
|
|
187
265
|
// eslint-disable-next-line no-console
|
|
188
266
|
// console.warn('ClientEvent', event);
|
|
189
267
|
switch (event.type) {
|
|
@@ -215,8 +293,142 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
215
293
|
}
|
|
216
294
|
break;
|
|
217
295
|
}
|
|
296
|
+
case ClientEventTypes_1.ClientEventTypes.PEER_CONNECTION_OPENED: {
|
|
297
|
+
const payload = (0, utils_1.parseJsonAs)(event.payload);
|
|
298
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
|
|
299
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
300
|
+
if (observedPeerConnection) {
|
|
301
|
+
observedPeerConnection.openedAt = event.timestamp;
|
|
302
|
+
}
|
|
303
|
+
else if (postBuffer) {
|
|
304
|
+
postBuffer.push(event);
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
logger.warn('Received PEER_CONNECTION_OPENED event without a corresponding observedPeerConnection', event);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
case ClientEventTypes_1.ClientEventTypes.PEER_CONNECTION_CLOSED: {
|
|
313
|
+
const payload = (0, utils_1.parseJsonAs)(event.payload);
|
|
314
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
|
|
315
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
316
|
+
if (observedPeerConnection) {
|
|
317
|
+
observedPeerConnection.closedAt = event.timestamp;
|
|
318
|
+
}
|
|
319
|
+
else if (postBuffer) {
|
|
320
|
+
postBuffer.push(event);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
logger.warn('Received PEER_CONNECTION_CLOSED event without a corresponding observedPeerConnection', event);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_ADDED: {
|
|
329
|
+
const payload = (0, utils_1.parseJsonAs)(event.payload);
|
|
330
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
|
|
331
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
332
|
+
const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
333
|
+
if (observedTrack) {
|
|
334
|
+
observedTrack.addedAt = event.timestamp;
|
|
335
|
+
}
|
|
336
|
+
else if (postBuffer) {
|
|
337
|
+
postBuffer.push(event);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
logger.warn('Received MEDIA_TRACK_ADDED event without a corresponding observedPeerConnection or observedTrack', event);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_REMOVED: {
|
|
346
|
+
const payload = (0, utils_1.parseJsonAs)(event.payload);
|
|
347
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
|
|
348
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
349
|
+
const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
350
|
+
if (observedTrack) {
|
|
351
|
+
observedTrack.removedAt = event.timestamp;
|
|
352
|
+
}
|
|
353
|
+
else if (postBuffer) {
|
|
354
|
+
postBuffer.push(event);
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
logger.warn('Received MEDIA_TRACK_REMOVED event without a corresponding observedPeerConnection or observedTrack', event);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
case ClientEventTypes_1.ClientEventTypes.DATA_CHANNEL_OPEN: {
|
|
363
|
+
const payload = (0, utils_1.parseJsonAs)(event.payload);
|
|
364
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
|
|
365
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
366
|
+
const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
|
|
367
|
+
if (observedDataChannel) {
|
|
368
|
+
observedDataChannel.addedAt = event.timestamp;
|
|
369
|
+
}
|
|
370
|
+
else if (postBuffer) {
|
|
371
|
+
postBuffer.push(event);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
logger.warn('Received DATA_CHANNEL_OPENED event without a corresponding observedPeerConnection or observedDataChannel', event);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
379
|
+
case ClientEventTypes_1.ClientEventTypes.DATA_CHANNEL_CLOSED: {
|
|
380
|
+
const payload = (0, utils_1.parseJsonAs)(event.payload);
|
|
381
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
|
|
382
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
383
|
+
const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
|
|
384
|
+
if (observedDataChannel) {
|
|
385
|
+
observedDataChannel.removedAt = event.timestamp;
|
|
386
|
+
}
|
|
387
|
+
else if (postBuffer) {
|
|
388
|
+
postBuffer.push(event);
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
logger.warn('Received DATA_CHANNEL_CLOSE event without a corresponding observedPeerConnection or observedDataChannel', event);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
break;
|
|
395
|
+
}
|
|
218
396
|
}
|
|
219
|
-
|
|
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);
|
|
411
|
+
}
|
|
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;
|
|
220
432
|
}
|
|
221
433
|
addMetadata(metadata) {
|
|
222
434
|
if (this.closed)
|
|
@@ -244,7 +456,6 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
244
456
|
addIssue(issue) {
|
|
245
457
|
if (this.closed)
|
|
246
458
|
return;
|
|
247
|
-
++this.deltaNumberOfIssues;
|
|
248
459
|
this.emit('issue', issue);
|
|
249
460
|
this.call.observer.emit('client-issue', this, issue);
|
|
250
461
|
}
|
|
@@ -255,7 +466,7 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
255
466
|
let observedPeerConnection = this.observedPeerConnections.get(sample.peerConnectionId);
|
|
256
467
|
if (!observedPeerConnection) {
|
|
257
468
|
if (!sample.peerConnectionId) {
|
|
258
|
-
return logger.warn(`ObservedClient received an invalid PeerConnectionSample (missing peerConnectionId field). ClientId: ${this.clientId}, CallId: ${this.call.callId}`, sample);
|
|
469
|
+
return (logger.warn(`ObservedClient received an invalid PeerConnectionSample (missing peerConnectionId field). ClientId: ${this.clientId}, CallId: ${this.call.callId}`, sample), void 0);
|
|
259
470
|
}
|
|
260
471
|
observedPeerConnection = new ObservedPeerConnection_1.ObservedPeerConnection(sample.peerConnectionId, this);
|
|
261
472
|
observedPeerConnection.once('close', () => {
|
|
@@ -265,96 +476,45 @@ class ObservedClient extends events_1.EventEmitter {
|
|
|
265
476
|
this.emit('newpeerconnection', observedPeerConnection);
|
|
266
477
|
}
|
|
267
478
|
observedPeerConnection.accept(sample);
|
|
268
|
-
observedPeerConnection
|
|
269
|
-
this.deltaDataChannelBytesReceived += observedPeerConnection.deltaDataChannelBytesReceived;
|
|
270
|
-
this.deltaDataChannelBytesSent += observedPeerConnection.deltaDataChannelBytesSent;
|
|
271
|
-
this.deltaDataChannelMessagesReceived += observedPeerConnection.deltaDataChannelMessagesReceived;
|
|
272
|
-
this.deltaDataChannelMessagesSent += observedPeerConnection.deltaDataChannelMessagesSent;
|
|
273
|
-
this.deltaInboundPacketsLost += observedPeerConnection.deltaInboundPacketsLost;
|
|
274
|
-
this.deltaInboundPacketsReceived += observedPeerConnection.deltaInboundPacketsReceived;
|
|
275
|
-
this.deltaOutboundPacketsSent += observedPeerConnection.deltaOutboundPacketsSent;
|
|
276
|
-
this.deltaReceivedAudioBytes += observedPeerConnection.deltaReceivedAudioBytes;
|
|
277
|
-
this.deltaReceivedVideoBytes += observedPeerConnection.deltaReceivedVideoBytes;
|
|
278
|
-
this.deltaSentAudioBytes += observedPeerConnection.deltaSentAudioBytes;
|
|
279
|
-
this.deltaSentVideoBytes += observedPeerConnection.deltaSentVideoBytes;
|
|
280
|
-
this.deltaTransportReceivedBytes += observedPeerConnection.deltaTransportReceivedBytes;
|
|
281
|
-
this.deltaTransportSentBytes += observedPeerConnection.deltaTransportSentBytes;
|
|
282
|
-
this.availableIncomingBitrate += observedPeerConnection.availableIncomingBitrate;
|
|
283
|
-
this.availableOutgoingBitrate += observedPeerConnection.availableOutgoingBitrate;
|
|
284
|
-
this.numberOfDataChannels += observedPeerConnection.observedDataChannels.size;
|
|
285
|
-
this.numberOfInbundTracks += observedPeerConnection.observedInboundTracks.size;
|
|
286
|
-
this.numberOfOutboundRtpStreams += observedPeerConnection.observedOutboundRtps.size;
|
|
287
|
-
this.numberOfOutboundTracks += observedPeerConnection.observedOutboundTracks.size;
|
|
288
|
-
this.numberOfInboundRtpStreams += observedPeerConnection.observedInboundRtps.size;
|
|
289
|
-
if (observedPeerConnection.currentRttInMs) {
|
|
290
|
-
this.deltaRttInMsMeasurements.push(observedPeerConnection.currentRttInMs);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
resetSummaryMetrics() {
|
|
294
|
-
this.totalDataChannelBytesReceived = 0;
|
|
295
|
-
this.totalDataChannelBytesSent = 0;
|
|
296
|
-
this.totalDataChannelMessagesReceived = 0;
|
|
297
|
-
this.totalDataChannelMessagesSent = 0;
|
|
298
|
-
this.totalInboundPacketsLost = 0;
|
|
299
|
-
this.totalInboundPacketsReceived = 0;
|
|
300
|
-
this.totalOutboundPacketsSent = 0;
|
|
301
|
-
this.totalReceivedAudioBytes = 0;
|
|
302
|
-
this.totalReceivedVideoBytes = 0;
|
|
303
|
-
this.totalSentAudioBytes = 0;
|
|
304
|
-
this.totalSentVideoBytes = 0;
|
|
305
|
-
this.totalSentBytes = 0;
|
|
306
|
-
this.totalReceivedBytes = 0;
|
|
307
|
-
this.numberOfIssues = 0;
|
|
308
|
-
this.totalScoreSum = 0;
|
|
309
|
-
this.numberOfScoreMeasurements = 0;
|
|
479
|
+
return observedPeerConnection;
|
|
310
480
|
}
|
|
311
|
-
|
|
312
|
-
return {
|
|
313
|
-
totalRttLt50Measurements: this.totalRttLt50Measurements,
|
|
314
|
-
totalRttLt150Measurements: this.totalRttLt150Measurements,
|
|
315
|
-
totalRttLt300Measurements: this.totalRttLt300Measurements,
|
|
316
|
-
totalRttGtOrEq300Measurements: this.totalRttGtOrEq300Measurements,
|
|
317
|
-
totalDataChannelBytesReceived: this.totalDataChannelBytesReceived,
|
|
318
|
-
totalDataChannelBytesSent: this.totalDataChannelBytesSent,
|
|
319
|
-
totalDataChannelMessagesReceived: this.totalDataChannelMessagesReceived,
|
|
320
|
-
totalDataChannelMessagesSent: this.totalDataChannelMessagesSent,
|
|
321
|
-
totalInboundPacketsLost: this.totalInboundPacketsLost,
|
|
322
|
-
totalInboundPacketsReceived: this.totalInboundPacketsReceived,
|
|
323
|
-
totalOutboundPacketsSent: this.totalOutboundPacketsSent,
|
|
324
|
-
totalReceivedAudioBytes: this.totalReceivedAudioBytes,
|
|
325
|
-
totalReceivedVideoBytes: this.totalReceivedVideoBytes,
|
|
326
|
-
totalSentAudioBytes: this.totalSentAudioBytes,
|
|
327
|
-
totalSentVideoBytes: this.totalSentVideoBytes,
|
|
328
|
-
totalSentBytes: this.totalSentBytes,
|
|
329
|
-
totalReceivedBytes: this.totalReceivedBytes,
|
|
330
|
-
numberOfIssues: this.numberOfIssues,
|
|
331
|
-
totalScoreSum: this.totalScoreSum,
|
|
332
|
-
numberOfScoreMeasurements: this.numberOfScoreMeasurements,
|
|
333
|
-
};
|
|
481
|
+
createEventMonitor(ctx) {
|
|
482
|
+
return new ObservedClientEventMonitor_1.ObservedClientEventMonitor(this, ctx ?? {});
|
|
334
483
|
}
|
|
335
|
-
|
|
336
|
-
if (this.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
this.currentRttInMs = undefined;
|
|
344
|
-
return;
|
|
484
|
+
_mergeInjections(sample) {
|
|
485
|
+
if (this.closed)
|
|
486
|
+
return sample;
|
|
487
|
+
if (this._injections.clientEvents) {
|
|
488
|
+
if (!sample.clientEvents)
|
|
489
|
+
sample.clientEvents = [];
|
|
490
|
+
sample.clientEvents.push(...this._injections.clientEvents);
|
|
491
|
+
this._injections.clientEvents = undefined;
|
|
345
492
|
}
|
|
346
|
-
if (this.
|
|
347
|
-
|
|
493
|
+
if (this._injections.clientIssues) {
|
|
494
|
+
if (!sample.clientIssues)
|
|
495
|
+
sample.clientIssues = [];
|
|
496
|
+
sample.clientIssues.push(...this._injections.clientIssues);
|
|
497
|
+
this._injections.clientIssues = undefined;
|
|
348
498
|
}
|
|
349
|
-
|
|
350
|
-
|
|
499
|
+
if (this._injections.extensionStats) {
|
|
500
|
+
if (!sample.extensionStats)
|
|
501
|
+
sample.extensionStats = [];
|
|
502
|
+
sample.extensionStats.push(...this._injections.extensionStats);
|
|
503
|
+
this._injections.extensionStats = undefined;
|
|
351
504
|
}
|
|
352
|
-
|
|
353
|
-
|
|
505
|
+
if (this._injections.attachments) {
|
|
506
|
+
if (!sample.attachments)
|
|
507
|
+
sample.attachments = {};
|
|
508
|
+
Object.assign(sample.attachments, this._injections.attachments);
|
|
509
|
+
this._injections.attachments = undefined;
|
|
354
510
|
}
|
|
355
|
-
|
|
356
|
-
|
|
511
|
+
if (this._injections.clientMetaItems) {
|
|
512
|
+
if (!sample.clientMetaItems)
|
|
513
|
+
sample.clientMetaItems = [];
|
|
514
|
+
sample.clientMetaItems.push(...this._injections.clientMetaItems);
|
|
515
|
+
this._injections.clientMetaItems = undefined;
|
|
357
516
|
}
|
|
517
|
+
return sample;
|
|
358
518
|
}
|
|
359
519
|
}
|
|
360
520
|
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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"}
|