@observertc/observer-js 1.0.1-c3edea3.0 → 1.0.1-ec27289.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 +41 -7
- package/lib/ObservedCall.d.ts.map +1 -1
- package/lib/ObservedCall.js +125 -13
- package/lib/ObservedCallSummary.d.ts +18 -0
- package/lib/ObservedCallSummary.d.ts.map +1 -0
- package/lib/ObservedClient.d.ts +70 -11
- package/lib/ObservedClient.d.ts.map +1 -1
- package/lib/ObservedClient.js +394 -72
- package/lib/ObservedClientEventMonitor.d.ts +89 -0
- package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
- package/lib/ObservedClientEventMonitor.js +247 -0
- package/lib/ObservedClientSummary.d.ts +23 -0
- package/lib/ObservedClientSummary.d.ts.map +1 -0
- package/lib/ObservedClientSummary.js +2 -0
- package/lib/ObservedDataChannel.d.ts +6 -0
- package/lib/ObservedDataChannel.d.ts.map +1 -1
- package/lib/ObservedDataChannel.js +30 -0
- package/lib/ObservedIceCandidatePair.d.ts +4 -0
- package/lib/ObservedIceCandidatePair.d.ts.map +1 -1
- package/lib/ObservedIceCandidatePair.js +28 -0
- package/lib/ObservedIceTransport.d.ts +4 -0
- package/lib/ObservedIceTransport.d.ts.map +1 -1
- package/lib/ObservedIceTransport.js +28 -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 +14 -2
- package/lib/ObservedPeerConnection.d.ts.map +1 -1
- package/lib/ObservedPeerConnection.js +106 -14
- package/lib/ObservedTURN.d.ts +31 -0
- package/lib/ObservedTURN.d.ts.map +1 -0
- package/lib/ObservedTURN.js +58 -0
- package/lib/ObservedTurnServer.d.ts +25 -0
- package/lib/ObservedTurnServer.d.ts.map +1 -0
- package/lib/ObservedTurnServer.js +59 -0
- package/lib/Observer.d.ts +38 -21
- package/lib/Observer.d.ts.map +1 -1
- package/lib/Observer.js +114 -40
- package/lib/ObserverSummary.d.ts +13 -0
- package/lib/ObserverSummary.d.ts.map +1 -0
- package/lib/ObserverSummary.js +2 -0
- package/lib/common/utils.d.ts +2 -1
- package/lib/common/utils.d.ts.map +1 -1
- package/lib/common/utils.js +11 -3
- package/lib/index.d.ts +5 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +7 -1
- package/lib/schema/ClientEventTypes.d.ts +100 -0
- package/lib/schema/ClientEventTypes.d.ts.map +1 -0
- package/lib/schema/ClientEventTypes.js +38 -0
- package/lib/schema/{metaTypes.d.ts → ClientMetaTypes.d.ts} +2 -2
- package/lib/schema/ClientMetaTypes.d.ts.map +1 -0
- package/lib/schema/ClientMetaTypes.js +16 -0
- package/lib/updaters/CallUpdater.d.ts.map +1 -0
- package/lib/updaters/CallUpdater.js +2 -0
- package/lib/updaters/ObserverUpdater.d.ts +5 -0
- package/lib/updaters/ObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/ObserverUpdater.js +2 -0
- package/lib/updaters/OnAllCallObserverUpdater_.d.ts +13 -0
- package/lib/updaters/OnAllCallObserverUpdater_.d.ts.map +1 -0
- package/lib/updaters/OnAllCallObserverUpdater_.js +38 -0
- package/lib/updaters/OnAllClientCallUpdater.d.ts +13 -0
- package/lib/updaters/OnAllClientCallUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAllClientCallUpdater.js +37 -0
- package/lib/updaters/OnAnyCallObserverUpdater_.d.ts +11 -0
- package/lib/updaters/OnAnyCallObserverUpdater_.d.ts.map +1 -0
- package/lib/updaters/OnAnyCallObserverUpdater_.js +27 -0
- package/lib/updaters/OnAnyClientCallUpdater.d.ts +11 -0
- package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAnyClientCallUpdater.js +27 -0
- package/lib/updaters/OnIntervalUpdater.d.ts +10 -0
- package/lib/updaters/OnIntervalUpdater.d.ts.map +1 -0
- package/lib/updaters/OnIntervalUpdater.js +17 -0
- package/lib/updaters/Updater.d.ts +6 -0
- package/lib/updaters/Updater.d.ts.map +1 -0
- package/lib/updaters/Updater.js +2 -0
- package/package.json +1 -1
- package/src/ObservedCall.ts +205 -16
- package/src/ObservedCallSummary.ts +22 -0
- package/src/ObservedClient.ts +492 -78
- package/src/ObservedClientEventMonitor.ts +301 -0
- package/src/ObservedClientSummary.ts +24 -0
- package/src/ObservedDataChannel.ts +32 -0
- package/src/ObservedIceCandidatePair.ts +26 -0
- package/src/ObservedIceTransport.ts +29 -0
- package/src/ObservedInboundTrack.ts +3 -0
- package/src/ObservedOutboundTrack.ts +3 -0
- package/src/ObservedPeerConnection.ts +120 -16
- package/src/ObservedTURN.ts +86 -0
- package/src/ObservedTurnServer.ts +72 -0
- package/src/Observer.ts +164 -64
- package/src/ObserverSummary.ts +15 -0
- package/src/common/utils.ts +12 -2
- package/src/index.ts +5 -0
- package/src/schema/ClientEventTypes.ts +112 -0
- package/src/schema/{metaTypes.ts → ClientMetaTypes.ts} +1 -1
- package/src/updaters/ObserverUpdater.ts +5 -0
- package/src/updaters/OnAllCallObserverUpdater_.ts +46 -0
- package/src/updaters/OnAllClientCallUpdater.ts +46 -0
- package/src/updaters/OnAnyCallObserverUpdater_.ts +32 -0
- package/src/updaters/OnAnyClientCallUpdater.ts +32 -0
- package/src/updaters/OnIntervalUpdater.ts +19 -0
- package/src/updaters/Updater.ts +5 -0
- package/tsconfig.json +1 -1
- package/lib/schema/eventTypes.d.ts +0 -33
- package/lib/schema/eventTypes.d.ts.map +0 -1
- package/lib/schema/eventTypes.js +0 -38
- package/lib/schema/metaTypes.d.ts.map +0 -1
- package/lib/schema/metaTypes.js +0 -16
- package/lib/utils/CallUpdater.d.ts.map +0 -1
- package/lib/utils/OnAllClientCallUpdater.d.ts +0 -16
- package/lib/utils/OnAllClientCallUpdater.d.ts.map +0 -1
- package/lib/utils/OnAllClientCallUpdater.js +0 -58
- package/lib/utils/onAnyClientCallUpdater.d.ts +0 -14
- package/lib/utils/onAnyClientCallUpdater.d.ts.map +0 -1
- package/lib/utils/onAnyClientCallUpdater.js +0 -51
- package/src/schema/eventTypes.ts +0 -36
- package/src/utils/OnAllClientCallUpdater.ts +0 -68
- package/src/utils/onAnyClientCallUpdater.ts +0 -59
- /package/lib/{utils/CallUpdater.js → ObservedCallSummary.js} +0 -0
- /package/lib/{utils → updaters}/CallUpdater.d.ts +0 -0
- /package/src/{utils → updaters}/CallUpdater.ts +0 -0
|
@@ -18,6 +18,7 @@ const ObservedRemoteInboundRtp_1 = require("./ObservedRemoteInboundRtp");
|
|
|
18
18
|
const ObservedRemoteOutboundRtp_1 = require("./ObservedRemoteOutboundRtp");
|
|
19
19
|
const ObservedInboundTrack_1 = require("./ObservedInboundTrack");
|
|
20
20
|
const ObservedOutboundTrack_1 = require("./ObservedOutboundTrack");
|
|
21
|
+
const utils_1 = require("./common/utils");
|
|
21
22
|
const logger = (0, logger_1.createLogger)('ObservedPeerConnection');
|
|
22
23
|
class ObservedPeerConnection extends events_1.EventEmitter {
|
|
23
24
|
peerConnectionId;
|
|
@@ -34,11 +35,15 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
34
35
|
// timestamp of the PEER_CONNECTION_CLOSED event
|
|
35
36
|
closedAt;
|
|
36
37
|
updated = Date.now();
|
|
38
|
+
availableIncomingBitrate = 0;
|
|
39
|
+
availableOutgoingBitrate = 0;
|
|
37
40
|
totalInboundPacketsLost = 0;
|
|
38
41
|
totalInboundPacketsReceived = 0;
|
|
39
42
|
totalOutboundPacketsSent = 0;
|
|
40
43
|
totalDataChannelBytesSent = 0;
|
|
41
44
|
totalDataChannelBytesReceived = 0;
|
|
45
|
+
totalDataChannelMessagesSent = 0;
|
|
46
|
+
totalDataChannelMessagesReceived = 0;
|
|
42
47
|
totalSentAudioBytes = 0;
|
|
43
48
|
totalSentVideoBytes = 0;
|
|
44
49
|
totalSentAudioPackets = 0;
|
|
@@ -52,6 +57,8 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
52
57
|
deltaOutboundPacketsSent = 0;
|
|
53
58
|
deltaDataChannelBytesSent = 0;
|
|
54
59
|
deltaDataChannelBytesReceived = 0;
|
|
60
|
+
deltaDataChannelMessagesSent = 0;
|
|
61
|
+
deltaDataChannelMessagesReceived = 0;
|
|
55
62
|
deltaInboundReceivedBytes = 0;
|
|
56
63
|
deltaOutboundSentBytes = 0;
|
|
57
64
|
deltaReceivedAudioBytes = 0;
|
|
@@ -60,16 +67,19 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
60
67
|
deltaReceivedVideoPackets = 0;
|
|
61
68
|
deltaSentAudioBytes = 0;
|
|
62
69
|
deltaSentVideoBytes = 0;
|
|
70
|
+
deltaTransportSentBytes = 0;
|
|
71
|
+
deltaTransportReceivedBytes = 0;
|
|
63
72
|
receivingPacketsPerSecond = 0;
|
|
64
73
|
sendingPacketsPerSecond = 0;
|
|
65
74
|
sendingAudioBitrate = 0;
|
|
66
75
|
sendingVideoBitrate = 0;
|
|
67
76
|
receivingAudioBitrate = 0;
|
|
68
77
|
receivingVideoBitrate = 0;
|
|
69
|
-
|
|
70
|
-
|
|
78
|
+
currentRttInMs;
|
|
79
|
+
currentJitter;
|
|
71
80
|
usingTCP = false;
|
|
72
81
|
usingTURN = false;
|
|
82
|
+
observedTurnServer;
|
|
73
83
|
observedCertificates = new Map();
|
|
74
84
|
observedCodecs = new Map();
|
|
75
85
|
observedDataChannels = new Map();
|
|
@@ -142,6 +152,11 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
142
152
|
return this.iceTransports.map((iceTransport) => iceTransport.getSelectedCandidatePair())
|
|
143
153
|
.filter((pair) => pair !== undefined);
|
|
144
154
|
}
|
|
155
|
+
get selectedIceCandiadtePairForTurn() {
|
|
156
|
+
return this.selectedIceCandidatePairs
|
|
157
|
+
.filter((pair) => pair.getLocalCandidate()?.candidateType === 'relay' &&
|
|
158
|
+
pair.getRemoteCandidate()?.url?.startsWith('turn:'));
|
|
159
|
+
}
|
|
145
160
|
close() {
|
|
146
161
|
if (this.closed)
|
|
147
162
|
return;
|
|
@@ -161,12 +176,17 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
161
176
|
this.observedPeerConnectionTransports.clear();
|
|
162
177
|
this.observedRemoteInboundRtps.clear();
|
|
163
178
|
this.observedRemoteOutboundRtps.clear();
|
|
179
|
+
this.client.call.observer.observedTURN.removePeerConnection(this);
|
|
180
|
+
if (!this.closedAt)
|
|
181
|
+
this.closedAt = Date.now();
|
|
164
182
|
this.emit('close');
|
|
165
183
|
}
|
|
166
184
|
accept(sample) {
|
|
167
185
|
if (this.closed)
|
|
168
186
|
return;
|
|
169
187
|
this._visited = true;
|
|
188
|
+
this.availableIncomingBitrate = 0;
|
|
189
|
+
this.availableOutgoingBitrate = 0;
|
|
170
190
|
this.deltaInboundPacketsLost = 0;
|
|
171
191
|
this.deltaInboundPacketsReceived = 0;
|
|
172
192
|
this.deltaOutboundPacketsSent = 0;
|
|
@@ -180,6 +200,8 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
180
200
|
this.deltaReceivedVideoPackets = 0;
|
|
181
201
|
this.deltaSentAudioBytes = 0;
|
|
182
202
|
this.deltaSentVideoBytes = 0;
|
|
203
|
+
this.deltaTransportReceivedBytes = 0;
|
|
204
|
+
this.deltaTransportSentBytes = 0;
|
|
183
205
|
this.sendingAudioBitrate = 0;
|
|
184
206
|
this.sendingVideoBitrate = 0;
|
|
185
207
|
this.receivingAudioBitrate = 0;
|
|
@@ -187,6 +209,8 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
187
209
|
const now = Date.now();
|
|
188
210
|
const elapsedTimeInMs = now - this.updated;
|
|
189
211
|
const elapsedTimeInSec = elapsedTimeInMs / 1000;
|
|
212
|
+
const rttMeasurementsInSec = [];
|
|
213
|
+
const jitterMeasurements = [];
|
|
190
214
|
if (sample.certificates) {
|
|
191
215
|
for (const certificate of sample.certificates) {
|
|
192
216
|
this._updateCertificateStats(certificate);
|
|
@@ -199,7 +223,13 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
199
223
|
}
|
|
200
224
|
if (sample.dataChannels) {
|
|
201
225
|
for (const dataChannel of sample.dataChannels) {
|
|
202
|
-
this._updateDataChannelStats(dataChannel);
|
|
226
|
+
const observedDataChannel = this._updateDataChannelStats(dataChannel);
|
|
227
|
+
if (!observedDataChannel)
|
|
228
|
+
continue;
|
|
229
|
+
this.deltaDataChannelBytesSent += observedDataChannel.deltaBytesSent;
|
|
230
|
+
this.deltaDataChannelBytesReceived += observedDataChannel.deltaBytesReceived;
|
|
231
|
+
this.deltaDataChannelMessagesSent += observedDataChannel.deltaMessagesSent;
|
|
232
|
+
this.deltaDataChannelMessagesReceived += observedDataChannel.deltaMessagesReceived;
|
|
203
233
|
}
|
|
204
234
|
}
|
|
205
235
|
if (sample.iceCandidates) {
|
|
@@ -209,12 +239,26 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
209
239
|
}
|
|
210
240
|
if (sample.iceCandidatePairs) {
|
|
211
241
|
for (const iceCandidatePair of sample.iceCandidatePairs) {
|
|
212
|
-
this._updateIceCandidatePairStats(iceCandidatePair);
|
|
242
|
+
const observedCandidatePair = this._updateIceCandidatePairStats(iceCandidatePair);
|
|
243
|
+
if (!observedCandidatePair)
|
|
244
|
+
continue;
|
|
245
|
+
if (observedCandidatePair.currentRoundTripTime) {
|
|
246
|
+
rttMeasurementsInSec.push(observedCandidatePair.currentRoundTripTime);
|
|
247
|
+
}
|
|
248
|
+
if (observedCandidatePair.availableIncomingBitrate) {
|
|
249
|
+
this.availableIncomingBitrate += observedCandidatePair.availableIncomingBitrate;
|
|
250
|
+
}
|
|
251
|
+
if (observedCandidatePair.availableOutgoingBitrate) {
|
|
252
|
+
this.availableOutgoingBitrate += observedCandidatePair.availableOutgoingBitrate;
|
|
253
|
+
}
|
|
213
254
|
}
|
|
214
255
|
}
|
|
215
256
|
if (sample.iceTransports) {
|
|
216
257
|
for (const iceTransport of sample.iceTransports) {
|
|
217
|
-
this._updateIceTransportStats(iceTransport);
|
|
258
|
+
const observedIceTransport = this._updateIceTransportStats(iceTransport);
|
|
259
|
+
if (!observedIceTransport)
|
|
260
|
+
return;
|
|
261
|
+
observedIceTransport.bytesReceived;
|
|
218
262
|
}
|
|
219
263
|
}
|
|
220
264
|
if (sample.inboundRtps) {
|
|
@@ -235,6 +279,9 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
235
279
|
this.deltaReceivedVideoPackets += observedInboundRtp.deltaReceivedPackets;
|
|
236
280
|
break;
|
|
237
281
|
}
|
|
282
|
+
if (observedInboundRtp.jitter) {
|
|
283
|
+
jitterMeasurements.push(observedInboundRtp.jitter);
|
|
284
|
+
}
|
|
238
285
|
}
|
|
239
286
|
}
|
|
240
287
|
if (sample.mediaPlayouts) {
|
|
@@ -268,12 +315,19 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
268
315
|
}
|
|
269
316
|
if (sample.peerConnectionTransports) {
|
|
270
317
|
for (const peerConnectionTransport of sample.peerConnectionTransports) {
|
|
271
|
-
this._updatePeerConnectionTransportStats(peerConnectionTransport);
|
|
318
|
+
const observedTransport = this._updatePeerConnectionTransportStats(peerConnectionTransport);
|
|
319
|
+
if (!observedTransport)
|
|
320
|
+
continue;
|
|
272
321
|
}
|
|
273
322
|
}
|
|
274
323
|
if (sample.remoteInboundRtps) {
|
|
275
324
|
for (const remoteInboundRtp of sample.remoteInboundRtps) {
|
|
276
|
-
this._updateRemoteInboundRtpStats(remoteInboundRtp);
|
|
325
|
+
const observedRemoteInboundRtp = this._updateRemoteInboundRtpStats(remoteInboundRtp);
|
|
326
|
+
if (!observedRemoteInboundRtp)
|
|
327
|
+
continue;
|
|
328
|
+
if (observedRemoteInboundRtp.roundTripTime) {
|
|
329
|
+
rttMeasurementsInSec.push(observedRemoteInboundRtp.roundTripTime);
|
|
330
|
+
}
|
|
277
331
|
}
|
|
278
332
|
}
|
|
279
333
|
if (sample.remoteOutboundRtps) {
|
|
@@ -300,6 +354,8 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
300
354
|
this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
|
|
301
355
|
this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
|
|
302
356
|
this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
|
|
357
|
+
this.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
|
|
358
|
+
this.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
|
|
303
359
|
this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
|
|
304
360
|
this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
|
|
305
361
|
this.totalSentAudioBytes += this.deltaSentAudioBytes;
|
|
@@ -310,17 +366,53 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
310
366
|
this.totalSentVideoPackets += this.deltaSentVideoBytes;
|
|
311
367
|
this.receivingPacketsPerSecond = this.deltaInboundPacketsReceived / elapsedTimeInSec;
|
|
312
368
|
this.sendingPacketsPerSecond = this.deltaOutboundPacketsSent / elapsedTimeInSec;
|
|
313
|
-
this.sendingAudioBitrate = this.deltaSentAudioBytes * 8 / elapsedTimeInSec;
|
|
314
|
-
this.sendingVideoBitrate = this.deltaSentVideoBytes * 8 / elapsedTimeInSec;
|
|
315
|
-
this.receivingAudioBitrate = this.deltaReceivedAudioBytes * 8 / elapsedTimeInSec;
|
|
316
|
-
this.receivingVideoBitrate = this.deltaReceivedVideoBytes * 8 / elapsedTimeInSec;
|
|
369
|
+
this.sendingAudioBitrate = (this.deltaSentAudioBytes * 8) / elapsedTimeInSec;
|
|
370
|
+
this.sendingVideoBitrate = (this.deltaSentVideoBytes * 8) / elapsedTimeInSec;
|
|
371
|
+
this.receivingAudioBitrate = (this.deltaReceivedAudioBytes * 8) / elapsedTimeInSec;
|
|
372
|
+
this.receivingVideoBitrate = (this.deltaReceivedVideoBytes * 8) / elapsedTimeInSec;
|
|
373
|
+
if (rttMeasurementsInSec.length > 0) {
|
|
374
|
+
this.currentRttInMs = (0, utils_1.getMedian)(rttMeasurementsInSec, false) * 1000;
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
this.currentRttInMs = undefined;
|
|
378
|
+
}
|
|
379
|
+
if (jitterMeasurements.length > 0) {
|
|
380
|
+
this.currentJitter = (0, utils_1.getMedian)(jitterMeasurements, false);
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
this.currentJitter = undefined;
|
|
384
|
+
}
|
|
385
|
+
const wasUsingTURN = this.usingTURN;
|
|
317
386
|
const selectedIceCandidatePairs = this.selectedIceCandidatePairs;
|
|
318
|
-
|
|
319
|
-
this.
|
|
320
|
-
|
|
387
|
+
const selectedCandidatePairForTurn = [];
|
|
388
|
+
this.usingTCP = false;
|
|
389
|
+
this.usingTURN = false;
|
|
390
|
+
for (const selectedCandidatePair of selectedIceCandidatePairs) {
|
|
391
|
+
if (selectedCandidatePair.getLocalCandidate()?.protocol === 'tcp') {
|
|
392
|
+
this.usingTCP = true;
|
|
393
|
+
}
|
|
394
|
+
if (selectedCandidatePair.getLocalCandidate()?.candidateType === 'relay' && selectedCandidatePair.getRemoteCandidate()?.url?.startsWith('turn:')) {
|
|
395
|
+
selectedCandidatePairForTurn.push(selectedCandidatePair);
|
|
396
|
+
this.usingTURN = true;
|
|
397
|
+
}
|
|
398
|
+
this.deltaTransportReceivedBytes += selectedCandidatePair.deltaBytesReceived;
|
|
399
|
+
this.deltaTransportSentBytes += selectedCandidatePair.deltaBytesSent;
|
|
400
|
+
}
|
|
401
|
+
if (this.usingTURN) {
|
|
402
|
+
if (!this.observedTurnServer) {
|
|
403
|
+
this.observedTurnServer = this.client.call.observer.observedTURN.addPeerConnection(this);
|
|
404
|
+
}
|
|
405
|
+
this.observedTurnServer?.updateTurnUsage(...selectedCandidatePairForTurn);
|
|
406
|
+
}
|
|
407
|
+
else if (wasUsingTURN) {
|
|
408
|
+
if (!this.usingTURN) {
|
|
409
|
+
this.client.call.observer.observedTURN.removePeerConnection(this);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
321
412
|
this.calculatedScore.value = sample.score;
|
|
322
413
|
this.updated = now;
|
|
323
414
|
this._checkVisited();
|
|
415
|
+
this.emit('update');
|
|
324
416
|
}
|
|
325
417
|
_checkVisited() {
|
|
326
418
|
for (const certificate of [...this.observedCertificates.values()]) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { EventEmitter } from 'stream';
|
|
3
|
+
import { ObservedPeerConnection } from './ObservedPeerConnection';
|
|
4
|
+
import { ObservedTurnServer } from './ObservedTurnServer';
|
|
5
|
+
export type ObservedTURNEventMap = {
|
|
6
|
+
'update': [ObservedTURN];
|
|
7
|
+
'close': [];
|
|
8
|
+
};
|
|
9
|
+
export declare interface ObservedTURN {
|
|
10
|
+
on<U extends keyof ObservedTURNEventMap>(event: U, listener: (...args: ObservedTURNEventMap[U]) => void): this;
|
|
11
|
+
off<U extends keyof ObservedTURNEventMap>(event: U, listener: (...args: ObservedTURNEventMap[U]) => void): this;
|
|
12
|
+
once<U extends keyof ObservedTURNEventMap>(event: U, listener: (...args: ObservedTURNEventMap[U]) => void): this;
|
|
13
|
+
emit<U extends keyof ObservedTURNEventMap>(event: U, ...args: ObservedTURNEventMap[U]): boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare class ObservedTURN extends EventEmitter {
|
|
16
|
+
totalBytesSent: number;
|
|
17
|
+
totalBytesReceived: number;
|
|
18
|
+
totalPacketsSent: number;
|
|
19
|
+
totalPacketsReceived: number;
|
|
20
|
+
packetsSentPerSecond: number;
|
|
21
|
+
packetsReceivedPerSecond: number;
|
|
22
|
+
outboundBitrate: number;
|
|
23
|
+
inboundBitrate: number;
|
|
24
|
+
numberOfClients: number;
|
|
25
|
+
readonly servers: Map<string, ObservedTurnServer>;
|
|
26
|
+
constructor();
|
|
27
|
+
update(): void;
|
|
28
|
+
addPeerConnection(peerConnection: ObservedPeerConnection): ObservedTurnServer | undefined;
|
|
29
|
+
removePeerConnection(peerConnection: ObservedPeerConnection): void;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ObservedTURN.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObservedTURN.d.ts","sourceRoot":"","sources":["../src/ObservedTURN.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAK1D,MAAM,MAAM,oBAAoB,GAAG;IAClC,QAAQ,EAAE,CAAC,YAAY,CAAC,CAAC;IACzB,OAAO,EAAE,EAAE,CAAC;CACZ,CAAA;AAED,MAAM,CAAC,OAAO,WAAW,YAAY;IACpC,EAAE,CAAC,CAAC,SAAS,MAAM,oBAAoB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAC/G,GAAG,CAAC,CAAC,SAAS,MAAM,oBAAoB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAChH,IAAI,CAAC,CAAC,SAAS,MAAM,oBAAoB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACjH,IAAI,CAAC,CAAC,SAAS,MAAM,oBAAoB,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CAChG;AAED,qBAAa,YAAa,SAAQ,YAAY;IACtC,cAAc,SAAK;IACnB,kBAAkB,SAAK;IACvB,gBAAgB,SAAK;IACrB,oBAAoB,SAAK;IAEzB,oBAAoB,SAAK;IACzB,wBAAwB,SAAK;IAC7B,eAAe,SAAK;IACpB,cAAc,SAAK;IACnB,eAAe,SAAK;IAE3B,SAAgB,OAAO,kCAAyC;;IAOzD,MAAM;IAgBN,iBAAiB,CAAC,cAAc,EAAE,sBAAsB;IAyBxD,oBAAoB,CAAC,cAAc,EAAE,sBAAsB;CAMlE"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ObservedTURN = void 0;
|
|
4
|
+
const stream_1 = require("stream");
|
|
5
|
+
const ObservedTurnServer_1 = require("./ObservedTurnServer");
|
|
6
|
+
const logger_1 = require("./common/logger");
|
|
7
|
+
const logger = (0, logger_1.createLogger)('ObservedTURN');
|
|
8
|
+
class ObservedTURN extends stream_1.EventEmitter {
|
|
9
|
+
totalBytesSent = 0;
|
|
10
|
+
totalBytesReceived = 0;
|
|
11
|
+
totalPacketsSent = 0;
|
|
12
|
+
totalPacketsReceived = 0;
|
|
13
|
+
packetsSentPerSecond = 0;
|
|
14
|
+
packetsReceivedPerSecond = 0;
|
|
15
|
+
outboundBitrate = 0;
|
|
16
|
+
inboundBitrate = 0;
|
|
17
|
+
numberOfClients = 0;
|
|
18
|
+
servers = new Map();
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
}
|
|
22
|
+
update() {
|
|
23
|
+
const clientIds = new Set();
|
|
24
|
+
this.packetsReceivedPerSecond = 0;
|
|
25
|
+
this.packetsSentPerSecond = 0;
|
|
26
|
+
this.outboundBitrate = 0;
|
|
27
|
+
this.inboundBitrate = 0;
|
|
28
|
+
for (const server of this.servers.values()) {
|
|
29
|
+
server.update();
|
|
30
|
+
server.observedPeerConnections.forEach((pc) => clientIds.add(pc.client.clientId));
|
|
31
|
+
}
|
|
32
|
+
this.numberOfClients = clientIds.size;
|
|
33
|
+
}
|
|
34
|
+
addPeerConnection(peerConnection) {
|
|
35
|
+
const turnPairs = peerConnection.selectedIceCandidatePairs.filter((pair) => pair.getLocalCandidate()?.candidateType === 'relay' && pair.getRemoteCandidate()?.url?.startsWith('turn:'));
|
|
36
|
+
if (turnPairs.length !== 1) {
|
|
37
|
+
return (logger.warn(`Expected exactly one TURN pair, but found for peerconnection ${peerConnection.peerConnectionId}`, turnPairs.length), undefined);
|
|
38
|
+
}
|
|
39
|
+
const candidatePair = turnPairs[0];
|
|
40
|
+
const rawUrl = candidatePair.getRemoteCandidate()?.url;
|
|
41
|
+
if (!rawUrl) {
|
|
42
|
+
return (logger.warn(`No remote candidate URL found for peerconnection ${peerConnection.peerConnectionId}`), undefined);
|
|
43
|
+
}
|
|
44
|
+
const turnUrl = new URL(rawUrl);
|
|
45
|
+
const turnServerUrl = `${turnUrl.protocol}//${turnUrl.hostname}:${turnUrl.port}`;
|
|
46
|
+
let turnServer = this.servers.get(turnServerUrl);
|
|
47
|
+
if (!turnServer) {
|
|
48
|
+
turnServer = new ObservedTurnServer_1.ObservedTurnServer(turnServerUrl, this);
|
|
49
|
+
}
|
|
50
|
+
return turnServer;
|
|
51
|
+
}
|
|
52
|
+
removePeerConnection(peerConnection) {
|
|
53
|
+
for (const turnServer of this.servers.values()) {
|
|
54
|
+
turnServer.observedPeerConnections.delete(peerConnection.peerConnectionId);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.ObservedTURN = ObservedTURN;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ObservedIceCandidatePair } from './ObservedIceCandidatePair';
|
|
2
|
+
import { ObservedPeerConnection } from './ObservedPeerConnection';
|
|
3
|
+
import { ObservedTURN } from './ObservedTURN';
|
|
4
|
+
export declare class ObservedTurnServer {
|
|
5
|
+
readonly url: string;
|
|
6
|
+
readonly observedTURN: ObservedTURN;
|
|
7
|
+
totalBytesSent: number;
|
|
8
|
+
totalBytesReceived: number;
|
|
9
|
+
totalPacketsSent: number;
|
|
10
|
+
totalPacketsReceived: number;
|
|
11
|
+
packetsSentPerSecond: number;
|
|
12
|
+
packetsReceivedPerSecond: number;
|
|
13
|
+
outboundBitrate: number;
|
|
14
|
+
inboundBitrate: number;
|
|
15
|
+
deltaBytesSent: number;
|
|
16
|
+
deltaBytesReceived: number;
|
|
17
|
+
deltaPacketsSent: number;
|
|
18
|
+
deltaPacketsReceived: number;
|
|
19
|
+
readonly observedPeerConnections: Map<string, ObservedPeerConnection>;
|
|
20
|
+
updated: number;
|
|
21
|
+
constructor(url: string, observedTURN: ObservedTURN);
|
|
22
|
+
updateTurnUsage(...selectedcandidatepairs: ObservedIceCandidatePair[]): void;
|
|
23
|
+
update(): void;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=ObservedTurnServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObservedTurnServer.d.ts","sourceRoot":"","sources":["../src/ObservedTurnServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,qBAAa,kBAAkB;aAqBb,GAAG,EAAE,MAAM;aACX,YAAY,EAAE,YAAY;IArBpC,cAAc,SAAK;IACnB,kBAAkB,SAAK;IACvB,gBAAgB,SAAK;IACrB,oBAAoB,SAAK;IAEzB,oBAAoB,SAAK;IACzB,wBAAwB,SAAK;IAC7B,eAAe,SAAK;IACpB,cAAc,SAAK;IAEnB,cAAc,SAAK;IACnB,kBAAkB,SAAK;IACvB,gBAAgB,SAAK;IACrB,oBAAoB,SAAK;IAEhC,SAAgB,uBAAuB,sCAA6C;IAE7E,OAAO,SAAc;gBAGX,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,YAAY;IAKpC,eAAe,CAAC,GAAG,sBAAsB,EAAE,wBAAwB,EAAE;IASrE,MAAM;CA+Bb"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ObservedTurnServer = void 0;
|
|
4
|
+
class ObservedTurnServer {
|
|
5
|
+
url;
|
|
6
|
+
observedTURN;
|
|
7
|
+
totalBytesSent = 0;
|
|
8
|
+
totalBytesReceived = 0;
|
|
9
|
+
totalPacketsSent = 0;
|
|
10
|
+
totalPacketsReceived = 0;
|
|
11
|
+
packetsSentPerSecond = 0;
|
|
12
|
+
packetsReceivedPerSecond = 0;
|
|
13
|
+
outboundBitrate = 0;
|
|
14
|
+
inboundBitrate = 0;
|
|
15
|
+
deltaBytesSent = 0;
|
|
16
|
+
deltaBytesReceived = 0;
|
|
17
|
+
deltaPacketsSent = 0;
|
|
18
|
+
deltaPacketsReceived = 0;
|
|
19
|
+
observedPeerConnections = new Map();
|
|
20
|
+
updated = Date.now();
|
|
21
|
+
constructor(url, observedTURN) {
|
|
22
|
+
this.url = url;
|
|
23
|
+
this.observedTURN = observedTURN;
|
|
24
|
+
}
|
|
25
|
+
updateTurnUsage(...selectedcandidatepairs) {
|
|
26
|
+
for (const selectedcandidatepair of selectedcandidatepairs) {
|
|
27
|
+
this.deltaBytesReceived += selectedcandidatepair.deltaBytesReceived;
|
|
28
|
+
this.deltaBytesSent += selectedcandidatepair.deltaBytesSent;
|
|
29
|
+
this.deltaPacketsReceived += selectedcandidatepair.deltaPacketsReceived;
|
|
30
|
+
this.deltaPacketsSent += selectedcandidatepair.deltaPacketsSent;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
update() {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
const deltaInS = (now - this.updated) / 1000;
|
|
36
|
+
this.packetsSentPerSecond = this.deltaPacketsSent / deltaInS;
|
|
37
|
+
this.packetsReceivedPerSecond = this.deltaPacketsReceived / deltaInS;
|
|
38
|
+
this.outboundBitrate = (this.deltaBytesReceived * 8) / deltaInS;
|
|
39
|
+
this.inboundBitrate = (this.deltaBytesSent * 8) / deltaInS;
|
|
40
|
+
this.totalBytesSent += this.deltaBytesSent;
|
|
41
|
+
this.totalBytesReceived += this.deltaBytesReceived;
|
|
42
|
+
this.totalPacketsSent += this.deltaPacketsSent;
|
|
43
|
+
this.totalPacketsReceived += this.deltaPacketsReceived;
|
|
44
|
+
this.observedTURN.totalBytesSent += this.deltaBytesSent;
|
|
45
|
+
this.observedTURN.totalBytesReceived += this.deltaBytesReceived;
|
|
46
|
+
this.observedTURN.totalPacketsSent += this.deltaPacketsSent;
|
|
47
|
+
this.observedTURN.totalPacketsReceived += this.deltaPacketsReceived;
|
|
48
|
+
this.observedTURN.inboundBitrate += this.inboundBitrate;
|
|
49
|
+
this.observedTURN.outboundBitrate += this.outboundBitrate;
|
|
50
|
+
this.observedTURN.packetsReceivedPerSecond += this.packetsReceivedPerSecond;
|
|
51
|
+
this.observedTURN.packetsSentPerSecond += this.packetsSentPerSecond;
|
|
52
|
+
this.deltaBytesSent = 0;
|
|
53
|
+
this.deltaBytesReceived = 0;
|
|
54
|
+
this.deltaPacketsSent = 0;
|
|
55
|
+
this.deltaPacketsReceived = 0;
|
|
56
|
+
this.updated = now;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.ObservedTurnServer = ObservedTurnServer;
|
package/lib/Observer.d.ts
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { Middleware, MiddlewareProcessor } from './common/Middleware';
|
|
3
2
|
import { ObservedCall, ObservedCallSettings } from './ObservedCall';
|
|
4
3
|
import { EventEmitter } from 'events';
|
|
5
|
-
import { ClientEvent, ClientMetaData, ClientIssue, ExtensionStat } from './schema/ClientSample';
|
|
4
|
+
import { ClientEvent, ClientMetaData, ClientIssue, ExtensionStat, ClientSample } from './schema/ClientSample';
|
|
6
5
|
import { ObservedClient } from './ObservedClient';
|
|
6
|
+
import { ObservedTURN } from './ObservedTURN';
|
|
7
|
+
import { Detectors } from './detectors/Detectors';
|
|
8
|
+
import { Updater } from './updaters/Updater';
|
|
7
9
|
export type ObserverEvents = {
|
|
10
|
+
'client-event': [ObservedClient, ClientEvent];
|
|
11
|
+
'call-updated': [ObservedCall];
|
|
12
|
+
'client-issue': [ObservedClient, ClientIssue];
|
|
13
|
+
'client-metadata': [ObservedClient, ClientMetaData];
|
|
14
|
+
'client-extension-stats': [ObservedClient, ExtensionStat];
|
|
8
15
|
'newcall': [ObservedCall];
|
|
16
|
+
'update': [];
|
|
9
17
|
'close': [];
|
|
10
18
|
};
|
|
11
|
-
export type
|
|
12
|
-
call
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
export type ObserverConfig = {
|
|
20
|
+
updatePolicy?: 'update-on-any-call-updated' | 'update-when-all-call-updated' | 'update-on-interval';
|
|
21
|
+
updateIntervalInMs?: number;
|
|
22
|
+
defaultCallUpdatePolicy?: ObservedCallSettings['updatePolicy'];
|
|
23
|
+
defaultCallUpdateIntervalInMs?: number;
|
|
15
24
|
};
|
|
16
25
|
export declare interface Observer {
|
|
17
26
|
on<U extends keyof ObserverEvents>(event: U, listener: (...args: ObserverEvents[U]) => void): this;
|
|
@@ -20,25 +29,33 @@ export declare interface Observer {
|
|
|
20
29
|
emit<U extends keyof ObserverEvents>(event: U, ...args: ObserverEvents[U]): boolean;
|
|
21
30
|
}
|
|
22
31
|
export declare class Observer extends EventEmitter {
|
|
23
|
-
readonly
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
issues: MiddlewareProcessor<ProcessorInputContext<ClientIssue>>;
|
|
27
|
-
extensionStats: MiddlewareProcessor<ProcessorInputContext<ExtensionStat>>;
|
|
28
|
-
};
|
|
32
|
+
readonly config: ObserverConfig;
|
|
33
|
+
readonly detectors: Detectors;
|
|
34
|
+
readonly observedTURN: ObservedTURN;
|
|
29
35
|
readonly observedCalls: Map<string, ObservedCall<Record<string, unknown>>>;
|
|
36
|
+
updater?: Updater;
|
|
30
37
|
closed: boolean;
|
|
31
|
-
|
|
38
|
+
totalAddedCall: number;
|
|
39
|
+
totalRemovedCall: number;
|
|
40
|
+
totalRttLt50Measurements: number;
|
|
41
|
+
totalRttLt150Measurements: number;
|
|
42
|
+
totalRttLt300Measurements: number;
|
|
43
|
+
totalRttGtOrEq300Measurements: number;
|
|
44
|
+
totalClientIssues: number;
|
|
45
|
+
numberOfClientsUsingTurn: number;
|
|
46
|
+
numberOfClients: number;
|
|
47
|
+
numberOfInboundRtpStreams: number;
|
|
48
|
+
numberOfOutboundRtpStreams: number;
|
|
49
|
+
numberOfDataChannels: number;
|
|
50
|
+
numberOfPeerConnections: number;
|
|
51
|
+
get numberOfCalls(): number;
|
|
52
|
+
private _timer?;
|
|
53
|
+
constructor(config?: ObserverConfig);
|
|
32
54
|
getObservedCall<T extends Record<string, unknown> = Record<string, unknown>>(callId: string): ObservedCall<T> | undefined;
|
|
33
55
|
createObservedCall<T extends Record<string, unknown> = Record<string, unknown>>(settings: ObservedCallSettings<T>): ObservedCall<T>;
|
|
34
|
-
addClientEventMiddleware(...middlewares: Middleware<ProcessorInputContext<ClientEvent>>[]): Observer;
|
|
35
|
-
removeClientEventMiddleware(...middlewares: Middleware<ProcessorInputContext<ClientEvent>>[]): Observer;
|
|
36
|
-
addClientMetaDataMiddleware(...middlewares: Middleware<ProcessorInputContext<ClientMetaData>>[]): Observer;
|
|
37
|
-
removeClientMetaDataMiddleware(...middlewares: Middleware<ProcessorInputContext<ClientMetaData>>[]): Observer;
|
|
38
|
-
addClientIssueMiddleware(...middlewares: Middleware<ProcessorInputContext<ClientIssue>>[]): Observer;
|
|
39
|
-
removeClientIssueMiddleware(...middlewares: Middleware<ProcessorInputContext<ClientIssue>>[]): Observer;
|
|
40
|
-
addExtensionStatMiddleware(...middlewares: Middleware<ProcessorInputContext<ExtensionStat>>[]): Observer;
|
|
41
|
-
removeExtensionStatMiddleware(...middlewares: Middleware<ProcessorInputContext<ExtensionStat>>[]): Observer;
|
|
42
56
|
close(): void;
|
|
57
|
+
accept(sample: ClientSample): void;
|
|
58
|
+
update(): void;
|
|
59
|
+
private _onObservedCallUpdated;
|
|
43
60
|
}
|
|
44
61
|
//# sourceMappingURL=Observer.d.ts.map
|
package/lib/Observer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Observer.d.ts","sourceRoot":"","sources":["../src/Observer.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"Observer.d.ts","sourceRoot":"","sources":["../src/Observer.ts"],"names":[],"mappings":"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"}
|