@observertc/observer-js 0.40.29 → 0.40.31

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.
@@ -5,6 +5,9 @@ import { ObservedOutboundTrack } from './ObservedOutboundTrack';
5
5
  import { Observer } from './Observer';
6
6
  import { PartialBy } from './common/utils';
7
7
  import { CallEventReport } from '@observertc/report-schemas-js';
8
+ import { ClientSample } from '@observertc/sample-schemas-js';
9
+ import { ClientIssue } from './monitors/CallSummary';
10
+ type ClientIssueDetectionConfig = Pick<ClientIssue, 'severity'>;
8
11
  export type ObservedCallModel = {
9
12
  serviceId: string;
10
13
  roomId: string;
@@ -13,6 +16,7 @@ export type ObservedCallModel = {
13
16
  export type ObservedCallEvents = {
14
17
  update: [];
15
18
  newclient: [ObservedClient];
19
+ callevent: [Omit<CallEventReport, 'callId' | 'serviceId' | 'roomId'>];
16
20
  close: [];
17
21
  };
18
22
  export declare interface ObservedCall {
@@ -26,6 +30,7 @@ export declare class ObservedCall<AppData extends Record<string, unknown> = Reco
26
30
  readonly observer: Observer;
27
31
  readonly appData: AppData;
28
32
  readonly created: number;
33
+ readonly processor: import("./common/Middleware").Processor<ClientSample>;
29
34
  private readonly _clients;
30
35
  readonly sfuStreamIdToOutboundAudioTrack: Map<string | number, ObservedOutboundTrack<"audio">>;
31
36
  readonly sfuStreamIdToOutboundVideoTrack: Map<string | number, ObservedOutboundTrack<"video">>;
@@ -47,6 +52,10 @@ export declare class ObservedCall<AppData extends Record<string, unknown> = Reco
47
52
  appData: ClientAppData;
48
53
  generateClientJoinedReport?: boolean;
49
54
  joined?: number;
55
+ detectIssues?: {
56
+ rejoin: ClientIssue['severity'] | ClientIssueDetectionConfig;
57
+ };
50
58
  }): ObservedClient<ClientAppData>;
51
59
  }
60
+ export {};
52
61
  //# sourceMappingURL=ObservedCall.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ObservedCall.d.ts","sourceRoot":"","sources":["../src/ObservedCall.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,MAAM,MAAM,iBAAiB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAChC,MAAM,EAAE,EAAE,CAAC;IACX,SAAS,EAAE,CAAC,cAAc,CAAC,CAAC;IAC5B,KAAK,EAAE,EAAE,CAAC;CACV,CAAA;AAED,MAAM,CAAC,OAAO,WAAW,YAAY;IACpC,EAAE,CAAC,CAAC,SAAS,MAAM,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3G,GAAG,CAAC,CAAC,SAAS,MAAM,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAC5G,IAAI,CAAC,CAAC,SAAS,MAAM,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7G,IAAI,CAAC,CAAC,SAAS,MAAM,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CAC5F;AAED,qBAAa,YAAY,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAE,SAAQ,YAAY;IAY/G,OAAO,CAAC,QAAQ,CAAC,MAAM;aACP,QAAQ,EAAE,QAAQ;aAClB,OAAO,EAAE,OAAO;IAbjC,SAAgB,OAAO,SAAc;IAErC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAE9D,SAAgB,+BAA+B,uDAA8D;IAC7G,SAAgB,+BAA+B,uDAA8D;IAC7G,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,MAAM,CAAC,CAAS;gBAGN,MAAM,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO;IAMjC,IAAW,SAAS,IAAI,MAAM,CAG7B;IAED,IAAW,OAAO,kDAEjB;IAED,IAAW,MAAM,WAGhB;IAED,IAAW,MAAM,WAGhB;IAED,IAAW,OAAO,WAEjB;IAED,IAAW,KAAK,uBAEf;IAED,IAAW,OAAO,IAAI,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAExD;IAED,IAAW,MAAM,YAEhB;IAEM,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM;IAUxB,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAE,EAAE,WAAW,CAAC;IAUxG,YAAY,CAAC,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,mBAAmB,GAAG;QAAE,OAAO,EAAE,aAAa,CAAC;QAAC,0BAA0B,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAmC5M"}
1
+ {"version":3,"file":"ObservedCall.d.ts","sourceRoot":"","sources":["../src/ObservedCall.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,7 @@ exports.ObservedCall = void 0;
15
15
  const events_1 = require("events");
16
16
  const ObservedClient_1 = require("./ObservedClient");
17
17
  const callEventReports_1 = require("./common/callEventReports");
18
+ const Middleware_1 = require("./common/Middleware");
18
19
  class ObservedCall extends events_1.EventEmitter {
19
20
  constructor(_model, observer, appData) {
20
21
  super();
@@ -22,6 +23,7 @@ class ObservedCall extends events_1.EventEmitter {
22
23
  this.observer = observer;
23
24
  this.appData = appData;
24
25
  this.created = Date.now();
26
+ this.processor = (0, Middleware_1.createProcessor)();
25
27
  this._clients = new Map();
26
28
  this.sfuStreamIdToOutboundAudioTrack = new Map();
27
29
  this.sfuStreamIdToOutboundVideoTrack = new Map();
@@ -71,11 +73,14 @@ class ObservedCall extends events_1.EventEmitter {
71
73
  createClient(config) {
72
74
  if (this._closed)
73
75
  throw new Error(`Call ${this.callId} is closed`);
74
- const { appData, generateClientJoinedReport, joined = Date.now() } = config, model = __rest(config, ["appData", "generateClientJoinedReport", "joined"]);
76
+ const { appData, generateClientJoinedReport, joined = Date.now(), detectIssues = {
77
+ rejoin: 'minor'
78
+ } } = config, model = __rest(config, ["appData", "generateClientJoinedReport", "joined", "detectIssues"]);
75
79
  const result = new ObservedClient_1.ObservedClient(model, this, appData);
76
- const onUpdate = () => {
80
+ const onUpdate = ({ sample }) => {
77
81
  this._updated = Date.now();
78
82
  this.emit('update');
83
+ this.processor.process(sample);
79
84
  };
80
85
  result.once('close', () => {
81
86
  result.off('update', onUpdate);
@@ -86,6 +91,19 @@ class ObservedCall extends events_1.EventEmitter {
86
91
  if (generateClientJoinedReport) {
87
92
  this.reports.addCallEventReport((0, callEventReports_1.createClientJoinedEventReport)(this.serviceId, result.mediaUnitId, this.roomId, this.callId, result.clientId, joined, result.userId, result.marker));
88
93
  }
94
+ if (detectIssues === null || detectIssues === void 0 ? void 0 : detectIssues.rejoin) {
95
+ const issueBaseConfig = typeof detectIssues.rejoin === 'object' ? detectIssues.rejoin : {
96
+ severity: detectIssues.rejoin
97
+ };
98
+ const rejoinedClientIssueListener = (event) => {
99
+ event.lastJoined;
100
+ result.addIssue(Object.assign({ timestamp: Date.now() }, issueBaseConfig));
101
+ };
102
+ result.once('close', () => {
103
+ result.off('rejoined', rejoinedClientIssueListener);
104
+ });
105
+ result.on('rejoined', rejoinedClientIssueListener);
106
+ }
89
107
  this.emit('newclient', result);
90
108
  return result;
91
109
  }
@@ -16,10 +16,15 @@ export type ObservedClientModel = {
16
16
  engine?: Engine;
17
17
  platform?: Platform;
18
18
  browser?: Browser;
19
+ coordinates?: {
20
+ latitude: number;
21
+ longitude: number;
22
+ };
19
23
  };
20
24
  export type ObservedClientEvents = {
21
25
  update: [
22
26
  {
27
+ sample: ClientSample;
23
28
  elapsedTimeInMs: number;
24
29
  }
25
30
  ];
@@ -53,6 +58,11 @@ export type ObservedClientEvents = {
53
58
  issue: [ClientIssue];
54
59
  usingturn: [boolean];
55
60
  usermediaerror: [string];
61
+ rejoined: [
62
+ {
63
+ lastJoined: number;
64
+ }
65
+ ];
56
66
  };
57
67
  export declare interface ObservedClient<AppData extends Record<string, unknown> = Record<string, unknown>> {
58
68
  on<U extends keyof ObservedClientEvents>(event: U, listener: (...args: ObservedClientEvents[U]) => void): this;
@@ -70,7 +80,8 @@ export declare class ObservedClient<AppData extends Record<string, unknown> = Re
70
80
  sfuId?: string;
71
81
  private readonly _peerConnections;
72
82
  private _closed;
73
- private _acceptedSample;
83
+ private _joinedEventAt?;
84
+ private _acceptedSamples;
74
85
  private _timeZoneOffsetInHours?;
75
86
  private _left?;
76
87
  usingTURN: boolean;
@@ -110,6 +121,14 @@ export declare class ObservedClient<AppData extends Record<string, unknown> = Re
110
121
  constructor(_model: ObservedClientModel, call: ObservedCall, appData: AppData);
111
122
  getSfu<T extends Record<string, unknown> = Record<string, unknown>>(): ObservedSfu<T> | undefined;
112
123
  get sfu(): ObservedSfu | undefined;
124
+ get coordinates(): {
125
+ latitude: number;
126
+ longitude: number;
127
+ } | undefined;
128
+ set coordinates(value: {
129
+ latitude: number;
130
+ longitude: number;
131
+ } | undefined);
113
132
  get clientId(): string;
114
133
  get roomId(): string;
115
134
  get serviceId(): string;
@@ -124,7 +143,7 @@ export declare class ObservedClient<AppData extends Record<string, unknown> = Re
124
143
  get engine(): Engine | undefined;
125
144
  get operationSystem(): OperationSystem | undefined;
126
145
  get platform(): Platform | undefined;
127
- get acceptedSample(): number;
146
+ get acceptedSamples(): number;
128
147
  get updated(): number;
129
148
  get closed(): boolean;
130
149
  get peerConnections(): ReadonlyMap<string, ObservedPeerConnection>;
@@ -1 +1 @@
1
- {"version":3,"file":"ObservedClient.d.ts","sourceRoot":"","sources":["../src/ObservedClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ObservedClient.d.ts","sourceRoot":"","sources":["../src/ObservedClient.ts"],"names":[],"mappings":"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"}
@@ -31,7 +31,7 @@ class ObservedClient extends events_1.EventEmitter {
31
31
  this._updated = Date.now();
32
32
  this._peerConnections = new Map();
33
33
  this._closed = false;
34
- this._acceptedSample = 0;
34
+ this._acceptedSamples = 0;
35
35
  this.usingTURN = false;
36
36
  this.availableOutgoingBitrate = 0;
37
37
  this.availableIncomingBitrate = 0;
@@ -75,6 +75,12 @@ class ObservedClient extends events_1.EventEmitter {
75
75
  return;
76
76
  return this.call.observer.observedSfus.get(this.sfuId);
77
77
  }
78
+ get coordinates() {
79
+ return this._model.coordinates;
80
+ }
81
+ set coordinates(value) {
82
+ this._model.coordinates = value;
83
+ }
78
84
  get clientId() {
79
85
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
80
86
  return this._model.clientId;
@@ -122,8 +128,8 @@ class ObservedClient extends events_1.EventEmitter {
122
128
  get platform() {
123
129
  return this._model.platform;
124
130
  }
125
- get acceptedSample() {
126
- return this._acceptedSample;
131
+ get acceptedSamples() {
132
+ return this._acceptedSamples;
127
133
  }
128
134
  get updated() {
129
135
  return this._updated;
@@ -196,7 +202,7 @@ class ObservedClient extends events_1.EventEmitter {
196
202
  throw new Error(`Sample client id (${sample.clientId}) does not match the client id of the observed client (${this.clientId})`);
197
203
  }
198
204
  const now = Date.now();
199
- ++this._acceptedSample;
205
+ ++this._acceptedSamples;
200
206
  for (const peerConnection of this._peerConnections.values()) {
201
207
  if (peerConnection.closed)
202
208
  continue;
@@ -277,7 +283,7 @@ class ObservedClient extends events_1.EventEmitter {
277
283
  callId: this.callId,
278
284
  clientId: this.clientId,
279
285
  userId: this.userId,
280
- timestamp: Date.now(),
286
+ timestamp: now,
281
287
  payload: extensionStats.payload,
282
288
  extensionType: extensionStats.type,
283
289
  });
@@ -285,6 +291,14 @@ class ObservedClient extends events_1.EventEmitter {
285
291
  for (let _21 of (_p = sample.customCallEvents) !== null && _p !== void 0 ? _p : []) {
286
292
  const { timestamp } = _21, callEvent = __rest(_21, ["timestamp"]);
287
293
  switch (callEvent.name) {
294
+ case CallEventType_1.CallEventType.CLIENT_JOINED: {
295
+ const lastJoined = this._joinedEventAt;
296
+ this._joinedEventAt = timestamp !== null && timestamp !== void 0 ? timestamp : sample.timestamp;
297
+ if (lastJoined && this._joinedEventAt && lastJoined !== this._joinedEventAt) {
298
+ this.emit('rejoined', { lastJoined });
299
+ }
300
+ break;
301
+ }
288
302
  case CallEventType_1.CallEventType.CLIENT_LEFT: {
289
303
  this._left = timestamp;
290
304
  break;
@@ -306,9 +320,11 @@ class ObservedClient extends events_1.EventEmitter {
306
320
  catch (err) {
307
321
  logger.warn(`Error parsing client issue: ${err === null || err === void 0 ? void 0 : err.message}`);
308
322
  }
323
+ break;
309
324
  }
310
325
  }
311
- this.reports.addCallEventReport(Object.assign({ serviceId: this.serviceId, mediaUnitId: this.mediaUnitId, roomId: this.roomId, callId: this.callId, clientId: this.clientId, userId: this.userId, timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : Date.now() }, callEvent));
326
+ this.reports.addCallEventReport(Object.assign({ serviceId: this.serviceId, mediaUnitId: this.mediaUnitId, roomId: this.roomId, callId: this.callId, clientId: this.clientId, userId: this.userId, timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : now }, callEvent));
327
+ this.call.emit('callevent', Object.assign({ mediaUnitId: this.mediaUnitId, clientId: this.clientId, userId: this.userId, timestamp: timestamp !== null && timestamp !== void 0 ? timestamp : now }, callEvent));
312
328
  }
313
329
  for (const userMediaError of (_q = sample.userMediaErrors) !== null && _q !== void 0 ? _q : []) {
314
330
  const callMetaReport = (0, callMetaReports_1.createCallMetaReport)(this.serviceId, this.mediaUnitId, this.roomId, this.callId, this.clientId, {
@@ -600,8 +616,11 @@ class ObservedClient extends events_1.EventEmitter {
600
616
  this.inboundAudioBitrate = (this.deltaReceivedAudioBytes * 8) / (Math.max(elapsedTimeInMs, 1) / 1000);
601
617
  this.inboundVideoBitrate = (this.deltaReceivedVideoBytes * 8) / (Math.max(elapsedTimeInMs, 1) / 1000);
602
618
  this.avgRttInMs = this._peerConnections.size ? sumRttInMs / this._peerConnections.size : undefined;
619
+ // to make sure when sample is emitted it can be associated to this client
620
+ sample.clientId = this.clientId;
603
621
  this._updated = now;
604
622
  this.emit('update', {
623
+ sample,
605
624
  elapsedTimeInMs,
606
625
  });
607
626
  }
@@ -0,0 +1,8 @@
1
+ export type Middleware<T> = (input: T, next: (nextInput: T) => void) => void;
2
+ export interface Processor<T> {
3
+ process(value: T): void;
4
+ addMiddleware(...middlewares: Middleware<T>[]): Processor<T>;
5
+ removeMiddleware(...middlewares: Middleware<T>[]): Processor<T>;
6
+ }
7
+ export declare function createProcessor<T>(): Processor<T>;
8
+ //# sourceMappingURL=Middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Middleware.d.ts","sourceRoot":"","sources":["../../src/common/Middleware.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAC3B,KAAK,EAAE,CAAC,EACR,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,IAAI,KACxB,IAAI,CAAC;AAEV,MAAM,WAAW,SAAS,CAAC,CAAC;IAC3B,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACxB,aAAa,CAAC,GAAG,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC7D,gBAAgB,CAAC,GAAG,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;CAChE;AAED,wBAAgB,eAAe,CAAC,CAAC,KAC9B,SAAS,CAAC,CAAC,CAAC,CA2Cd"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createProcessor = void 0;
4
+ function createProcessor() {
5
+ const stack = [];
6
+ const result = {
7
+ addMiddleware: (...middlewares) => {
8
+ if (middlewares && 0 < middlewares.length) {
9
+ stack.push(...middlewares);
10
+ }
11
+ return result;
12
+ },
13
+ removeMiddleware: (...middlewares) => {
14
+ if (middlewares && 0 < middlewares.length) {
15
+ for (const process of middlewares) {
16
+ const index = stack.indexOf(process);
17
+ if (0 < index)
18
+ stack.splice(index, 1);
19
+ }
20
+ }
21
+ return result;
22
+ },
23
+ process: (value) => {
24
+ let prevIndex = -1;
25
+ const execute = (index, input) => {
26
+ if (index <= prevIndex) {
27
+ throw new Error('middleware must call next() only once!');
28
+ }
29
+ prevIndex = index;
30
+ const middleware = stack[index];
31
+ if (!middleware)
32
+ return;
33
+ const next = (nextInput) => execute(index + 1, nextInput);
34
+ return middleware(input, next);
35
+ };
36
+ return execute(0, value);
37
+ },
38
+ };
39
+ return result;
40
+ }
41
+ exports.createProcessor = createProcessor;
@@ -13,10 +13,7 @@ export type ClientIssueMonitorEvents = {
13
13
  minor: [ClientIssueMonitorEmittedIssueEvent];
14
14
  critical: [ClientIssueMonitorEmittedIssueEvent];
15
15
  };
16
- export type ClientIssueMonitorConfig = {
17
- detectUserMediaClientIssues?: boolean;
18
- detectMediaTrackQualityLimitationClientIssues?: boolean;
19
- };
16
+ export type ClientIssueMonitorConfig = {};
20
17
  export declare interface ClientIssueMonitor {
21
18
  on<U extends keyof ClientIssueMonitorEvents>(event: U, listener: (...args: ClientIssueMonitorEvents[U]) => void): this;
22
19
  off<U extends keyof ClientIssueMonitorEvents>(event: U, listener: (...args: ClientIssueMonitorEvents[U]) => void): this;
@@ -1 +1 @@
1
- {"version":3,"file":"ClientIssueMonitor.d.ts","sourceRoot":"","sources":["../../src/monitors/ClientIssueMonitor.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,MAAM,mCAAmC,GAAG,WAAW,GAAG;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACtC,KAAK,EAAE,EAAE,CAAC;IACV,KAAK,EAAE,CAAC,mCAAmC,CAAC,CAAC;IAC7C,KAAK,EAAE,CAAC,mCAAmC,CAAC,CAAC;IAC7C,KAAK,EAAE,CAAC,mCAAmC,CAAC,CAAC;IAC7C,QAAQ,EAAE,CAAC,mCAAmC,CAAC,CAAC;CAEhD,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACtC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,6CAA6C,CAAC,EAAE,OAAO,CAAC;CACxD,CAAA;AAED,MAAM,CAAC,OAAO,WAAW,kBAAkB;IAC1C,EAAE,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACvH,GAAG,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACxH,IAAI,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACzH,IAAI,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CACxG;AAED,qBAAa,kBAAmB,SAAQ,YAAY;aAGlC,MAAM,EAAE,wBAAwB;IAFjD,OAAO,CAAC,OAAO,CAAS;gBAEP,MAAM,GAAE,wBAA6B;IAM/C,OAAO,CAAC,IAAI,EAAE,YAAY;IAajC,OAAO,CAAC,UAAU;IAyBlB,IAAW,MAAM,YAEhB;IAEM,KAAK;CAMZ"}
1
+ {"version":3,"file":"ClientIssueMonitor.d.ts","sourceRoot":"","sources":["../../src/monitors/ClientIssueMonitor.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,MAAM,mCAAmC,GAAG,WAAW,GAAG;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACtC,KAAK,EAAE,EAAE,CAAC;IACV,KAAK,EAAE,CAAC,mCAAmC,CAAC,CAAC;IAC7C,KAAK,EAAE,CAAC,mCAAmC,CAAC,CAAC;IAC7C,KAAK,EAAE,CAAC,mCAAmC,CAAC,CAAC;IAC7C,QAAQ,EAAE,CAAC,mCAAmC,CAAC,CAAC;CAEhD,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,EAEtC,CAAA;AAED,MAAM,CAAC,OAAO,WAAW,kBAAkB;IAC1C,EAAE,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACvH,GAAG,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACxH,IAAI,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACzH,IAAI,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CACxG;AAED,qBAAa,kBAAmB,SAAQ,YAAY;aAGlC,MAAM,EAAE,wBAAwB;IAFjD,OAAO,CAAC,OAAO,CAAS;gBAEP,MAAM,GAAE,wBAA6B;IAM/C,OAAO,CAAC,IAAI,EAAE,YAAY;IAajC,OAAO,CAAC,UAAU;IAyBlB,IAAW,MAAM,YAEhB;IAEM,KAAK;CAMZ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@observertc/observer-js",
3
- "version": "0.40.29",
3
+ "version": "0.40.31",
4
4
  "description": "Server Side NodeJS Library for processing ObserveRTC Samples",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -1,10 +1,15 @@
1
1
  import { EventEmitter } from 'events';
2
- import { ObservedClient, ObservedClientModel } from './ObservedClient';
2
+ import { ObservedClient, ObservedClientEvents, ObservedClientModel } from './ObservedClient';
3
3
  import { ObservedOutboundTrack } from './ObservedOutboundTrack';
4
4
  import { Observer } from './Observer';
5
5
  import { createClientJoinedEventReport } from './common/callEventReports';
6
6
  import { PartialBy } from './common/utils';
7
7
  import { CallEventReport } from '@observertc/report-schemas-js';
8
+ import { createProcessor } from './common/Middleware';
9
+ import { ClientSample } from '@observertc/sample-schemas-js';
10
+ import { ClientIssue } from './monitors/CallSummary';
11
+
12
+ type ClientIssueDetectionConfig = Pick<ClientIssue, 'severity'>;
8
13
 
9
14
  export type ObservedCallModel = {
10
15
  serviceId: string;
@@ -15,6 +20,7 @@ export type ObservedCallModel = {
15
20
  export type ObservedCallEvents = {
16
21
  update: [],
17
22
  newclient: [ObservedClient],
23
+ callevent: [Omit<CallEventReport, 'callId' | 'serviceId' | 'roomId'>],
18
24
  close: [],
19
25
  }
20
26
 
@@ -28,6 +34,8 @@ export declare interface ObservedCall {
28
34
  export class ObservedCall<AppData extends Record<string, unknown> = Record<string, unknown>> extends EventEmitter {
29
35
  public readonly created = Date.now();
30
36
 
37
+ public readonly processor = createProcessor<ClientSample>();
38
+
31
39
  private readonly _clients = new Map<string, ObservedClient>();
32
40
 
33
41
  public readonly sfuStreamIdToOutboundAudioTrack = new Map<string | number, ObservedOutboundTrack<'audio'>>();
@@ -100,21 +108,39 @@ export class ObservedCall<AppData extends Record<string, unknown> = Record<strin
100
108
  });
101
109
  }
102
110
 
103
- public createClient<ClientAppData extends Record<string, unknown> = Record<string, unknown>>(config: ObservedClientModel & { appData: ClientAppData, generateClientJoinedReport?: boolean, joined?: number }) {
111
+ public createClient<ClientAppData extends Record<string, unknown> = Record<string, unknown>>(config: ObservedClientModel & {
112
+ appData: ClientAppData,
113
+ generateClientJoinedReport?: boolean,
114
+ joined?: number,
115
+ detectIssues?: {
116
+ rejoin: ClientIssue['severity'] | ClientIssueDetectionConfig,
117
+ },
118
+ }) {
104
119
  if (this._closed) throw new Error(`Call ${this.callId} is closed`);
105
120
 
106
- const { appData, generateClientJoinedReport, joined = Date.now(), ...model } = config;
121
+ const {
122
+ appData,
123
+ generateClientJoinedReport,
124
+ joined = Date.now(),
125
+ detectIssues = {
126
+ rejoin: 'minor'
127
+ },
128
+ ...model
129
+ } = config;
107
130
 
108
131
  const result = new ObservedClient(model, this, appData);
109
- const onUpdate = () => {
132
+ const onUpdate = ({ sample }: { sample: ClientSample }) => {
110
133
  this._updated = Date.now();
111
134
  this.emit('update');
135
+
136
+ this.processor.process(sample);
112
137
  };
113
138
 
114
139
  result.once('close', () => {
115
140
  result.off('update', onUpdate);
116
141
  this._clients.delete(result.clientId);
117
142
  });
143
+
118
144
  result.on('update', onUpdate);
119
145
  this._clients.set(result.clientId, result);
120
146
 
@@ -131,6 +157,25 @@ export class ObservedCall<AppData extends Record<string, unknown> = Record<strin
131
157
  ));
132
158
  }
133
159
 
160
+ if (detectIssues?.rejoin) {
161
+ const issueBaseConfig = typeof detectIssues.rejoin === 'object' ? detectIssues.rejoin : {
162
+ severity: detectIssues.rejoin
163
+ };
164
+
165
+ const rejoinedClientIssueListener = (event: ObservedClientEvents['rejoined'][0]) => {
166
+ event.lastJoined;
167
+ result.addIssue({
168
+ timestamp: Date.now(),
169
+ ...issueBaseConfig,
170
+ });
171
+ };
172
+
173
+ result.once('close', () => {
174
+ result.off('rejoined', rejoinedClientIssueListener);
175
+ });
176
+ result.on('rejoined', rejoinedClientIssueListener);
177
+ }
178
+
134
179
  this.emit('newclient', result);
135
180
 
136
181
  return result;
@@ -23,10 +23,15 @@ export type ObservedClientModel= {
23
23
  engine?: Engine,
24
24
  platform?: Platform,
25
25
  browser?: Browser,
26
+ coordinates?: {
27
+ latitude: number;
28
+ longitude: number;
29
+ },
26
30
  };
27
31
 
28
32
  export type ObservedClientEvents = {
29
33
  update: [{
34
+ sample: ClientSample,
30
35
  elapsedTimeInMs: number,
31
36
  }],
32
37
  close: [],
@@ -51,6 +56,9 @@ export type ObservedClientEvents = {
51
56
  issue: [ClientIssue],
52
57
  usingturn: [boolean],
53
58
  usermediaerror: [string],
59
+ rejoined: [{
60
+ lastJoined: number,
61
+ }],
54
62
  };
55
63
 
56
64
  export declare interface ObservedClient<AppData extends Record<string, unknown> = Record<string, unknown>> {
@@ -71,7 +79,8 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
71
79
 
72
80
  private _closed = false;
73
81
 
74
- private _acceptedSample = 0;
82
+ private _joinedEventAt?: number;
83
+ private _acceptedSamples = 0;
75
84
  private _timeZoneOffsetInHours?: number;
76
85
  private _left?: number;
77
86
 
@@ -137,6 +146,14 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
137
146
  return this.call.observer.observedSfus.get(this.sfuId);
138
147
  }
139
148
 
149
+ public get coordinates() {
150
+ return this._model.coordinates;
151
+ }
152
+
153
+ public set coordinates(value: { latitude: number; longitude: number } | undefined) {
154
+ this._model.coordinates = value;
155
+ }
156
+
140
157
  public get clientId(): string {
141
158
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
142
159
  return this._model.clientId!;
@@ -198,8 +215,8 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
198
215
  return this._model.platform;
199
216
  }
200
217
 
201
- public get acceptedSample() {
202
- return this._acceptedSample;
218
+ public get acceptedSamples() {
219
+ return this._acceptedSamples;
203
220
  }
204
221
 
205
222
  public get updated() {
@@ -296,7 +313,7 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
296
313
  }
297
314
  const now = Date.now();
298
315
 
299
- ++this._acceptedSample;
316
+ ++this._acceptedSamples;
300
317
 
301
318
  for (const peerConnection of this._peerConnections.values()) {
302
319
  if (peerConnection.closed) continue;
@@ -464,7 +481,7 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
464
481
  callId: this.callId,
465
482
  clientId: this.clientId,
466
483
  userId: this.userId,
467
- timestamp: Date.now(),
484
+ timestamp: now,
468
485
  payload: extensionStats.payload,
469
486
  extensionType: extensionStats.type,
470
487
  });
@@ -472,6 +489,16 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
472
489
 
473
490
  for (const { timestamp, ...callEvent } of sample.customCallEvents ?? []) {
474
491
  switch (callEvent.name) {
492
+ case CallEventType.CLIENT_JOINED: {
493
+ const lastJoined = this._joinedEventAt;
494
+
495
+ this._joinedEventAt = timestamp ?? sample.timestamp;
496
+
497
+ if (lastJoined && this._joinedEventAt && lastJoined !== this._joinedEventAt) {
498
+ this.emit('rejoined', { lastJoined });
499
+ }
500
+ break;
501
+ }
475
502
  case CallEventType.CLIENT_LEFT: {
476
503
  this._left = timestamp;
477
504
  break;
@@ -494,8 +521,10 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
494
521
  } catch (err) {
495
522
  logger.warn(`Error parsing client issue: ${(err as Error)?.message}`);
496
523
  }
524
+ break;
497
525
  }
498
526
  }
527
+
499
528
  this.reports.addCallEventReport({
500
529
  serviceId: this.serviceId,
501
530
  mediaUnitId: this.mediaUnitId,
@@ -503,9 +532,18 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
503
532
  callId: this.callId,
504
533
  clientId: this.clientId,
505
534
  userId: this.userId,
506
- timestamp: timestamp ?? Date.now(),
535
+ timestamp: timestamp ?? now,
536
+ ...callEvent,
537
+ });
538
+
539
+ this.call.emit('callevent', {
540
+ mediaUnitId: this.mediaUnitId,
541
+ clientId: this.clientId,
542
+ userId: this.userId,
543
+ timestamp: timestamp ?? now,
507
544
  ...callEvent,
508
545
  });
546
+
509
547
  }
510
548
 
511
549
  for (const userMediaError of sample.userMediaErrors ?? []) {
@@ -903,8 +941,12 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
903
941
 
904
942
  this.avgRttInMs = this._peerConnections.size ? sumRttInMs / this._peerConnections.size : undefined;
905
943
 
944
+ // to make sure when sample is emitted it can be associated to this client
945
+ sample.clientId = this.clientId;
946
+
906
947
  this._updated = now;
907
948
  this.emit('update', {
949
+ sample,
908
950
  elapsedTimeInMs,
909
951
  });
910
952
  }
@@ -0,0 +1,56 @@
1
+ export type Middleware<T> = (
2
+ input: T,
3
+ next: (nextInput: T) => void,
4
+ ) => void;
5
+
6
+ export interface Processor<T> {
7
+ process(value: T): void;
8
+ addMiddleware(...middlewares: Middleware<T>[]): Processor<T>;
9
+ removeMiddleware(...middlewares: Middleware<T>[]): Processor<T>;
10
+ }
11
+
12
+ export function createProcessor<T>(
13
+ ): Processor<T> {
14
+ const stack: Middleware<T>[] = [];
15
+ const result: Processor<T> = {
16
+ addMiddleware: (...middlewares: Middleware<T>[]) => {
17
+ if (middlewares && 0 < middlewares.length) {
18
+ stack.push(...middlewares);
19
+ }
20
+
21
+ return result;
22
+ },
23
+
24
+ removeMiddleware: (...middlewares: Middleware<T>[]) => {
25
+ if (middlewares && 0 < middlewares.length) {
26
+ for (const process of middlewares) {
27
+ const index = stack.indexOf(process);
28
+
29
+ if (0 < index) stack.splice(index, 1);
30
+ }
31
+ }
32
+
33
+ return result;
34
+ },
35
+ process: (value: T) => {
36
+ let prevIndex = -1;
37
+ const execute = (index: number, input: T): void => {
38
+ if (index <= prevIndex) {
39
+ throw new Error('middleware must call next() only once!');
40
+ }
41
+ prevIndex = index;
42
+ const middleware = stack[index];
43
+
44
+ if (!middleware) return;
45
+
46
+ const next = (nextInput: T) => execute(index + 1, nextInput);
47
+
48
+ return middleware(input, next);
49
+ };
50
+
51
+ return execute(0, value);
52
+ },
53
+ };
54
+
55
+ return result;
56
+ }
@@ -18,8 +18,7 @@ export type ClientIssueMonitorEvents = {
18
18
  }
19
19
 
20
20
  export type ClientIssueMonitorConfig = {
21
- detectUserMediaClientIssues?: boolean;
22
- detectMediaTrackQualityLimitationClientIssues?: boolean;
21
+ // empty
23
22
  }
24
23
 
25
24
  export declare interface ClientIssueMonitor {