@observertc/observer-js 1.0.1-c3edea3.0 → 1.0.1-c9e7581.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 +43 -7
- package/lib/ObservedCall.d.ts.map +1 -1
- package/lib/ObservedCall.js +142 -14
- package/lib/ObservedCallEventMonitor.d.ts +104 -0
- package/lib/ObservedCallEventMonitor.d.ts.map +1 -0
- package/lib/ObservedCallEventMonitor.js +314 -0
- package/lib/ObservedCallSummary.d.ts +18 -0
- package/lib/ObservedCallSummary.d.ts.map +1 -0
- package/lib/ObservedClient.d.ts +71 -11
- package/lib/ObservedClient.d.ts.map +1 -1
- package/lib/ObservedClient.js +509 -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 +6 -1
- package/lib/ObservedIceCandidatePair.d.ts.map +1 -1
- package/lib/ObservedIceCandidatePair.js +45 -1
- 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 +3 -0
- package/lib/ObservedInboundTrack.d.ts.map +1 -1
- package/lib/ObservedInboundTrack.js +3 -0
- package/lib/ObservedOutboundTrack.d.ts +3 -0
- package/lib/ObservedOutboundTrack.d.ts.map +1 -1
- package/lib/ObservedOutboundTrack.js +3 -0
- package/lib/ObservedPeerConnection.d.ts +36 -2
- package/lib/ObservedPeerConnection.d.ts.map +1 -1
- package/lib/ObservedPeerConnection.js +184 -29
- 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 +43 -22
- package/lib/Observer.d.ts.map +1 -1
- package/lib/Observer.js +126 -40
- package/lib/ObserverEventMonitor.d.ts +138 -0
- package/lib/ObserverEventMonitor.d.ts.map +1 -0
- package/lib/ObserverEventMonitor.js +433 -0
- 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 +6 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +9 -1
- package/lib/schema/ClientEventTypes.d.ts +228 -0
- package/lib/schema/ClientEventTypes.d.ts.map +1 -0
- package/lib/schema/ClientEventTypes.js +41 -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/schema/ClientSample.d.ts +1 -1
- package/lib/schema/ClientSample.d.ts.map +1 -1
- 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 +15 -0
- package/lib/updaters/OnAllCallObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAllCallObserverUpdater.js +50 -0
- package/lib/updaters/OnAllClientCallUpdater.d.ts +15 -0
- package/lib/updaters/OnAllClientCallUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAllClientCallUpdater.js +53 -0
- package/lib/updaters/OnAnyCallObserverUpdater.d.ts +12 -0
- package/lib/updaters/OnAnyCallObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAnyCallObserverUpdater.js +37 -0
- package/lib/updaters/OnAnyClientCallUpdater.d.ts +12 -0
- package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAnyClientCallUpdater.js +36 -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/lib/utils/MediasoupRemoteTrackResolver.d.ts +25 -0
- package/lib/utils/MediasoupRemoteTrackResolver.d.ts.map +1 -0
- package/lib/utils/MediasoupRemoteTrackResolver.js +110 -0
- package/package.json +1 -1
- package/src/ObservedCall.ts +222 -17
- package/src/ObservedCallEventMonitor.ts +392 -0
- package/src/ObservedCallSummary.ts +22 -0
- package/src/ObservedClient.ts +608 -79
- package/src/ObservedClientEventMonitor.ts +301 -0
- package/src/ObservedClientSummary.ts +24 -0
- package/src/ObservedDataChannel.ts +32 -0
- package/src/ObservedIceCandidatePair.ts +44 -2
- package/src/ObservedIceTransport.ts +29 -0
- package/src/ObservedInboundTrack.ts +5 -0
- package/src/ObservedOutboundTrack.ts +5 -0
- package/src/ObservedPeerConnection.ts +219 -46
- package/src/ObservedTURN.ts +86 -0
- package/src/ObservedTurnServer.ts +72 -0
- package/src/Observer.ts +179 -64
- package/src/ObserverEventMonitor.ts +551 -0
- package/src/ObserverSummary.ts +15 -0
- package/src/common/utils.ts +12 -2
- package/src/index.ts +6 -1
- package/src/schema/ClientEventTypes.ts +280 -0
- package/src/schema/{metaTypes.ts → ClientMetaTypes.ts} +1 -1
- package/src/schema/ClientSample.ts +1 -1
- package/src/updaters/ObserverUpdater.ts +5 -0
- package/src/updaters/OnAllCallObserverUpdater.ts +59 -0
- package/src/updaters/OnAllClientCallUpdater.ts +61 -0
- package/src/updaters/OnAnyCallObserverUpdater.ts +41 -0
- package/src/updaters/OnAnyClientCallUpdater.ts +39 -0
- package/src/updaters/OnIntervalUpdater.ts +19 -0
- package/src/updaters/Updater.ts +5 -0
- package/src/utils/MediasoupRemoteTrackResolver.ts +155 -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
package/src/ObservedClient.ts
CHANGED
|
@@ -3,10 +3,10 @@ import { ObservedPeerConnection } from './ObservedPeerConnection';
|
|
|
3
3
|
import { createLogger } from './common/logger';
|
|
4
4
|
// eslint-disable-next-line camelcase
|
|
5
5
|
import { ClientEvent, ClientMetaData, ClientSample, PeerConnectionSample, ClientIssue, ExtensionStat } from './schema/ClientSample';
|
|
6
|
-
import * as MetaData from './schema/
|
|
7
|
-
import {
|
|
6
|
+
import * as MetaData from './schema/ClientMetaTypes';
|
|
7
|
+
import { ClientEventTypes } from './schema/ClientEventTypes';
|
|
8
8
|
import { ObservedCall } from './ObservedCall';
|
|
9
|
-
import {
|
|
9
|
+
import { ClientMetaTypes } from './schema/ClientMetaTypes';
|
|
10
10
|
import { parseJsonAs } from './common/utils';
|
|
11
11
|
import { CalculatedScore } from './scores/CalculatedScore';
|
|
12
12
|
import { Detectors } from './detectors/Detectors';
|
|
@@ -27,12 +27,15 @@ export type ObservedClientEvents = {
|
|
|
27
27
|
];
|
|
28
28
|
close: [];
|
|
29
29
|
joined: [];
|
|
30
|
+
issue: [ClientIssue];
|
|
31
|
+
metaData: [ClientMetaData];
|
|
30
32
|
rejoined: [timestamp: number];
|
|
31
33
|
left: [];
|
|
32
34
|
usingturn: [boolean];
|
|
33
35
|
usermediaerror: [string];
|
|
36
|
+
extensionStats: [ExtensionStat];
|
|
37
|
+
clientEvent: [ClientEvent];
|
|
34
38
|
|
|
35
|
-
// do we need this?
|
|
36
39
|
newpeerconnection: [ObservedPeerConnection];
|
|
37
40
|
};
|
|
38
41
|
|
|
@@ -53,7 +56,7 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
53
56
|
value: undefined,
|
|
54
57
|
};
|
|
55
58
|
|
|
56
|
-
public appData
|
|
59
|
+
public appData: AppData;
|
|
57
60
|
public attachments?: Record<string, unknown>;
|
|
58
61
|
|
|
59
62
|
public updated = Date.now();
|
|
@@ -62,6 +65,8 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
62
65
|
|
|
63
66
|
public joinedAt?: number;
|
|
64
67
|
public leftAt?: number;
|
|
68
|
+
public closedAt?: number;
|
|
69
|
+
public lastSampleTimestamp?: number;
|
|
65
70
|
// the timestamp of the CLIENT_JOINED event
|
|
66
71
|
public operationSystem?: MetaData.OperationSystem;
|
|
67
72
|
public engine?: MetaData.Engine;
|
|
@@ -70,47 +75,85 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
70
75
|
public mediaConstraints: string[] = [];
|
|
71
76
|
|
|
72
77
|
public usingTURN = false;
|
|
78
|
+
public usingTCP = false;
|
|
73
79
|
public availableOutgoingBitrate = 0;
|
|
74
80
|
public availableIncomingBitrate = 0;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
public
|
|
98
|
-
public
|
|
99
|
-
public
|
|
100
|
-
public
|
|
101
|
-
public
|
|
81
|
+
|
|
82
|
+
public totalInboundPacketsLost = 0;
|
|
83
|
+
public totalInboundPacketsReceived = 0;
|
|
84
|
+
public totalOutboundPacketsSent = 0;
|
|
85
|
+
public totalDataChannelBytesSent = 0;
|
|
86
|
+
public totalDataChannelBytesReceived = 0;
|
|
87
|
+
public totalDataChannelMessagesSent = 0;
|
|
88
|
+
public totalDataChannelMessagesReceived = 0;
|
|
89
|
+
public totalReceivedAudioBytes = 0;
|
|
90
|
+
public totalReceivedVideoBytes = 0;
|
|
91
|
+
public totalSentAudioBytes = 0;
|
|
92
|
+
public totalSentVideoBytes = 0;
|
|
93
|
+
public totalSentBytes = 0;
|
|
94
|
+
public totalReceivedBytes = 0;
|
|
95
|
+
|
|
96
|
+
public deltaReceivedAudioBytes = 0;
|
|
97
|
+
public deltaReceivedVideoBytes = 0;
|
|
98
|
+
public deltaSentAudioBytes = 0;
|
|
99
|
+
public deltaSentVideoBytes = 0;
|
|
100
|
+
public deltaDataChannelBytesSent = 0;
|
|
101
|
+
public deltaDataChannelBytesReceived = 0;
|
|
102
|
+
public deltaDataChannelMessagesSent = 0;
|
|
103
|
+
public deltaDataChannelMessagesReceived = 0;
|
|
104
|
+
public deltaInboundPacketsLost = 0;
|
|
105
|
+
public deltaInboundPacketsReceived = 0;
|
|
106
|
+
public deltaOutboundPacketsSent = 0;
|
|
107
|
+
public deltaTransportSentBytes = 0;
|
|
108
|
+
public deltaTransportReceivedBytes = 0;
|
|
109
|
+
public deltaRttLt50Measurements = 0;
|
|
110
|
+
public deltaRttLt150Measurements = 0;
|
|
111
|
+
public deltaRttLt300Measurements = 0;
|
|
112
|
+
public deltaRttGtOrEq300Measurements = 0;
|
|
113
|
+
|
|
114
|
+
public currentMaxRttInMs?: number;
|
|
115
|
+
public currentMinRttInMs?: number;
|
|
116
|
+
public currentAvgRttInMs?: number;
|
|
117
|
+
|
|
118
|
+
public sendingAudioBitrate = 0;
|
|
119
|
+
public sendingVideoBitrate = 0;
|
|
120
|
+
public receivingAudioBitrate = 0;
|
|
121
|
+
public receivingVideoBitrate = 0;
|
|
122
|
+
|
|
123
|
+
public numberOfInboundRtpStreams = 0;
|
|
124
|
+
public numberOfInbundTracks = 0;
|
|
125
|
+
public numberOfOutboundRtpStreams = 0;
|
|
126
|
+
public numberOfOutboundTracks = 0;
|
|
127
|
+
public numberOfDataChannels = 0;
|
|
128
|
+
|
|
129
|
+
public totalRttLt50Measurements = 0;
|
|
130
|
+
public totalRttLt150Measurements = 0;
|
|
131
|
+
public totalRttLt300Measurements = 0;
|
|
132
|
+
public totalRttGtOrEq300Measurements = 0;
|
|
133
|
+
public deltaNumberOfIssues = 0;
|
|
134
|
+
|
|
135
|
+
public totalScoreSum = 0;
|
|
136
|
+
public numberOfScoreMeasurements = 0;
|
|
137
|
+
public totalNumberOfIssues = 0;
|
|
102
138
|
|
|
103
139
|
public readonly mediaDevices: MetaData.MediaDeviceInfo[] = [];
|
|
104
140
|
public issues: ClientIssue[] = [];
|
|
105
141
|
|
|
142
|
+
private _injections: Pick<ClientSample, 'clientEvents' | 'clientIssues' | 'extensionStats' | 'attachments' | 'clientMetaItems'> = {};
|
|
143
|
+
|
|
106
144
|
public constructor(settings: ObservedClientSettings<AppData>, public readonly call: ObservedCall) {
|
|
107
145
|
super();
|
|
108
146
|
this.setMaxListeners(Infinity);
|
|
109
147
|
|
|
110
148
|
this.clientId = settings.clientId;
|
|
111
|
-
this.appData = settings.appData;
|
|
149
|
+
this.appData = settings.appData ?? {} as AppData;
|
|
150
|
+
|
|
112
151
|
this.detectors = new Detectors();
|
|
113
152
|
}
|
|
153
|
+
|
|
154
|
+
public get numberOfPeerConnections() {
|
|
155
|
+
return this.observedPeerConnections.size;
|
|
156
|
+
}
|
|
114
157
|
|
|
115
158
|
public get score() {
|
|
116
159
|
return this.calculatedScore.value;
|
|
@@ -121,6 +164,14 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
121
164
|
this.closed = true;
|
|
122
165
|
|
|
123
166
|
Array.from(this.observedPeerConnections.values()).forEach((peerConnection) => peerConnection.close());
|
|
167
|
+
if (!this.leftAt) {
|
|
168
|
+
this.leftAt = this.lastSampleTimestamp;
|
|
169
|
+
|
|
170
|
+
if (this.leftAt) {
|
|
171
|
+
this.emit('left');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
this.closedAt = Date.now();
|
|
124
175
|
|
|
125
176
|
this.emit('close');
|
|
126
177
|
}
|
|
@@ -129,38 +180,180 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
129
180
|
if (this.closed) throw new Error(`Client ${this.clientId} is closed`);
|
|
130
181
|
|
|
131
182
|
const now = Date.now();
|
|
183
|
+
const elapsedInMs = now - this.updated;
|
|
184
|
+
const elapsedInSeconds = elapsedInMs / 1000;
|
|
185
|
+
let sumOfRtts = 0;
|
|
186
|
+
let numberOfRttMeasurements = 0;
|
|
187
|
+
|
|
188
|
+
++this.acceptedSamples;
|
|
189
|
+
|
|
190
|
+
this.availableIncomingBitrate = 0;
|
|
191
|
+
this.availableOutgoingBitrate = 0;
|
|
192
|
+
this.deltaDataChannelBytesReceived = 0;
|
|
193
|
+
this.deltaDataChannelBytesSent = 0;
|
|
194
|
+
this.deltaDataChannelMessagesReceived = 0;
|
|
195
|
+
this.deltaDataChannelMessagesSent = 0;
|
|
196
|
+
this.deltaInboundPacketsLost = 0;
|
|
197
|
+
this.deltaInboundPacketsReceived = 0;
|
|
198
|
+
this.deltaOutboundPacketsSent = 0;
|
|
199
|
+
this.deltaReceivedAudioBytes = 0;
|
|
200
|
+
this.deltaReceivedVideoBytes = 0;
|
|
201
|
+
this.deltaSentAudioBytes = 0;
|
|
202
|
+
this.deltaSentVideoBytes = 0;
|
|
203
|
+
this.deltaTransportReceivedBytes = 0;
|
|
204
|
+
this.deltaTransportSentBytes = 0;
|
|
205
|
+
this.deltaRttLt50Measurements = 0;
|
|
206
|
+
this.deltaRttLt150Measurements = 0;
|
|
207
|
+
this.deltaRttLt300Measurements = 0;
|
|
208
|
+
this.deltaRttGtOrEq300Measurements = 0;
|
|
209
|
+
this.deltaNumberOfIssues = 0;
|
|
210
|
+
|
|
211
|
+
this.numberOfDataChannels = 0;
|
|
212
|
+
this.numberOfInboundRtpStreams = 0;
|
|
213
|
+
this.numberOfInbundTracks = 0;
|
|
214
|
+
this.numberOfOutboundRtpStreams = 0;
|
|
215
|
+
this.numberOfOutboundTracks = 0;
|
|
216
|
+
this.usingTURN = false;
|
|
217
|
+
this.usingTCP = false;
|
|
218
|
+
this.currentMinRttInMs = undefined;
|
|
219
|
+
this.currentMaxRttInMs = undefined;
|
|
220
|
+
|
|
221
|
+
this._mergeInjections(sample);
|
|
222
|
+
|
|
223
|
+
const clientEventsPostBuffer: ClientEvent[] = [];
|
|
224
|
+
|
|
225
|
+
for (const clientEvent of sample.clientEvents ?? []) {
|
|
226
|
+
this._processClientEvent(clientEvent, clientEventsPostBuffer);
|
|
227
|
+
|
|
228
|
+
this.call.observer.emit('client-event', this, clientEvent);
|
|
229
|
+
}
|
|
132
230
|
|
|
133
|
-
sample.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
sample.
|
|
231
|
+
for (const metaData of sample.clientMetaItems ?? []) {
|
|
232
|
+
this.addMetadata(metaData);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
for (const issue of sample.clientIssues ?? []) {
|
|
236
|
+
this.addIssue(issue);
|
|
237
|
+
|
|
238
|
+
++this.deltaNumberOfIssues;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
for (const extensionStat of sample.extensionStats ?? []) {
|
|
242
|
+
this.addExtensionStats(extensionStat);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
for (const pcSample of sample.peerConnections ?? []) {
|
|
246
|
+
const observedPeerConnection = this._updatePeerConnection(pcSample);
|
|
247
|
+
|
|
248
|
+
if (!observedPeerConnection) continue;
|
|
249
|
+
|
|
250
|
+
this.deltaDataChannelBytesReceived += observedPeerConnection.deltaDataChannelBytesReceived;
|
|
251
|
+
this.deltaDataChannelBytesSent += observedPeerConnection.deltaDataChannelBytesSent;
|
|
252
|
+
this.deltaDataChannelMessagesReceived += observedPeerConnection.deltaDataChannelMessagesReceived;
|
|
253
|
+
this.deltaDataChannelMessagesSent += observedPeerConnection.deltaDataChannelMessagesSent;
|
|
254
|
+
this.deltaInboundPacketsLost += observedPeerConnection.deltaInboundPacketsLost;
|
|
255
|
+
this.deltaInboundPacketsReceived += observedPeerConnection.deltaInboundPacketsReceived;
|
|
256
|
+
this.deltaOutboundPacketsSent += observedPeerConnection.deltaOutboundPacketsSent;
|
|
257
|
+
this.deltaReceivedAudioBytes += observedPeerConnection.deltaReceivedAudioBytes;
|
|
258
|
+
this.deltaReceivedVideoBytes += observedPeerConnection.deltaReceivedVideoBytes;
|
|
259
|
+
this.deltaSentAudioBytes += observedPeerConnection.deltaSentAudioBytes;
|
|
260
|
+
this.deltaSentVideoBytes += observedPeerConnection.deltaSentVideoBytes;
|
|
261
|
+
this.deltaTransportReceivedBytes += observedPeerConnection.deltaTransportReceivedBytes;
|
|
262
|
+
this.deltaTransportSentBytes += observedPeerConnection.deltaTransportSentBytes;
|
|
263
|
+
|
|
264
|
+
this.availableIncomingBitrate += observedPeerConnection.availableIncomingBitrate;
|
|
265
|
+
this.availableOutgoingBitrate += observedPeerConnection.availableOutgoingBitrate;
|
|
266
|
+
|
|
267
|
+
this.numberOfDataChannels += observedPeerConnection.observedDataChannels.size;
|
|
268
|
+
this.numberOfInbundTracks += observedPeerConnection.observedInboundTracks.size;
|
|
269
|
+
this.numberOfOutboundRtpStreams += observedPeerConnection.observedOutboundRtps.size;
|
|
270
|
+
this.numberOfOutboundTracks += observedPeerConnection.observedOutboundTracks.size;
|
|
271
|
+
this.numberOfInboundRtpStreams += observedPeerConnection.observedInboundRtps.size;
|
|
272
|
+
|
|
273
|
+
if (observedPeerConnection.usingTURN) {
|
|
274
|
+
this.usingTURN = true;
|
|
275
|
+
}
|
|
276
|
+
if (observedPeerConnection.usingTCP) {
|
|
277
|
+
this.usingTCP = true;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (observedPeerConnection.currentRttInMs) {
|
|
281
|
+
if (this.currentMinRttInMs === undefined || observedPeerConnection.currentRttInMs < this.currentMinRttInMs) {
|
|
282
|
+
this.currentMinRttInMs = observedPeerConnection.currentRttInMs;
|
|
283
|
+
}
|
|
284
|
+
if (this.currentMaxRttInMs === undefined || observedPeerConnection.currentRttInMs > this.currentMaxRttInMs) {
|
|
285
|
+
this.currentMaxRttInMs = observedPeerConnection.currentRttInMs;
|
|
286
|
+
}
|
|
287
|
+
if (observedPeerConnection.currentRttInMs < 50) {
|
|
288
|
+
this.deltaRttLt50Measurements += 1;
|
|
289
|
+
} else if (observedPeerConnection.currentRttInMs < 150) {
|
|
290
|
+
this.deltaRttLt150Measurements += 1;
|
|
291
|
+
} else if (observedPeerConnection.currentRttInMs < 300) {
|
|
292
|
+
this.deltaRttLt300Measurements += 1;
|
|
293
|
+
} else if (300 <= observedPeerConnection.currentRttInMs) {
|
|
294
|
+
this.deltaRttGtOrEq300Measurements += 1;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
sumOfRtts += observedPeerConnection.currentRttInMs;
|
|
298
|
+
++numberOfRttMeasurements;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
for (const clientEvent of clientEventsPostBuffer) {
|
|
303
|
+
this._processClientEvent(clientEvent);
|
|
304
|
+
}
|
|
138
305
|
|
|
139
306
|
// emit new attachments?
|
|
140
307
|
this.attachments = sample.attachments;
|
|
141
308
|
|
|
309
|
+
this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
|
|
310
|
+
this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
|
|
311
|
+
this.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
|
|
312
|
+
this.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
|
|
313
|
+
this.totalInboundPacketsLost += this.deltaInboundPacketsLost;
|
|
314
|
+
this.totalInboundPacketsReceived += this.deltaInboundPacketsReceived;
|
|
315
|
+
this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
|
|
316
|
+
this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
|
|
317
|
+
this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
|
|
318
|
+
this.totalSentAudioBytes += this.deltaSentAudioBytes;
|
|
319
|
+
this.totalSentVideoBytes += this.deltaSentVideoBytes;
|
|
320
|
+
this.totalReceivedBytes += this.deltaTransportReceivedBytes;
|
|
321
|
+
this.totalSentBytes += this.deltaTransportSentBytes;
|
|
322
|
+
this.totalRttLt50Measurements += this.deltaRttLt50Measurements;
|
|
323
|
+
this.totalRttLt150Measurements += this.deltaRttLt150Measurements;
|
|
324
|
+
this.totalRttLt300Measurements += this.deltaRttLt300Measurements;
|
|
325
|
+
this.totalRttGtOrEq300Measurements += this.deltaRttGtOrEq300Measurements;
|
|
326
|
+
this.totalNumberOfIssues += this.deltaNumberOfIssues;
|
|
327
|
+
|
|
328
|
+
this.receivingAudioBitrate = (this.deltaReceivedAudioBytes * 8) / (elapsedInSeconds);
|
|
329
|
+
this.receivingVideoBitrate = (this.totalReceivedVideoBytes * 8) / (elapsedInSeconds);
|
|
330
|
+
this.sendingAudioBitrate = (this.deltaSentAudioBytes * 8) / (elapsedInSeconds);
|
|
331
|
+
this.sendingVideoBitrate = (this.deltaSentVideoBytes * 8) / (elapsedInSeconds);
|
|
332
|
+
this.currentAvgRttInMs = 0 < numberOfRttMeasurements ? sumOfRtts / numberOfRttMeasurements : undefined;
|
|
333
|
+
|
|
142
334
|
this.calculatedScore.value = sample.score;
|
|
143
335
|
this.detectors.update();
|
|
144
336
|
|
|
337
|
+
this.lastSampleTimestamp = sample.timestamp;
|
|
145
338
|
// emit update
|
|
146
339
|
this.emit('update', {
|
|
147
340
|
sample,
|
|
148
341
|
elapsedTimeInMs: now - this.updated,
|
|
149
342
|
});
|
|
150
343
|
this.updated = now;
|
|
344
|
+
|
|
345
|
+
// if result changed after update
|
|
346
|
+
if (this.calculatedScore.value) {
|
|
347
|
+
this.totalScoreSum += this.calculatedScore.value;
|
|
348
|
+
++this.numberOfScoreMeasurements;
|
|
349
|
+
}
|
|
151
350
|
}
|
|
152
351
|
|
|
153
|
-
private _processClientEvent(event: ClientEvent) {
|
|
352
|
+
private _processClientEvent(event: ClientEvent, postBuffer?: ClientEvent[]) {
|
|
353
|
+
// eslint-disable-next-line no-console
|
|
354
|
+
// console.warn('ClientEvent', event);
|
|
154
355
|
switch (event.type) {
|
|
155
|
-
case
|
|
156
|
-
// update call timestamp if it's the first time
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
case ClientEventType.CALL_ENDED: {
|
|
160
|
-
// update call timestamp if it's the first time
|
|
161
|
-
break;
|
|
162
|
-
}
|
|
163
|
-
case ClientEventType.CLIENT_JOINED: {
|
|
356
|
+
case ClientEventTypes.CLIENT_JOINED: {
|
|
164
357
|
if (event.timestamp) {
|
|
165
358
|
if (!this.joinedAt) {
|
|
166
359
|
this.joinedAt = event.timestamp;
|
|
@@ -172,78 +365,321 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
172
365
|
logger.warn(`Client ${this.clientId} joinedAt timestamp was updated to ${event.timestamp}. the joined event will not be emitted.`);
|
|
173
366
|
}
|
|
174
367
|
}
|
|
368
|
+
logger.debug('Client %s joined at %o', this.clientId, event);
|
|
175
369
|
break;
|
|
176
370
|
}
|
|
177
|
-
case
|
|
371
|
+
case ClientEventTypes.CLIENT_LEFT: {
|
|
178
372
|
if (event.timestamp) {
|
|
179
373
|
if (!this.leftAt) {
|
|
180
374
|
this.leftAt = event.timestamp;
|
|
181
375
|
this.emit('left');
|
|
376
|
+
} else {
|
|
377
|
+
logger.warn(`Client ${this.clientId} leftAt timestamp was already set`);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
}
|
|
381
|
+
logger.debug('Client %s left at %o', this.clientId, event);
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
case ClientEventTypes.PEER_CONNECTION_OPENED: {
|
|
385
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
386
|
+
|
|
387
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
|
|
388
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
389
|
+
|
|
390
|
+
if (observedPeerConnection) {
|
|
391
|
+
observedPeerConnection.openedAt = event.timestamp;
|
|
392
|
+
} else if (postBuffer) {
|
|
393
|
+
postBuffer.push(event);
|
|
394
|
+
} else {
|
|
395
|
+
logger.warn('Received PEER_CONNECTION_OPENED event without a corresponding observedPeerConnection: %o', event);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
}
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
case ClientEventTypes.PEER_CONNECTION_CLOSED: {
|
|
402
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
403
|
+
|
|
404
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
|
|
405
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
406
|
+
|
|
407
|
+
if (observedPeerConnection) {
|
|
408
|
+
observedPeerConnection.closedAt = event.timestamp;
|
|
409
|
+
} else if (postBuffer) {
|
|
410
|
+
postBuffer.push(event);
|
|
411
|
+
} else {
|
|
412
|
+
logger.warn('Received PEER_CONNECTION_CLOSED event without a corresponding observedPeerConnection: %o', event);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
case ClientEventTypes.MEDIA_TRACK_ADDED: {
|
|
418
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
419
|
+
|
|
420
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
|
|
421
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
422
|
+
const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
423
|
+
|
|
424
|
+
if (observedTrack) {
|
|
425
|
+
observedTrack.addedAt = event.timestamp;
|
|
426
|
+
} else if (postBuffer) {
|
|
427
|
+
postBuffer.push(event);
|
|
428
|
+
} else {
|
|
429
|
+
logger.warn('Received MEDIA_TRACK_ADDED event without a corresponding observedPeerConnection or observedTrack: %o', event);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
case ClientEventTypes.MEDIA_TRACK_REMOVED: {
|
|
435
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
436
|
+
|
|
437
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
|
|
438
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
439
|
+
const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
440
|
+
|
|
441
|
+
if (observedTrack) {
|
|
442
|
+
observedTrack.removedAt = event.timestamp;
|
|
443
|
+
} else if (postBuffer) {
|
|
444
|
+
postBuffer.push(event);
|
|
445
|
+
} else {
|
|
446
|
+
logger.warn('Received MEDIA_TRACK_REMOVED event without a corresponding observedPeerConnection or observedTrack: %o', event);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
case ClientEventTypes.DATA_CHANNEL_OPEN: {
|
|
452
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
453
|
+
|
|
454
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
|
|
455
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
456
|
+
const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
|
|
457
|
+
|
|
458
|
+
if (observedDataChannel) {
|
|
459
|
+
observedDataChannel.addedAt = event.timestamp;
|
|
460
|
+
} else if (postBuffer) {
|
|
461
|
+
postBuffer.push(event);
|
|
462
|
+
} else {
|
|
463
|
+
logger.warn('Received DATA_CHANNEL_OPENED event without a corresponding observedPeerConnection or observedDataChannel: %o', event);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
break;
|
|
467
|
+
}
|
|
468
|
+
case ClientEventTypes.DATA_CHANNEL_CLOSED: {
|
|
469
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
470
|
+
|
|
471
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
|
|
472
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
473
|
+
const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
|
|
474
|
+
|
|
475
|
+
if (observedDataChannel) {
|
|
476
|
+
observedDataChannel.removedAt = event.timestamp;
|
|
477
|
+
} else if (postBuffer) {
|
|
478
|
+
postBuffer.push(event);
|
|
479
|
+
} else {
|
|
480
|
+
logger.warn('Received DATA_CHANNEL_CLOSE event without a corresponding observedPeerConnection or observedDataChannel: %o', event);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
case ClientEventTypes.MEDIA_TRACK_MUTED: {
|
|
486
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
487
|
+
|
|
488
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
|
|
489
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
490
|
+
const observedInboundTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId);
|
|
491
|
+
const observedOutboundTrack = observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
492
|
+
|
|
493
|
+
if (observedPeerConnection) {
|
|
494
|
+
if (observedInboundTrack) {
|
|
495
|
+
observedInboundTrack.muted = true;
|
|
496
|
+
observedPeerConnection?.emit('muted-inbound-track', observedInboundTrack);
|
|
497
|
+
} else if (observedOutboundTrack) {
|
|
498
|
+
observedOutboundTrack.muted = true;
|
|
499
|
+
observedPeerConnection?.emit('muted-outbound-track', observedOutboundTrack);
|
|
500
|
+
}
|
|
501
|
+
} else if (postBuffer) {
|
|
502
|
+
postBuffer.push(event);
|
|
503
|
+
} else {
|
|
504
|
+
logger.warn('Received MEDIA_TRACK_MUTED event without a corresponding observedPeerConnection or observedTrack: %o', event);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
case ClientEventTypes.MEDIA_TRACK_UNMUTED: {
|
|
511
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
512
|
+
|
|
513
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
|
|
514
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
515
|
+
const observedInboundTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId);
|
|
516
|
+
const observedOutboundTrack = observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
517
|
+
|
|
518
|
+
if (observedPeerConnection) {
|
|
519
|
+
if (observedInboundTrack) {
|
|
520
|
+
observedInboundTrack.muted = false;
|
|
521
|
+
observedPeerConnection?.emit('unmuted-inbound-track', observedInboundTrack);
|
|
522
|
+
} else if (observedOutboundTrack) {
|
|
523
|
+
observedOutboundTrack.muted = false;
|
|
524
|
+
observedPeerConnection?.emit('unmuted-outbound-track', observedOutboundTrack);
|
|
525
|
+
}
|
|
526
|
+
} else if (postBuffer) {
|
|
527
|
+
postBuffer.push(event);
|
|
528
|
+
} else {
|
|
529
|
+
logger.warn('Received MEDIA_TRACK_UNMUTED event without a corresponding observedPeerConnection or observedTrack: %o', event);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
case ClientEventTypes.ICE_CONNECTION_STATE_CHANGED: {
|
|
535
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
536
|
+
|
|
537
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.iceConnectionState && typeof payload.iceConnectionState === 'string') {
|
|
538
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
539
|
+
|
|
540
|
+
if (observedPeerConnection) {
|
|
541
|
+
observedPeerConnection.iceConnectionState = payload.iceConnectionState;
|
|
542
|
+
observedPeerConnection.emit('iceconnectionstatechange', {
|
|
543
|
+
state: payload.iceConnectionState,
|
|
544
|
+
});
|
|
545
|
+
} else if (postBuffer) {
|
|
546
|
+
postBuffer.push(event);
|
|
547
|
+
} else {
|
|
548
|
+
logger.warn('Received ICE_CONNECTION_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
553
|
+
case ClientEventTypes.ICE_GATHERING_STATE_CHANGED: {
|
|
554
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
555
|
+
|
|
556
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.iceGatheringState && typeof payload.iceGatheringState === 'string') {
|
|
557
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
558
|
+
|
|
559
|
+
if (observedPeerConnection) {
|
|
560
|
+
observedPeerConnection.iceGatheringState = payload.iceGatheringState;
|
|
561
|
+
observedPeerConnection.emit('icegatheringstatechange', {
|
|
562
|
+
state: payload.iceGatheringState,
|
|
563
|
+
});
|
|
564
|
+
} else if (postBuffer) {
|
|
565
|
+
postBuffer.push(event);
|
|
566
|
+
} else {
|
|
567
|
+
logger.warn('Received ICE_GATHERING_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
break;
|
|
571
|
+
}
|
|
572
|
+
case ClientEventTypes.PEER_CONNECTION_STATE_CHANGED: {
|
|
573
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
574
|
+
|
|
575
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.peerConnectionState && typeof payload.peerConnectionState === 'string') {
|
|
576
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
577
|
+
|
|
578
|
+
if (observedPeerConnection) {
|
|
579
|
+
observedPeerConnection.connectionState = payload.peerConnectionState;
|
|
580
|
+
observedPeerConnection.emit('connectionstatechange', {
|
|
581
|
+
state: payload.peerConnectionState,
|
|
582
|
+
});
|
|
583
|
+
} else if (postBuffer) {
|
|
584
|
+
postBuffer.push(event);
|
|
585
|
+
} else {
|
|
586
|
+
logger.warn('Received PEER_CONNECTION_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
|
|
182
587
|
}
|
|
183
588
|
}
|
|
184
589
|
break;
|
|
185
590
|
}
|
|
186
591
|
}
|
|
592
|
+
|
|
593
|
+
this.emit('clientEvent', event);
|
|
594
|
+
}
|
|
187
595
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
596
|
+
public injectMetaData(metaData: ClientMetaData) {
|
|
597
|
+
if (this.closed) return;
|
|
598
|
+
|
|
599
|
+
if (!this._injections.clientMetaItems) this._injections.clientMetaItems = [];
|
|
600
|
+
|
|
601
|
+
this._injections.clientMetaItems.push(metaData);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
public injectEvent(event: ClientEvent) {
|
|
605
|
+
if (this.closed) return;
|
|
606
|
+
|
|
607
|
+
if (!this._injections.clientEvents) this._injections.clientEvents = [];
|
|
608
|
+
|
|
609
|
+
this._injections.clientEvents.push(event);
|
|
193
610
|
}
|
|
194
611
|
|
|
195
|
-
public
|
|
612
|
+
public injectIssue(issue: ClientIssue) {
|
|
613
|
+
if (this.closed) return;
|
|
614
|
+
|
|
615
|
+
if (!this._injections.clientIssues) this._injections.clientIssues = [];
|
|
616
|
+
|
|
617
|
+
this._injections.clientIssues.push(issue);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
public injectExtensionStat(stat: ExtensionStat) {
|
|
621
|
+
if (this.closed) return;
|
|
622
|
+
|
|
623
|
+
if (!this._injections.extensionStats) this._injections.extensionStats = [];
|
|
624
|
+
|
|
625
|
+
this._injections.extensionStats.push(stat);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
public injectAttachment(key: string, value: unknown) {
|
|
629
|
+
if (this.closed) return;
|
|
630
|
+
|
|
631
|
+
if (!this._injections.attachments) this._injections.attachments = {};
|
|
632
|
+
|
|
633
|
+
this._injections.attachments[key] = value;
|
|
634
|
+
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
public addMetadata(metadata: ClientMetaData) {
|
|
638
|
+
if (this.closed) return;
|
|
639
|
+
|
|
196
640
|
switch (metadata.type) {
|
|
197
|
-
case
|
|
641
|
+
case ClientMetaTypes.BROWSER: {
|
|
198
642
|
this.browser = parseJsonAs(metadata.payload);
|
|
199
643
|
break;
|
|
200
644
|
}
|
|
201
|
-
case
|
|
645
|
+
case ClientMetaTypes.ENGINE: {
|
|
202
646
|
this.engine = parseJsonAs(metadata.payload);
|
|
203
647
|
break;
|
|
204
648
|
}
|
|
205
|
-
case
|
|
649
|
+
case ClientMetaTypes.PLATFORM: {
|
|
206
650
|
this.platform = parseJsonAs(metadata.payload);
|
|
207
651
|
break;
|
|
208
652
|
}
|
|
209
|
-
case
|
|
653
|
+
case ClientMetaTypes.OPERATION_SYSTEM: {
|
|
210
654
|
this.operationSystem = parseJsonAs(metadata.payload);
|
|
211
655
|
break;
|
|
212
656
|
}
|
|
213
657
|
}
|
|
214
658
|
|
|
215
|
-
this.call.observer.
|
|
216
|
-
call: this.call,
|
|
217
|
-
client: this,
|
|
218
|
-
data: metadata,
|
|
219
|
-
});
|
|
659
|
+
this.call.observer.emit('client-metadata', this, metadata);
|
|
220
660
|
}
|
|
221
661
|
|
|
222
|
-
public
|
|
223
|
-
this.
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
});
|
|
662
|
+
public addIssue(issue: ClientIssue) {
|
|
663
|
+
if (this.closed) return;
|
|
664
|
+
|
|
665
|
+
this.emit('issue', issue);
|
|
666
|
+
this.call.observer.emit('client-issue', this, issue);
|
|
228
667
|
}
|
|
229
668
|
|
|
230
|
-
public
|
|
231
|
-
this.call.observer.
|
|
232
|
-
|
|
233
|
-
client: this,
|
|
234
|
-
data: stats,
|
|
235
|
-
});
|
|
669
|
+
public addExtensionStats(stats: ExtensionStat) {
|
|
670
|
+
this.call.observer.emit('client-extension-stats', this, stats);
|
|
671
|
+
this.emit('extensionStats', stats);
|
|
236
672
|
}
|
|
237
673
|
|
|
238
|
-
private _updatePeerConnection(sample: PeerConnectionSample) {
|
|
674
|
+
private _updatePeerConnection(sample: PeerConnectionSample): ObservedPeerConnection | undefined {
|
|
239
675
|
let observedPeerConnection = this.observedPeerConnections.get(sample.peerConnectionId);
|
|
240
676
|
|
|
241
677
|
if (!observedPeerConnection) {
|
|
242
678
|
if (!sample.peerConnectionId) {
|
|
243
|
-
return logger.warn(
|
|
679
|
+
return (logger.warn(
|
|
244
680
|
`ObservedClient received an invalid PeerConnectionSample (missing peerConnectionId field). ClientId: ${this.clientId}, CallId: ${this.call.callId}`,
|
|
245
681
|
sample
|
|
246
|
-
);
|
|
682
|
+
), void 0);
|
|
247
683
|
}
|
|
248
684
|
|
|
249
685
|
observedPeerConnection = new ObservedPeerConnection(sample.peerConnectionId, this);
|
|
@@ -252,8 +688,101 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
252
688
|
this.observedPeerConnections.delete(sample.peerConnectionId);
|
|
253
689
|
});
|
|
254
690
|
this.observedPeerConnections.set(sample.peerConnectionId, observedPeerConnection);
|
|
691
|
+
|
|
692
|
+
this.emit('newpeerconnection', observedPeerConnection);
|
|
255
693
|
}
|
|
256
694
|
|
|
257
695
|
observedPeerConnection.accept(sample);
|
|
696
|
+
|
|
697
|
+
return observedPeerConnection;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
private _mergeInjections(sample: ClientSample): ClientSample {
|
|
701
|
+
if (this.closed) return sample;
|
|
702
|
+
|
|
703
|
+
if (this._injections.clientEvents) {
|
|
704
|
+
if (!sample.clientEvents) sample.clientEvents = [];
|
|
705
|
+
sample.clientEvents.push(...this._injections.clientEvents);
|
|
706
|
+
|
|
707
|
+
this._injections.clientEvents = undefined;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
if (this._injections.clientIssues) {
|
|
711
|
+
if (!sample.clientIssues) sample.clientIssues = [];
|
|
712
|
+
sample.clientIssues.push(...this._injections.clientIssues);
|
|
713
|
+
|
|
714
|
+
this._injections.clientIssues = undefined;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
if (this._injections.extensionStats) {
|
|
718
|
+
if (!sample.extensionStats) sample.extensionStats = [];
|
|
719
|
+
sample.extensionStats.push(...this._injections.extensionStats);
|
|
720
|
+
|
|
721
|
+
this._injections.extensionStats = undefined;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
if (this._injections.attachments) {
|
|
725
|
+
if (!sample.attachments) sample.attachments = {};
|
|
726
|
+
Object.assign(sample.attachments, this._injections.attachments);
|
|
727
|
+
|
|
728
|
+
this._injections.attachments = undefined;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (this._injections.clientMetaItems) {
|
|
732
|
+
if (!sample.clientMetaItems) sample.clientMetaItems = [];
|
|
733
|
+
sample.clientMetaItems.push(...this._injections.clientMetaItems);
|
|
734
|
+
|
|
735
|
+
this._injections.clientMetaItems = undefined;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
return sample;
|
|
258
739
|
}
|
|
740
|
+
|
|
741
|
+
// public resetSummaryMetrics() {
|
|
742
|
+
// this.totalDataChannelBytesReceived = 0;
|
|
743
|
+
// this.totalDataChannelBytesSent = 0;
|
|
744
|
+
// this.totalDataChannelMessagesReceived = 0;
|
|
745
|
+
// this.totalDataChannelMessagesSent = 0;
|
|
746
|
+
// this.totalInboundPacketsLost = 0;
|
|
747
|
+
// this.totalInboundPacketsReceived = 0;
|
|
748
|
+
// this.totalOutboundPacketsSent = 0;
|
|
749
|
+
// this.totalReceivedAudioBytes = 0;
|
|
750
|
+
// this.totalReceivedVideoBytes = 0;
|
|
751
|
+
// this.totalSentAudioBytes = 0;
|
|
752
|
+
// this.totalSentVideoBytes = 0;
|
|
753
|
+
// this.totalSentBytes = 0;
|
|
754
|
+
// this.totalReceivedBytes = 0;
|
|
755
|
+
|
|
756
|
+
// this.totalNumberOfIssues = 0;
|
|
757
|
+
|
|
758
|
+
// this.totalScoreSum = 0;
|
|
759
|
+
// this.numberOfScoreMeasurements = 0;
|
|
760
|
+
// }
|
|
761
|
+
|
|
762
|
+
// public createSummary(): ObservedClientSummary {
|
|
763
|
+
// return {
|
|
764
|
+
// totalRttLt50Measurements: this.totalRttLt50Measurements,
|
|
765
|
+
// totalRttLt150Measurements: this.totalRttLt150Measurements,
|
|
766
|
+
// totalRttLt300Measurements: this.totalRttLt300Measurements,
|
|
767
|
+
// totalRttGtOrEq300Measurements: this.totalRttGtOrEq300Measurements,
|
|
768
|
+
// totalDataChannelBytesReceived: this.totalDataChannelBytesReceived,
|
|
769
|
+
// totalDataChannelBytesSent: this.totalDataChannelBytesSent,
|
|
770
|
+
// totalDataChannelMessagesReceived: this.totalDataChannelMessagesReceived,
|
|
771
|
+
// totalDataChannelMessagesSent: this.totalDataChannelMessagesSent,
|
|
772
|
+
// totalInboundPacketsLost: this.totalInboundPacketsLost,
|
|
773
|
+
// totalInboundPacketsReceived: this.totalInboundPacketsReceived,
|
|
774
|
+
// totalOutboundPacketsSent: this.totalOutboundPacketsSent,
|
|
775
|
+
// totalReceivedAudioBytes: this.totalReceivedAudioBytes,
|
|
776
|
+
// totalReceivedVideoBytes: this.totalReceivedVideoBytes,
|
|
777
|
+
// totalSentAudioBytes: this.totalSentAudioBytes,
|
|
778
|
+
// totalSentVideoBytes: this.totalSentVideoBytes,
|
|
779
|
+
// totalSentBytes: this.totalSentBytes,
|
|
780
|
+
// totalReceivedBytes: this.totalReceivedBytes,
|
|
781
|
+
|
|
782
|
+
// numberOfIssues: this.totalNumberOfIssues,
|
|
783
|
+
|
|
784
|
+
// totalScoreSum: this.totalScoreSum,
|
|
785
|
+
// numberOfScoreMeasurements: this.numberOfScoreMeasurements,
|
|
786
|
+
// };
|
|
787
|
+
// }
|
|
259
788
|
}
|