@observertc/observer-js 1.0.1-9d3744d.0 → 1.0.1-a6fb9d3.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/README.md +535 -1
- package/lib/ObservedCall.d.ts +8 -7
- package/lib/ObservedCall.d.ts.map +1 -1
- package/lib/ObservedCall.js +42 -38
- package/lib/ObservedCallEventMonitor.d.ts +104 -0
- package/lib/ObservedCallEventMonitor.d.ts.map +1 -0
- package/lib/ObservedCallEventMonitor.js +314 -0
- package/lib/ObservedClient.d.ts +20 -10
- package/lib/ObservedClient.d.ts.map +1 -1
- package/lib/ObservedClient.js +330 -13
- package/lib/ObservedClientEventMonitor.d.ts +91 -0
- package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
- package/lib/ObservedClientEventMonitor.js +254 -0
- package/lib/ObservedTURN.d.ts +1 -1
- package/lib/ObservedTURN.d.ts.map +1 -1
- package/lib/ObservedTURN.js +1 -0
- package/lib/ObservedTurnServer.d.ts +2 -2
- package/lib/ObservedTurnServer.d.ts.map +1 -1
- package/lib/Observer.d.ts +9 -6
- package/lib/Observer.d.ts.map +1 -1
- package/lib/Observer.js +26 -25
- package/lib/ObserverEventMonitor.d.ts +138 -0
- package/lib/ObserverEventMonitor.d.ts.map +1 -0
- package/lib/ObserverEventMonitor.js +433 -0
- package/lib/common/ObserverSummary.d.ts.map +1 -0
- package/lib/common/SummaryTypes.d.ts +75 -0
- package/lib/common/SummaryTypes.d.ts.map +1 -0
- package/lib/common/SummaryTypes.js +2 -0
- package/lib/index.d.ts +19 -17
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +21 -17
- package/lib/mediasoup/ObservedMediasoupRouter.d.ts +7 -0
- package/lib/mediasoup/ObservedMediasoupRouter.d.ts.map +1 -0
- package/lib/mediasoup/ObservedMediasoupRouter.js +12 -0
- package/lib/monitors/SummaryMonitor.d.ts +19 -0
- package/lib/monitors/SummaryMonitor.d.ts.map +1 -0
- package/lib/monitors/SummaryMonitor.js +129 -0
- package/lib/schema/ClientEventTypes.d.ts +147 -19
- package/lib/schema/ClientEventTypes.d.ts.map +1 -1
- package/lib/schema/ClientEventTypes.js +5 -2
- package/lib/schema/ClientSample.d.ts +1 -1
- package/lib/schema/ClientSample.d.ts.map +1 -1
- package/lib/updaters/{OnAllCallObserverUpdater_.d.ts → OnAllCallObserverUpdater.d.ts} +3 -1
- package/lib/updaters/OnAllCallObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/{OnAllCallObserverUpdater_.js → OnAllCallObserverUpdater.js} +13 -1
- package/lib/updaters/OnAllClientCallUpdater.d.ts +2 -0
- package/lib/updaters/OnAllClientCallUpdater.d.ts.map +1 -1
- package/lib/updaters/OnAllClientCallUpdater.js +16 -0
- package/lib/updaters/{OnAnyCallObserverUpdater_.d.ts → OnAnyCallObserverUpdater.d.ts} +2 -1
- package/lib/updaters/OnAnyCallObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/{OnAnyCallObserverUpdater_.js → OnAnyCallObserverUpdater.js} +11 -1
- package/lib/updaters/OnAnyClientCallUpdater.d.ts +1 -0
- package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +1 -1
- package/lib/updaters/OnAnyClientCallUpdater.js +11 -2
- 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/lib/utils/RemoteTrackResolver.d.ts +2 -2
- package/lib/utils/RemoteTrackResolver.d.ts.map +1 -1
- package/lib/{ObservedCertificate.d.ts → webrtc/ObservedCertificate.d.ts} +1 -1
- package/lib/webrtc/ObservedCertificate.d.ts.map +1 -0
- package/lib/{ObservedCodec.d.ts → webrtc/ObservedCodec.d.ts} +1 -1
- package/lib/webrtc/ObservedCodec.d.ts.map +1 -0
- package/lib/{ObservedDataChannel.d.ts → webrtc/ObservedDataChannel.d.ts} +3 -1
- package/lib/webrtc/ObservedDataChannel.d.ts.map +1 -0
- package/lib/{ObservedDataChannel.js → webrtc/ObservedDataChannel.js} +2 -0
- package/lib/{ObservedIceCandidate.d.ts → webrtc/ObservedIceCandidate.d.ts} +1 -1
- package/lib/webrtc/ObservedIceCandidate.d.ts.map +1 -0
- package/lib/{ObservedIceCandidatePair.d.ts → webrtc/ObservedIceCandidatePair.d.ts} +3 -2
- package/lib/webrtc/ObservedIceCandidatePair.d.ts.map +1 -0
- package/lib/{ObservedIceCandidatePair.js → webrtc/ObservedIceCandidatePair.js} +17 -1
- package/lib/{ObservedIceTransport.d.ts → webrtc/ObservedIceTransport.d.ts} +1 -1
- package/lib/webrtc/ObservedIceTransport.d.ts.map +1 -0
- package/lib/{ObservedInboundRtp.d.ts → webrtc/ObservedInboundRtp.d.ts} +2 -2
- package/lib/webrtc/ObservedInboundRtp.d.ts.map +1 -0
- package/lib/{ObservedInboundTrack.d.ts → webrtc/ObservedInboundTrack.d.ts} +7 -4
- package/lib/webrtc/ObservedInboundTrack.d.ts.map +1 -0
- package/lib/{ObservedInboundTrack.js → webrtc/ObservedInboundTrack.js} +4 -1
- package/lib/{ObservedMediaPlayout.d.ts → webrtc/ObservedMediaPlayout.d.ts} +2 -2
- package/lib/webrtc/ObservedMediaPlayout.d.ts.map +1 -0
- package/lib/{ObservedMediaSource.d.ts → webrtc/ObservedMediaSource.d.ts} +2 -2
- package/lib/webrtc/ObservedMediaSource.d.ts.map +1 -0
- package/lib/{ObservedOutboundRtp.d.ts → webrtc/ObservedOutboundRtp.d.ts} +2 -2
- package/lib/webrtc/ObservedOutboundRtp.d.ts.map +1 -0
- package/lib/{ObservedOutboundTrack.d.ts → webrtc/ObservedOutboundTrack.d.ts} +7 -4
- package/lib/webrtc/ObservedOutboundTrack.d.ts.map +1 -0
- package/lib/{ObservedOutboundTrack.js → webrtc/ObservedOutboundTrack.js} +4 -1
- package/lib/{ObservedPeerConnection.d.ts → webrtc/ObservedPeerConnection.d.ts} +26 -4
- package/lib/webrtc/ObservedPeerConnection.d.ts.map +1 -0
- package/lib/{ObservedPeerConnection.js → webrtc/ObservedPeerConnection.js} +82 -17
- package/lib/{ObservedPeerConnectionTransport.d.ts → webrtc/ObservedPeerConnectionTransport.d.ts} +1 -1
- package/lib/webrtc/ObservedPeerConnectionTransport.d.ts.map +1 -0
- package/lib/{ObservedRemoteInboundRtp.d.ts → webrtc/ObservedRemoteInboundRtp.d.ts} +2 -2
- package/lib/webrtc/ObservedRemoteInboundRtp.d.ts.map +1 -0
- package/lib/{ObservedRemoteOutboundRtp.d.ts → webrtc/ObservedRemoteOutboundRtp.d.ts} +2 -2
- package/lib/webrtc/ObservedRemoteOutboundRtp.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/ObservedCall.ts +44 -48
- package/src/ObservedCallEventMonitor.ts +392 -0
- package/src/ObservedClient.ts +363 -22
- package/src/ObservedClientEventMonitor.ts +309 -0
- package/src/ObservedTURN.ts +2 -1
- package/src/ObservedTurnServer.ts +2 -2
- package/src/Observer.ts +37 -33
- package/src/ObserverEventMonitor.ts +551 -0
- package/src/common/SummaryTypes.ts +91 -0
- package/src/index.ts +19 -18
- package/src/mediasoup/ObservedMediasoupRouter.ts +12 -0
- package/src/monitors/SummaryMonitor.ts +181 -0
- package/src/schema/ClientEventTypes.ts +187 -19
- package/src/schema/ClientSample.ts +1 -1
- package/src/updaters/{OnAllCallObserverUpdater_.ts → OnAllCallObserverUpdater.ts} +14 -1
- package/src/updaters/OnAllClientCallUpdater.ts +15 -0
- package/src/updaters/{OnAnyCallObserverUpdater_.ts → OnAnyCallObserverUpdater.ts} +12 -3
- package/src/updaters/OnAnyClientCallUpdater.ts +9 -2
- package/src/utils/MediasoupRemoteTrackResolver.ts +155 -0
- package/src/utils/RemoteTrackResolver.ts +2 -2
- package/src/{ObservedCertificate.ts → webrtc/ObservedCertificate.ts} +1 -1
- package/src/{ObservedCodec.ts → webrtc/ObservedCodec.ts} +1 -1
- package/src/{ObservedDataChannel.ts → webrtc/ObservedDataChannel.ts} +4 -1
- package/src/{ObservedIceCandidate.ts → webrtc/ObservedIceCandidate.ts} +1 -1
- package/src/{ObservedIceCandidatePair.ts → webrtc/ObservedIceCandidatePair.ts} +19 -3
- package/src/{ObservedIceTransport.ts → webrtc/ObservedIceTransport.ts} +1 -1
- package/src/{ObservedInboundRtp.ts → webrtc/ObservedInboundRtp.ts} +2 -2
- package/src/{ObservedInboundTrack.ts → webrtc/ObservedInboundTrack.ts} +9 -4
- package/src/{ObservedMediaPlayout.ts → webrtc/ObservedMediaPlayout.ts} +2 -2
- package/src/{ObservedMediaSource.ts → webrtc/ObservedMediaSource.ts} +2 -2
- package/src/{ObservedOutboundRtp.ts → webrtc/ObservedOutboundRtp.ts} +2 -2
- package/src/{ObservedOutboundTrack.ts → webrtc/ObservedOutboundTrack.ts} +9 -4
- package/src/{ObservedPeerConnection.ts → webrtc/ObservedPeerConnection.ts} +124 -37
- package/src/{ObservedPeerConnectionTransport.ts → webrtc/ObservedPeerConnectionTransport.ts} +1 -1
- package/src/{ObservedRemoteInboundRtp.ts → webrtc/ObservedRemoteInboundRtp.ts} +2 -2
- package/src/{ObservedRemoteOutboundRtp.ts → webrtc/ObservedRemoteOutboundRtp.ts} +2 -2
- package/lib/ObservedCertificate.d.ts.map +0 -1
- package/lib/ObservedCodec.d.ts.map +0 -1
- package/lib/ObservedDataChannel.d.ts.map +0 -1
- package/lib/ObservedIceCandidate.d.ts.map +0 -1
- package/lib/ObservedIceCandidatePair.d.ts.map +0 -1
- package/lib/ObservedIceTransport.d.ts.map +0 -1
- package/lib/ObservedInboundRtp.d.ts.map +0 -1
- package/lib/ObservedInboundTrack.d.ts.map +0 -1
- package/lib/ObservedMediaPlayout.d.ts.map +0 -1
- package/lib/ObservedMediaSource.d.ts.map +0 -1
- package/lib/ObservedOutboundRtp.d.ts.map +0 -1
- package/lib/ObservedOutboundTrack.d.ts.map +0 -1
- package/lib/ObservedPeerConnection.d.ts.map +0 -1
- package/lib/ObservedPeerConnectionTransport.d.ts.map +0 -1
- package/lib/ObservedRemoteInboundRtp.d.ts.map +0 -1
- package/lib/ObservedRemoteOutboundRtp.d.ts.map +0 -1
- package/lib/ObserverSummary.d.ts.map +0 -1
- package/lib/updaters/OnAllCallObserverUpdater_.d.ts.map +0 -1
- package/lib/updaters/OnAnyCallObserverUpdater_.d.ts.map +0 -1
- /package/lib/{ObserverSummary.d.ts → common/ObserverSummary.d.ts} +0 -0
- /package/lib/{ObserverSummary.js → common/ObserverSummary.js} +0 -0
- /package/lib/{ObservedCertificate.js → webrtc/ObservedCertificate.js} +0 -0
- /package/lib/{ObservedCodec.js → webrtc/ObservedCodec.js} +0 -0
- /package/lib/{ObservedIceCandidate.js → webrtc/ObservedIceCandidate.js} +0 -0
- /package/lib/{ObservedIceTransport.js → webrtc/ObservedIceTransport.js} +0 -0
- /package/lib/{ObservedInboundRtp.js → webrtc/ObservedInboundRtp.js} +0 -0
- /package/lib/{ObservedMediaPlayout.js → webrtc/ObservedMediaPlayout.js} +0 -0
- /package/lib/{ObservedMediaSource.js → webrtc/ObservedMediaSource.js} +0 -0
- /package/lib/{ObservedOutboundRtp.js → webrtc/ObservedOutboundRtp.js} +0 -0
- /package/lib/{ObservedPeerConnectionTransport.js → webrtc/ObservedPeerConnectionTransport.js} +0 -0
- /package/lib/{ObservedRemoteInboundRtp.js → webrtc/ObservedRemoteInboundRtp.js} +0 -0
- /package/lib/{ObservedRemoteOutboundRtp.js → webrtc/ObservedRemoteOutboundRtp.js} +0 -0
- /package/src/{ObserverSummary.ts → common/ObserverSummary.ts} +0 -0
package/src/ObservedClient.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
-
import { ObservedPeerConnection } from './ObservedPeerConnection';
|
|
2
|
+
import { ObservedPeerConnection } from './webrtc/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';
|
|
@@ -10,21 +10,18 @@ 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';
|
|
13
|
+
import { clear } from 'console';
|
|
13
14
|
|
|
14
15
|
const logger = createLogger('ObservedClient');
|
|
15
16
|
|
|
16
17
|
export type ObservedClientSettings<AppData extends Record<string, unknown> = Record<string, unknown>> = {
|
|
17
18
|
clientId: string;
|
|
19
|
+
maxIdleTimeMs?: number;
|
|
18
20
|
appData?: AppData;
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
export type ObservedClientEvents = {
|
|
22
|
-
update: [
|
|
23
|
-
{
|
|
24
|
-
sample: ClientSample;
|
|
25
|
-
elapsedTimeInMs: number;
|
|
26
|
-
}
|
|
27
|
-
];
|
|
24
|
+
update: [sample: ClientSample, elapsedTimeInMs: number];
|
|
28
25
|
close: [];
|
|
29
26
|
joined: [];
|
|
30
27
|
issue: [ClientIssue];
|
|
@@ -33,8 +30,9 @@ export type ObservedClientEvents = {
|
|
|
33
30
|
left: [];
|
|
34
31
|
usingturn: [boolean];
|
|
35
32
|
usermediaerror: [string];
|
|
33
|
+
extensionStats: [ExtensionStat];
|
|
34
|
+
clientEvent: [ClientEvent];
|
|
36
35
|
|
|
37
|
-
// do we need this?
|
|
38
36
|
newpeerconnection: [ObservedPeerConnection];
|
|
39
37
|
};
|
|
40
38
|
|
|
@@ -48,14 +46,12 @@ export declare interface ObservedClient {
|
|
|
48
46
|
export class ObservedClient<AppData extends Record<string, unknown> = Record<string, unknown>> extends EventEmitter {
|
|
49
47
|
public readonly detectors: Detectors;
|
|
50
48
|
|
|
51
|
-
public readonly clientId: string;
|
|
52
49
|
public readonly observedPeerConnections = new Map<string, ObservedPeerConnection>();
|
|
53
50
|
public readonly calculatedScore: CalculatedScore = {
|
|
54
51
|
weight: 1,
|
|
55
52
|
value: undefined,
|
|
56
53
|
};
|
|
57
54
|
|
|
58
|
-
public appData: AppData;
|
|
59
55
|
public attachments?: Record<string, unknown>;
|
|
60
56
|
|
|
61
57
|
public updated = Date.now();
|
|
@@ -64,6 +60,8 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
64
60
|
|
|
65
61
|
public joinedAt?: number;
|
|
66
62
|
public leftAt?: number;
|
|
63
|
+
public closedAt?: number;
|
|
64
|
+
public lastSampleTimestamp?: number;
|
|
67
65
|
// the timestamp of the CLIENT_JOINED event
|
|
68
66
|
public operationSystem?: MetaData.OperationSystem;
|
|
69
67
|
public engine?: MetaData.Engine;
|
|
@@ -136,15 +134,27 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
136
134
|
public readonly mediaDevices: MetaData.MediaDeviceInfo[] = [];
|
|
137
135
|
public issues: ClientIssue[] = [];
|
|
138
136
|
|
|
139
|
-
|
|
137
|
+
private _injections: Pick<ClientSample, 'clientEvents' | 'clientIssues' | 'extensionStats' | 'attachments' | 'clientMetaItems'> = {};
|
|
138
|
+
private _autoCloseTimer?: ReturnType<typeof setTimeout>;
|
|
139
|
+
|
|
140
|
+
public constructor(
|
|
141
|
+
public readonly settings: ObservedClientSettings<AppData>,
|
|
142
|
+
public readonly call: ObservedCall
|
|
143
|
+
) {
|
|
140
144
|
super();
|
|
141
145
|
this.setMaxListeners(Infinity);
|
|
146
|
+
this._createAutoClose();
|
|
142
147
|
|
|
143
|
-
this.clientId = settings.clientId;
|
|
144
|
-
this.appData = settings.appData ?? {} as AppData;
|
|
145
|
-
|
|
146
148
|
this.detectors = new Detectors();
|
|
147
149
|
}
|
|
150
|
+
|
|
151
|
+
public get clientId() {
|
|
152
|
+
return this.settings.clientId;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public get appData(): AppData {
|
|
156
|
+
return this.settings.appData ?? {} as AppData;
|
|
157
|
+
}
|
|
148
158
|
|
|
149
159
|
public get numberOfPeerConnections() {
|
|
150
160
|
return this.observedPeerConnections.size;
|
|
@@ -158,13 +168,42 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
158
168
|
if (this.closed) return;
|
|
159
169
|
this.closed = true;
|
|
160
170
|
|
|
171
|
+
this._injections.clientEvents?.forEach((clientEvent) => this._processClientEvent(clientEvent));
|
|
172
|
+
this._injections.clientIssues?.forEach((clientIssue) => this.addIssue(clientIssue));
|
|
173
|
+
this._injections.extensionStats?.forEach((extensionStat) => this.addExtensionStats(extensionStat));
|
|
174
|
+
this._injections.clientMetaItems?.forEach((clientMetaItem) => this.addMetadata(clientMetaItem));
|
|
175
|
+
|
|
161
176
|
Array.from(this.observedPeerConnections.values()).forEach((peerConnection) => peerConnection.close());
|
|
177
|
+
if (!this.leftAt) {
|
|
178
|
+
this.leftAt = this.lastSampleTimestamp;
|
|
179
|
+
|
|
180
|
+
if (this.leftAt) {
|
|
181
|
+
this.emit('left');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
this.closedAt = Date.now();
|
|
162
185
|
|
|
163
186
|
this.emit('close');
|
|
164
187
|
}
|
|
165
188
|
|
|
189
|
+
private _createAutoClose() {
|
|
190
|
+
if (this.closed) return;
|
|
191
|
+
if (this.settings.maxIdleTimeMs === undefined || this.settings.maxIdleTimeMs < 1) return;
|
|
192
|
+
|
|
193
|
+
clearTimeout(this._autoCloseTimer);
|
|
194
|
+
|
|
195
|
+
this._autoCloseTimer = setTimeout(() => {
|
|
196
|
+
if (this.closed) return;
|
|
197
|
+
|
|
198
|
+
logger.debug(`Client ${this.clientId} is idle for ${this.settings.maxIdleTimeMs}ms, closing...`);
|
|
199
|
+
this.close();
|
|
200
|
+
}, this.settings.maxIdleTimeMs);
|
|
201
|
+
}
|
|
202
|
+
|
|
166
203
|
public accept(sample: ClientSample): void {
|
|
167
204
|
if (this.closed) throw new Error(`Client ${this.clientId} is closed`);
|
|
205
|
+
|
|
206
|
+
this._createAutoClose();
|
|
168
207
|
|
|
169
208
|
const now = Date.now();
|
|
170
209
|
const elapsedInMs = now - this.updated;
|
|
@@ -204,9 +243,15 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
204
243
|
this.usingTCP = false;
|
|
205
244
|
this.currentMinRttInMs = undefined;
|
|
206
245
|
this.currentMaxRttInMs = undefined;
|
|
207
|
-
|
|
246
|
+
|
|
247
|
+
this._mergeInjections(sample);
|
|
248
|
+
|
|
249
|
+
const clientEventsPostBuffer: ClientEvent[] = [];
|
|
250
|
+
|
|
208
251
|
for (const clientEvent of sample.clientEvents ?? []) {
|
|
209
|
-
this._processClientEvent(clientEvent);
|
|
252
|
+
this._processClientEvent(clientEvent, clientEventsPostBuffer);
|
|
253
|
+
|
|
254
|
+
this.call.observer.emit('client-event', this, clientEvent);
|
|
210
255
|
}
|
|
211
256
|
|
|
212
257
|
for (const metaData of sample.clientMetaItems ?? []) {
|
|
@@ -280,7 +325,9 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
280
325
|
}
|
|
281
326
|
}
|
|
282
327
|
|
|
283
|
-
|
|
328
|
+
for (const clientEvent of clientEventsPostBuffer) {
|
|
329
|
+
this._processClientEvent(clientEvent);
|
|
330
|
+
}
|
|
284
331
|
|
|
285
332
|
// emit new attachments?
|
|
286
333
|
this.attachments = sample.attachments;
|
|
@@ -313,11 +360,12 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
313
360
|
this.calculatedScore.value = sample.score;
|
|
314
361
|
this.detectors.update();
|
|
315
362
|
|
|
363
|
+
this.lastSampleTimestamp = sample.timestamp;
|
|
316
364
|
// emit update
|
|
317
|
-
this.emit('update',
|
|
365
|
+
this.emit('update',
|
|
318
366
|
sample,
|
|
319
|
-
|
|
320
|
-
|
|
367
|
+
now - this.updated,
|
|
368
|
+
);
|
|
321
369
|
this.updated = now;
|
|
322
370
|
|
|
323
371
|
// if result changed after update
|
|
@@ -327,7 +375,7 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
327
375
|
}
|
|
328
376
|
}
|
|
329
377
|
|
|
330
|
-
private _processClientEvent(event: ClientEvent) {
|
|
378
|
+
private _processClientEvent(event: ClientEvent, postBuffer?: ClientEvent[]) {
|
|
331
379
|
// eslint-disable-next-line no-console
|
|
332
380
|
// console.warn('ClientEvent', event);
|
|
333
381
|
switch (event.type) {
|
|
@@ -343,6 +391,7 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
343
391
|
logger.warn(`Client ${this.clientId} joinedAt timestamp was updated to ${event.timestamp}. the joined event will not be emitted.`);
|
|
344
392
|
}
|
|
345
393
|
}
|
|
394
|
+
logger.debug('Client %s joined at %o', this.clientId, event);
|
|
346
395
|
break;
|
|
347
396
|
}
|
|
348
397
|
case ClientEventTypes.CLIENT_LEFT: {
|
|
@@ -353,12 +402,262 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
353
402
|
} else {
|
|
354
403
|
logger.warn(`Client ${this.clientId} leftAt timestamp was already set`);
|
|
355
404
|
}
|
|
405
|
+
|
|
406
|
+
}
|
|
407
|
+
logger.debug('Client %s left at %o', this.clientId, event);
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
case ClientEventTypes.PEER_CONNECTION_OPENED: {
|
|
411
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
412
|
+
|
|
413
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
|
|
414
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
415
|
+
|
|
416
|
+
if (observedPeerConnection) {
|
|
417
|
+
observedPeerConnection.openedAt = event.timestamp;
|
|
418
|
+
} else if (postBuffer) {
|
|
419
|
+
postBuffer.push(event);
|
|
420
|
+
} else {
|
|
421
|
+
logger.warn('Received PEER_CONNECTION_OPENED event without a corresponding observedPeerConnection: %o', event);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
}
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
case ClientEventTypes.PEER_CONNECTION_CLOSED: {
|
|
428
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
429
|
+
|
|
430
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
|
|
431
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
432
|
+
|
|
433
|
+
if (observedPeerConnection) {
|
|
434
|
+
observedPeerConnection.closedAt = event.timestamp;
|
|
435
|
+
} else if (postBuffer) {
|
|
436
|
+
postBuffer.push(event);
|
|
437
|
+
} else {
|
|
438
|
+
logger.warn('Received PEER_CONNECTION_CLOSED event without a corresponding observedPeerConnection: %o', event);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
case ClientEventTypes.MEDIA_TRACK_ADDED: {
|
|
444
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
445
|
+
|
|
446
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
|
|
447
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
448
|
+
const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
449
|
+
|
|
450
|
+
if (observedTrack) {
|
|
451
|
+
observedTrack.addedAt = event.timestamp;
|
|
452
|
+
} else if (postBuffer) {
|
|
453
|
+
postBuffer.push(event);
|
|
454
|
+
} else {
|
|
455
|
+
logger.warn('Received MEDIA_TRACK_ADDED event without a corresponding observedPeerConnection or observedTrack: %o', event);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
case ClientEventTypes.MEDIA_TRACK_REMOVED: {
|
|
461
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
462
|
+
|
|
463
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
|
|
464
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
465
|
+
const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
466
|
+
|
|
467
|
+
if (observedTrack) {
|
|
468
|
+
observedTrack.removedAt = event.timestamp;
|
|
469
|
+
} else if (postBuffer) {
|
|
470
|
+
postBuffer.push(event);
|
|
471
|
+
} else {
|
|
472
|
+
logger.warn('Received MEDIA_TRACK_REMOVED event without a corresponding observedPeerConnection or observedTrack: %o', event);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
break;
|
|
476
|
+
}
|
|
477
|
+
case ClientEventTypes.DATA_CHANNEL_OPEN: {
|
|
478
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
479
|
+
|
|
480
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
|
|
481
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
482
|
+
const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
|
|
483
|
+
|
|
484
|
+
if (observedDataChannel) {
|
|
485
|
+
observedDataChannel.addedAt = event.timestamp;
|
|
486
|
+
} else if (postBuffer) {
|
|
487
|
+
postBuffer.push(event);
|
|
488
|
+
} else {
|
|
489
|
+
logger.warn('Received DATA_CHANNEL_OPENED event without a corresponding observedPeerConnection or observedDataChannel: %o', event);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
case ClientEventTypes.DATA_CHANNEL_CLOSED: {
|
|
495
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
496
|
+
|
|
497
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
|
|
498
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
499
|
+
const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
|
|
500
|
+
|
|
501
|
+
if (observedDataChannel) {
|
|
502
|
+
observedDataChannel.removedAt = event.timestamp;
|
|
503
|
+
} else if (postBuffer) {
|
|
504
|
+
postBuffer.push(event);
|
|
505
|
+
} else {
|
|
506
|
+
logger.warn('Received DATA_CHANNEL_CLOSE event without a corresponding observedPeerConnection or observedDataChannel: %o', event);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
case ClientEventTypes.MEDIA_TRACK_MUTED: {
|
|
512
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
513
|
+
|
|
514
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
|
|
515
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
516
|
+
const observedInboundTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId);
|
|
517
|
+
const observedOutboundTrack = observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
518
|
+
|
|
519
|
+
if (observedPeerConnection) {
|
|
520
|
+
if (observedInboundTrack) {
|
|
521
|
+
observedInboundTrack.muted = true;
|
|
522
|
+
observedPeerConnection?.emit('muted-inbound-track', observedInboundTrack);
|
|
523
|
+
} else if (observedOutboundTrack) {
|
|
524
|
+
observedOutboundTrack.muted = true;
|
|
525
|
+
observedPeerConnection?.emit('muted-outbound-track', observedOutboundTrack);
|
|
526
|
+
}
|
|
527
|
+
} else if (postBuffer) {
|
|
528
|
+
postBuffer.push(event);
|
|
529
|
+
} else {
|
|
530
|
+
logger.warn('Received MEDIA_TRACK_MUTED event without a corresponding observedPeerConnection or observedTrack: %o', event);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
case ClientEventTypes.MEDIA_TRACK_UNMUTED: {
|
|
537
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
538
|
+
|
|
539
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
|
|
540
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
541
|
+
const observedInboundTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId);
|
|
542
|
+
const observedOutboundTrack = observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
543
|
+
|
|
544
|
+
if (observedPeerConnection) {
|
|
545
|
+
if (observedInboundTrack) {
|
|
546
|
+
observedInboundTrack.muted = false;
|
|
547
|
+
observedPeerConnection?.emit('unmuted-inbound-track', observedInboundTrack);
|
|
548
|
+
} else if (observedOutboundTrack) {
|
|
549
|
+
observedOutboundTrack.muted = false;
|
|
550
|
+
observedPeerConnection?.emit('unmuted-outbound-track', observedOutboundTrack);
|
|
551
|
+
}
|
|
552
|
+
} else if (postBuffer) {
|
|
553
|
+
postBuffer.push(event);
|
|
554
|
+
} else {
|
|
555
|
+
logger.warn('Received MEDIA_TRACK_UNMUTED event without a corresponding observedPeerConnection or observedTrack: %o', event);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
case ClientEventTypes.ICE_CONNECTION_STATE_CHANGED: {
|
|
561
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
562
|
+
|
|
563
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.iceConnectionState && typeof payload.iceConnectionState === 'string') {
|
|
564
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
565
|
+
|
|
566
|
+
if (observedPeerConnection) {
|
|
567
|
+
observedPeerConnection.iceConnectionState = payload.iceConnectionState;
|
|
568
|
+
observedPeerConnection.emit('iceconnectionstatechange', {
|
|
569
|
+
state: payload.iceConnectionState,
|
|
570
|
+
});
|
|
571
|
+
} else if (postBuffer) {
|
|
572
|
+
postBuffer.push(event);
|
|
573
|
+
} else {
|
|
574
|
+
logger.warn('Received ICE_CONNECTION_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
case ClientEventTypes.ICE_GATHERING_STATE_CHANGED: {
|
|
580
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
581
|
+
|
|
582
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.iceGatheringState && typeof payload.iceGatheringState === 'string') {
|
|
583
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
584
|
+
|
|
585
|
+
if (observedPeerConnection) {
|
|
586
|
+
observedPeerConnection.iceGatheringState = payload.iceGatheringState;
|
|
587
|
+
observedPeerConnection.emit('icegatheringstatechange', {
|
|
588
|
+
state: payload.iceGatheringState,
|
|
589
|
+
});
|
|
590
|
+
} else if (postBuffer) {
|
|
591
|
+
postBuffer.push(event);
|
|
592
|
+
} else {
|
|
593
|
+
logger.warn('Received ICE_GATHERING_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
break;
|
|
597
|
+
}
|
|
598
|
+
case ClientEventTypes.PEER_CONNECTION_STATE_CHANGED: {
|
|
599
|
+
const payload = parseJsonAs<Record<string, unknown>>(event.payload);
|
|
600
|
+
|
|
601
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.peerConnectionState && typeof payload.peerConnectionState === 'string') {
|
|
602
|
+
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
603
|
+
|
|
604
|
+
if (observedPeerConnection) {
|
|
605
|
+
observedPeerConnection.connectionState = payload.peerConnectionState;
|
|
606
|
+
observedPeerConnection.emit('connectionstatechange', {
|
|
607
|
+
state: payload.peerConnectionState,
|
|
608
|
+
});
|
|
609
|
+
} else if (postBuffer) {
|
|
610
|
+
postBuffer.push(event);
|
|
611
|
+
} else {
|
|
612
|
+
logger.warn('Received PEER_CONNECTION_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
|
|
613
|
+
}
|
|
356
614
|
}
|
|
357
615
|
break;
|
|
358
616
|
}
|
|
359
617
|
}
|
|
618
|
+
|
|
619
|
+
this.emit('clientEvent', event);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
public injectMetaData(metaData: ClientMetaData) {
|
|
623
|
+
if (this.closed) return;
|
|
624
|
+
|
|
625
|
+
if (!this._injections.clientMetaItems) this._injections.clientMetaItems = [];
|
|
626
|
+
|
|
627
|
+
this._injections.clientMetaItems.push(metaData);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
public injectEvent(event: ClientEvent) {
|
|
631
|
+
if (this.closed) return;
|
|
632
|
+
|
|
633
|
+
if (!this._injections.clientEvents) this._injections.clientEvents = [];
|
|
360
634
|
|
|
361
|
-
this.
|
|
635
|
+
this._injections.clientEvents.push(event);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
public injectIssue(issue: ClientIssue) {
|
|
639
|
+
if (this.closed) return;
|
|
640
|
+
|
|
641
|
+
if (!this._injections.clientIssues) this._injections.clientIssues = [];
|
|
642
|
+
|
|
643
|
+
this._injections.clientIssues.push(issue);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
public injectExtensionStat(stat: ExtensionStat) {
|
|
647
|
+
if (this.closed) return;
|
|
648
|
+
|
|
649
|
+
if (!this._injections.extensionStats) this._injections.extensionStats = [];
|
|
650
|
+
|
|
651
|
+
this._injections.extensionStats.push(stat);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
public injectAttachment(key: string, value: unknown) {
|
|
655
|
+
if (this.closed) return;
|
|
656
|
+
|
|
657
|
+
if (!this._injections.attachments) this._injections.attachments = {};
|
|
658
|
+
|
|
659
|
+
this._injections.attachments[key] = value;
|
|
660
|
+
|
|
362
661
|
}
|
|
363
662
|
|
|
364
663
|
public addMetadata(metadata: ClientMetaData) {
|
|
@@ -395,6 +694,7 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
395
694
|
|
|
396
695
|
public addExtensionStats(stats: ExtensionStat) {
|
|
397
696
|
this.call.observer.emit('client-extension-stats', this, stats);
|
|
697
|
+
this.emit('extensionStats', stats);
|
|
398
698
|
}
|
|
399
699
|
|
|
400
700
|
private _updatePeerConnection(sample: PeerConnectionSample): ObservedPeerConnection | undefined {
|
|
@@ -423,6 +723,47 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
423
723
|
return observedPeerConnection;
|
|
424
724
|
}
|
|
425
725
|
|
|
726
|
+
private _mergeInjections(sample: ClientSample): ClientSample {
|
|
727
|
+
if (this.closed) return sample;
|
|
728
|
+
|
|
729
|
+
if (this._injections.clientEvents) {
|
|
730
|
+
if (!sample.clientEvents) sample.clientEvents = [];
|
|
731
|
+
sample.clientEvents.push(...this._injections.clientEvents);
|
|
732
|
+
|
|
733
|
+
this._injections.clientEvents = undefined;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
if (this._injections.clientIssues) {
|
|
737
|
+
if (!sample.clientIssues) sample.clientIssues = [];
|
|
738
|
+
sample.clientIssues.push(...this._injections.clientIssues);
|
|
739
|
+
|
|
740
|
+
this._injections.clientIssues = undefined;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
if (this._injections.extensionStats) {
|
|
744
|
+
if (!sample.extensionStats) sample.extensionStats = [];
|
|
745
|
+
sample.extensionStats.push(...this._injections.extensionStats);
|
|
746
|
+
|
|
747
|
+
this._injections.extensionStats = undefined;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
if (this._injections.attachments) {
|
|
751
|
+
if (!sample.attachments) sample.attachments = {};
|
|
752
|
+
Object.assign(sample.attachments, this._injections.attachments);
|
|
753
|
+
|
|
754
|
+
this._injections.attachments = undefined;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
if (this._injections.clientMetaItems) {
|
|
758
|
+
if (!sample.clientMetaItems) sample.clientMetaItems = [];
|
|
759
|
+
sample.clientMetaItems.push(...this._injections.clientMetaItems);
|
|
760
|
+
|
|
761
|
+
this._injections.clientMetaItems = undefined;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
return sample;
|
|
765
|
+
}
|
|
766
|
+
|
|
426
767
|
// public resetSummaryMetrics() {
|
|
427
768
|
// this.totalDataChannelBytesReceived = 0;
|
|
428
769
|
// this.totalDataChannelBytesSent = 0;
|