@observertc/observer-js 0.30.2-beta → 0.30.4-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/ObservedClient.d.ts +34 -22
- package/lib/ObservedClient.d.ts.map +1 -1
- package/lib/ObservedClient.js +95 -13
- package/lib/ObservedInboundTrack.d.ts +20 -8
- package/lib/ObservedInboundTrack.d.ts.map +1 -1
- package/lib/ObservedInboundTrack.js +59 -26
- package/lib/ObservedOutboundTrack.d.ts +20 -3
- package/lib/ObservedOutboundTrack.d.ts.map +1 -1
- package/lib/ObservedOutboundTrack.js +53 -9
- package/lib/ObservedPeerConnection.d.ts +15 -10
- package/lib/ObservedPeerConnection.d.ts.map +1 -1
- package/lib/ObservedPeerConnection.js +113 -19
- package/package.json +1 -1
- package/src/ObservedClient.ts +119 -28
- package/src/ObservedInboundTrack.ts +62 -17
- package/src/ObservedOutboundTrack.ts +70 -9
- package/src/ObservedPeerConnection.ts +146 -23
- package/lib/common/ReportsCollector.d.ts +0 -23
- package/lib/common/ReportsCollector.d.ts.map +0 -1
- package/lib/common/ReportsCollector.js +0 -26
- package/src/common/ReportsCollector.ts +0 -71
|
@@ -61,6 +61,17 @@ class ObservedOutboundTrack extends events_1.EventEmitter {
|
|
|
61
61
|
this._model = _model;
|
|
62
62
|
this.peerConnection = peerConnection;
|
|
63
63
|
this._storageProvider = _storageProvider;
|
|
64
|
+
this.bitrate = 0;
|
|
65
|
+
this.totalLostPackets = 0;
|
|
66
|
+
this.totalSentPackets = 0;
|
|
67
|
+
this.totalSentBytes = 0;
|
|
68
|
+
this.totalSentFrames = 0;
|
|
69
|
+
this.deltaLostPackets = 0;
|
|
70
|
+
this.deltaSentPackets = 0;
|
|
71
|
+
this.deltaSentBytes = 0;
|
|
72
|
+
this.deltaSentFrames = 0;
|
|
73
|
+
this.deltaEncodedFrames = 0;
|
|
74
|
+
this.created = Date.now();
|
|
64
75
|
this._stats = new Map();
|
|
65
76
|
this._execute = (0, SingleExecutor_1.createSingleExecutor)();
|
|
66
77
|
this._closed = false;
|
|
@@ -78,9 +89,6 @@ class ObservedOutboundTrack extends events_1.EventEmitter {
|
|
|
78
89
|
get sfuStreamId() {
|
|
79
90
|
return this._model.sfuStreamId;
|
|
80
91
|
}
|
|
81
|
-
get closed() {
|
|
82
|
-
return this._closed;
|
|
83
|
-
}
|
|
84
92
|
get remoteInboundTracks() {
|
|
85
93
|
return this._remoteInboundTracks;
|
|
86
94
|
}
|
|
@@ -90,6 +98,15 @@ class ObservedOutboundTrack extends events_1.EventEmitter {
|
|
|
90
98
|
get updated() {
|
|
91
99
|
return this._updated;
|
|
92
100
|
}
|
|
101
|
+
get stats() {
|
|
102
|
+
return this._stats;
|
|
103
|
+
}
|
|
104
|
+
get uptimeInMs() {
|
|
105
|
+
return this._updated - this.created;
|
|
106
|
+
}
|
|
107
|
+
get closed() {
|
|
108
|
+
return this._closed;
|
|
109
|
+
}
|
|
93
110
|
close() {
|
|
94
111
|
if (this._closed)
|
|
95
112
|
return;
|
|
@@ -98,11 +115,17 @@ class ObservedOutboundTrack extends events_1.EventEmitter {
|
|
|
98
115
|
.catch(() => void 0)
|
|
99
116
|
.finally(() => this.emit('close'));
|
|
100
117
|
}
|
|
101
|
-
|
|
102
|
-
|
|
118
|
+
resetMetrics() {
|
|
119
|
+
this.bitrate = 0;
|
|
120
|
+
this.rttInMs = 0;
|
|
121
|
+
this.deltaLostPackets = 0;
|
|
122
|
+
this.deltaSentPackets = 0;
|
|
123
|
+
this.deltaSentBytes = 0;
|
|
124
|
+
this.deltaSentFrames = 0;
|
|
125
|
+
this.deltaEncodedFrames = 0;
|
|
103
126
|
}
|
|
104
127
|
update(sample, timestamp) {
|
|
105
|
-
var _a, _b;
|
|
128
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
106
129
|
return __awaiter(this, void 0, void 0, function* () {
|
|
107
130
|
if (this._closed)
|
|
108
131
|
return;
|
|
@@ -116,13 +139,34 @@ class ObservedOutboundTrack extends events_1.EventEmitter {
|
|
|
116
139
|
const lastStat = this._stats.get(sample.ssrc);
|
|
117
140
|
const rttInMs = sample.roundTripTime ? sample.roundTripTime * 1000 : undefined;
|
|
118
141
|
const bitrate = (((_a = sample.bytesSent) !== null && _a !== void 0 ? _a : 0) - ((_b = lastStat === null || lastStat === void 0 ? void 0 : lastStat.bytesSent) !== null && _b !== void 0 ? _b : 0)) * 8 / (elapsedTimeInMs / 1000);
|
|
119
|
-
|
|
120
|
-
|
|
142
|
+
const deltaLostPackets = ((_c = sample.packetsLost) !== null && _c !== void 0 ? _c : 0) - ((_d = lastStat === null || lastStat === void 0 ? void 0 : lastStat.packetsLost) !== null && _d !== void 0 ? _d : 0);
|
|
143
|
+
const deltaSentPackets = ((_e = sample.packetsSent) !== null && _e !== void 0 ? _e : 0) - ((_f = lastStat === null || lastStat === void 0 ? void 0 : lastStat.packetsSent) !== null && _f !== void 0 ? _f : 0);
|
|
144
|
+
const deltaSentBytes = ((_g = sample.bytesSent) !== null && _g !== void 0 ? _g : 0) - ((_h = lastStat === null || lastStat === void 0 ? void 0 : lastStat.bytesSent) !== null && _h !== void 0 ? _h : 0);
|
|
145
|
+
let deltaEncodedFrames;
|
|
146
|
+
let deltaSentFrames;
|
|
147
|
+
if (this.kind === 'video') {
|
|
148
|
+
const videoSample = sample;
|
|
149
|
+
const lastVideoStats = lastStat;
|
|
150
|
+
deltaEncodedFrames = ((_j = videoSample.framesEncoded) !== null && _j !== void 0 ? _j : 0) - ((_k = lastVideoStats === null || lastVideoStats === void 0 ? void 0 : lastVideoStats.framesEncoded) !== null && _k !== void 0 ? _k : 0);
|
|
151
|
+
deltaSentFrames = ((_l = videoSample.framesSent) !== null && _l !== void 0 ? _l : 0) - ((_m = lastVideoStats === null || lastVideoStats === void 0 ? void 0 : lastVideoStats.framesSent) !== null && _m !== void 0 ? _m : 0);
|
|
152
|
+
}
|
|
121
153
|
const stats = Object.assign(Object.assign({}, sample), { rttInMs,
|
|
122
|
-
bitrate, ssrc: sample.ssrc
|
|
154
|
+
bitrate, ssrc: sample.ssrc, deltaLostPackets,
|
|
155
|
+
deltaSentPackets,
|
|
156
|
+
deltaSentBytes,
|
|
157
|
+
deltaEncodedFrames,
|
|
158
|
+
deltaSentFrames });
|
|
123
159
|
this._stats.set(sample.ssrc, stats);
|
|
124
160
|
this.bitrate = [...this._stats.values()].reduce((acc, stat) => acc + stat.bitrate, 0);
|
|
125
161
|
this.rttInMs = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.rttInMs) !== null && _a !== void 0 ? _a : 0); }, 0) / (this._stats.size || 1);
|
|
162
|
+
this.totalLostPackets = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.packetsLost) !== null && _a !== void 0 ? _a : 0); }, 0);
|
|
163
|
+
this.totalSentPackets = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.packetsSent) !== null && _a !== void 0 ? _a : 0); }, 0);
|
|
164
|
+
this.totalSentBytes = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.bytesSent) !== null && _a !== void 0 ? _a : 0); }, 0);
|
|
165
|
+
this.deltaEncodedFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.deltaEncodedFrames) !== null && _a !== void 0 ? _a : 0); }, 0);
|
|
166
|
+
this.deltaSentFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.deltaSentFrames) !== null && _a !== void 0 ? _a : 0); }, 0);
|
|
167
|
+
this.deltaLostPackets = [...this._stats.values()].reduce((acc, stat) => acc + stat.deltaLostPackets, 0);
|
|
168
|
+
this.deltaSentPackets = [...this._stats.values()].reduce((acc, stat) => acc + stat.deltaSentPackets, 0);
|
|
169
|
+
this.deltaSentBytes = [...this._stats.values()].reduce((acc, stat) => acc + stat.deltaSentBytes, 0);
|
|
126
170
|
// setting up sfu connection as it is not always available at the first sample
|
|
127
171
|
if (sample.sfuStreamId && !this._model.sfuStreamId) {
|
|
128
172
|
this._model.sfuStreamId = sample.sfuStreamId;
|
|
@@ -13,9 +13,6 @@ export type ObservedPeerConnectionEvents = {
|
|
|
13
13
|
newinboudvideotrack: [ObservedInboundTrack<'video'>];
|
|
14
14
|
newoutboundaudiotrack: [ObservedOutboundTrack<'audio'>];
|
|
15
15
|
newoutboundvideotrack: [ObservedOutboundTrack<'video'>];
|
|
16
|
-
iceconnectionstatechange: [string];
|
|
17
|
-
icegatheringstatechange: [string];
|
|
18
|
-
connectionstatechange: [string];
|
|
19
16
|
};
|
|
20
17
|
export type ObservedPeerConnectionConfig = {
|
|
21
18
|
peerConnectionId: string;
|
|
@@ -32,26 +29,31 @@ export declare class ObservedPeerConnection extends EventEmitter {
|
|
|
32
29
|
readonly client: ObservedClient;
|
|
33
30
|
private readonly _storageProvider;
|
|
34
31
|
static create(config: ObservedPeerConnectionConfig, client: ObservedClient, storageProvider: StorageProvider): Promise<ObservedPeerConnection>;
|
|
32
|
+
created: number;
|
|
35
33
|
totalInboundPacketsLost: number;
|
|
36
34
|
totalInboundPacketsReceived: number;
|
|
37
|
-
totalOutboundPacketsLost: number;
|
|
38
|
-
totalOutboundPacketsReceived: number;
|
|
39
35
|
totalOutboundPacketsSent: number;
|
|
40
36
|
totalDataChannelBytesSent: number;
|
|
41
37
|
totalDataChannelBytesReceived: number;
|
|
42
38
|
totalSentAudioBytes: number;
|
|
43
39
|
totalSentVideoBytes: number;
|
|
40
|
+
totalSentAudioPackets: number;
|
|
41
|
+
totalSentVideoPackets: number;
|
|
42
|
+
totalReceivedAudioPacktes: number;
|
|
43
|
+
totalReceivedVideoPackets: number;
|
|
44
44
|
totalReceivedAudioBytes: number;
|
|
45
45
|
totalReceivedVideoBytes: number;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
deltaOutboundPacketsReceived: number;
|
|
50
|
-
deltaOutboundPacketsSent: number;
|
|
46
|
+
deltaInboundLostPackets: number;
|
|
47
|
+
deltaInboundReceivedPackets: number;
|
|
48
|
+
deltaOutboundSentPackets: number;
|
|
51
49
|
deltaDataChannelBytesSent: number;
|
|
52
50
|
deltaDataChannelBytesReceived: number;
|
|
51
|
+
deltaInboundReceivedBytes: number;
|
|
52
|
+
deltaOutboundSentBytes: number;
|
|
53
53
|
deltaReceivedAudioBytes: number;
|
|
54
54
|
deltaReceivedVideoBytes: number;
|
|
55
|
+
deltaReceivedAudioPackets: number;
|
|
56
|
+
deltaReceivedVideoPackets: number;
|
|
55
57
|
deltaSentAudioBytes: number;
|
|
56
58
|
deltaSentVideoBytes: number;
|
|
57
59
|
sendingAudioBitrate: number;
|
|
@@ -81,8 +83,11 @@ export declare class ObservedPeerConnection extends EventEmitter {
|
|
|
81
83
|
get inboundVideoTracks(): ReadonlyMap<string, ObservedInboundTrack<'video'>>;
|
|
82
84
|
get outboundAudioTracks(): ReadonlyMap<string, ObservedOutboundTrack<'audio'>>;
|
|
83
85
|
get outboundVideoTracks(): ReadonlyMap<string, ObservedOutboundTrack<'video'>>;
|
|
86
|
+
get uptimeInMs(): number;
|
|
84
87
|
get closed(): boolean;
|
|
85
88
|
close(): void;
|
|
89
|
+
getTrack(trackId: string): ObservedInboundTrack<'audio'> | ObservedInboundTrack<'video'> | ObservedOutboundTrack<'audio'> | ObservedOutboundTrack<'video'> | undefined;
|
|
90
|
+
resetMetrics(): void;
|
|
86
91
|
updateMetrics(): void;
|
|
87
92
|
update(sample: PeerConnectionTransport, timestamp: number): void;
|
|
88
93
|
updateSelectedCandidate(localCandidate: IceLocalCandidate, remoteCandidate: IceRemoteCandidate): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObservedPeerConnection.d.ts","sourceRoot":"","sources":["../src/ObservedPeerConnection.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC/G,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAG7F,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,MAAM,4BAA4B,GAAG;IAC1C,MAAM,EAAE,EAAE,CAAC;IACX,KAAK,EAAE,EAAE,CAAC;IACV,mBAAmB,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,mBAAmB,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,qBAAqB,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC;IACxD,qBAAqB,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ObservedPeerConnection.d.ts","sourceRoot":"","sources":["../src/ObservedPeerConnection.ts"],"names":[],"mappings":"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"}
|
|
@@ -60,26 +60,31 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
60
60
|
this._model = _model;
|
|
61
61
|
this.client = client;
|
|
62
62
|
this._storageProvider = _storageProvider;
|
|
63
|
+
this.created = Date.now();
|
|
63
64
|
this.totalInboundPacketsLost = 0;
|
|
64
65
|
this.totalInboundPacketsReceived = 0;
|
|
65
|
-
this.totalOutboundPacketsLost = 0;
|
|
66
|
-
this.totalOutboundPacketsReceived = 0;
|
|
67
66
|
this.totalOutboundPacketsSent = 0;
|
|
68
67
|
this.totalDataChannelBytesSent = 0;
|
|
69
68
|
this.totalDataChannelBytesReceived = 0;
|
|
70
69
|
this.totalSentAudioBytes = 0;
|
|
71
70
|
this.totalSentVideoBytes = 0;
|
|
71
|
+
this.totalSentAudioPackets = 0;
|
|
72
|
+
this.totalSentVideoPackets = 0;
|
|
73
|
+
this.totalReceivedAudioPacktes = 0;
|
|
74
|
+
this.totalReceivedVideoPackets = 0;
|
|
72
75
|
this.totalReceivedAudioBytes = 0;
|
|
73
76
|
this.totalReceivedVideoBytes = 0;
|
|
74
|
-
this.
|
|
75
|
-
this.
|
|
76
|
-
this.
|
|
77
|
-
this.deltaOutboundPacketsReceived = 0;
|
|
78
|
-
this.deltaOutboundPacketsSent = 0;
|
|
77
|
+
this.deltaInboundLostPackets = 0;
|
|
78
|
+
this.deltaInboundReceivedPackets = 0;
|
|
79
|
+
this.deltaOutboundSentPackets = 0;
|
|
79
80
|
this.deltaDataChannelBytesSent = 0;
|
|
80
81
|
this.deltaDataChannelBytesReceived = 0;
|
|
82
|
+
this.deltaInboundReceivedBytes = 0;
|
|
83
|
+
this.deltaOutboundSentBytes = 0;
|
|
81
84
|
this.deltaReceivedAudioBytes = 0;
|
|
82
85
|
this.deltaReceivedVideoBytes = 0;
|
|
86
|
+
this.deltaReceivedAudioPackets = 0;
|
|
87
|
+
this.deltaReceivedVideoPackets = 0;
|
|
83
88
|
this.deltaSentAudioBytes = 0;
|
|
84
89
|
this.deltaSentVideoBytes = 0;
|
|
85
90
|
this.sendingAudioBitrate = 0;
|
|
@@ -126,6 +131,9 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
126
131
|
get outboundVideoTracks() {
|
|
127
132
|
return this._outboundVideoTracks;
|
|
128
133
|
}
|
|
134
|
+
get uptimeInMs() {
|
|
135
|
+
return this._updated - this.created;
|
|
136
|
+
}
|
|
129
137
|
get closed() {
|
|
130
138
|
return this._closed;
|
|
131
139
|
}
|
|
@@ -141,28 +149,94 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
141
149
|
.catch(() => void 0)
|
|
142
150
|
.finally(() => this.emit('close'));
|
|
143
151
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
this.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
this.
|
|
150
|
-
this.
|
|
151
|
-
this.
|
|
152
|
-
this.receivingAudioBitrate = 0;
|
|
153
|
-
this.receivingVideoBitrate = 0;
|
|
152
|
+
getTrack(trackId) {
|
|
153
|
+
var _a, _b, _c;
|
|
154
|
+
return (_c = (_b = (_a = this._inboundAudioTracks.get(trackId)) !== null && _a !== void 0 ? _a : this._inboundVideoTracks.get(trackId)) !== null && _b !== void 0 ? _b : this._outboundAudioTracks.get(trackId)) !== null && _c !== void 0 ? _c : this._outboundVideoTracks.get(trackId);
|
|
155
|
+
}
|
|
156
|
+
resetMetrics() {
|
|
157
|
+
this.deltaInboundLostPackets = 0;
|
|
158
|
+
this.deltaInboundReceivedPackets = 0;
|
|
159
|
+
this.deltaOutboundSentPackets = 0;
|
|
154
160
|
this.deltaDataChannelBytesSent = 0;
|
|
155
161
|
this.deltaDataChannelBytesReceived = 0;
|
|
156
162
|
this.deltaReceivedAudioBytes = 0;
|
|
157
163
|
this.deltaReceivedVideoBytes = 0;
|
|
158
164
|
this.deltaSentAudioBytes = 0;
|
|
159
165
|
this.deltaSentVideoBytes = 0;
|
|
166
|
+
this._inboundAudioTracks.forEach((track) => track.resetMetrics());
|
|
167
|
+
this._inboundVideoTracks.forEach((track) => track.resetMetrics());
|
|
168
|
+
this._outboundAudioTracks.forEach((track) => track.resetMetrics());
|
|
169
|
+
this._outboundVideoTracks.forEach((track) => track.resetMetrics());
|
|
170
|
+
}
|
|
171
|
+
updateMetrics() {
|
|
172
|
+
this.totalInboundPacketsLost = 0;
|
|
173
|
+
this.totalInboundPacketsReceived = 0;
|
|
174
|
+
this.totalOutboundPacketsSent = 0;
|
|
175
|
+
this.totalDataChannelBytesSent = 0;
|
|
176
|
+
this.totalDataChannelBytesReceived = 0;
|
|
177
|
+
this.totalSentAudioBytes = 0;
|
|
178
|
+
this.totalSentVideoBytes = 0;
|
|
179
|
+
this.totalReceivedAudioBytes = 0;
|
|
180
|
+
this.totalReceivedVideoBytes = 0;
|
|
181
|
+
this.sendingAudioBitrate = 0;
|
|
182
|
+
this.sendingVideoBitrate = 0;
|
|
183
|
+
this.receivingAudioBitrate = 0;
|
|
184
|
+
this.receivingVideoBitrate = 0;
|
|
185
|
+
let sumRttInS = 0;
|
|
160
186
|
this._inboundAudioTracks.forEach((track) => {
|
|
161
|
-
|
|
187
|
+
var _a;
|
|
188
|
+
this.deltaInboundLostPackets += track.deltaLostPackets;
|
|
189
|
+
this.deltaInboundReceivedPackets += track.deltaReceivedPackets;
|
|
190
|
+
this.deltaInboundReceivedBytes += track.deltaBytesReceived;
|
|
191
|
+
this.deltaReceivedAudioBytes += track.deltaBytesReceived;
|
|
192
|
+
this.deltaReceivedAudioPackets += track.deltaReceivedPackets;
|
|
193
|
+
this.receivingAudioBitrate += track.bitrate;
|
|
194
|
+
this.totalInboundPacketsLost += track.totalLostPackets;
|
|
195
|
+
this.totalInboundPacketsReceived += track.totalReceivedPackets;
|
|
196
|
+
this.totalReceivedAudioBytes += track.totalBytesReceived;
|
|
197
|
+
this.totalReceivedAudioPacktes += track.totalReceivedPackets;
|
|
198
|
+
sumRttInS = ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0) / 1000.0;
|
|
162
199
|
});
|
|
163
200
|
this._inboundVideoTracks.forEach((track) => {
|
|
164
|
-
|
|
201
|
+
var _a;
|
|
202
|
+
this.deltaInboundLostPackets += track.deltaLostPackets;
|
|
203
|
+
this.deltaInboundReceivedPackets += track.deltaReceivedPackets;
|
|
204
|
+
this.deltaInboundReceivedBytes += track.deltaBytesReceived;
|
|
205
|
+
this.deltaReceivedVideoBytes += track.deltaBytesReceived;
|
|
206
|
+
this.deltaReceivedVideoPackets += track.deltaReceivedPackets;
|
|
207
|
+
this.receivingVideoBitrate += track.bitrate;
|
|
208
|
+
this.totalInboundPacketsLost += track.totalLostPackets;
|
|
209
|
+
this.totalInboundPacketsReceived += track.totalReceivedPackets;
|
|
210
|
+
this.totalReceivedVideoBytes += track.totalBytesReceived;
|
|
211
|
+
this.totalReceivedVideoPackets += track.totalReceivedPackets;
|
|
212
|
+
sumRttInS = ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0) / 1000.0;
|
|
213
|
+
});
|
|
214
|
+
this._outboundAudioTracks.forEach((track) => {
|
|
215
|
+
var _a;
|
|
216
|
+
this.deltaOutboundSentPackets += track.deltaSentPackets;
|
|
217
|
+
this.deltaOutboundSentBytes += track.deltaSentBytes;
|
|
218
|
+
this.deltaSentAudioBytes += track.deltaSentBytes;
|
|
219
|
+
this.deltaSentAudioBytes += track.deltaSentPackets;
|
|
220
|
+
this.sendingAudioBitrate += track.bitrate;
|
|
221
|
+
this.totalOutboundPacketsSent += track.totalSentPackets;
|
|
222
|
+
this.totalSentAudioBytes += track.totalSentBytes;
|
|
223
|
+
this.totalSentAudioPackets += track.totalSentPackets;
|
|
224
|
+
sumRttInS = ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0) / 1000.0;
|
|
225
|
+
});
|
|
226
|
+
this._outboundVideoTracks.forEach((track) => {
|
|
227
|
+
var _a;
|
|
228
|
+
this.deltaOutboundSentPackets += track.deltaSentPackets;
|
|
229
|
+
this.deltaOutboundSentBytes += track.deltaSentBytes;
|
|
230
|
+
this.deltaSentVideoBytes += track.deltaSentBytes;
|
|
231
|
+
this.deltaSentVideoBytes += track.deltaSentPackets;
|
|
232
|
+
this.sendingVideoBitrate += track.bitrate;
|
|
233
|
+
this.totalOutboundPacketsSent += track.totalSentPackets;
|
|
234
|
+
this.totalSentVideoBytes += track.totalSentBytes;
|
|
235
|
+
this.totalSentVideoPackets += track.totalSentPackets;
|
|
236
|
+
sumRttInS = ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0) / 1000.0;
|
|
165
237
|
});
|
|
238
|
+
const nrOfBelongings = this._inboundAudioTracks.size + this._inboundVideoTracks.size + this._outboundAudioTracks.size + this._outboundVideoTracks.size;
|
|
239
|
+
this.avgRttInS = 0 < nrOfBelongings ? sumRttInS / nrOfBelongings : undefined;
|
|
166
240
|
}
|
|
167
241
|
update(sample, timestamp) {
|
|
168
242
|
if (this._closed)
|
|
@@ -187,6 +261,11 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
187
261
|
kind: 'audio',
|
|
188
262
|
trackId: config.trackId,
|
|
189
263
|
}, this, this._storageProvider);
|
|
264
|
+
const pendingTracksTimestamp = this.client.ωpendingCreatedTracksTimestamp.get(result.trackId);
|
|
265
|
+
if (pendingTracksTimestamp) {
|
|
266
|
+
this.client.ωpendingCreatedTracksTimestamp.delete(result.trackId);
|
|
267
|
+
result.created = pendingTracksTimestamp;
|
|
268
|
+
}
|
|
190
269
|
result.on('close', () => {
|
|
191
270
|
this._inboundAudioTracks.delete(result.trackId);
|
|
192
271
|
this._model.inboundTrackIds = this._model.inboundTrackIds.filter((id) => id !== result.trackId);
|
|
@@ -207,6 +286,11 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
207
286
|
kind: 'video',
|
|
208
287
|
trackId: config.trackId,
|
|
209
288
|
}, this, this._storageProvider);
|
|
289
|
+
const pendingTracksTimestamp = this.client.ωpendingCreatedTracksTimestamp.get(result.trackId);
|
|
290
|
+
if (pendingTracksTimestamp) {
|
|
291
|
+
this.client.ωpendingCreatedTracksTimestamp.delete(result.trackId);
|
|
292
|
+
result.created = pendingTracksTimestamp;
|
|
293
|
+
}
|
|
210
294
|
result.on('close', () => {
|
|
211
295
|
this._inboundVideoTracks.delete(result.trackId);
|
|
212
296
|
this._model.inboundTrackIds = this._model.inboundTrackIds.filter((id) => id !== result.trackId);
|
|
@@ -227,6 +311,11 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
227
311
|
kind: 'audio',
|
|
228
312
|
trackId: config.trackId,
|
|
229
313
|
}, this, this._storageProvider);
|
|
314
|
+
const pendingTracksTimestamp = this.client.ωpendingCreatedTracksTimestamp.get(result.trackId);
|
|
315
|
+
if (pendingTracksTimestamp) {
|
|
316
|
+
this.client.ωpendingCreatedTracksTimestamp.delete(result.trackId);
|
|
317
|
+
result.created = pendingTracksTimestamp;
|
|
318
|
+
}
|
|
230
319
|
result.on('close', () => {
|
|
231
320
|
this._outboundAudioTracks.delete(result.trackId);
|
|
232
321
|
this._model.outboundTrackIds = this._model.outboundTrackIds.filter((id) => id !== result.trackId);
|
|
@@ -249,6 +338,11 @@ class ObservedPeerConnection extends events_1.EventEmitter {
|
|
|
249
338
|
kind: 'video',
|
|
250
339
|
trackId: config.trackId,
|
|
251
340
|
}, this, this._storageProvider);
|
|
341
|
+
const pendingTracksTimestamp = this.client.ωpendingCreatedTracksTimestamp.get(result.trackId);
|
|
342
|
+
if (pendingTracksTimestamp) {
|
|
343
|
+
this.client.ωpendingCreatedTracksTimestamp.delete(result.trackId);
|
|
344
|
+
result.created = pendingTracksTimestamp;
|
|
345
|
+
}
|
|
252
346
|
result.on('close', () => {
|
|
253
347
|
this._outboundVideoTracks.delete(result.trackId);
|
|
254
348
|
result.sfuStreamId && this.client.call.sfuStreamIdToOutboundVideoTrack.set(result.sfuStreamId, result);
|
package/package.json
CHANGED
package/src/ObservedClient.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClientSample } from '@observertc/sample-schemas-js';
|
|
1
|
+
import { ClientSample, IceLocalCandidate, IceRemoteCandidate } from '@observertc/sample-schemas-js';
|
|
2
2
|
import { ObservedCall } from './ObservedCall';
|
|
3
3
|
import * as Models from './models/Models';
|
|
4
4
|
import { StorageProvider } from './storages/StorageProvider';
|
|
@@ -34,6 +34,23 @@ export type ObservedClientEvents = {
|
|
|
34
34
|
close: [],
|
|
35
35
|
'processing-sample-overflow': [],
|
|
36
36
|
newpeerconnection: [ObservedPeerConnection],
|
|
37
|
+
iceconnectionstatechange: [{
|
|
38
|
+
peerConnection: ObservedPeerConnection,
|
|
39
|
+
state: string,
|
|
40
|
+
}],
|
|
41
|
+
icegatheringstatechange: [{
|
|
42
|
+
peerConnection: ObservedPeerConnection,
|
|
43
|
+
state: string,
|
|
44
|
+
}],
|
|
45
|
+
connectionstatechange: [{
|
|
46
|
+
peerConnection: ObservedPeerConnection,
|
|
47
|
+
state: string,
|
|
48
|
+
}],
|
|
49
|
+
selectedcandidatepair: [{
|
|
50
|
+
peerConnection: ObservedPeerConnection,
|
|
51
|
+
localCandidate: IceLocalCandidate,
|
|
52
|
+
remoteCandidate: IceRemoteCandidate,
|
|
53
|
+
}],
|
|
37
54
|
};
|
|
38
55
|
|
|
39
56
|
export declare interface ObservedClient<AppData extends Record<string, unknown> = Record<string, unknown>> {
|
|
@@ -88,6 +105,8 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
88
105
|
return result;
|
|
89
106
|
}
|
|
90
107
|
|
|
108
|
+
public created = Date.now();
|
|
109
|
+
|
|
91
110
|
private readonly _peerConnections = new Map<string, ObservedPeerConnection>();
|
|
92
111
|
private readonly _execute = createSingleExecutor();
|
|
93
112
|
|
|
@@ -101,38 +120,23 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
101
120
|
|
|
102
121
|
public totalInboundPacketsLost = 0;
|
|
103
122
|
public totalInboundPacketsReceived = 0;
|
|
104
|
-
public totalOutboundPacketsLost = 0;
|
|
105
|
-
public totalOutboundPacketsReceived = 0;
|
|
106
123
|
public totalOutboundPacketsSent = 0;
|
|
107
124
|
public totalDataChannelBytesSent = 0;
|
|
108
125
|
public totalDataChannelBytesReceived = 0;
|
|
109
|
-
public
|
|
110
|
-
public
|
|
111
|
-
public totalReceivedAudioBytes = 0;
|
|
112
|
-
public totalReceivedVideoBytes = 0;
|
|
113
|
-
|
|
114
|
-
public deltaInboundPacketsLost?: number;
|
|
115
|
-
public deltaInboundPacketsReceived?: number;
|
|
116
|
-
public deltaOutboundPacketsLost?: number;
|
|
117
|
-
public deltaOutboundPacketsReceived?: number;
|
|
118
|
-
public deltaOutboundPacketsSent?: number;
|
|
119
|
-
public deltaDataChannelBytesSent?: number;
|
|
120
|
-
public deltaDataChannelBytesReceived?: number;
|
|
121
|
-
public deltaReceivedAudioBytes?: number;
|
|
122
|
-
public deltaReceivedVideoBytes?: number;
|
|
123
|
-
public deltaSentAudioBytes?: number;
|
|
124
|
-
public deltaSentVideoBytes?: number;
|
|
126
|
+
public totalSentBytes = 0;
|
|
127
|
+
public totalReceivedBytes = 0;
|
|
125
128
|
|
|
126
129
|
public avgRttInS?: number;
|
|
127
|
-
public
|
|
128
|
-
public
|
|
129
|
-
public receivingAudioBitrate?: number;
|
|
130
|
-
public receivingVideoBitrate?: number;
|
|
130
|
+
public sendingBitrate?: number;
|
|
131
|
+
public receivingBitrate?: number;
|
|
131
132
|
|
|
132
133
|
public readonly mediaDevices: string[] = [];
|
|
133
134
|
public readonly codecs: string[] = [];
|
|
134
135
|
public readonly userMediaErrors: string[] = [];
|
|
135
136
|
|
|
137
|
+
public readonly ωpendingCreatedTracksTimestamp = new Map<string, number>();
|
|
138
|
+
public readonly ωpendingCreatedPeerConnectionTimestamp = new Map<string, number>();
|
|
139
|
+
|
|
136
140
|
private constructor(
|
|
137
141
|
private readonly _model: Models.Client,
|
|
138
142
|
public readonly call: ObservedCall,
|
|
@@ -212,6 +216,10 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
212
216
|
return this._updated;
|
|
213
217
|
}
|
|
214
218
|
|
|
219
|
+
public get uptimeInMs() {
|
|
220
|
+
return this._updated - this.created;
|
|
221
|
+
}
|
|
222
|
+
|
|
215
223
|
public get closed() {
|
|
216
224
|
return this._closed;
|
|
217
225
|
}
|
|
@@ -244,6 +252,11 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
244
252
|
}
|
|
245
253
|
|
|
246
254
|
return this._execute(async () => {
|
|
255
|
+
for (const peerConnection of this._peerConnections.values()) {
|
|
256
|
+
if (peerConnection.closed) continue;
|
|
257
|
+
peerConnection.resetMetrics();
|
|
258
|
+
}
|
|
259
|
+
|
|
247
260
|
let executeSave = false;
|
|
248
261
|
|
|
249
262
|
if (this.userId !== sample.userId) {
|
|
@@ -398,22 +411,54 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
398
411
|
});
|
|
399
412
|
}
|
|
400
413
|
|
|
401
|
-
for (const { timestamp
|
|
414
|
+
for (const { timestamp, ...callEvent } of sample.customCallEvents ?? []) {
|
|
402
415
|
const peerConnection = this._peerConnections.get(callEvent.peerConnectionId ?? '');
|
|
403
416
|
|
|
404
417
|
switch (callEvent.name) {
|
|
418
|
+
case CallEventType.CLIENT_JOINED:
|
|
419
|
+
this.created = timestamp ?? this.created;
|
|
420
|
+
break;
|
|
405
421
|
case CallEventType.CLIENT_LEFT:
|
|
406
422
|
this._leaveReported = true;
|
|
407
423
|
break;
|
|
408
424
|
case CallEventType.ICE_CONNECTION_STATE_CHANGED:
|
|
409
|
-
peerConnection && callEvent.value &&
|
|
425
|
+
peerConnection && callEvent.value && this.emit('iceconnectionstatechange', {
|
|
426
|
+
peerConnection,
|
|
427
|
+
state: callEvent.value,
|
|
428
|
+
});
|
|
410
429
|
break;
|
|
411
430
|
case CallEventType.ICE_GATHERING_STATE_CHANGED:
|
|
412
|
-
peerConnection && callEvent.value &&
|
|
431
|
+
peerConnection && callEvent.value && this.emit('icegatheringstatechange', {
|
|
432
|
+
peerConnection,
|
|
433
|
+
state: callEvent.value,
|
|
434
|
+
});
|
|
413
435
|
break;
|
|
414
436
|
case CallEventType.PEER_CONNECTION_STATE_CHANGED:
|
|
415
|
-
peerConnection && callEvent.value &&
|
|
437
|
+
peerConnection && callEvent.value && this.emit('connectionstatechange', {
|
|
438
|
+
peerConnection,
|
|
439
|
+
state: callEvent.value,
|
|
440
|
+
});
|
|
416
441
|
break;
|
|
442
|
+
case CallEventType.PEER_CONNECTION_OPENED: {
|
|
443
|
+
if (!callEvent.peerConnectionId) break;
|
|
444
|
+
if (peerConnection) {
|
|
445
|
+
peerConnection.created = timestamp ?? peerConnection.created;
|
|
446
|
+
} else {
|
|
447
|
+
this.ωpendingCreatedPeerConnectionTimestamp.set(callEvent.peerConnectionId, timestamp ?? Date.now());
|
|
448
|
+
}
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
case CallEventType.MEDIA_TRACK_ADDED: {
|
|
452
|
+
if (!callEvent.mediaTrackId) break;
|
|
453
|
+
const track = peerConnection?.getTrack(callEvent.mediaTrackId);
|
|
454
|
+
|
|
455
|
+
if (track) {
|
|
456
|
+
track.created = timestamp ?? track.created;
|
|
457
|
+
} else {
|
|
458
|
+
this.ωpendingCreatedTracksTimestamp.set(callEvent.mediaTrackId, timestamp ?? Date.now());
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
417
462
|
}
|
|
418
463
|
|
|
419
464
|
this.reports.addCallEventReport({
|
|
@@ -423,7 +468,7 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
423
468
|
callId: this.callId,
|
|
424
469
|
clientId: this.clientId,
|
|
425
470
|
userId: this.userId,
|
|
426
|
-
timestamp,
|
|
471
|
+
timestamp: timestamp ?? Date.now(),
|
|
427
472
|
...callEvent,
|
|
428
473
|
});
|
|
429
474
|
}
|
|
@@ -712,6 +757,35 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
712
757
|
}
|
|
713
758
|
}
|
|
714
759
|
}
|
|
760
|
+
|
|
761
|
+
// update metrics
|
|
762
|
+
this.totalSentBytes = 0;
|
|
763
|
+
this.totalReceivedBytes = 0;
|
|
764
|
+
this.totalOutboundPacketsSent = 0;
|
|
765
|
+
this.totalInboundPacketsReceived = 0;
|
|
766
|
+
this.totalInboundPacketsLost = 0;
|
|
767
|
+
this.totalDataChannelBytesSent = 0;
|
|
768
|
+
this.totalDataChannelBytesReceived = 0;
|
|
769
|
+
this.sendingBitrate = 0;
|
|
770
|
+
this.receivingBitrate = 0;
|
|
771
|
+
let sumRttInS = 0;
|
|
772
|
+
|
|
773
|
+
for (const peerConnection of this._peerConnections.values()) {
|
|
774
|
+
if (peerConnection.closed) continue;
|
|
775
|
+
peerConnection.updateMetrics();
|
|
776
|
+
this.totalSentBytes += peerConnection.totalSentAudioBytes + peerConnection.totalSentVideoBytes;
|
|
777
|
+
this.totalReceivedBytes += peerConnection.totalReceivedAudioBytes + peerConnection.totalReceivedVideoBytes;
|
|
778
|
+
this.totalOutboundPacketsSent += peerConnection.totalOutboundPacketsSent;
|
|
779
|
+
this.totalInboundPacketsReceived += peerConnection.totalInboundPacketsReceived;
|
|
780
|
+
this.totalInboundPacketsLost += peerConnection.totalInboundPacketsLost;
|
|
781
|
+
this.totalDataChannelBytesSent += peerConnection.totalDataChannelBytesSent;
|
|
782
|
+
this.totalDataChannelBytesReceived += peerConnection.totalDataChannelBytesReceived;
|
|
783
|
+
this.sendingBitrate += peerConnection.sendingAudioBitrate + peerConnection.sendingVideoBitrate;
|
|
784
|
+
this.receivingBitrate += peerConnection.receivingAudioBitrate + peerConnection.receivingVideoBitrate;
|
|
785
|
+
sumRttInS += peerConnection.avgRttInS ?? 0;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
this.avgRttInS = this._peerConnections.size ? sumRttInS / this._peerConnections.size : -1;
|
|
715
789
|
|
|
716
790
|
if (executeSave) await this._save();
|
|
717
791
|
|
|
@@ -727,11 +801,28 @@ export class ObservedClient<AppData extends Record<string, unknown> = Record<str
|
|
|
727
801
|
peerConnectionId,
|
|
728
802
|
}, this, this._storageProvider);
|
|
729
803
|
|
|
804
|
+
const pendingTracksTimestamp = this.ωpendingCreatedTracksTimestamp.get(peerConnectionId);
|
|
805
|
+
|
|
806
|
+
if (pendingTracksTimestamp) {
|
|
807
|
+
result.created = pendingTracksTimestamp;
|
|
808
|
+
this.ωpendingCreatedTracksTimestamp.delete(peerConnectionId);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
const onNewSelectedCandidatePair = ({ localCandidate, remoteCandidate }: { localCandidate: IceLocalCandidate, remoteCandidate: IceRemoteCandidate }) => {
|
|
812
|
+
this.emit('selectedcandidatepair', {
|
|
813
|
+
peerConnection: result,
|
|
814
|
+
localCandidate,
|
|
815
|
+
remoteCandidate,
|
|
816
|
+
});
|
|
817
|
+
};
|
|
818
|
+
|
|
730
819
|
result.once('close', () => {
|
|
820
|
+
result.ICE.off('new-selected-candidate-pair', onNewSelectedCandidatePair);
|
|
731
821
|
this._peerConnections.delete(peerConnectionId);
|
|
732
822
|
this._model.peerConnectionIds = this._model.peerConnectionIds.filter((id) => id !== peerConnectionId);
|
|
733
823
|
this._save().catch(() => void 0);
|
|
734
824
|
});
|
|
825
|
+
result.ICE.on('new-selected-candidate-pair', onNewSelectedCandidatePair);
|
|
735
826
|
this._peerConnections.set(peerConnectionId, result);
|
|
736
827
|
this._model.peerConnectionIds.push(peerConnectionId);
|
|
737
828
|
await this._save();
|