UNPKG

@observertc/observer-js

Version:

Server Side NodeJS Library for processing ObserveRTC Samples

220 lines (219 loc) 9.05 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ObservedCall = void 0; const events_1 = require("events"); const ObservedClient_1 = require("./ObservedClient"); const DefaultCallScoreCalculator_1 = require("./scores/DefaultCallScoreCalculator"); const Detectors_1 = require("./detectors/Detectors"); const OnAllClientCallUpdater_1 = require("./updaters/OnAllClientCallUpdater"); const OnIntervalUpdater_1 = require("./updaters/OnIntervalUpdater"); const OnAnyClientCallUpdater_1 = require("./updaters/OnAnyClientCallUpdater"); const ObservedCallEventMonitor_1 = require("./ObservedCallEventMonitor"); class ObservedCall extends events_1.EventEmitter { observer; detectors; updater; scoreCalculator; callId; observedClients = new Map(); clientsUsedTurn = new Set(); calculatedScore = { weight: 1, value: undefined, }; remoteTrackResolver; totalAddedClients = 0; totalRemovedClients = 0; totalClientsReceivedAudioBytes = 0; totalClientsReceivedVideoBytes = 0; totalClientsReceivedDataChannelBytes = 0; totalClientsReceivedBytes = 0; totalClientsSentAudioBytes = 0; totalClientsSentDataChannelBytes = 0; totalClientsSentVideoBytes = 0; totalClientsSentBytes = 0; totalRttLt50Measurements = 0; totalRttLt150Measurements = 0; totalRttLt300Measurements = 0; totalRttGtOrEq300Measurements = 0; numberOfIssues = 0; numberOfPeerConnections = 0; numberOfInboundRtpStreams = 0; numberOfOutboundRtpStreams = 0; numberOfDataChannels = 0; maxNumberOfClients = 0; deltaNumberOfIssues = 0; deltaRttLt50Measurements = 0; deltaRttLt150Measurements = 0; deltaRttLt300Measurements = 0; deltaRttGtOrEq300Measurements = 0; appData; closed = false; startedAt; endedAt; closedAt; _callStartedEvent; _callEndedEvent; constructor(settings, observer) { super(); this.observer = observer; this.setMaxListeners(Infinity); this.callId = settings.callId; this.appData = settings.appData ?? {}; this.scoreCalculator = new DefaultCallScoreCalculator_1.DefaultCallScoreCalculator(this); this.detectors = new Detectors_1.Detectors(); if (settings.updateIntervalInMs) { if (settings.updatePolicy !== 'update-on-interval') { throw new Error('updatePolicy must be update-on-interval if updateIntervalInMs is set in config'); } } switch (settings.updatePolicy) { case 'update-on-any-client-updated': this.updater = new OnAnyClientCallUpdater_1.OnAnyClientCallUpdater(this); break; case 'update-when-all-client-updated': this.updater = new OnAllClientCallUpdater_1.OnAllClientCallUpdater(this); break; case 'update-on-interval': if (!settings.updateIntervalInMs) { throw new Error('updateIntervalInMs setting in config must be set if updatePolicy is update-on-interval'); } this.updater = new OnIntervalUpdater_1.OnIntervalUpdater(settings.updateIntervalInMs, this.update.bind(this)); break; } switch (settings.remoteTrackResolvePolicy) { case 'mediasoup-sfu': break; } this._callStartedEvent = { emitted: false, }; this._callEndedEvent = { emitted: false, }; } get numberOfClients() { return this.observedClients.size; } get score() { return this.calculatedScore.value; } close() { if (this.closed) return; this.update(); // last update before closing this.closed = true; this.updater?.close(); let minSampleTimestamps; let maxSampleTimestamps; for (const client of this.observedClients.values()) { client.close(); if (client.joinedAt) minSampleTimestamps = Math.min(minSampleTimestamps ?? client.joinedAt, client.joinedAt); if (client.leftAt) maxSampleTimestamps = Math.max(maxSampleTimestamps ?? client.leftAt, client.leftAt); } if (this.startedAt === undefined) this.startedAt = minSampleTimestamps; if (this.endedAt === undefined) this.endedAt = maxSampleTimestamps; this.closedAt = Date.now(); this.emit('close'); } getObservedClient(clientId) { if (this.closed || !this.observedClients.has(clientId)) return; return this.observedClients.get(clientId); } createObservedClient(settings) { if (this.closed) throw new Error(`Call ${this.callId} is closed`); if (this.observedClients.has(settings.clientId)) throw new Error(`Client with id ${settings.clientId} already exists`); const result = new ObservedClient_1.ObservedClient(settings, this); const wasEmpty = this.observedClients.size === 0; const onUpdate = () => this._onClientUpdate(result); const joined = () => this._clientJoined(result); const left = () => this._clientLeft(result); result.once('close', () => { result.off('update', onUpdate); result.off('joined', joined); result.off('left', left); this.observedClients.delete(settings.clientId); if (this.observedClients.size === 0) { this.emit('empty'); } ++this.totalRemovedClients; }); result.on('update', onUpdate); result.on('joined', joined); result.on('left', left); ++this.totalAddedClients; this.observedClients.set(settings.clientId, result); this.maxNumberOfClients = Math.max(this.maxNumberOfClients, this.observedClients.size); this.emit('newclient', result); if (wasEmpty) { this.emit('not-empty'); } return result; } createEventMonitor(context) { return new ObservedCallEventMonitor_1.ObservedCallEventMonitor(this, context); } update() { if (this.closed) return; this.numberOfInboundRtpStreams = 0; this.numberOfOutboundRtpStreams = 0; this.numberOfPeerConnections = 0; this.numberOfDataChannels = 0; for (const client of this.observedClients.values()) { this.numberOfInboundRtpStreams += client.numberOfInboundRtpStreams; this.numberOfOutboundRtpStreams += client.numberOfOutboundRtpStreams; this.numberOfPeerConnections += client.numberOfPeerConnections; this.numberOfDataChannels += client.numberOfDataChannels; } this.detectors.update(); this.scoreCalculator.update(); this.emit('update'); this.deltaNumberOfIssues = 0; this.deltaRttLt50Measurements = 0; this.deltaRttLt150Measurements = 0; this.deltaRttLt300Measurements = 0; this.deltaRttGtOrEq300Measurements = 0; } _onClientUpdate(client) { this.totalClientsReceivedAudioBytes += client.deltaReceivedAudioBytes; this.totalClientsReceivedVideoBytes += client.deltaReceivedVideoBytes; this.totalClientsReceivedDataChannelBytes += client.deltaDataChannelBytesReceived; this.totalClientsReceivedBytes += client.deltaTransportReceivedBytes; this.totalClientsSentAudioBytes += client.deltaSentAudioBytes; this.totalClientsSentVideoBytes += client.deltaSentVideoBytes; this.totalClientsSentDataChannelBytes += client.deltaDataChannelBytesSent; this.totalClientsSentBytes += client.deltaTransportSentBytes; this.deltaRttLt50Measurements += client.deltaRttLt50Measurements; this.deltaRttLt150Measurements += client.deltaRttLt150Measurements; this.deltaRttLt300Measurements += client.deltaRttLt300Measurements; this.deltaRttGtOrEq300Measurements += client.deltaRttGtOrEq300Measurements; this.totalRttLt50Measurements += client.deltaRttLt50Measurements; this.totalRttLt150Measurements += client.deltaRttLt150Measurements; this.totalRttLt300Measurements += client.deltaRttLt300Measurements; this.totalRttGtOrEq300Measurements += client.deltaRttGtOrEq300Measurements; this.deltaNumberOfIssues += client.deltaNumberOfIssues; this.numberOfIssues += client.deltaNumberOfIssues; if (client.usingTURN) { this.clientsUsedTurn.add(client.clientId); } } _clientJoined(client) { if (!client.joinedAt) return; this.startedAt = Math.min(this.startedAt ?? client.joinedAt, client.joinedAt); } _clientLeft(client) { if (!client.leftAt) return; this.endedAt = Math.max(this.endedAt ?? client.leftAt, client.leftAt); } } exports.ObservedCall = ObservedCall;