@observertc/observer-js 1.3.0-rc.3 → 1.3.0-rc.5
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 +28 -16
- package/dist/index.d.mts +29 -20
- package/dist/index.d.ts +29 -20
- package/dist/index.js +41 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -404,7 +404,7 @@ See [Mediasoup router observation](#mediasoup-router-observation) for the full d
|
|
|
404
404
|
| Event | Extra | Fires when |
|
|
405
405
|
|-------|-------|-----------|
|
|
406
406
|
| `client-added` | — | a client is created |
|
|
407
|
-
| `client-sink-created` | `{ sink: Sink<ClientSample> }` | the client's sample sink was created
|
|
407
|
+
| `client-sink-created` | `{ sink: Sink<ClientSample> }` | the client's sample sink was created through `saveClientSamples`; fires right after `client-added` |
|
|
408
408
|
| `client-updated` | `{ sample: ClientSample, elapsedTimeInMs: number, context?: AcceptContext }` | the client processed a sample |
|
|
409
409
|
| `client-closed` | — | the client closed |
|
|
410
410
|
| `client-joined` | — | first `CLIENT_JOINED` event seen |
|
|
@@ -480,7 +480,10 @@ type ObserverConfig<AppData = Record<string, unknown>> = {
|
|
|
480
480
|
createCallAppData?: (p: { callId: string; observer: Observer; acceptCtx?: AcceptContext }) => Record<string, unknown>;
|
|
481
481
|
createClientAppData?: (p: { clientId: string; observedCall: ObservedCall; acceptCtx?: AcceptContext }) => Record<string, unknown>;
|
|
482
482
|
// a JSONL file per client: return its path, or undefined for none (see Sinks).
|
|
483
|
-
|
|
483
|
+
// where each client's samples are saved: exactly one of jsonlPath / sink, each a per-client callback (see Sinks).
|
|
484
|
+
saveClientSamples?:
|
|
485
|
+
| { jsonlPath: (p: { id: string; clientId: string; observedCall: ObservedCall }) => string | undefined }
|
|
486
|
+
| { sink: (p: { id: string; clientId: string; observedCall: ObservedCall }) => Sink<ClientSample> | undefined };
|
|
484
487
|
// remote-track-resolver factory — produces a call's RemoteTrackResolver (see Remote track resolution).
|
|
485
488
|
createRemoteTrackResolver?: (observedCall: ObservedCall) => RemoteTrackResolver | undefined;
|
|
486
489
|
};
|
|
@@ -1947,7 +1950,7 @@ and never crashes the process.
|
|
|
1947
1950
|
import type { Sink, SinkSettings } from '@observertc/observer-js';
|
|
1948
1951
|
|
|
1949
1952
|
interface Sink<T = unknown> { // typically: class X extends EventEmitter implements Sink<T>
|
|
1950
|
-
readonly id: string;
|
|
1953
|
+
readonly id: string; // unique per observer
|
|
1951
1954
|
write(record: T): boolean; // `false` once ended (nothing written), or on backpressure
|
|
1952
1955
|
end(): void; // idempotent; MUST emit `ended` synchronously, then flush and emit `close`
|
|
1953
1956
|
on / once / off(event, listener); // the events below
|
|
@@ -1977,18 +1980,20 @@ its id — refuse writes after it, and emit `close` / `error` for its destinatio
|
|
|
1977
1980
|
### Client samples
|
|
1978
1981
|
|
|
1979
1982
|
A client writes every accepted sample to the sink registered under its **client id** in its call's
|
|
1980
|
-
registry (`observedClient.sink` returns it), and ends that sink when it closes.
|
|
1981
|
-
|
|
1983
|
+
registry (`observedClient.sink` returns it), and ends that sink when it closes. The
|
|
1984
|
+
**`saveClientSamples`** config option decides it — exactly one of two per-client callbacks, the same
|
|
1985
|
+
`jsonlPath` / `sink` pair as `createExtensionStats` takes:
|
|
1982
1986
|
|
|
1983
|
-
|
|
|
1984
|
-
|
|
1985
|
-
| `{ jsonlPath }` |
|
|
1986
|
-
| `{ sink }` | your `Sink<ClientSample
|
|
1987
|
-
| `undefined` | none |
|
|
1987
|
+
| `saveClientSamples` | Called per client with `{ id, observedCall, clientId }`, returns | Sink |
|
|
1988
|
+
|---------------------|------------------------------------------------------------------|------|
|
|
1989
|
+
| `{ jsonlPath }` | the path of the client's file, or `undefined` | a `JsonlFileSink` at that path, created by the library under the client id |
|
|
1990
|
+
| `{ sink }` | your `Sink<ClientSample>`, or `undefined` | that sink; its `id` must be `id` |
|
|
1988
1991
|
|
|
1989
1992
|
```ts
|
|
1990
1993
|
const observer = new Observer({
|
|
1991
|
-
|
|
1994
|
+
saveClientSamples: {
|
|
1995
|
+
jsonlPath: ({ observedCall, clientId }) => `./stats/${observedCall.callId}__${clientId}.jsonl`,
|
|
1996
|
+
},
|
|
1992
1997
|
});
|
|
1993
1998
|
|
|
1994
1999
|
observer.on('client-sink-created', ({ observedClient, sink }) => {
|
|
@@ -1996,10 +2001,15 @@ observer.on('client-sink-created', ({ observedClient, sink }) => {
|
|
|
1996
2001
|
});
|
|
1997
2002
|
```
|
|
1998
2003
|
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2004
|
+
**A client's sample sink id is its client id.** The `id` the callbacks receive is that id, and
|
|
2005
|
+
with `jsonlPath` the library uses it for you. Sink ids are unique per observer, so **client ids
|
|
2006
|
+
must be unique across the observer's open calls** — client monitors generate uuids, so this
|
|
2007
|
+
normally holds. A client whose id is already a sink id gets no sink, and a warning is logged.
|
|
2008
|
+
|
|
2009
|
+
The callback is called only when the id is free, so a clash opens no file; `undefined` gives that
|
|
2010
|
+
client no sink. A returned sink with a different id is ended and not used. Giving both `jsonlPath`
|
|
2011
|
+
and `sink` is a compile error (and refused at runtime). For a JSONL file with a custom serializer,
|
|
2012
|
+
use `sink: ({ id }) => new JsonlFileSink({ id, path, serializeSample })`.
|
|
2003
2013
|
|
|
2004
2014
|
Any other destination works the same way — return your own implementation:
|
|
2005
2015
|
|
|
@@ -2031,7 +2041,9 @@ class HttpSink extends EventEmitter implements ClientSampleSink {
|
|
|
2031
2041
|
}
|
|
2032
2042
|
|
|
2033
2043
|
new Observer({
|
|
2034
|
-
|
|
2044
|
+
saveClientSamples: {
|
|
2045
|
+
sink: ({ id, clientId }) => new HttpSink({ id, url: `https://stats.example.com/${clientId}` }), // id: the client id
|
|
2046
|
+
},
|
|
2035
2047
|
});
|
|
2036
2048
|
|
|
2037
2049
|
// Or later, on `client-added`, if the client has no sink yet:
|
package/dist/index.d.mts
CHANGED
|
@@ -59,6 +59,12 @@ type SinkDestination<T = unknown> = {
|
|
|
59
59
|
sink: Sink<T>;
|
|
60
60
|
jsonlPath?: never;
|
|
61
61
|
};
|
|
62
|
+
/** What the `saveClientSamples` callbacks receive: `id` is the client's sample sink id, the client id. */
|
|
63
|
+
type ClientSinkParams<Call = unknown> = {
|
|
64
|
+
id: string;
|
|
65
|
+
observedCall: Call;
|
|
66
|
+
clientId: string;
|
|
67
|
+
};
|
|
62
68
|
|
|
63
69
|
/** A sink class `SinkRegistry.create` can construct: its constructor takes one settings object (with `id`). */
|
|
64
70
|
type SinkConstructor = new (settings: any) => Sink<any>;
|
|
@@ -2190,7 +2196,6 @@ declare class ObservedOutboundTrack implements OutboundTrackSample {
|
|
|
2190
2196
|
readonly id: string;
|
|
2191
2197
|
readonly kind: MediaKind;
|
|
2192
2198
|
private readonly _peerConnection;
|
|
2193
|
-
private readonly _outboundRtps?;
|
|
2194
2199
|
private readonly _mediaSource?;
|
|
2195
2200
|
private _visited;
|
|
2196
2201
|
appData?: Record<string, unknown>;
|
|
@@ -2222,11 +2227,12 @@ declare class ObservedOutboundTrack implements OutboundTrackSample {
|
|
|
2222
2227
|
* latest tick. Needs a `RemoteTrackResolver`: without links there are no receivers to ask.
|
|
2223
2228
|
*/
|
|
2224
2229
|
receivedRmsAudioLevel?: number;
|
|
2225
|
-
constructor(timestamp: number, id: string, kind: MediaKind, _peerConnection: ObservedPeerConnection,
|
|
2230
|
+
constructor(timestamp: number, id: string, kind: MediaKind, _peerConnection: ObservedPeerConnection, _mediaSource?: ObservedMediaSource | undefined);
|
|
2226
2231
|
get score(): number | undefined;
|
|
2227
2232
|
get visited(): boolean;
|
|
2228
2233
|
get degraded(): boolean;
|
|
2229
2234
|
getPeerConnection(): ObservedPeerConnection;
|
|
2235
|
+
/** The outbound RTPs of this track's media source, looked up on every call. */
|
|
2230
2236
|
getOutboundRtps(): ObservedOutboundRtp[] | undefined;
|
|
2231
2237
|
getMediaSource(): ObservedMediaSource | undefined;
|
|
2232
2238
|
/** The capture device behind this track, when the client sent `AUDIO_INPUT_DEVICE` metadata for it. */
|
|
@@ -2689,6 +2695,7 @@ declare class ObservedPeerConnection extends EventEmitter {
|
|
|
2689
2695
|
private _updateMediaSourceStats;
|
|
2690
2696
|
private _updateOutboundRtpStats;
|
|
2691
2697
|
private _updateOutboundTrackSample;
|
|
2698
|
+
private _removeOutboundTrack;
|
|
2692
2699
|
private _updatePeerConnectionTransportStats;
|
|
2693
2700
|
private _updateRemoteInboundRtpStats;
|
|
2694
2701
|
private _updateRemoteOutboundRtpStats;
|
|
@@ -4004,7 +4011,7 @@ declare class ObservedClient<AppData extends Record<string, unknown> = Record<st
|
|
|
4004
4011
|
/** The distinct `publicAddress`es currently known by this client's open peer connections. */
|
|
4005
4012
|
/**
|
|
4006
4013
|
* The sink this client's samples are written to: whatever is registered under its client id in
|
|
4007
|
-
* `call.sinks` (the one `
|
|
4014
|
+
* `call.sinks` (the one created through `saveClientSamples`, or a sink the application added), if any.
|
|
4008
4015
|
*/
|
|
4009
4016
|
get sink(): Sink<ClientSample> | undefined;
|
|
4010
4017
|
get publicAddresses(): string[];
|
|
@@ -4090,6 +4097,7 @@ declare class RemoteTrackResolver {
|
|
|
4090
4097
|
readonly observedCall: ObservedCall;
|
|
4091
4098
|
private readonly resolvers;
|
|
4092
4099
|
private readonly _publisherIdToOutboundTrack;
|
|
4100
|
+
private readonly _outboundTrackPublisherIds;
|
|
4093
4101
|
private readonly _subscriberIdToInboundTrack;
|
|
4094
4102
|
/**
|
|
4095
4103
|
* Tracks whose publisher id the strategy could not resolve **yet**.
|
|
@@ -5883,8 +5891,8 @@ declare class ObservedCall<AppData extends Record<string, unknown> = Record<stri
|
|
|
5883
5891
|
private _onClientUpdate;
|
|
5884
5892
|
private _clientJoined;
|
|
5885
5893
|
private _clientLeft;
|
|
5886
|
-
/** Emit an Observer-bus event scoped to this call. */
|
|
5887
5894
|
private _createClientSink;
|
|
5895
|
+
/** Emit an Observer-bus event scoped to this call. */
|
|
5888
5896
|
private _notify;
|
|
5889
5897
|
}
|
|
5890
5898
|
|
|
@@ -6445,6 +6453,14 @@ type ClientAppDataFactory = (params: {
|
|
|
6445
6453
|
observedCall: ObservedCall;
|
|
6446
6454
|
acceptCtx?: AcceptContext;
|
|
6447
6455
|
}) => Record<string, unknown>;
|
|
6456
|
+
/** `ObserverConfig.saveClientSamples`: exactly one of the two per-client callbacks. */
|
|
6457
|
+
type SaveClientSamplesConfig = {
|
|
6458
|
+
jsonlPath: (params: ClientSinkParams<ObservedCall>) => string | undefined;
|
|
6459
|
+
sink?: never;
|
|
6460
|
+
} | {
|
|
6461
|
+
sink: (params: ClientSinkParams<ObservedCall>) => Sink<ClientSample> | undefined;
|
|
6462
|
+
jsonlPath?: never;
|
|
6463
|
+
};
|
|
6448
6464
|
type ObserverConfig<AppData extends Record<string, unknown> = Record<string, unknown>> = {
|
|
6449
6465
|
/**
|
|
6450
6466
|
* Application-owned data for the observer itself. Never read or modified by the library.
|
|
@@ -6598,22 +6614,15 @@ type ObserverConfig<AppData extends Record<string, unknown> = Record<string, unk
|
|
|
6598
6614
|
/** Same as `createCallAppData`, for clients. Receives the (already-created) parent call. */
|
|
6599
6615
|
createClientAppData?: ClientAppDataFactory;
|
|
6600
6616
|
/**
|
|
6601
|
-
*
|
|
6602
|
-
*
|
|
6603
|
-
* client
|
|
6604
|
-
* when the client closes; `client-sink-created` announces it.
|
|
6605
|
-
*
|
|
6606
|
-
* ```ts
|
|
6607
|
-
* createClientSink: ({ observedCall, clientId }) => ({ jsonlPath: `./stats/${observedCall.callId}__${clientId}.jsonl` }),
|
|
6608
|
-
* ```
|
|
6617
|
+
* Where each client's samples are saved: exactly one of `jsonlPath` (return the path of the
|
|
6618
|
+
* client's JSONL file) and `sink` (return a sink whose `id` is `params.id`), each called per
|
|
6619
|
+
* client; `undefined` gives that client no sink. See the README's *Sinks* section.
|
|
6609
6620
|
*
|
|
6610
|
-
*
|
|
6621
|
+
* A client's sample sink id is its client id (`params.id`). Sink ids are unique per observer, so
|
|
6622
|
+
* client ids must be unique across the observer's open calls; a client whose id is already a sink
|
|
6623
|
+
* id gets no sink, and a warning is logged.
|
|
6611
6624
|
*/
|
|
6612
|
-
|
|
6613
|
-
id: string;
|
|
6614
|
-
observedCall: ObservedCall;
|
|
6615
|
-
clientId: string;
|
|
6616
|
-
}) => SinkDestination<ClientSample> | undefined;
|
|
6625
|
+
saveClientSamples?: SaveClientSamplesConfig;
|
|
6617
6626
|
/**
|
|
6618
6627
|
* Optional factory invoked when a call is created, producing the call's `RemoteTrackResolver`
|
|
6619
6628
|
* (or `undefined` for none). Use the built-ins
|
|
@@ -7183,7 +7192,7 @@ declare function setObserverLogger(logger: ObserverLogger): void;
|
|
|
7183
7192
|
/** The lifecycle events a client sample sink may emit. Same as {@link SinkEvents}. */
|
|
7184
7193
|
type ClientSampleSinkEvents = SinkEvents;
|
|
7185
7194
|
/**
|
|
7186
|
-
* A per-client destination for accepted samples. Return one from `ObserverConfig.
|
|
7195
|
+
* A per-client destination for accepted samples. Return one from `ObserverConfig.saveClientSamples.sink`
|
|
7187
7196
|
* (with the `id` it receives), or create one under the client id with
|
|
7188
7197
|
* `observedCall.sinks.create(MySink, { id: clientId, ... })`.
|
|
7189
7198
|
*
|
|
@@ -7253,4 +7262,4 @@ declare function createInMemorySink(samples?: ClientSample[]): InMemorySink;
|
|
|
7253
7262
|
declare function createDefaultMediasoupRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
|
|
7254
7263
|
declare function createP2pRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
|
|
7255
7264
|
|
|
7256
|
-
export { type AcceptContext, type AcceptMiddleware, type AcceptMiddlewarePayload, type ActiveClientIssue, type ActiveIssueTracker, ActiveIssuesRegistry, AudioEchoDetector, type AudioEchoDetectorConfig, AudioEchoTypes, type AudioInputDevice, type AvailableCallScopeDetectorsConfigs, type AvailableDetectorsConfigs, type AvailableObserverScopeDetectorsConfigs, type AvailableValidatorConfigs, CODEC_MISMATCH_ISSUE, type CalculatedScore, type CallAppDataFactory, CallConcurrentIssueDetector, type CallConcurrentIssueDetectorConfig, type CallConcurrentIssueGroup, CallConcurrentIssueTypes, type CallHealth, CallHealthAggregator, type CallIssue, type CallIssueSpread, type CallScopedEventName, type CallSummary, type CallSummaryClients, CallSummaryCollector, type CallSummaryConfig, type CallSummaryEnricher, type CallSummaryEnrichers, type CallSummaryScores, type CallSummarySection, type CallSummaryTruncation, type CallSummaryTurnServers, type CertificateStats, type ClientAppDataFactory, type ClientEvent, ClientEventTypes, type ClientHealth, type ClientHealthThresholds, type ClientIssue, type ClientLocation, type ClientLocationResolver, type ClientMetaData, ClientMetaTypes, type ClientPopulation, type ClientPopulationAxis, ClientPopulationIssueDetector, type ClientPopulationIssueDetectorConfig, ClientPopulationIssueTypes, type ClientSample, type ClientSampleSink, type ClientSampleSinkEvents, type CodecConsistencyReportPayload, CodecConsistencyValidator, type CodecConsistencyValidatorConfig, type CodecEvidence, type CodecStats, type CorroboratedPublisherFault, type CreateExtensionStatsSettings, type DataChannelStats, type Detector, Detectors, type ExtensionStat, ExtensionStatsRegistry, GEOHASH_CELL_SIZES, type IceCandidatePairStats, type IceCandidateStats, type IceTransportStats, InMemorySink, type InboundRtpStats, type InboundTrackSample, type Issue, type IssueBase, type IssueConclusion, IssueFanOutDetector, type IssueFanOutDetectorConfig, IssueFanOutTypes, type IssueFaultDomain, JsonlFileSink, type JsonlFileSinkOptions, LOWEST_COMMON_DENOMINATOR_ISSUE, type Logger, type MannKendallResult, type MediaKind, type MediaPlayoutStats, type MediaSourceStats, type MediasoupConsumerSample, type MediasoupConsumerSampleEvent, type MediasoupDataConsumerSample, type MediasoupDataProducerSample, type MediasoupDirectTransportSample, type MediasoupDirectTransportSampleEventMap, type MediasoupPipeTransportSample, type MediasoupPipeTransportSampleEventMap, type MediasoupPlainTransportSample, type MediasoupPlainTransportSampleEventMap, type MediasoupProducerSample, type MediasoupProducerSampleEvent, type MediasoupRouterSample, type MediasoupSampleEnricher, type MediasoupTransportSample, type MediasoupWebRtcTransportSample, type MediasoupWebRtcTransportSampleEventMap, type Middleware, MiddlewareProcessor, ObservedCall, type ObservedCallScope, type ObservedCallSettings, ObservedCertificate, ObservedClient, ObservedClientIssueRegistry, type ObservedClientScope, type ObservedClientSettings, ObservedCodec, ObservedDataChannel, ObservedIceCandidate, ObservedIceCandidatePair, ObservedIceTransport, ObservedInboundRtp, ObservedInboundTrack, ObservedMediaPlayout, ObservedMediaSource, ObservedMediasoupRouter, type ObservedMediasoupRouterEvents, type ObservedMediasoupRouterScope, type ObservedMediasoupRouterSettings, ObservedOutboundRtp, ObservedOutboundTrack, ObservedPeerConnection, type ObservedPeerConnectionScope, ObservedPeerConnectionTransport, ObservedRemoteInboundRtp, ObservedRemoteOutboundRtp, ObservedTURN, type ObservedTURNEventMap, ObservedTurnServer, Observer, ObserverConcurrentIssueDetector, type ObserverConcurrentIssueDetectorConfig, type ObserverConcurrentIssueGroup, ObserverConcurrentIssueTypes, type ObserverEventBase, type ObserverEvents, type ObserverIssue, type ObserverIssueSpread, type ObserverLogger, type OutboundRtpStats, type OutboundTrackSample, type PageHinkleyResult, type PeerConnectionSample, type PeerConnectionTransportStats, type PsnrSum, PublisherFaultCorroborationDetector, type PublisherFaultCorroborationDetectorConfig, PublisherFaultTypes, type QualityLimitationDurations, RESOLVED_ISSUE_SUFFIX, RTT_HISTOGRAM_BUCKET_WIDTH_IN_MS, RTT_HISTOGRAM_NUMBER_OF_BUCKETS, type RemoteInboundRtpStats, type RemoteOutboundRtpStats, type RemoteTrackLinkEvidence, RemoteTrackResolver, type RemoteTrackResolverFactory, type RemoteTrackResolverReportPayload, RemoteTrackResolverValidator, type RemoteTrackResolverValidatorConfig, type RemoteTrackResolvers, type ResolvedActiveClientIssue, type RttSummary, type RunningValidator, SCORE_HISTOGRAM_BUCKET_WIDTH, SCORE_HISTOGRAM_NUMBER_OF_BUCKETS, type SampleRejectedReason, type ScoreCalculator, type ScoreSummary, SfuCongestionDetector, type SfuCongestionDetectorBucket, type SfuCongestionDetectorConfig, type SfuCongestionDetectorEvaluation, type SfuCongestionDetectorReport, type SimulcastReceiverEvidence, type SimulcastReceiverReportPayload, SimulcastReceiverValidator, type SimulcastReceiverValidatorConfig, type Sink, type SinkConstructor, type SinkCreateSettings, type SinkDestination, type SinkEvents, SinkRegistry, type SinkSettings, SlidingWindow, type SlidingWindowEntry, type StatsSummary, TrackDeliveryMismatchDetector, type TrackDeliveryMismatchDetectorConfig, TrackDeliveryMismatchTypes, TrendTester, type TrendTesterConfig, type TurnServerHealth, TurnServerHealthDetector, type TurnServerHealthDetectorConfig, TurnServerHealthTypes, TurnServerOutageDetector, type TurnServerOutageDetectorConfig, TurnServerOutageTypes, UNRESOLVED_TRACK_LINKS_ISSUE, UnconsumedTrackDetector, type UnconsumedTrackDetectorConfig, UnconsumedTrackTypes, type ValidationReport, type Validator, type ValidatorName, baseIssueType, concludeCallIssue, concludeObserverIssue, correlation, counterDelta, createCallSummary, createDefaultMediasoupRemoteTrackResolverFactory, createInMemorySink, createJsonlFileSink, createLogger, createP2pRemoteTrackResolverFactory, defaultCallSummaryConfig, defaultClientHealthThresholds, geohash, isClientIssueResolutionEntry, isPublicIpAddress, issuePayloadAsString, mannKendall, mannKendallVerdict, median, medianAbsoluteDeviation, pageHinkley, percentile, percentileOfHistogram, percentileOfSorted, robustZScore, schemaVersion, setObserverLogger, summarize };
|
|
7265
|
+
export { type AcceptContext, type AcceptMiddleware, type AcceptMiddlewarePayload, type ActiveClientIssue, type ActiveIssueTracker, ActiveIssuesRegistry, AudioEchoDetector, type AudioEchoDetectorConfig, AudioEchoTypes, type AudioInputDevice, type AvailableCallScopeDetectorsConfigs, type AvailableDetectorsConfigs, type AvailableObserverScopeDetectorsConfigs, type AvailableValidatorConfigs, CODEC_MISMATCH_ISSUE, type CalculatedScore, type CallAppDataFactory, CallConcurrentIssueDetector, type CallConcurrentIssueDetectorConfig, type CallConcurrentIssueGroup, CallConcurrentIssueTypes, type CallHealth, CallHealthAggregator, type CallIssue, type CallIssueSpread, type CallScopedEventName, type CallSummary, type CallSummaryClients, CallSummaryCollector, type CallSummaryConfig, type CallSummaryEnricher, type CallSummaryEnrichers, type CallSummaryScores, type CallSummarySection, type CallSummaryTruncation, type CallSummaryTurnServers, type CertificateStats, type ClientAppDataFactory, type ClientEvent, ClientEventTypes, type ClientHealth, type ClientHealthThresholds, type ClientIssue, type ClientLocation, type ClientLocationResolver, type ClientMetaData, ClientMetaTypes, type ClientPopulation, type ClientPopulationAxis, ClientPopulationIssueDetector, type ClientPopulationIssueDetectorConfig, ClientPopulationIssueTypes, type ClientSample, type ClientSampleSink, type ClientSampleSinkEvents, type ClientSinkParams, type CodecConsistencyReportPayload, CodecConsistencyValidator, type CodecConsistencyValidatorConfig, type CodecEvidence, type CodecStats, type CorroboratedPublisherFault, type CreateExtensionStatsSettings, type DataChannelStats, type Detector, Detectors, type ExtensionStat, ExtensionStatsRegistry, GEOHASH_CELL_SIZES, type IceCandidatePairStats, type IceCandidateStats, type IceTransportStats, InMemorySink, type InboundRtpStats, type InboundTrackSample, type Issue, type IssueBase, type IssueConclusion, IssueFanOutDetector, type IssueFanOutDetectorConfig, IssueFanOutTypes, type IssueFaultDomain, JsonlFileSink, type JsonlFileSinkOptions, LOWEST_COMMON_DENOMINATOR_ISSUE, type Logger, type MannKendallResult, type MediaKind, type MediaPlayoutStats, type MediaSourceStats, type MediasoupConsumerSample, type MediasoupConsumerSampleEvent, type MediasoupDataConsumerSample, type MediasoupDataProducerSample, type MediasoupDirectTransportSample, type MediasoupDirectTransportSampleEventMap, type MediasoupPipeTransportSample, type MediasoupPipeTransportSampleEventMap, type MediasoupPlainTransportSample, type MediasoupPlainTransportSampleEventMap, type MediasoupProducerSample, type MediasoupProducerSampleEvent, type MediasoupRouterSample, type MediasoupSampleEnricher, type MediasoupTransportSample, type MediasoupWebRtcTransportSample, type MediasoupWebRtcTransportSampleEventMap, type Middleware, MiddlewareProcessor, ObservedCall, type ObservedCallScope, type ObservedCallSettings, ObservedCertificate, ObservedClient, ObservedClientIssueRegistry, type ObservedClientScope, type ObservedClientSettings, ObservedCodec, ObservedDataChannel, ObservedIceCandidate, ObservedIceCandidatePair, ObservedIceTransport, ObservedInboundRtp, ObservedInboundTrack, ObservedMediaPlayout, ObservedMediaSource, ObservedMediasoupRouter, type ObservedMediasoupRouterEvents, type ObservedMediasoupRouterScope, type ObservedMediasoupRouterSettings, ObservedOutboundRtp, ObservedOutboundTrack, ObservedPeerConnection, type ObservedPeerConnectionScope, ObservedPeerConnectionTransport, ObservedRemoteInboundRtp, ObservedRemoteOutboundRtp, ObservedTURN, type ObservedTURNEventMap, ObservedTurnServer, Observer, ObserverConcurrentIssueDetector, type ObserverConcurrentIssueDetectorConfig, type ObserverConcurrentIssueGroup, ObserverConcurrentIssueTypes, type ObserverEventBase, type ObserverEvents, type ObserverIssue, type ObserverIssueSpread, type ObserverLogger, type OutboundRtpStats, type OutboundTrackSample, type PageHinkleyResult, type PeerConnectionSample, type PeerConnectionTransportStats, type PsnrSum, PublisherFaultCorroborationDetector, type PublisherFaultCorroborationDetectorConfig, PublisherFaultTypes, type QualityLimitationDurations, RESOLVED_ISSUE_SUFFIX, RTT_HISTOGRAM_BUCKET_WIDTH_IN_MS, RTT_HISTOGRAM_NUMBER_OF_BUCKETS, type RemoteInboundRtpStats, type RemoteOutboundRtpStats, type RemoteTrackLinkEvidence, RemoteTrackResolver, type RemoteTrackResolverFactory, type RemoteTrackResolverReportPayload, RemoteTrackResolverValidator, type RemoteTrackResolverValidatorConfig, type RemoteTrackResolvers, type ResolvedActiveClientIssue, type RttSummary, type RunningValidator, SCORE_HISTOGRAM_BUCKET_WIDTH, SCORE_HISTOGRAM_NUMBER_OF_BUCKETS, type SampleRejectedReason, type SaveClientSamplesConfig, type ScoreCalculator, type ScoreSummary, SfuCongestionDetector, type SfuCongestionDetectorBucket, type SfuCongestionDetectorConfig, type SfuCongestionDetectorEvaluation, type SfuCongestionDetectorReport, type SimulcastReceiverEvidence, type SimulcastReceiverReportPayload, SimulcastReceiverValidator, type SimulcastReceiverValidatorConfig, type Sink, type SinkConstructor, type SinkCreateSettings, type SinkDestination, type SinkEvents, SinkRegistry, type SinkSettings, SlidingWindow, type SlidingWindowEntry, type StatsSummary, TrackDeliveryMismatchDetector, type TrackDeliveryMismatchDetectorConfig, TrackDeliveryMismatchTypes, TrendTester, type TrendTesterConfig, type TurnServerHealth, TurnServerHealthDetector, type TurnServerHealthDetectorConfig, TurnServerHealthTypes, TurnServerOutageDetector, type TurnServerOutageDetectorConfig, TurnServerOutageTypes, UNRESOLVED_TRACK_LINKS_ISSUE, UnconsumedTrackDetector, type UnconsumedTrackDetectorConfig, UnconsumedTrackTypes, type ValidationReport, type Validator, type ValidatorName, baseIssueType, concludeCallIssue, concludeObserverIssue, correlation, counterDelta, createCallSummary, createDefaultMediasoupRemoteTrackResolverFactory, createInMemorySink, createJsonlFileSink, createLogger, createP2pRemoteTrackResolverFactory, defaultCallSummaryConfig, defaultClientHealthThresholds, geohash, isClientIssueResolutionEntry, isPublicIpAddress, issuePayloadAsString, mannKendall, mannKendallVerdict, median, medianAbsoluteDeviation, pageHinkley, percentile, percentileOfHistogram, percentileOfSorted, robustZScore, schemaVersion, setObserverLogger, summarize };
|
package/dist/index.d.ts
CHANGED
|
@@ -59,6 +59,12 @@ type SinkDestination<T = unknown> = {
|
|
|
59
59
|
sink: Sink<T>;
|
|
60
60
|
jsonlPath?: never;
|
|
61
61
|
};
|
|
62
|
+
/** What the `saveClientSamples` callbacks receive: `id` is the client's sample sink id, the client id. */
|
|
63
|
+
type ClientSinkParams<Call = unknown> = {
|
|
64
|
+
id: string;
|
|
65
|
+
observedCall: Call;
|
|
66
|
+
clientId: string;
|
|
67
|
+
};
|
|
62
68
|
|
|
63
69
|
/** A sink class `SinkRegistry.create` can construct: its constructor takes one settings object (with `id`). */
|
|
64
70
|
type SinkConstructor = new (settings: any) => Sink<any>;
|
|
@@ -2190,7 +2196,6 @@ declare class ObservedOutboundTrack implements OutboundTrackSample {
|
|
|
2190
2196
|
readonly id: string;
|
|
2191
2197
|
readonly kind: MediaKind;
|
|
2192
2198
|
private readonly _peerConnection;
|
|
2193
|
-
private readonly _outboundRtps?;
|
|
2194
2199
|
private readonly _mediaSource?;
|
|
2195
2200
|
private _visited;
|
|
2196
2201
|
appData?: Record<string, unknown>;
|
|
@@ -2222,11 +2227,12 @@ declare class ObservedOutboundTrack implements OutboundTrackSample {
|
|
|
2222
2227
|
* latest tick. Needs a `RemoteTrackResolver`: without links there are no receivers to ask.
|
|
2223
2228
|
*/
|
|
2224
2229
|
receivedRmsAudioLevel?: number;
|
|
2225
|
-
constructor(timestamp: number, id: string, kind: MediaKind, _peerConnection: ObservedPeerConnection,
|
|
2230
|
+
constructor(timestamp: number, id: string, kind: MediaKind, _peerConnection: ObservedPeerConnection, _mediaSource?: ObservedMediaSource | undefined);
|
|
2226
2231
|
get score(): number | undefined;
|
|
2227
2232
|
get visited(): boolean;
|
|
2228
2233
|
get degraded(): boolean;
|
|
2229
2234
|
getPeerConnection(): ObservedPeerConnection;
|
|
2235
|
+
/** The outbound RTPs of this track's media source, looked up on every call. */
|
|
2230
2236
|
getOutboundRtps(): ObservedOutboundRtp[] | undefined;
|
|
2231
2237
|
getMediaSource(): ObservedMediaSource | undefined;
|
|
2232
2238
|
/** The capture device behind this track, when the client sent `AUDIO_INPUT_DEVICE` metadata for it. */
|
|
@@ -2689,6 +2695,7 @@ declare class ObservedPeerConnection extends EventEmitter {
|
|
|
2689
2695
|
private _updateMediaSourceStats;
|
|
2690
2696
|
private _updateOutboundRtpStats;
|
|
2691
2697
|
private _updateOutboundTrackSample;
|
|
2698
|
+
private _removeOutboundTrack;
|
|
2692
2699
|
private _updatePeerConnectionTransportStats;
|
|
2693
2700
|
private _updateRemoteInboundRtpStats;
|
|
2694
2701
|
private _updateRemoteOutboundRtpStats;
|
|
@@ -4004,7 +4011,7 @@ declare class ObservedClient<AppData extends Record<string, unknown> = Record<st
|
|
|
4004
4011
|
/** The distinct `publicAddress`es currently known by this client's open peer connections. */
|
|
4005
4012
|
/**
|
|
4006
4013
|
* The sink this client's samples are written to: whatever is registered under its client id in
|
|
4007
|
-
* `call.sinks` (the one `
|
|
4014
|
+
* `call.sinks` (the one created through `saveClientSamples`, or a sink the application added), if any.
|
|
4008
4015
|
*/
|
|
4009
4016
|
get sink(): Sink<ClientSample> | undefined;
|
|
4010
4017
|
get publicAddresses(): string[];
|
|
@@ -4090,6 +4097,7 @@ declare class RemoteTrackResolver {
|
|
|
4090
4097
|
readonly observedCall: ObservedCall;
|
|
4091
4098
|
private readonly resolvers;
|
|
4092
4099
|
private readonly _publisherIdToOutboundTrack;
|
|
4100
|
+
private readonly _outboundTrackPublisherIds;
|
|
4093
4101
|
private readonly _subscriberIdToInboundTrack;
|
|
4094
4102
|
/**
|
|
4095
4103
|
* Tracks whose publisher id the strategy could not resolve **yet**.
|
|
@@ -5883,8 +5891,8 @@ declare class ObservedCall<AppData extends Record<string, unknown> = Record<stri
|
|
|
5883
5891
|
private _onClientUpdate;
|
|
5884
5892
|
private _clientJoined;
|
|
5885
5893
|
private _clientLeft;
|
|
5886
|
-
/** Emit an Observer-bus event scoped to this call. */
|
|
5887
5894
|
private _createClientSink;
|
|
5895
|
+
/** Emit an Observer-bus event scoped to this call. */
|
|
5888
5896
|
private _notify;
|
|
5889
5897
|
}
|
|
5890
5898
|
|
|
@@ -6445,6 +6453,14 @@ type ClientAppDataFactory = (params: {
|
|
|
6445
6453
|
observedCall: ObservedCall;
|
|
6446
6454
|
acceptCtx?: AcceptContext;
|
|
6447
6455
|
}) => Record<string, unknown>;
|
|
6456
|
+
/** `ObserverConfig.saveClientSamples`: exactly one of the two per-client callbacks. */
|
|
6457
|
+
type SaveClientSamplesConfig = {
|
|
6458
|
+
jsonlPath: (params: ClientSinkParams<ObservedCall>) => string | undefined;
|
|
6459
|
+
sink?: never;
|
|
6460
|
+
} | {
|
|
6461
|
+
sink: (params: ClientSinkParams<ObservedCall>) => Sink<ClientSample> | undefined;
|
|
6462
|
+
jsonlPath?: never;
|
|
6463
|
+
};
|
|
6448
6464
|
type ObserverConfig<AppData extends Record<string, unknown> = Record<string, unknown>> = {
|
|
6449
6465
|
/**
|
|
6450
6466
|
* Application-owned data for the observer itself. Never read or modified by the library.
|
|
@@ -6598,22 +6614,15 @@ type ObserverConfig<AppData extends Record<string, unknown> = Record<string, unk
|
|
|
6598
6614
|
/** Same as `createCallAppData`, for clients. Receives the (already-created) parent call. */
|
|
6599
6615
|
createClientAppData?: ClientAppDataFactory;
|
|
6600
6616
|
/**
|
|
6601
|
-
*
|
|
6602
|
-
*
|
|
6603
|
-
* client
|
|
6604
|
-
* when the client closes; `client-sink-created` announces it.
|
|
6605
|
-
*
|
|
6606
|
-
* ```ts
|
|
6607
|
-
* createClientSink: ({ observedCall, clientId }) => ({ jsonlPath: `./stats/${observedCall.callId}__${clientId}.jsonl` }),
|
|
6608
|
-
* ```
|
|
6617
|
+
* Where each client's samples are saved: exactly one of `jsonlPath` (return the path of the
|
|
6618
|
+
* client's JSONL file) and `sink` (return a sink whose `id` is `params.id`), each called per
|
|
6619
|
+
* client; `undefined` gives that client no sink. See the README's *Sinks* section.
|
|
6609
6620
|
*
|
|
6610
|
-
*
|
|
6621
|
+
* A client's sample sink id is its client id (`params.id`). Sink ids are unique per observer, so
|
|
6622
|
+
* client ids must be unique across the observer's open calls; a client whose id is already a sink
|
|
6623
|
+
* id gets no sink, and a warning is logged.
|
|
6611
6624
|
*/
|
|
6612
|
-
|
|
6613
|
-
id: string;
|
|
6614
|
-
observedCall: ObservedCall;
|
|
6615
|
-
clientId: string;
|
|
6616
|
-
}) => SinkDestination<ClientSample> | undefined;
|
|
6625
|
+
saveClientSamples?: SaveClientSamplesConfig;
|
|
6617
6626
|
/**
|
|
6618
6627
|
* Optional factory invoked when a call is created, producing the call's `RemoteTrackResolver`
|
|
6619
6628
|
* (or `undefined` for none). Use the built-ins
|
|
@@ -7183,7 +7192,7 @@ declare function setObserverLogger(logger: ObserverLogger): void;
|
|
|
7183
7192
|
/** The lifecycle events a client sample sink may emit. Same as {@link SinkEvents}. */
|
|
7184
7193
|
type ClientSampleSinkEvents = SinkEvents;
|
|
7185
7194
|
/**
|
|
7186
|
-
* A per-client destination for accepted samples. Return one from `ObserverConfig.
|
|
7195
|
+
* A per-client destination for accepted samples. Return one from `ObserverConfig.saveClientSamples.sink`
|
|
7187
7196
|
* (with the `id` it receives), or create one under the client id with
|
|
7188
7197
|
* `observedCall.sinks.create(MySink, { id: clientId, ... })`.
|
|
7189
7198
|
*
|
|
@@ -7253,4 +7262,4 @@ declare function createInMemorySink(samples?: ClientSample[]): InMemorySink;
|
|
|
7253
7262
|
declare function createDefaultMediasoupRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
|
|
7254
7263
|
declare function createP2pRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
|
|
7255
7264
|
|
|
7256
|
-
export { type AcceptContext, type AcceptMiddleware, type AcceptMiddlewarePayload, type ActiveClientIssue, type ActiveIssueTracker, ActiveIssuesRegistry, AudioEchoDetector, type AudioEchoDetectorConfig, AudioEchoTypes, type AudioInputDevice, type AvailableCallScopeDetectorsConfigs, type AvailableDetectorsConfigs, type AvailableObserverScopeDetectorsConfigs, type AvailableValidatorConfigs, CODEC_MISMATCH_ISSUE, type CalculatedScore, type CallAppDataFactory, CallConcurrentIssueDetector, type CallConcurrentIssueDetectorConfig, type CallConcurrentIssueGroup, CallConcurrentIssueTypes, type CallHealth, CallHealthAggregator, type CallIssue, type CallIssueSpread, type CallScopedEventName, type CallSummary, type CallSummaryClients, CallSummaryCollector, type CallSummaryConfig, type CallSummaryEnricher, type CallSummaryEnrichers, type CallSummaryScores, type CallSummarySection, type CallSummaryTruncation, type CallSummaryTurnServers, type CertificateStats, type ClientAppDataFactory, type ClientEvent, ClientEventTypes, type ClientHealth, type ClientHealthThresholds, type ClientIssue, type ClientLocation, type ClientLocationResolver, type ClientMetaData, ClientMetaTypes, type ClientPopulation, type ClientPopulationAxis, ClientPopulationIssueDetector, type ClientPopulationIssueDetectorConfig, ClientPopulationIssueTypes, type ClientSample, type ClientSampleSink, type ClientSampleSinkEvents, type CodecConsistencyReportPayload, CodecConsistencyValidator, type CodecConsistencyValidatorConfig, type CodecEvidence, type CodecStats, type CorroboratedPublisherFault, type CreateExtensionStatsSettings, type DataChannelStats, type Detector, Detectors, type ExtensionStat, ExtensionStatsRegistry, GEOHASH_CELL_SIZES, type IceCandidatePairStats, type IceCandidateStats, type IceTransportStats, InMemorySink, type InboundRtpStats, type InboundTrackSample, type Issue, type IssueBase, type IssueConclusion, IssueFanOutDetector, type IssueFanOutDetectorConfig, IssueFanOutTypes, type IssueFaultDomain, JsonlFileSink, type JsonlFileSinkOptions, LOWEST_COMMON_DENOMINATOR_ISSUE, type Logger, type MannKendallResult, type MediaKind, type MediaPlayoutStats, type MediaSourceStats, type MediasoupConsumerSample, type MediasoupConsumerSampleEvent, type MediasoupDataConsumerSample, type MediasoupDataProducerSample, type MediasoupDirectTransportSample, type MediasoupDirectTransportSampleEventMap, type MediasoupPipeTransportSample, type MediasoupPipeTransportSampleEventMap, type MediasoupPlainTransportSample, type MediasoupPlainTransportSampleEventMap, type MediasoupProducerSample, type MediasoupProducerSampleEvent, type MediasoupRouterSample, type MediasoupSampleEnricher, type MediasoupTransportSample, type MediasoupWebRtcTransportSample, type MediasoupWebRtcTransportSampleEventMap, type Middleware, MiddlewareProcessor, ObservedCall, type ObservedCallScope, type ObservedCallSettings, ObservedCertificate, ObservedClient, ObservedClientIssueRegistry, type ObservedClientScope, type ObservedClientSettings, ObservedCodec, ObservedDataChannel, ObservedIceCandidate, ObservedIceCandidatePair, ObservedIceTransport, ObservedInboundRtp, ObservedInboundTrack, ObservedMediaPlayout, ObservedMediaSource, ObservedMediasoupRouter, type ObservedMediasoupRouterEvents, type ObservedMediasoupRouterScope, type ObservedMediasoupRouterSettings, ObservedOutboundRtp, ObservedOutboundTrack, ObservedPeerConnection, type ObservedPeerConnectionScope, ObservedPeerConnectionTransport, ObservedRemoteInboundRtp, ObservedRemoteOutboundRtp, ObservedTURN, type ObservedTURNEventMap, ObservedTurnServer, Observer, ObserverConcurrentIssueDetector, type ObserverConcurrentIssueDetectorConfig, type ObserverConcurrentIssueGroup, ObserverConcurrentIssueTypes, type ObserverEventBase, type ObserverEvents, type ObserverIssue, type ObserverIssueSpread, type ObserverLogger, type OutboundRtpStats, type OutboundTrackSample, type PageHinkleyResult, type PeerConnectionSample, type PeerConnectionTransportStats, type PsnrSum, PublisherFaultCorroborationDetector, type PublisherFaultCorroborationDetectorConfig, PublisherFaultTypes, type QualityLimitationDurations, RESOLVED_ISSUE_SUFFIX, RTT_HISTOGRAM_BUCKET_WIDTH_IN_MS, RTT_HISTOGRAM_NUMBER_OF_BUCKETS, type RemoteInboundRtpStats, type RemoteOutboundRtpStats, type RemoteTrackLinkEvidence, RemoteTrackResolver, type RemoteTrackResolverFactory, type RemoteTrackResolverReportPayload, RemoteTrackResolverValidator, type RemoteTrackResolverValidatorConfig, type RemoteTrackResolvers, type ResolvedActiveClientIssue, type RttSummary, type RunningValidator, SCORE_HISTOGRAM_BUCKET_WIDTH, SCORE_HISTOGRAM_NUMBER_OF_BUCKETS, type SampleRejectedReason, type ScoreCalculator, type ScoreSummary, SfuCongestionDetector, type SfuCongestionDetectorBucket, type SfuCongestionDetectorConfig, type SfuCongestionDetectorEvaluation, type SfuCongestionDetectorReport, type SimulcastReceiverEvidence, type SimulcastReceiverReportPayload, SimulcastReceiverValidator, type SimulcastReceiverValidatorConfig, type Sink, type SinkConstructor, type SinkCreateSettings, type SinkDestination, type SinkEvents, SinkRegistry, type SinkSettings, SlidingWindow, type SlidingWindowEntry, type StatsSummary, TrackDeliveryMismatchDetector, type TrackDeliveryMismatchDetectorConfig, TrackDeliveryMismatchTypes, TrendTester, type TrendTesterConfig, type TurnServerHealth, TurnServerHealthDetector, type TurnServerHealthDetectorConfig, TurnServerHealthTypes, TurnServerOutageDetector, type TurnServerOutageDetectorConfig, TurnServerOutageTypes, UNRESOLVED_TRACK_LINKS_ISSUE, UnconsumedTrackDetector, type UnconsumedTrackDetectorConfig, UnconsumedTrackTypes, type ValidationReport, type Validator, type ValidatorName, baseIssueType, concludeCallIssue, concludeObserverIssue, correlation, counterDelta, createCallSummary, createDefaultMediasoupRemoteTrackResolverFactory, createInMemorySink, createJsonlFileSink, createLogger, createP2pRemoteTrackResolverFactory, defaultCallSummaryConfig, defaultClientHealthThresholds, geohash, isClientIssueResolutionEntry, isPublicIpAddress, issuePayloadAsString, mannKendall, mannKendallVerdict, median, medianAbsoluteDeviation, pageHinkley, percentile, percentileOfHistogram, percentileOfSorted, robustZScore, schemaVersion, setObserverLogger, summarize };
|
|
7265
|
+
export { type AcceptContext, type AcceptMiddleware, type AcceptMiddlewarePayload, type ActiveClientIssue, type ActiveIssueTracker, ActiveIssuesRegistry, AudioEchoDetector, type AudioEchoDetectorConfig, AudioEchoTypes, type AudioInputDevice, type AvailableCallScopeDetectorsConfigs, type AvailableDetectorsConfigs, type AvailableObserverScopeDetectorsConfigs, type AvailableValidatorConfigs, CODEC_MISMATCH_ISSUE, type CalculatedScore, type CallAppDataFactory, CallConcurrentIssueDetector, type CallConcurrentIssueDetectorConfig, type CallConcurrentIssueGroup, CallConcurrentIssueTypes, type CallHealth, CallHealthAggregator, type CallIssue, type CallIssueSpread, type CallScopedEventName, type CallSummary, type CallSummaryClients, CallSummaryCollector, type CallSummaryConfig, type CallSummaryEnricher, type CallSummaryEnrichers, type CallSummaryScores, type CallSummarySection, type CallSummaryTruncation, type CallSummaryTurnServers, type CertificateStats, type ClientAppDataFactory, type ClientEvent, ClientEventTypes, type ClientHealth, type ClientHealthThresholds, type ClientIssue, type ClientLocation, type ClientLocationResolver, type ClientMetaData, ClientMetaTypes, type ClientPopulation, type ClientPopulationAxis, ClientPopulationIssueDetector, type ClientPopulationIssueDetectorConfig, ClientPopulationIssueTypes, type ClientSample, type ClientSampleSink, type ClientSampleSinkEvents, type ClientSinkParams, type CodecConsistencyReportPayload, CodecConsistencyValidator, type CodecConsistencyValidatorConfig, type CodecEvidence, type CodecStats, type CorroboratedPublisherFault, type CreateExtensionStatsSettings, type DataChannelStats, type Detector, Detectors, type ExtensionStat, ExtensionStatsRegistry, GEOHASH_CELL_SIZES, type IceCandidatePairStats, type IceCandidateStats, type IceTransportStats, InMemorySink, type InboundRtpStats, type InboundTrackSample, type Issue, type IssueBase, type IssueConclusion, IssueFanOutDetector, type IssueFanOutDetectorConfig, IssueFanOutTypes, type IssueFaultDomain, JsonlFileSink, type JsonlFileSinkOptions, LOWEST_COMMON_DENOMINATOR_ISSUE, type Logger, type MannKendallResult, type MediaKind, type MediaPlayoutStats, type MediaSourceStats, type MediasoupConsumerSample, type MediasoupConsumerSampleEvent, type MediasoupDataConsumerSample, type MediasoupDataProducerSample, type MediasoupDirectTransportSample, type MediasoupDirectTransportSampleEventMap, type MediasoupPipeTransportSample, type MediasoupPipeTransportSampleEventMap, type MediasoupPlainTransportSample, type MediasoupPlainTransportSampleEventMap, type MediasoupProducerSample, type MediasoupProducerSampleEvent, type MediasoupRouterSample, type MediasoupSampleEnricher, type MediasoupTransportSample, type MediasoupWebRtcTransportSample, type MediasoupWebRtcTransportSampleEventMap, type Middleware, MiddlewareProcessor, ObservedCall, type ObservedCallScope, type ObservedCallSettings, ObservedCertificate, ObservedClient, ObservedClientIssueRegistry, type ObservedClientScope, type ObservedClientSettings, ObservedCodec, ObservedDataChannel, ObservedIceCandidate, ObservedIceCandidatePair, ObservedIceTransport, ObservedInboundRtp, ObservedInboundTrack, ObservedMediaPlayout, ObservedMediaSource, ObservedMediasoupRouter, type ObservedMediasoupRouterEvents, type ObservedMediasoupRouterScope, type ObservedMediasoupRouterSettings, ObservedOutboundRtp, ObservedOutboundTrack, ObservedPeerConnection, type ObservedPeerConnectionScope, ObservedPeerConnectionTransport, ObservedRemoteInboundRtp, ObservedRemoteOutboundRtp, ObservedTURN, type ObservedTURNEventMap, ObservedTurnServer, Observer, ObserverConcurrentIssueDetector, type ObserverConcurrentIssueDetectorConfig, type ObserverConcurrentIssueGroup, ObserverConcurrentIssueTypes, type ObserverEventBase, type ObserverEvents, type ObserverIssue, type ObserverIssueSpread, type ObserverLogger, type OutboundRtpStats, type OutboundTrackSample, type PageHinkleyResult, type PeerConnectionSample, type PeerConnectionTransportStats, type PsnrSum, PublisherFaultCorroborationDetector, type PublisherFaultCorroborationDetectorConfig, PublisherFaultTypes, type QualityLimitationDurations, RESOLVED_ISSUE_SUFFIX, RTT_HISTOGRAM_BUCKET_WIDTH_IN_MS, RTT_HISTOGRAM_NUMBER_OF_BUCKETS, type RemoteInboundRtpStats, type RemoteOutboundRtpStats, type RemoteTrackLinkEvidence, RemoteTrackResolver, type RemoteTrackResolverFactory, type RemoteTrackResolverReportPayload, RemoteTrackResolverValidator, type RemoteTrackResolverValidatorConfig, type RemoteTrackResolvers, type ResolvedActiveClientIssue, type RttSummary, type RunningValidator, SCORE_HISTOGRAM_BUCKET_WIDTH, SCORE_HISTOGRAM_NUMBER_OF_BUCKETS, type SampleRejectedReason, type SaveClientSamplesConfig, type ScoreCalculator, type ScoreSummary, SfuCongestionDetector, type SfuCongestionDetectorBucket, type SfuCongestionDetectorConfig, type SfuCongestionDetectorEvaluation, type SfuCongestionDetectorReport, type SimulcastReceiverEvidence, type SimulcastReceiverReportPayload, SimulcastReceiverValidator, type SimulcastReceiverValidatorConfig, type Sink, type SinkConstructor, type SinkCreateSettings, type SinkDestination, type SinkEvents, SinkRegistry, type SinkSettings, SlidingWindow, type SlidingWindowEntry, type StatsSummary, TrackDeliveryMismatchDetector, type TrackDeliveryMismatchDetectorConfig, TrackDeliveryMismatchTypes, TrendTester, type TrendTesterConfig, type TurnServerHealth, TurnServerHealthDetector, type TurnServerHealthDetectorConfig, TurnServerHealthTypes, TurnServerOutageDetector, type TurnServerOutageDetectorConfig, TurnServerOutageTypes, UNRESOLVED_TRACK_LINKS_ISSUE, UnconsumedTrackDetector, type UnconsumedTrackDetectorConfig, UnconsumedTrackTypes, type ValidationReport, type Validator, type ValidatorName, baseIssueType, concludeCallIssue, concludeObserverIssue, correlation, counterDelta, createCallSummary, createDefaultMediasoupRemoteTrackResolverFactory, createInMemorySink, createJsonlFileSink, createLogger, createP2pRemoteTrackResolverFactory, defaultCallSummaryConfig, defaultClientHealthThresholds, geohash, isClientIssueResolutionEntry, isPublicIpAddress, issuePayloadAsString, mannKendall, mannKendallVerdict, median, medianAbsoluteDeviation, pageHinkley, percentile, percentileOfHistogram, percentileOfSorted, robustZScore, schemaVersion, setObserverLogger, summarize };
|
package/dist/index.js
CHANGED
|
@@ -312,11 +312,11 @@ var SinkRegistry = class {
|
|
|
312
312
|
}
|
|
313
313
|
/** End every sink of this registry and of its descendants. */
|
|
314
314
|
clear() {
|
|
315
|
-
for (const sink of [...this._sinks.
|
|
315
|
+
for (const [id, sink] of [...this._sinks.entries()]) {
|
|
316
316
|
try {
|
|
317
317
|
sink.end();
|
|
318
318
|
} catch (err) {
|
|
319
|
-
logger.warn("Sink %s failed to end: %o",
|
|
319
|
+
logger.warn("Sink %s failed to end: %o", id, err);
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
322
|
}
|
|
@@ -1912,19 +1912,17 @@ function isPublicIpAddress(address) {
|
|
|
1912
1912
|
|
|
1913
1913
|
// src/ObservedOutboundTrack.ts
|
|
1914
1914
|
var ObservedOutboundTrack = class {
|
|
1915
|
-
constructor(timestamp, id, kind, _peerConnection,
|
|
1915
|
+
constructor(timestamp, id, kind, _peerConnection, _mediaSource) {
|
|
1916
1916
|
this.timestamp = timestamp;
|
|
1917
1917
|
this.id = id;
|
|
1918
1918
|
this.kind = kind;
|
|
1919
1919
|
this._peerConnection = _peerConnection;
|
|
1920
|
-
this._outboundRtps = _outboundRtps;
|
|
1921
1920
|
this._mediaSource = _mediaSource;
|
|
1922
1921
|
}
|
|
1923
1922
|
timestamp;
|
|
1924
1923
|
id;
|
|
1925
1924
|
kind;
|
|
1926
1925
|
_peerConnection;
|
|
1927
|
-
_outboundRtps;
|
|
1928
1926
|
_mediaSource;
|
|
1929
1927
|
_visited = false;
|
|
1930
1928
|
appData;
|
|
@@ -1975,8 +1973,11 @@ var ObservedOutboundTrack = class {
|
|
|
1975
1973
|
getPeerConnection() {
|
|
1976
1974
|
return this._peerConnection;
|
|
1977
1975
|
}
|
|
1976
|
+
/** The outbound RTPs of this track's media source, looked up on every call. */
|
|
1978
1977
|
getOutboundRtps() {
|
|
1979
|
-
|
|
1978
|
+
const mediaSource = this._mediaSource;
|
|
1979
|
+
if (!mediaSource) return void 0;
|
|
1980
|
+
return [...this._peerConnection.observedOutboundRtps.values()].filter((rtp) => rtp.mediaSourceId === mediaSource.id);
|
|
1980
1981
|
}
|
|
1981
1982
|
getMediaSource() {
|
|
1982
1983
|
return this._mediaSource;
|
|
@@ -1995,7 +1996,7 @@ var ObservedOutboundTrack = class {
|
|
|
1995
1996
|
this.remoteFractionLost = void 0;
|
|
1996
1997
|
this.remoteRttInMs = void 0;
|
|
1997
1998
|
this.qualityLimitationReason = void 0;
|
|
1998
|
-
for (const rtp of this.
|
|
1999
|
+
for (const rtp of this.getOutboundRtps() ?? []) {
|
|
1999
2000
|
this.bitrate = (this.bitrate ?? 0) + rtp.bitrate;
|
|
2000
2001
|
this.deltaPacketsSent = (this.deltaPacketsSent ?? 0) + rtp.deltaPacketsSent;
|
|
2001
2002
|
if (rtp.remoteFractionLost !== void 0) {
|
|
@@ -2660,9 +2661,7 @@ var ObservedPeerConnection = class extends import_node_events2.EventEmitter {
|
|
|
2660
2661
|
}
|
|
2661
2662
|
for (const observedOutboundTrack of [...this.observedOutboundTracks.values()]) {
|
|
2662
2663
|
if (observedOutboundTrack.visited) continue;
|
|
2663
|
-
this.
|
|
2664
|
-
this.emit("removed-outbound-track", observedOutboundTrack);
|
|
2665
|
-
this._notify("outbound-track-removed", { ...this.eventScope, observedOutboundTrack });
|
|
2664
|
+
this._removeOutboundTrack(observedOutboundTrack);
|
|
2666
2665
|
}
|
|
2667
2666
|
for (const observedPeerConnectionTransport of [...this.observedPeerConnectionTransports.values()]) {
|
|
2668
2667
|
if (observedPeerConnectionTransport.visited) continue;
|
|
@@ -2923,6 +2922,11 @@ var ObservedPeerConnection = class extends import_node_events2.EventEmitter {
|
|
|
2923
2922
|
}
|
|
2924
2923
|
_updateOutboundTrackSample(stats) {
|
|
2925
2924
|
let observedOutboundTrack = this.observedOutboundTracks.get(stats.id);
|
|
2925
|
+
const mediaSource = [...this.observedMediaSources.values()].filter((source) => source.trackIdentifier === stats.id).pop();
|
|
2926
|
+
if (observedOutboundTrack && observedOutboundTrack.getMediaSource() !== mediaSource) {
|
|
2927
|
+
this._removeOutboundTrack(observedOutboundTrack);
|
|
2928
|
+
observedOutboundTrack = void 0;
|
|
2929
|
+
}
|
|
2926
2930
|
if (!observedOutboundTrack) {
|
|
2927
2931
|
if (!stats.timestamp || !stats.id || !stats.kind) {
|
|
2928
2932
|
return logger3.warn(
|
|
@@ -2930,15 +2934,12 @@ var ObservedPeerConnection = class extends import_node_events2.EventEmitter {
|
|
|
2930
2934
|
stats
|
|
2931
2935
|
);
|
|
2932
2936
|
}
|
|
2933
|
-
const observedMediaSource = [...this.observedMediaSources.values()].find((mediaSource) => mediaSource.trackIdentifier === stats.id);
|
|
2934
|
-
const outboundRtps = observedMediaSource ? [...this.observedOutboundRtps.values()].filter((outboundRtp) => outboundRtp.mediaSourceId === observedMediaSource?.id) : void 0;
|
|
2935
2937
|
observedOutboundTrack = new ObservedOutboundTrack(
|
|
2936
2938
|
stats.timestamp,
|
|
2937
2939
|
stats.id,
|
|
2938
2940
|
stats.kind,
|
|
2939
2941
|
this,
|
|
2940
|
-
|
|
2941
|
-
observedMediaSource
|
|
2942
|
+
mediaSource
|
|
2942
2943
|
);
|
|
2943
2944
|
observedOutboundTrack.update(stats);
|
|
2944
2945
|
this.observedOutboundTracks.set(stats.id, observedOutboundTrack);
|
|
@@ -2949,6 +2950,11 @@ var ObservedPeerConnection = class extends import_node_events2.EventEmitter {
|
|
|
2949
2950
|
this._notify("outbound-track-updated", { ...this.eventScope, observedOutboundTrack });
|
|
2950
2951
|
return observedOutboundTrack;
|
|
2951
2952
|
}
|
|
2953
|
+
_removeOutboundTrack(observedOutboundTrack) {
|
|
2954
|
+
this.observedOutboundTracks.delete(observedOutboundTrack.id);
|
|
2955
|
+
this.emit("removed-outbound-track", observedOutboundTrack);
|
|
2956
|
+
this._notify("outbound-track-removed", { ...this.eventScope, observedOutboundTrack });
|
|
2957
|
+
}
|
|
2952
2958
|
_updatePeerConnectionTransportStats(stats) {
|
|
2953
2959
|
let observedPeerConnectionTransport = this.observedPeerConnectionTransports.get(stats.id);
|
|
2954
2960
|
if (!observedPeerConnectionTransport) {
|
|
@@ -3258,7 +3264,7 @@ var ObservedClient = class extends import_node_events3.EventEmitter {
|
|
|
3258
3264
|
/** The distinct `publicAddress`es currently known by this client's open peer connections. */
|
|
3259
3265
|
/**
|
|
3260
3266
|
* The sink this client's samples are written to: whatever is registered under its client id in
|
|
3261
|
-
* `call.sinks` (the one `
|
|
3267
|
+
* `call.sinks` (the one created through `saveClientSamples`, or a sink the application added), if any.
|
|
3262
3268
|
*/
|
|
3263
3269
|
get sink() {
|
|
3264
3270
|
return this.call.sinks.get(this.clientId);
|
|
@@ -5411,17 +5417,26 @@ var ObservedCall = class extends import_node_events4.EventEmitter {
|
|
|
5411
5417
|
if (!client.leftAt) return;
|
|
5412
5418
|
this.endedAt = Math.max(this.endedAt ?? client.leftAt, client.leftAt);
|
|
5413
5419
|
}
|
|
5414
|
-
/** Emit an Observer-bus event scoped to this call. */
|
|
5415
5420
|
_createClientSink(clientId) {
|
|
5416
|
-
const
|
|
5417
|
-
if (!
|
|
5421
|
+
const config = this.observer.config.saveClientSamples;
|
|
5422
|
+
if (!config || !config.jsonlPath && !config.sink) return void 0;
|
|
5423
|
+
if (config.jsonlPath && config.sink) {
|
|
5424
|
+
logger6.warn("saveClientSamples: give either jsonlPath or sink, not both; no client samples are saved");
|
|
5425
|
+
return void 0;
|
|
5426
|
+
}
|
|
5418
5427
|
if (this.observer.sinks.get(clientId)) {
|
|
5419
5428
|
logger6.warn("No sample sink for client %s in call %s: sink id %s is already in use", clientId, this.callId, clientId);
|
|
5420
5429
|
return void 0;
|
|
5421
5430
|
}
|
|
5422
|
-
const
|
|
5423
|
-
|
|
5431
|
+
const params = { id: clientId, observedCall: this, clientId };
|
|
5432
|
+
if (config.jsonlPath) {
|
|
5433
|
+
const jsonlPath = config.jsonlPath(params);
|
|
5434
|
+
return jsonlPath === void 0 ? void 0 : this.sinks.createFromDestination(clientId, { jsonlPath });
|
|
5435
|
+
}
|
|
5436
|
+
const sink = config.sink?.(params);
|
|
5437
|
+
return sink ? this.sinks.createFromDestination(clientId, { sink }) : void 0;
|
|
5424
5438
|
}
|
|
5439
|
+
/** Emit an Observer-bus event scoped to this call. */
|
|
5425
5440
|
_notify(type, ...args) {
|
|
5426
5441
|
this.observer.emit(type, ...args);
|
|
5427
5442
|
}
|
|
@@ -8169,6 +8184,7 @@ var RemoteTrackResolver = class {
|
|
|
8169
8184
|
observer.off("outbound-track-updated", onOutboundUpdated);
|
|
8170
8185
|
this._pendingInboundTracks.clear();
|
|
8171
8186
|
this._pendingOutboundTracks.clear();
|
|
8187
|
+
this._outboundTrackPublisherIds.clear();
|
|
8172
8188
|
});
|
|
8173
8189
|
observer.on("inbound-track-added", onInboundAdded);
|
|
8174
8190
|
observer.on("inbound-track-removed", onInboundRemoved);
|
|
@@ -8180,6 +8196,8 @@ var RemoteTrackResolver = class {
|
|
|
8180
8196
|
observedCall;
|
|
8181
8197
|
resolvers;
|
|
8182
8198
|
_publisherIdToOutboundTrack = /* @__PURE__ */ new Map();
|
|
8199
|
+
// The publisher id each outbound track was indexed under, so removal does not depend on its current attachments.
|
|
8200
|
+
_outboundTrackPublisherIds = /* @__PURE__ */ new Map();
|
|
8183
8201
|
_subscriberIdToInboundTrack = /* @__PURE__ */ new Map();
|
|
8184
8202
|
/**
|
|
8185
8203
|
* Tracks whose publisher id the strategy could not resolve **yet**.
|
|
@@ -8255,6 +8273,7 @@ var RemoteTrackResolver = class {
|
|
|
8255
8273
|
}
|
|
8256
8274
|
this._pendingOutboundTracks.delete(outboundTrack);
|
|
8257
8275
|
this._publisherIdToOutboundTrack.set(publisherId, outboundTrack);
|
|
8276
|
+
this._outboundTrackPublisherIds.set(outboundTrack, publisherId);
|
|
8258
8277
|
this.observedCall.unconsumedOutboundTracks.add(outboundTrack);
|
|
8259
8278
|
for (const observedClient of this.observedCall.observedClients.values()) {
|
|
8260
8279
|
for (const observedPeerConnection of observedClient.observedPeerConnections.values()) {
|
|
@@ -8269,7 +8288,8 @@ var RemoteTrackResolver = class {
|
|
|
8269
8288
|
}
|
|
8270
8289
|
_removeOutboundTrack(outboundTrack) {
|
|
8271
8290
|
this._pendingOutboundTracks.delete(outboundTrack);
|
|
8272
|
-
const publisherId = this.
|
|
8291
|
+
const publisherId = this._outboundTrackPublisherIds.get(outboundTrack);
|
|
8292
|
+
this._outboundTrackPublisherIds.delete(outboundTrack);
|
|
8273
8293
|
if (publisherId && this._publisherIdToOutboundTrack.get(publisherId) === outboundTrack) {
|
|
8274
8294
|
this._publisherIdToOutboundTrack.delete(publisherId);
|
|
8275
8295
|
}
|