@observertc/client-monitor-js 3.3.1 → 3.4.1-e6caa47.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 CHANGED
@@ -1,23 +1,22 @@
1
- Javascript library to monitor WebRTC applications
2
- ---
1
+ ## Javascript library to monitor WebRTC applications
3
2
 
4
3
  @observertc/client-monitor-js is a client side library to monitor [WebRTCStats](https://www.w3.org/TR/webrtc-stats/) and to integrate your app to observertc components.
5
4
 
6
5
  Table of Contents:
7
6
 
8
- * [Quick Start](#quick-start)
9
- * [Integrations](#integrations)
10
- - [Mediasoup](#mediasoup)
11
- * [Detectors and Alerts](#detectors-and-alerts)
12
- - [Audio Desync Detector](#audio-desync-detector)
13
- - [CPU Performance Detector](#cpu-performance-detector)
14
- * [Calculated updates](#calculated-updates)
15
- * [Configurations](#configurations)
16
- * [NPM package](#npm-package)
17
- * [API docs](#api-docs)
18
- * [Schemas](#schemas)
19
- * [Getting Involved](#getting-involved)
20
- * [License](#license)
7
+ - [Quick Start](#quick-start)
8
+ - [Integrations](#integrations)
9
+ - [Mediasoup](#mediasoup)
10
+ - [Detectors and Alerts](#detectors-and-alerts)
11
+ - [Audio Desync Detector](#audio-desync-detector)
12
+ - [CPU Performance Detector](#cpu-performance-detector)
13
+ - [Calculated updates](#calculated-updates)
14
+ - [Configurations](#configurations)
15
+ - [NPM package](#npm-package)
16
+ - [API docs](#api-docs)
17
+ - [Schemas](#schemas)
18
+ - [Getting Involved](#getting-involved)
19
+ - [License](#license)
21
20
 
22
21
  ## Qucik Start
23
22
 
@@ -38,7 +37,7 @@ const config = {
38
37
  const monitor = createClientMonitor(config);
39
38
  const statsCollector = monitor.collectors.collectFromRTCPeerConnection(peerConnection);
40
39
 
41
- monitor.on('stats-collected', () => {
40
+ monitor.on("stats-collected", () => {
42
41
  const storage = monitor.storage;
43
42
  for (const inboundRtp of storage.inboundRtps()) {
44
43
  const trackId = inboundRtp.getTrackId();
@@ -51,11 +50,11 @@ statsCollector.close();
51
50
  ```
52
51
 
53
52
  The above example do as follows:
54
- 1. create a client monitor, which collect stats every 5s
55
- 2. setup a stats collector from a peer connection
56
- 3. register an event called after stats are collected
57
- 4. print out the inbound rtps and then close the stats collector we registered in step 3.
58
53
 
54
+ 1. create a client monitor, which collect stats every 5s
55
+ 2. setup a stats collector from a peer connection
56
+ 3. register an event called after stats are collected
57
+ 4. print out the inbound rtps and then close the stats collector we registered in step 3.
59
58
 
60
59
  ## Integrations
61
60
 
@@ -72,29 +71,28 @@ const config = {
72
71
  const monitor = createClientMonitor(config);
73
72
  const mediasoupStatsCollector = monitor.collectors.collectFromMediasoupDevice(mediasoupDevice);
74
73
 
75
- monitor.on('stats-collected', () => {
74
+ monitor.on("stats-collected", () => {
76
75
  // do your stuff
77
76
 
78
- // you can close detach mediasoup
77
+ // you can close detach mediasoup
79
78
  // collector by calling the close
80
79
  mediasoupStatsCollector.close();
81
- })
80
+ });
82
81
  ```
83
82
 
84
- **Important Note**: The created collector is hooked on the device 'newtransport' event,
83
+ **Important Note**: The created collector is hooked on the device 'newtransport' event,
85
84
  and can detect transports automatically when they are created after the device is added.
86
85
  If you create transports before you add the device to the monitor,
87
- transports you created before will not be monitored automatically, you need to add them
86
+ transports you created before will not be monitored automatically, you need to add them
88
87
  to the statscollector, like this:
89
88
 
90
89
  ```javascript
91
- const myTransport = // your transport created before the device is added to the monitor
92
- mediasoupStatsCollector.addTransport(myTransport)
90
+ const myTransport = mediasoupStatsCollector.addTransport(myTransport); // your transport created before the device is added to the monitor
93
91
  ```
94
92
 
95
93
  ## Calculated Updates
96
94
 
97
- The Calculated Updates lets you observer metrics derived from the polled webrtc stats captured by the library. These calculated updates provide a richer, more nuanced understanding of your application's client-side behavior, offering valuable insights beyond what raw stats metrics can give you.
95
+ The Calculated Updates lets you observer metrics derived from the polled webrtc stats captured by the library. These calculated updates provide a richer, more nuanced understanding of your application's client-side behavior, offering valuable insights beyond what raw stats metrics can give you.
98
96
 
99
97
  ### Storage Updates
100
98
 
@@ -119,7 +117,7 @@ monitor.on('stats-collected', () => {
119
117
  ### PeerConnection Updates
120
118
 
121
119
  ```javascript
122
- import { createClientMonitor } from 'client-monitor-js';
120
+ import { createClientMonitor } from "client-monitor-js";
123
121
 
124
122
  // Create a ClientMonitor instance
125
123
  const monitor = createClientMonitor({
@@ -127,22 +125,21 @@ const monitor = createClientMonitor({
127
125
  });
128
126
 
129
127
  const storage = monitor.storage;
130
- monitor.on('stats-collected', () => {
128
+ monitor.on("stats-collected", () => {
131
129
  for (const peerConnection of storage.peerConnections()) {
132
- console.log('average RTT in seconds', peerConnection.avgRttInS);
133
- console.log('Sending audio bitrate on PC', peerConnection.sendingAudioBitrate);
134
- console.log('Sending video bitrate on PC', peerConnection.sendingVideoBitrate);
135
- console.log('Receiving audio bitrate on PC', peerConnection.receivingAudioBitrate);
136
- console.log('Receiving video bitrate on PC', peerConnection.receivingVideoBitrate);
130
+ console.log("average RTT in seconds", peerConnection.avgRttInS);
131
+ console.log("Sending audio bitrate on PC", peerConnection.sendingAudioBitrate);
132
+ console.log("Sending video bitrate on PC", peerConnection.sendingVideoBitrate);
133
+ console.log("Receiving audio bitrate on PC", peerConnection.receivingAudioBitrate);
134
+ console.log("Receiving video bitrate on PC", peerConnection.receivingVideoBitrate);
137
135
  }
138
136
  });
139
-
140
137
  ```
141
138
 
142
139
  ### Inbound RTP stats updates
143
140
 
144
141
  ```javascript
145
- import { createClientMonitor } from 'client-monitor-js';
142
+ import { createClientMonitor } from "client-monitor-js";
146
143
 
147
144
  // Create a ClientMonitor instance
148
145
  const monitor = createClientMonitor({
@@ -150,24 +147,22 @@ const monitor = createClientMonitor({
150
147
  });
151
148
 
152
149
  const storage = monitor.storage;
153
- monitor.on('stats-collected', () => {
150
+ monitor.on("stats-collected", () => {
154
151
  for (const inboundRtp of storage.inboundRtps()) {
152
+ console.log("mean opinion score for inbound-rtp", inboundRtp.score);
155
153
 
156
- console.log('mean opinion score for inbound-rtp', inboundRtp.score);
157
-
158
- console.log('receiving bitrate', inboundRtp.receivingBitrate);
159
- console.log('lost packets since last stats-collected', inboundRtp.lostPackets);
160
- console.log('received packets since last stats-collected', inboundRtp.receivedPackets);
161
- console.log('decoded frames since last stats-collected', inboundRtp.decodedFrames);
154
+ console.log("receiving bitrate", inboundRtp.receivingBitrate);
155
+ console.log("lost packets since last stats-collected", inboundRtp.lostPackets);
156
+ console.log("received packets since last stats-collected", inboundRtp.receivedPackets);
157
+ console.log("decoded frames since last stats-collected", inboundRtp.decodedFrames);
162
158
  }
163
159
  });
164
-
165
160
  ```
166
161
 
167
162
  ### Outbound RTP stats updates
168
163
 
169
164
  ```javascript
170
- import { createClientMonitor } from 'client-monitor-js';
165
+ import { createClientMonitor } from "client-monitor-js";
171
166
 
172
167
  // Create a ClientMonitor instance
173
168
  const monitor = createClientMonitor({
@@ -175,19 +170,20 @@ const monitor = createClientMonitor({
175
170
  });
176
171
 
177
172
  const storage = monitor.storage;
178
- monitor.on('stats-collected', () => {
173
+ monitor.on("stats-collected", () => {
179
174
  for (const outboundRtp of storage.outboundRtps()) {
175
+ console.log("stability score outbound-rtp", outboundRtp.score);
180
176
 
181
- console.log('stability score outbound-rtp', outboundRtp.score);
177
+ console.log("sending bitrate", outboundRtp.sendingBitrate);
178
+ console.log("sent packets since last stats-collected", outboundRtp.sentPackets);
182
179
 
183
- console.log('sending bitrate', outboundRtp.sendingBitrate);
184
- console.log('sent packets since last stats-collected', outboundRtp.sentPackets);
185
-
186
180
  const remoteInboundRtp = outboundRtp.getRemoteInboundRtp();
187
- console.log('Received packets on remote inbound-rtp belongs to this outbound-rtp', remoteInboundRtp?.receivedPackets);
181
+ console.log(
182
+ "Received packets on remote inbound-rtp belongs to this outbound-rtp",
183
+ remoteInboundRtp?.receivedPackets
184
+ );
188
185
  }
189
186
  });
190
-
191
187
  ```
192
188
 
193
189
  ## Detectors and Alerts
@@ -195,8 +191,9 @@ monitor.on('stats-collected', () => {
195
191
  Detectors and alerts provide events of tracking and responding to anomalies or performance issues based on the polled stats. Detectors are components that continuously monitor for specific conditions in the polled stats, and set an alert if certain thresholds are hit. You can subscribe to alerts of an instantiated client-monitor-js and configure detectors via initial configurations.
196
192
 
197
193
  List of built-in alerts:
198
- * `audio-desync-alert`: triggered when for an audio track several acceleration and deceleration is detected in a short amount of time indicating that the controlling system tries compensate discrepancies.
199
- * `cpu-performance-alert`: triggered whenever a browser detects quality limitation becasue of CPU, or the number of decoded frames per sec hit a certain threshold
194
+
195
+ - `audio-desync-alert`: triggered when for an audio track several acceleration and deceleration is detected in a short amount of time indicating that the controlling system tries compensate discrepancies.
196
+ - `cpu-performance-alert`: triggered whenever a browser detects quality limitation becasue of CPU, or the number of decoded frames per sec hit a certain threshold
200
197
 
201
198
  ### Audio Desync Detector
202
199
 
@@ -275,24 +272,19 @@ const config = {
275
272
  /**
276
273
  * By setting it, the monitor calls the added statsCollectors periodically
277
274
  * and pulls the stats.
278
- *
279
- * DEFAULT: undefined
275
+ *
276
+ * DEFAULT: 5000
280
277
  */
281
278
  collectingPeriodInMs: 5000,
282
- /**
283
- * By setting it, the monitor make samples periodically.
284
- *
285
- * DEFAULT: undefined
286
- */
287
- samplingPeriodInMs: 10000,
288
279
 
289
280
  /**
290
- * This is the interval the monitor periodically checks
291
- * if collecting or sampling action should be invoked or not.
292
- *
293
- * DEFAULT: if collecting or sampling period is set the default value is 1000, otherwise it's undefined
281
+ * By setting this, the observer makes samples after n number or collected stats.
282
+ *
283
+ * For example if the value is 10, the observer makes a sample after 10 collected stats (in every 10 collectingPeriodInMs).
284
+ *
285
+ * DEFAULT: 1
294
286
  */
295
- tickingTimeInMs: 10000,
287
+ samplingTick: 1,
296
288
  };
297
289
  ```
298
290
 
@@ -308,11 +300,10 @@ https://observertc.org/docs/api/client-monitor-js-v2/
308
300
 
309
301
  https://github.com/observertc/schemas
310
302
 
311
-
312
303
  ## Getting Involved
313
304
 
314
- Client-monitor is made with the intention to provide an open-source monitoring solution for
315
- WebRTC developers. If you are interested in getting involved
305
+ Client-monitor is made with the intention to provide an open-source monitoring solution for
306
+ WebRTC developers. If you are interested in getting involved
316
307
  please read our [contribution](CONTRIBUTING.md) guideline.
317
308
 
318
309
  ## License
@@ -16,17 +16,13 @@ export type ClientMonitorConfig = {
16
16
  */
17
17
  collectingPeriodInMs?: number;
18
18
  /**
19
- * By setting this, the observer makes samples periodically.
19
+ * By setting this, the observer makes samples after n number or collected stats.
20
20
  *
21
- * DEFAULT: undefined
22
- */
23
- samplingPeriodInMs?: number;
24
- /**
25
- * Sets the ticking time of the timer that invokes processes for collecting, sampling, and sending.
21
+ * For example if the value is 10, the observer makes a sample after 10 collected stats (in every 10 collectingPeriodInMs).
26
22
  *
27
- * DEFAULT: 1000
23
+ * DEFAULT: undefined
28
24
  */
29
- tickingTimeInMs?: number;
25
+ samplingTick?: number;
30
26
  };
31
27
  export type AlertState = 'on' | 'off';
32
28
  export interface ClientMonitorEvents {
@@ -101,10 +97,11 @@ export declare class ClientMonitor extends TypedEventEmitter<ClientMonitorEvents
101
97
  };
102
98
  private readonly _detectors;
103
99
  private readonly _sampler;
104
- private readonly _timer;
100
+ private _timer?;
105
101
  private _lastCollectedAt;
106
102
  private _lastSampledAt;
107
103
  private _closed;
104
+ private _actualCollectingTick;
108
105
  constructor(_config: ClientMonitorConfig);
109
106
  get closed(): boolean;
110
107
  close(): void;
@@ -118,7 +115,7 @@ export declare class ClientMonitor extends TypedEventEmitter<ClientMonitorEvents
118
115
  addCustomCallEvent(event: CustomCallEvent): void;
119
116
  addLocalSDP(localSDP: string[]): void;
120
117
  setCollectingPeriod(collectingPeriodInMs: number): void;
121
- setSamplingPeriod(samplingPeriodInMs: number): void;
118
+ setSamplingTick(samplingTick: number): void;
122
119
  get audioDesyncDetector(): {
123
120
  id: string;
124
121
  update: () => Promise<void>;
@@ -132,6 +129,26 @@ export declare class ClientMonitor extends TypedEventEmitter<ClientMonitorEvents
132
129
  addCongestionDetector(config?: CongestionDetectorConfig): void;
133
130
  getTrackStats(trackId: string): TrackStats | undefined;
134
131
  getPeerConnectionStats(peerConnectionId: string): PeerConnectionEntry | undefined;
132
+ get codecs(): import("./entries/StatsEntryInterfaces").CodecEntry[];
133
+ get inboundRtps(): import("./entries/StatsEntryInterfaces").InboundRtpEntry[];
134
+ get outboundRtps(): import("./entries/StatsEntryInterfaces").OutboundRtpEntry[];
135
+ get remoteInboundRtps(): import("./entries/StatsEntryInterfaces").RemoteInboundRtpEntry[];
136
+ get remoteOutboundRtps(): import("./entries/StatsEntryInterfaces").RemoteOutboundRtpEntry[];
137
+ get mediaSources(): import("./entries/StatsEntryInterfaces").MediaSourceEntry[];
138
+ get contributingSources(): import("./entries/StatsEntryInterfaces").ContributingSourceEntry[];
139
+ get dataChannels(): import("./entries/StatsEntryInterfaces").DataChannelEntry[];
140
+ get transceivers(): import("./entries/StatsEntryInterfaces").TransceiverEntry[];
141
+ get senders(): import("./entries/StatsEntryInterfaces").SenderEntry[];
142
+ get receivers(): import("./entries/StatsEntryInterfaces").ReceiverEntry[];
143
+ get transports(): import("./entries/StatsEntryInterfaces").TransportEntry[];
144
+ get sctpTransports(): import("./entries/StatsEntryInterfaces").SctpTransportEntry[];
145
+ get iceCandidatePairs(): import("./entries/StatsEntryInterfaces").IceCandidatePairEntry[];
146
+ get iceLocalCandidates(): import("./entries/StatsEntryInterfaces").LocalCandidateEntry[];
147
+ get iceRemoteCandidates(): import("./entries/StatsEntryInterfaces").RemoteCandidateEntry[];
148
+ get certificates(): import("./entries/StatsEntryInterfaces").CertificateEntry[];
149
+ get iceServers(): import("./entries/StatsEntryInterfaces").IceServerEntry[];
150
+ get peerConnections(): PeerConnectionEntry[];
151
+ get tracks(): TrackStats[];
135
152
  private _setupTimer;
136
153
  }
137
154
  //# sourceMappingURL=ClientMonitor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ClientMonitor.d.ts","sourceRoot":"","sources":["../src/ClientMonitor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ClientMonitor.d.ts","sourceRoot":"","sources":["../src/ClientMonitor.ts"],"names":[],"mappings":"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"}
@@ -29,7 +29,6 @@ const logger_1 = require("./utils/logger");
29
29
  const ClientMetaData_1 = require("./ClientMetaData");
30
30
  const StatsStorage_1 = require("./entries/StatsStorage");
31
31
  const TypedEmitter_1 = require("./utils/TypedEmitter");
32
- const Timer_1 = require("./utils/Timer");
33
32
  const Sampler_1 = require("./Sampler");
34
33
  const Adapter_1 = require("./collectors/Adapter");
35
34
  const validators = __importStar(require("./utils/validators"));
@@ -47,10 +46,10 @@ class ClientMonitor extends TypedEmitter_1.TypedEventEmitter {
47
46
  clientMonitor: this,
48
47
  });
49
48
  this._sampler = new Sampler_1.Sampler(this.storage);
50
- this._timer = (0, Timer_1.createTimer)();
51
49
  this._lastCollectedAt = Date.now();
52
50
  this._lastSampledAt = 0;
53
51
  this._closed = false;
52
+ this._actualCollectingTick = 0;
54
53
  this.meta = new ClientMetaData_1.ClientMetaData();
55
54
  this._sampler.addBrowser(this.meta.browser);
56
55
  this._sampler.addEngine(this.meta.engine);
@@ -84,10 +83,11 @@ class ClientMonitor extends TypedEmitter_1.TypedEventEmitter {
84
83
  return;
85
84
  }
86
85
  this._closed = true;
87
- this._timer.clear();
86
+ clearInterval(this._timer);
88
87
  this.storage.clear();
89
88
  this.collectors.clear();
90
89
  this._sampler.clear();
90
+ this._timer = undefined;
91
91
  }
92
92
  async collect() {
93
93
  const collectedStats = await this.collectors.collect();
@@ -98,6 +98,10 @@ class ClientMonitor extends TypedEmitter_1.TypedEventEmitter {
98
98
  elapsedSinceLastCollectedInMs: timestamp - this._lastCollectedAt,
99
99
  });
100
100
  this._lastCollectedAt = timestamp;
101
+ if (this._config.samplingTick && this._config.samplingTick <= ++this._actualCollectingTick) {
102
+ this._actualCollectingTick = 0;
103
+ this.sample();
104
+ }
101
105
  return collectedStats;
102
106
  }
103
107
  sample() {
@@ -154,8 +158,8 @@ class ClientMonitor extends TypedEmitter_1.TypedEventEmitter {
154
158
  this._config.collectingPeriodInMs = collectingPeriodInMs;
155
159
  this._setupTimer();
156
160
  }
157
- setSamplingPeriod(samplingPeriodInMs) {
158
- this._config.samplingPeriodInMs = samplingPeriodInMs;
161
+ setSamplingTick(samplingTick) {
162
+ this._config.samplingTick = samplingTick;
159
163
  this._setupTimer();
160
164
  }
161
165
  get audioDesyncDetector() {
@@ -196,27 +200,74 @@ class ClientMonitor extends TypedEmitter_1.TypedEventEmitter {
196
200
  getPeerConnectionStats(peerConnectionId) {
197
201
  return this.storage.getPeerConnection(peerConnectionId);
198
202
  }
203
+ get codecs() {
204
+ return [...this.storage.codecs()];
205
+ }
206
+ get inboundRtps() {
207
+ return [...this.storage.inboundRtps()];
208
+ }
209
+ get outboundRtps() {
210
+ return [...this.storage.outboundRtps()];
211
+ }
212
+ get remoteInboundRtps() {
213
+ return [...this.storage.remoteInboundRtps()];
214
+ }
215
+ get remoteOutboundRtps() {
216
+ return [...this.storage.remoteOutboundRtps()];
217
+ }
218
+ get mediaSources() {
219
+ return [...this.storage.mediaSources()];
220
+ }
221
+ get contributingSources() {
222
+ return [...this.storage.contributingSources()];
223
+ }
224
+ get dataChannels() {
225
+ return [...this.storage.dataChannels()];
226
+ }
227
+ get transceivers() {
228
+ return [...this.storage.transceivers()];
229
+ }
230
+ get senders() {
231
+ return [...this.storage.senders()];
232
+ }
233
+ get receivers() {
234
+ return [...this.storage.receivers()];
235
+ }
236
+ get transports() {
237
+ return [...this.storage.transports()];
238
+ }
239
+ get sctpTransports() {
240
+ return [...this.storage.sctpTransports()];
241
+ }
242
+ get iceCandidatePairs() {
243
+ return [...this.storage.iceCandidatePairs()];
244
+ }
245
+ get iceLocalCandidates() {
246
+ return [...this.storage.localCandidates()];
247
+ }
248
+ get iceRemoteCandidates() {
249
+ return [...this.storage.remoteCandidates()];
250
+ }
251
+ get certificates() {
252
+ return [...this.storage.certificates()];
253
+ }
254
+ get iceServers() {
255
+ return [...this.storage.iceServers()];
256
+ }
257
+ get peerConnections() {
258
+ return [...this.storage.peerConnections()];
259
+ }
260
+ get tracks() {
261
+ return [...this.storage.tracks()];
262
+ }
199
263
  _setupTimer() {
200
- if (!this._config.tickingTimeInMs) {
264
+ this._timer && clearInterval(this._timer);
265
+ this._timer = undefined;
266
+ if (!this._config.collectingPeriodInMs)
201
267
  return;
202
- }
203
- if (this._config.collectingPeriodInMs) {
204
- this._timer.setCollectingAction({
205
- action: () => this.collect().then(() => {
206
- // empty
207
- }),
208
- fixedDelayInMs: this._config.collectingPeriodInMs,
209
- });
210
- }
211
- if (this._config.samplingPeriodInMs) {
212
- this._timer.setSamplingAction({
213
- action: async () => {
214
- this.sample();
215
- },
216
- fixedDelayInMs: this._config.samplingPeriodInMs,
217
- });
218
- }
219
- this._timer.tickTimeInMs = this._config.tickingTimeInMs;
268
+ this._timer = setInterval(() => {
269
+ this.collect().catch(err => logger.error(err));
270
+ }, this._config.collectingPeriodInMs);
220
271
  }
221
272
  }
222
273
  exports.ClientMonitor = ClientMonitor;
@@ -202,7 +202,7 @@ class PeerConnectionEntryManifest {
202
202
  entry.droppedFrames = (stats.framesDropped ?? 0) - (entry.stats.framesDropped ?? 0);
203
203
  entry.receivedSamples = (stats.totalSamplesReceived ?? 0) - (entry.stats.totalSamplesReceived ?? 0);
204
204
  entry.silentConcealedSamples = (stats.silentConcealedSamples ?? 0) - (entry.stats.silentConcealedSamples ?? 0);
205
- entry.fractionLoss = entry.lostPackets / (entry.lostPackets + entry.receivedPackets);
205
+ entry.fractionLoss = entry.lostPackets === 0 && entry.receivedPackets === 0 ? 0 : entry.lostPackets / (entry.lostPackets + entry.receivedPackets);
206
206
  entry.stats = stats;
207
207
  entry.visited = true;
208
208
  if (entry.stats.kind === 'audio') {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,YAAY,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AACpF,YAAY,EAAE,4BAA4B,EAAE,MAAM,2CAA2C,CAAC;AAC9F,YAAY,EACR,aAAa,EACb,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC/E,YAAY,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AACvF,YAAY,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AACjF,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,YAAY,EACR,QAAQ,GACX,MAAM,eAAe,CAAC;AAEvB,YAAY,EACR,YAAY,EACZ,kBAAkB,GACrB,MAAM,wBAAwB,CAAA;AAE/B,YAAY,EACR,UAAU,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,mBAAmB,GACtB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,QAAQ,MAAM,8BAA8B,CAAC;AAEzD,YAAY,EACX,YAAY,EACZ,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EACf,eAAe,GAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAyC,MAAM,gBAAgB,CAAC;AAEjF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG;IAC/D;;OAEG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACvB,GAAG,aAAa,CAahB;AAED,OAAO,EACH,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,YAAY,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AACpF,YAAY,EAAE,4BAA4B,EAAE,MAAM,2CAA2C,CAAC;AAC9F,YAAY,EACR,aAAa,EACb,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC/E,YAAY,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AACvF,YAAY,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AACjF,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,YAAY,EACR,QAAQ,GACX,MAAM,eAAe,CAAC;AAEvB,YAAY,EACR,YAAY,EACZ,kBAAkB,GACrB,MAAM,wBAAwB,CAAA;AAE/B,YAAY,EACR,UAAU,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,mBAAmB,GACtB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,QAAQ,MAAM,8BAA8B,CAAC;AAEzD,YAAY,EACX,YAAY,EACZ,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EACf,eAAe,GAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAyC,MAAM,gBAAgB,CAAC;AAEjF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG;IAC/D;;OAEG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACvB,GAAG,aAAa,CAchB;AAED,OAAO,EACH,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,gBAAgB,CAAC"}
package/lib/index.js CHANGED
@@ -34,17 +34,17 @@ let loggerSet = false;
34
34
  * @param config the given config to setup the observer
35
35
  */
36
36
  function createClientMonitor(config) {
37
- if (config && 0 < ((config?.collectingPeriodInMs ?? 0) + (config?.samplingPeriodInMs ?? 0))) {
38
- if (!config.tickingTimeInMs) {
39
- config.tickingTimeInMs = 1000;
40
- }
41
- }
42
37
  if (!loggerSet && config?.logLevel) {
43
38
  (0, logger_1.addLoggerProcess)((0, logger_1.createConsoleLogger)(config.logLevel));
44
39
  loggerSet = true;
45
40
  }
41
+ if (config && !config.samplingTick)
42
+ config.samplingTick = 1;
46
43
  return new ClientMonitor_1.ClientMonitor({
47
- ...(config ?? {}),
44
+ ...(config ?? {
45
+ collectingPeriodInMs: 5000,
46
+ samplingTick: 1,
47
+ }),
48
48
  });
49
49
  }
50
50
  exports.createClientMonitor = createClientMonitor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@observertc/client-monitor-js",
3
- "version": "3.3.1",
3
+ "version": "3.4.1-e6caa47.0",
4
4
  "description": "ObserveRTC Client Integration Javascript Library",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -1,15 +0,0 @@
1
- export type Timer = ReturnType<typeof createTimer>;
2
- export declare function createTimer(tickTimeInMs?: number): {
3
- readonly active: boolean;
4
- tickTimeInMs: number | undefined;
5
- setCollectingAction: (config: {
6
- action?: () => Promise<void>;
7
- fixedDelayInMs?: number;
8
- }) => void;
9
- setSamplingAction: (config: {
10
- action?: () => Promise<void>;
11
- fixedDelayInMs?: number;
12
- }) => void;
13
- clear: () => void;
14
- };
15
- //# sourceMappingURL=Timer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Timer.d.ts","sourceRoot":"","sources":["../../src/utils/Timer.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,wBAAgB,WAAW,CAAC,YAAY,CAAC,EAAE,MAAM;;;kCAkDR;QAAE,MAAM,CAAC,EAAE,MAAM,QAAQ,IAAI,CAAC,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,KAAG,IAAI;gCAgBlE;QAAE,MAAM,CAAC,EAAE,MAAM,QAAQ,IAAI,CAAC,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,KAAG,IAAI;;EAoCtG"}
@@ -1,100 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createTimer = void 0;
4
- const logger_1 = require("./logger");
5
- const logger = (0, logger_1.createLogger)(`Timer`);
6
- function createTimer(tickTimeInMs) {
7
- let timer;
8
- let collecting;
9
- let sampling;
10
- if (tickTimeInMs) {
11
- setTickingTime(tickTimeInMs);
12
- }
13
- function setTickingTime(tickInMs) {
14
- if (timer) {
15
- clearInterval(timer);
16
- timer = undefined;
17
- }
18
- if (!tickInMs) {
19
- return;
20
- }
21
- timer = setInterval(() => {
22
- if (!collecting && !sampling) {
23
- return;
24
- }
25
- const now = Date.now();
26
- let promise = Promise.resolve();
27
- if (collecting) {
28
- if (collecting.invoked) {
29
- if (collecting.invoked + collecting.fixedDelayInMs <= now) {
30
- promise = promise.then(() => collecting?.action() ?? Promise.resolve());
31
- collecting.invoked = now;
32
- }
33
- }
34
- else {
35
- promise = promise.then(() => collecting?.action() ?? Promise.resolve());
36
- collecting.invoked = now;
37
- }
38
- }
39
- if (sampling) {
40
- if (sampling.invoked) {
41
- if (sampling.invoked + sampling.fixedDelayInMs <= now) {
42
- promise = promise.then(() => sampling?.action() ?? Promise.resolve());
43
- sampling.invoked = now;
44
- }
45
- }
46
- else {
47
- promise = promise.then(() => sampling?.action() ?? Promise.resolve());
48
- sampling.invoked = now;
49
- }
50
- }
51
- promise.catch(err => {
52
- logger.warn(`Error occurred while executing timer action`, err);
53
- });
54
- }, tickInMs);
55
- }
56
- function setCollectingAction(config) {
57
- const { action, fixedDelayInMs, } = config;
58
- if (!action || !fixedDelayInMs) {
59
- collecting = undefined;
60
- return;
61
- }
62
- collecting = {
63
- action,
64
- created: Date.now(),
65
- fixedDelayInMs,
66
- };
67
- }
68
- function setSamplingAction(config) {
69
- const { action, fixedDelayInMs, } = config;
70
- if (!action || !fixedDelayInMs) {
71
- sampling = undefined;
72
- return;
73
- }
74
- sampling = {
75
- action,
76
- created: Date.now(),
77
- fixedDelayInMs,
78
- };
79
- }
80
- function clear() {
81
- if (timer) {
82
- clearInterval(timer);
83
- timer = undefined;
84
- }
85
- collecting = undefined;
86
- sampling = undefined;
87
- }
88
- return {
89
- get active() {
90
- return !!timer;
91
- },
92
- set tickTimeInMs(value) {
93
- setTickingTime(value);
94
- },
95
- setCollectingAction,
96
- setSamplingAction,
97
- clear,
98
- };
99
- }
100
- exports.createTimer = createTimer;