@observertc/observer-js 1.3.0-rc.4 → 1.3.0-rc.6
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 +38 -0
- package/dist/index.d.mts +73 -3
- package/dist/index.d.ts +73 -3
- package/dist/index.js +115 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +114 -15
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1975,6 +1975,7 @@ its id — refuse writes after it, and emit `close` / `error` for its destinatio
|
|
|
1975
1975
|
| Export | Notes |
|
|
1976
1976
|
|--------|-------|
|
|
1977
1977
|
| `JsonlFileSink<T = ClientSample>` / `createJsonlFileSink<T>({ path, serializeSample? })` | appends one JSON line per record; wraps `fs.WriteStream` and re-emits its events; exposes `readonly path`. The directory **must exist** |
|
|
1978
|
+
| `RollingJsonlFileSink<T>` | JSONL over a sequence of files for long-lived owners: rolls on `maxBytes`, `maxAgeMs` or `roll()`; `file-closed` per finished file. See [Rolling files](#rolling-files) |
|
|
1978
1979
|
| `InMemorySink` / `createInMemorySink(samples?)` | collects client samples into `.samples`; emits `close` on `end()` |
|
|
1979
1980
|
|
|
1980
1981
|
### Client samples
|
|
@@ -2101,6 +2102,43 @@ and the extension stats' sinks are ended. The owner's other sinks end with its `
|
|
|
2101
2102
|
usual. `extensionStats.close()` can also be called directly; it ends only the extension stats'
|
|
2102
2103
|
sinks.
|
|
2103
2104
|
|
|
2105
|
+
### Rolling files
|
|
2106
|
+
|
|
2107
|
+
`JsonlFileSink` writes one file for the sink's whole life — right for calls and clients, which come
|
|
2108
|
+
and go. An owner that lives for days or months, such as the observer itself, needs its records cut
|
|
2109
|
+
into several files. `RollingJsonlFileSink` does that: it writes JSONL to a sequence of files, closing
|
|
2110
|
+
the current one and opening the next (*rolling*) before a write that would exceed `maxBytes`, once
|
|
2111
|
+
the current file has been open for `maxAgeMs`, or when `roll()` is called.
|
|
2112
|
+
|
|
2113
|
+
```ts
|
|
2114
|
+
const sink = new RollingJsonlFileSink({
|
|
2115
|
+
id: 'sfu-cpu',
|
|
2116
|
+
path: ({ index, openedAt }) => `./stats/sfu-cpu-${openedAt}-${index}.jsonl`,
|
|
2117
|
+
maxBytes: 100 * 1024 * 1024,
|
|
2118
|
+
maxAgeMs: 60 * 60 * 1000,
|
|
2119
|
+
});
|
|
2120
|
+
|
|
2121
|
+
sink.on('file-closed', (path, index) => uploadFile(path)); // flushed & fd closed → ready
|
|
2122
|
+
|
|
2123
|
+
observer.createExtensionStats({ id: 'sfu-cpu', sink });
|
|
2124
|
+
setInterval(async () => observer.acceptExtensionStats('sfu-cpu', await readCpu()), 5_000).unref();
|
|
2125
|
+
```
|
|
2126
|
+
|
|
2127
|
+
| Option / member | Meaning |
|
|
2128
|
+
|-----------------|---------|
|
|
2129
|
+
| `path({ index, openedAt })` | the path of each file, called when it is opened (`index` 0, 1, 2, …; `openedAt` = `Date.now()`). Must give a new path per `index` |
|
|
2130
|
+
| `maxBytes?`, `maxAgeMs?` | roll before a write that would make the file larger than `maxBytes`, or once it has been open for `maxAgeMs` |
|
|
2131
|
+
| `serializeSample?` | custom serializer; defaults to `JSON.stringify` |
|
|
2132
|
+
| `roll()` | close the current file and continue in a new one |
|
|
2133
|
+
| `path`, `index` | the file currently written to |
|
|
2134
|
+
|
|
2135
|
+
- Nothing is dropped: each record goes to exactly one file.
|
|
2136
|
+
- The limits are checked on `write`, so the sink runs no timers: a file is not rolled while nothing
|
|
2137
|
+
is written to it, and an empty file is never rolled (`roll()` on one is a no-op).
|
|
2138
|
+
- `file-closed` (`path`, `index`) fires for every finished file, in index order, the last one
|
|
2139
|
+
included. `close` fires once, after `end()` has closed every file. The owner ends the sink as
|
|
2140
|
+
usual — here when the observer closes.
|
|
2141
|
+
|
|
2104
2142
|
### Other records: e.g. mediasoup pipe transport stats
|
|
2105
2143
|
|
|
2106
2144
|
```ts
|
package/dist/index.d.mts
CHANGED
|
@@ -2196,7 +2196,6 @@ declare class ObservedOutboundTrack implements OutboundTrackSample {
|
|
|
2196
2196
|
readonly id: string;
|
|
2197
2197
|
readonly kind: MediaKind;
|
|
2198
2198
|
private readonly _peerConnection;
|
|
2199
|
-
private readonly _outboundRtps?;
|
|
2200
2199
|
private readonly _mediaSource?;
|
|
2201
2200
|
private _visited;
|
|
2202
2201
|
appData?: Record<string, unknown>;
|
|
@@ -2228,11 +2227,12 @@ declare class ObservedOutboundTrack implements OutboundTrackSample {
|
|
|
2228
2227
|
* latest tick. Needs a `RemoteTrackResolver`: without links there are no receivers to ask.
|
|
2229
2228
|
*/
|
|
2230
2229
|
receivedRmsAudioLevel?: number;
|
|
2231
|
-
constructor(timestamp: number, id: string, kind: MediaKind, _peerConnection: ObservedPeerConnection,
|
|
2230
|
+
constructor(timestamp: number, id: string, kind: MediaKind, _peerConnection: ObservedPeerConnection, _mediaSource?: ObservedMediaSource | undefined);
|
|
2232
2231
|
get score(): number | undefined;
|
|
2233
2232
|
get visited(): boolean;
|
|
2234
2233
|
get degraded(): boolean;
|
|
2235
2234
|
getPeerConnection(): ObservedPeerConnection;
|
|
2235
|
+
/** The outbound RTPs of this track's media source, looked up on every call. */
|
|
2236
2236
|
getOutboundRtps(): ObservedOutboundRtp[] | undefined;
|
|
2237
2237
|
getMediaSource(): ObservedMediaSource | undefined;
|
|
2238
2238
|
/** The capture device behind this track, when the client sent `AUDIO_INPUT_DEVICE` metadata for it. */
|
|
@@ -2695,6 +2695,7 @@ declare class ObservedPeerConnection extends EventEmitter {
|
|
|
2695
2695
|
private _updateMediaSourceStats;
|
|
2696
2696
|
private _updateOutboundRtpStats;
|
|
2697
2697
|
private _updateOutboundTrackSample;
|
|
2698
|
+
private _removeOutboundTrack;
|
|
2698
2699
|
private _updatePeerConnectionTransportStats;
|
|
2699
2700
|
private _updateRemoteInboundRtpStats;
|
|
2700
2701
|
private _updateRemoteOutboundRtpStats;
|
|
@@ -4096,6 +4097,7 @@ declare class RemoteTrackResolver {
|
|
|
4096
4097
|
readonly observedCall: ObservedCall;
|
|
4097
4098
|
private readonly resolvers;
|
|
4098
4099
|
private readonly _publisherIdToOutboundTrack;
|
|
4100
|
+
private readonly _outboundTrackPublisherIds;
|
|
4099
4101
|
private readonly _subscriberIdToInboundTrack;
|
|
4100
4102
|
/**
|
|
4101
4103
|
* Tracks whose publisher id the strategy could not resolve **yet**.
|
|
@@ -7234,6 +7236,74 @@ declare class JsonlFileSink<T = ClientSample> extends EventEmitter implements Si
|
|
|
7234
7236
|
/** Build a JSONL file sink for a single path. */
|
|
7235
7237
|
declare function createJsonlFileSink<T = ClientSample>(options: JsonlFileSinkOptions<T>): JsonlFileSink<T>;
|
|
7236
7238
|
|
|
7239
|
+
/** The file a `RollingJsonlFileSink` is about to open: the sequence number and when it opens. */
|
|
7240
|
+
type RollingJsonlFileInfo = {
|
|
7241
|
+
/** 0 for the first file, then 1, 2, … */
|
|
7242
|
+
index: number;
|
|
7243
|
+
/** `Date.now()` when the file is opened. */
|
|
7244
|
+
openedAt: number;
|
|
7245
|
+
};
|
|
7246
|
+
type RollingJsonlFileSinkOptions<T = unknown> = Partial<SinkSettings> & {
|
|
7247
|
+
/** The path of each file, called when it is opened. Must give a new path per `index`. */
|
|
7248
|
+
path: (file: RollingJsonlFileInfo) => string;
|
|
7249
|
+
/** Roll before a write that would make the current file larger than this, in bytes. */
|
|
7250
|
+
maxBytes?: number;
|
|
7251
|
+
/** Roll before a write once the current file has been open for this long, in ms. */
|
|
7252
|
+
maxAgeMs?: number;
|
|
7253
|
+
/** Optional custom serializer; defaults to `JSON.stringify`. */
|
|
7254
|
+
serializeSample?: (record: T) => string;
|
|
7255
|
+
};
|
|
7256
|
+
type RollingJsonlFileSinkEvents = {
|
|
7257
|
+
ended: SinkEvents['ended'];
|
|
7258
|
+
close: SinkEvents['close'];
|
|
7259
|
+
error: SinkEvents['error'];
|
|
7260
|
+
finish: SinkEvents['finish'];
|
|
7261
|
+
drain: SinkEvents['drain'];
|
|
7262
|
+
/** A file is complete: flushed and its descriptor closed. Fires for every file, the last one included. */
|
|
7263
|
+
'file-closed': [path: string, index: number];
|
|
7264
|
+
};
|
|
7265
|
+
declare interface RollingJsonlFileSink {
|
|
7266
|
+
on<E extends keyof RollingJsonlFileSinkEvents>(event: E, listener: (...args: RollingJsonlFileSinkEvents[E]) => void): this;
|
|
7267
|
+
once<E extends keyof RollingJsonlFileSinkEvents>(event: E, listener: (...args: RollingJsonlFileSinkEvents[E]) => void): this;
|
|
7268
|
+
off<E extends keyof RollingJsonlFileSinkEvents>(event: E, listener: (...args: RollingJsonlFileSinkEvents[E]) => void): this;
|
|
7269
|
+
emit<E extends keyof RollingJsonlFileSinkEvents>(event: E, ...args: RollingJsonlFileSinkEvents[E]): boolean;
|
|
7270
|
+
}
|
|
7271
|
+
/**
|
|
7272
|
+
* A JSONL file sink for long-lived owners (e.g. an observer's extension stats over days): it writes
|
|
7273
|
+
* to a sequence of files, closing the current one and opening the next — *rolling* — when it would
|
|
7274
|
+
* exceed `maxBytes`, when it has been open for `maxAgeMs`, or when `roll()` is called. Nothing is
|
|
7275
|
+
* dropped: each record goes to exactly one file.
|
|
7276
|
+
*
|
|
7277
|
+
* The limits are checked on `write`, so a file is never rolled while nothing is written to it, and
|
|
7278
|
+
* an empty file is never rolled. `file-closed` announces each finished file (ready to upload or
|
|
7279
|
+
* move), in index order; `close` fires once, after every file is closed by `end()`.
|
|
7280
|
+
*/
|
|
7281
|
+
declare class RollingJsonlFileSink<T = unknown> extends EventEmitter implements Sink<T> {
|
|
7282
|
+
readonly id: string;
|
|
7283
|
+
private readonly _options;
|
|
7284
|
+
private readonly _serializeSample;
|
|
7285
|
+
private _stream;
|
|
7286
|
+
private _path;
|
|
7287
|
+
private _index;
|
|
7288
|
+
private _openedAt;
|
|
7289
|
+
private _bytes;
|
|
7290
|
+
private _ended;
|
|
7291
|
+
private _closing;
|
|
7292
|
+
constructor(options: RollingJsonlFileSinkOptions<T>);
|
|
7293
|
+
/** The file currently written to. */
|
|
7294
|
+
get path(): string;
|
|
7295
|
+
/** The index of the file currently written to. */
|
|
7296
|
+
get index(): number;
|
|
7297
|
+
get ended(): boolean;
|
|
7298
|
+
write(record: T): boolean;
|
|
7299
|
+
/** Close the current file and continue in a new one. A no-op on an empty file or an ended sink. */
|
|
7300
|
+
roll(): void;
|
|
7301
|
+
/** No more writes: emits `ended`, closes the current file (`file-closed`), then emits `close`. */
|
|
7302
|
+
end(): void;
|
|
7303
|
+
private _open;
|
|
7304
|
+
private _closeCurrent;
|
|
7305
|
+
}
|
|
7306
|
+
|
|
7237
7307
|
declare interface InMemorySink {
|
|
7238
7308
|
on<E extends keyof SinkEvents>(event: E, listener: (...args: SinkEvents[E]) => void): this;
|
|
7239
7309
|
once<E extends keyof SinkEvents>(event: E, listener: (...args: SinkEvents[E]) => void): this;
|
|
@@ -7260,4 +7330,4 @@ declare function createInMemorySink(samples?: ClientSample[]): InMemorySink;
|
|
|
7260
7330
|
declare function createDefaultMediasoupRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
|
|
7261
7331
|
declare function createP2pRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
|
|
7262
7332
|
|
|
7263
|
-
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 };
|
|
7333
|
+
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 RollingJsonlFileInfo, RollingJsonlFileSink, type RollingJsonlFileSinkEvents, type RollingJsonlFileSinkOptions, 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
|
@@ -2196,7 +2196,6 @@ declare class ObservedOutboundTrack implements OutboundTrackSample {
|
|
|
2196
2196
|
readonly id: string;
|
|
2197
2197
|
readonly kind: MediaKind;
|
|
2198
2198
|
private readonly _peerConnection;
|
|
2199
|
-
private readonly _outboundRtps?;
|
|
2200
2199
|
private readonly _mediaSource?;
|
|
2201
2200
|
private _visited;
|
|
2202
2201
|
appData?: Record<string, unknown>;
|
|
@@ -2228,11 +2227,12 @@ declare class ObservedOutboundTrack implements OutboundTrackSample {
|
|
|
2228
2227
|
* latest tick. Needs a `RemoteTrackResolver`: without links there are no receivers to ask.
|
|
2229
2228
|
*/
|
|
2230
2229
|
receivedRmsAudioLevel?: number;
|
|
2231
|
-
constructor(timestamp: number, id: string, kind: MediaKind, _peerConnection: ObservedPeerConnection,
|
|
2230
|
+
constructor(timestamp: number, id: string, kind: MediaKind, _peerConnection: ObservedPeerConnection, _mediaSource?: ObservedMediaSource | undefined);
|
|
2232
2231
|
get score(): number | undefined;
|
|
2233
2232
|
get visited(): boolean;
|
|
2234
2233
|
get degraded(): boolean;
|
|
2235
2234
|
getPeerConnection(): ObservedPeerConnection;
|
|
2235
|
+
/** The outbound RTPs of this track's media source, looked up on every call. */
|
|
2236
2236
|
getOutboundRtps(): ObservedOutboundRtp[] | undefined;
|
|
2237
2237
|
getMediaSource(): ObservedMediaSource | undefined;
|
|
2238
2238
|
/** The capture device behind this track, when the client sent `AUDIO_INPUT_DEVICE` metadata for it. */
|
|
@@ -2695,6 +2695,7 @@ declare class ObservedPeerConnection extends EventEmitter {
|
|
|
2695
2695
|
private _updateMediaSourceStats;
|
|
2696
2696
|
private _updateOutboundRtpStats;
|
|
2697
2697
|
private _updateOutboundTrackSample;
|
|
2698
|
+
private _removeOutboundTrack;
|
|
2698
2699
|
private _updatePeerConnectionTransportStats;
|
|
2699
2700
|
private _updateRemoteInboundRtpStats;
|
|
2700
2701
|
private _updateRemoteOutboundRtpStats;
|
|
@@ -4096,6 +4097,7 @@ declare class RemoteTrackResolver {
|
|
|
4096
4097
|
readonly observedCall: ObservedCall;
|
|
4097
4098
|
private readonly resolvers;
|
|
4098
4099
|
private readonly _publisherIdToOutboundTrack;
|
|
4100
|
+
private readonly _outboundTrackPublisherIds;
|
|
4099
4101
|
private readonly _subscriberIdToInboundTrack;
|
|
4100
4102
|
/**
|
|
4101
4103
|
* Tracks whose publisher id the strategy could not resolve **yet**.
|
|
@@ -7234,6 +7236,74 @@ declare class JsonlFileSink<T = ClientSample> extends EventEmitter implements Si
|
|
|
7234
7236
|
/** Build a JSONL file sink for a single path. */
|
|
7235
7237
|
declare function createJsonlFileSink<T = ClientSample>(options: JsonlFileSinkOptions<T>): JsonlFileSink<T>;
|
|
7236
7238
|
|
|
7239
|
+
/** The file a `RollingJsonlFileSink` is about to open: the sequence number and when it opens. */
|
|
7240
|
+
type RollingJsonlFileInfo = {
|
|
7241
|
+
/** 0 for the first file, then 1, 2, … */
|
|
7242
|
+
index: number;
|
|
7243
|
+
/** `Date.now()` when the file is opened. */
|
|
7244
|
+
openedAt: number;
|
|
7245
|
+
};
|
|
7246
|
+
type RollingJsonlFileSinkOptions<T = unknown> = Partial<SinkSettings> & {
|
|
7247
|
+
/** The path of each file, called when it is opened. Must give a new path per `index`. */
|
|
7248
|
+
path: (file: RollingJsonlFileInfo) => string;
|
|
7249
|
+
/** Roll before a write that would make the current file larger than this, in bytes. */
|
|
7250
|
+
maxBytes?: number;
|
|
7251
|
+
/** Roll before a write once the current file has been open for this long, in ms. */
|
|
7252
|
+
maxAgeMs?: number;
|
|
7253
|
+
/** Optional custom serializer; defaults to `JSON.stringify`. */
|
|
7254
|
+
serializeSample?: (record: T) => string;
|
|
7255
|
+
};
|
|
7256
|
+
type RollingJsonlFileSinkEvents = {
|
|
7257
|
+
ended: SinkEvents['ended'];
|
|
7258
|
+
close: SinkEvents['close'];
|
|
7259
|
+
error: SinkEvents['error'];
|
|
7260
|
+
finish: SinkEvents['finish'];
|
|
7261
|
+
drain: SinkEvents['drain'];
|
|
7262
|
+
/** A file is complete: flushed and its descriptor closed. Fires for every file, the last one included. */
|
|
7263
|
+
'file-closed': [path: string, index: number];
|
|
7264
|
+
};
|
|
7265
|
+
declare interface RollingJsonlFileSink {
|
|
7266
|
+
on<E extends keyof RollingJsonlFileSinkEvents>(event: E, listener: (...args: RollingJsonlFileSinkEvents[E]) => void): this;
|
|
7267
|
+
once<E extends keyof RollingJsonlFileSinkEvents>(event: E, listener: (...args: RollingJsonlFileSinkEvents[E]) => void): this;
|
|
7268
|
+
off<E extends keyof RollingJsonlFileSinkEvents>(event: E, listener: (...args: RollingJsonlFileSinkEvents[E]) => void): this;
|
|
7269
|
+
emit<E extends keyof RollingJsonlFileSinkEvents>(event: E, ...args: RollingJsonlFileSinkEvents[E]): boolean;
|
|
7270
|
+
}
|
|
7271
|
+
/**
|
|
7272
|
+
* A JSONL file sink for long-lived owners (e.g. an observer's extension stats over days): it writes
|
|
7273
|
+
* to a sequence of files, closing the current one and opening the next — *rolling* — when it would
|
|
7274
|
+
* exceed `maxBytes`, when it has been open for `maxAgeMs`, or when `roll()` is called. Nothing is
|
|
7275
|
+
* dropped: each record goes to exactly one file.
|
|
7276
|
+
*
|
|
7277
|
+
* The limits are checked on `write`, so a file is never rolled while nothing is written to it, and
|
|
7278
|
+
* an empty file is never rolled. `file-closed` announces each finished file (ready to upload or
|
|
7279
|
+
* move), in index order; `close` fires once, after every file is closed by `end()`.
|
|
7280
|
+
*/
|
|
7281
|
+
declare class RollingJsonlFileSink<T = unknown> extends EventEmitter implements Sink<T> {
|
|
7282
|
+
readonly id: string;
|
|
7283
|
+
private readonly _options;
|
|
7284
|
+
private readonly _serializeSample;
|
|
7285
|
+
private _stream;
|
|
7286
|
+
private _path;
|
|
7287
|
+
private _index;
|
|
7288
|
+
private _openedAt;
|
|
7289
|
+
private _bytes;
|
|
7290
|
+
private _ended;
|
|
7291
|
+
private _closing;
|
|
7292
|
+
constructor(options: RollingJsonlFileSinkOptions<T>);
|
|
7293
|
+
/** The file currently written to. */
|
|
7294
|
+
get path(): string;
|
|
7295
|
+
/** The index of the file currently written to. */
|
|
7296
|
+
get index(): number;
|
|
7297
|
+
get ended(): boolean;
|
|
7298
|
+
write(record: T): boolean;
|
|
7299
|
+
/** Close the current file and continue in a new one. A no-op on an empty file or an ended sink. */
|
|
7300
|
+
roll(): void;
|
|
7301
|
+
/** No more writes: emits `ended`, closes the current file (`file-closed`), then emits `close`. */
|
|
7302
|
+
end(): void;
|
|
7303
|
+
private _open;
|
|
7304
|
+
private _closeCurrent;
|
|
7305
|
+
}
|
|
7306
|
+
|
|
7237
7307
|
declare interface InMemorySink {
|
|
7238
7308
|
on<E extends keyof SinkEvents>(event: E, listener: (...args: SinkEvents[E]) => void): this;
|
|
7239
7309
|
once<E extends keyof SinkEvents>(event: E, listener: (...args: SinkEvents[E]) => void): this;
|
|
@@ -7260,4 +7330,4 @@ declare function createInMemorySink(samples?: ClientSample[]): InMemorySink;
|
|
|
7260
7330
|
declare function createDefaultMediasoupRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
|
|
7261
7331
|
declare function createP2pRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
|
|
7262
7332
|
|
|
7263
|
-
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 };
|
|
7333
|
+
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 RollingJsonlFileInfo, RollingJsonlFileSink, type RollingJsonlFileSinkEvents, type RollingJsonlFileSinkOptions, 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
|
@@ -84,6 +84,7 @@ __export(src_exports, {
|
|
|
84
84
|
RTT_HISTOGRAM_NUMBER_OF_BUCKETS: () => RTT_HISTOGRAM_NUMBER_OF_BUCKETS,
|
|
85
85
|
RemoteTrackResolver: () => RemoteTrackResolver,
|
|
86
86
|
RemoteTrackResolverValidator: () => RemoteTrackResolverValidator,
|
|
87
|
+
RollingJsonlFileSink: () => RollingJsonlFileSink,
|
|
87
88
|
SCORE_HISTOGRAM_BUCKET_WIDTH: () => SCORE_HISTOGRAM_BUCKET_WIDTH,
|
|
88
89
|
SCORE_HISTOGRAM_NUMBER_OF_BUCKETS: () => SCORE_HISTOGRAM_NUMBER_OF_BUCKETS,
|
|
89
90
|
SfuCongestionDetector: () => SfuCongestionDetector,
|
|
@@ -1912,19 +1913,17 @@ function isPublicIpAddress(address) {
|
|
|
1912
1913
|
|
|
1913
1914
|
// src/ObservedOutboundTrack.ts
|
|
1914
1915
|
var ObservedOutboundTrack = class {
|
|
1915
|
-
constructor(timestamp, id, kind, _peerConnection,
|
|
1916
|
+
constructor(timestamp, id, kind, _peerConnection, _mediaSource) {
|
|
1916
1917
|
this.timestamp = timestamp;
|
|
1917
1918
|
this.id = id;
|
|
1918
1919
|
this.kind = kind;
|
|
1919
1920
|
this._peerConnection = _peerConnection;
|
|
1920
|
-
this._outboundRtps = _outboundRtps;
|
|
1921
1921
|
this._mediaSource = _mediaSource;
|
|
1922
1922
|
}
|
|
1923
1923
|
timestamp;
|
|
1924
1924
|
id;
|
|
1925
1925
|
kind;
|
|
1926
1926
|
_peerConnection;
|
|
1927
|
-
_outboundRtps;
|
|
1928
1927
|
_mediaSource;
|
|
1929
1928
|
_visited = false;
|
|
1930
1929
|
appData;
|
|
@@ -1975,8 +1974,11 @@ var ObservedOutboundTrack = class {
|
|
|
1975
1974
|
getPeerConnection() {
|
|
1976
1975
|
return this._peerConnection;
|
|
1977
1976
|
}
|
|
1977
|
+
/** The outbound RTPs of this track's media source, looked up on every call. */
|
|
1978
1978
|
getOutboundRtps() {
|
|
1979
|
-
|
|
1979
|
+
const mediaSource = this._mediaSource;
|
|
1980
|
+
if (!mediaSource) return void 0;
|
|
1981
|
+
return [...this._peerConnection.observedOutboundRtps.values()].filter((rtp) => rtp.mediaSourceId === mediaSource.id);
|
|
1980
1982
|
}
|
|
1981
1983
|
getMediaSource() {
|
|
1982
1984
|
return this._mediaSource;
|
|
@@ -1995,7 +1997,7 @@ var ObservedOutboundTrack = class {
|
|
|
1995
1997
|
this.remoteFractionLost = void 0;
|
|
1996
1998
|
this.remoteRttInMs = void 0;
|
|
1997
1999
|
this.qualityLimitationReason = void 0;
|
|
1998
|
-
for (const rtp of this.
|
|
2000
|
+
for (const rtp of this.getOutboundRtps() ?? []) {
|
|
1999
2001
|
this.bitrate = (this.bitrate ?? 0) + rtp.bitrate;
|
|
2000
2002
|
this.deltaPacketsSent = (this.deltaPacketsSent ?? 0) + rtp.deltaPacketsSent;
|
|
2001
2003
|
if (rtp.remoteFractionLost !== void 0) {
|
|
@@ -2660,9 +2662,7 @@ var ObservedPeerConnection = class extends import_node_events2.EventEmitter {
|
|
|
2660
2662
|
}
|
|
2661
2663
|
for (const observedOutboundTrack of [...this.observedOutboundTracks.values()]) {
|
|
2662
2664
|
if (observedOutboundTrack.visited) continue;
|
|
2663
|
-
this.
|
|
2664
|
-
this.emit("removed-outbound-track", observedOutboundTrack);
|
|
2665
|
-
this._notify("outbound-track-removed", { ...this.eventScope, observedOutboundTrack });
|
|
2665
|
+
this._removeOutboundTrack(observedOutboundTrack);
|
|
2666
2666
|
}
|
|
2667
2667
|
for (const observedPeerConnectionTransport of [...this.observedPeerConnectionTransports.values()]) {
|
|
2668
2668
|
if (observedPeerConnectionTransport.visited) continue;
|
|
@@ -2923,6 +2923,11 @@ var ObservedPeerConnection = class extends import_node_events2.EventEmitter {
|
|
|
2923
2923
|
}
|
|
2924
2924
|
_updateOutboundTrackSample(stats) {
|
|
2925
2925
|
let observedOutboundTrack = this.observedOutboundTracks.get(stats.id);
|
|
2926
|
+
const mediaSource = [...this.observedMediaSources.values()].filter((source) => source.trackIdentifier === stats.id).pop();
|
|
2927
|
+
if (observedOutboundTrack && observedOutboundTrack.getMediaSource() !== mediaSource) {
|
|
2928
|
+
this._removeOutboundTrack(observedOutboundTrack);
|
|
2929
|
+
observedOutboundTrack = void 0;
|
|
2930
|
+
}
|
|
2926
2931
|
if (!observedOutboundTrack) {
|
|
2927
2932
|
if (!stats.timestamp || !stats.id || !stats.kind) {
|
|
2928
2933
|
return logger3.warn(
|
|
@@ -2930,15 +2935,12 @@ var ObservedPeerConnection = class extends import_node_events2.EventEmitter {
|
|
|
2930
2935
|
stats
|
|
2931
2936
|
);
|
|
2932
2937
|
}
|
|
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
2938
|
observedOutboundTrack = new ObservedOutboundTrack(
|
|
2936
2939
|
stats.timestamp,
|
|
2937
2940
|
stats.id,
|
|
2938
2941
|
stats.kind,
|
|
2939
2942
|
this,
|
|
2940
|
-
|
|
2941
|
-
observedMediaSource
|
|
2943
|
+
mediaSource
|
|
2942
2944
|
);
|
|
2943
2945
|
observedOutboundTrack.update(stats);
|
|
2944
2946
|
this.observedOutboundTracks.set(stats.id, observedOutboundTrack);
|
|
@@ -2949,6 +2951,11 @@ var ObservedPeerConnection = class extends import_node_events2.EventEmitter {
|
|
|
2949
2951
|
this._notify("outbound-track-updated", { ...this.eventScope, observedOutboundTrack });
|
|
2950
2952
|
return observedOutboundTrack;
|
|
2951
2953
|
}
|
|
2954
|
+
_removeOutboundTrack(observedOutboundTrack) {
|
|
2955
|
+
this.observedOutboundTracks.delete(observedOutboundTrack.id);
|
|
2956
|
+
this.emit("removed-outbound-track", observedOutboundTrack);
|
|
2957
|
+
this._notify("outbound-track-removed", { ...this.eventScope, observedOutboundTrack });
|
|
2958
|
+
}
|
|
2952
2959
|
_updatePeerConnectionTransportStats(stats) {
|
|
2953
2960
|
let observedPeerConnectionTransport = this.observedPeerConnectionTransports.get(stats.id);
|
|
2954
2961
|
if (!observedPeerConnectionTransport) {
|
|
@@ -8113,9 +8120,96 @@ var TrendTester = class {
|
|
|
8113
8120
|
}
|
|
8114
8121
|
};
|
|
8115
8122
|
|
|
8116
|
-
// src/sinks/
|
|
8123
|
+
// src/sinks/RollingJsonlFileSink.ts
|
|
8124
|
+
var fs2 = __toESM(require("fs"));
|
|
8117
8125
|
var import_node_events8 = require("events");
|
|
8118
|
-
var
|
|
8126
|
+
var RollingJsonlFileSink = class extends import_node_events8.EventEmitter {
|
|
8127
|
+
id;
|
|
8128
|
+
_options;
|
|
8129
|
+
_serializeSample;
|
|
8130
|
+
_stream;
|
|
8131
|
+
_path;
|
|
8132
|
+
_index = -1;
|
|
8133
|
+
_openedAt = 0;
|
|
8134
|
+
_bytes = 0;
|
|
8135
|
+
_ended = false;
|
|
8136
|
+
// Resolves once every file closed so far has closed and been announced, in index order: the
|
|
8137
|
+
// streams close independently, so a later file could otherwise be announced before an earlier one.
|
|
8138
|
+
_closing = Promise.resolve();
|
|
8139
|
+
constructor(options) {
|
|
8140
|
+
super();
|
|
8141
|
+
this._options = options;
|
|
8142
|
+
this._serializeSample = options.serializeSample ?? ((record) => JSON.stringify(record));
|
|
8143
|
+
this._open();
|
|
8144
|
+
this.id = options.id ?? this._path;
|
|
8145
|
+
}
|
|
8146
|
+
/** The file currently written to. */
|
|
8147
|
+
get path() {
|
|
8148
|
+
return this._path;
|
|
8149
|
+
}
|
|
8150
|
+
/** The index of the file currently written to. */
|
|
8151
|
+
get index() {
|
|
8152
|
+
return this._index;
|
|
8153
|
+
}
|
|
8154
|
+
get ended() {
|
|
8155
|
+
return this._ended;
|
|
8156
|
+
}
|
|
8157
|
+
write(record) {
|
|
8158
|
+
if (this._ended) return false;
|
|
8159
|
+
const line = `${this._serializeSample(record)}
|
|
8160
|
+
`;
|
|
8161
|
+
const bytes = Buffer.byteLength(line);
|
|
8162
|
+
const { maxBytes, maxAgeMs } = this._options;
|
|
8163
|
+
if (maxAgeMs !== void 0 && maxAgeMs <= Date.now() - this._openedAt) this.roll();
|
|
8164
|
+
if (maxBytes !== void 0 && maxBytes < this._bytes + bytes) this.roll();
|
|
8165
|
+
this._bytes += bytes;
|
|
8166
|
+
return this._stream.write(line);
|
|
8167
|
+
}
|
|
8168
|
+
/** Close the current file and continue in a new one. A no-op on an empty file or an ended sink. */
|
|
8169
|
+
roll() {
|
|
8170
|
+
if (this._ended || this._bytes === 0) return;
|
|
8171
|
+
this._closeCurrent();
|
|
8172
|
+
this._open();
|
|
8173
|
+
}
|
|
8174
|
+
/** No more writes: emits `ended`, closes the current file (`file-closed`), then emits `close`. */
|
|
8175
|
+
end() {
|
|
8176
|
+
if (this._ended) return;
|
|
8177
|
+
this._ended = true;
|
|
8178
|
+
this.emit("ended");
|
|
8179
|
+
this._closeCurrent();
|
|
8180
|
+
void this._closing.then(() => {
|
|
8181
|
+
this.emit("finish");
|
|
8182
|
+
this.emit("close");
|
|
8183
|
+
});
|
|
8184
|
+
}
|
|
8185
|
+
_open() {
|
|
8186
|
+
++this._index;
|
|
8187
|
+
this._openedAt = Date.now();
|
|
8188
|
+
this._bytes = 0;
|
|
8189
|
+
this._path = this._options.path({ index: this._index, openedAt: this._openedAt });
|
|
8190
|
+
const stream = fs2.createWriteStream(this._path, { flags: "a" });
|
|
8191
|
+
stream.on("drain", () => this.emit("drain"));
|
|
8192
|
+
stream.on("error", (err) => this.emit("error", err));
|
|
8193
|
+
this._stream = stream;
|
|
8194
|
+
}
|
|
8195
|
+
_closeCurrent() {
|
|
8196
|
+
const stream = this._stream;
|
|
8197
|
+
const path = this._path;
|
|
8198
|
+
const index = this._index;
|
|
8199
|
+
const closed = new Promise((resolve) => {
|
|
8200
|
+
stream.once("close", () => resolve());
|
|
8201
|
+
stream.once("error", () => resolve());
|
|
8202
|
+
});
|
|
8203
|
+
this._closing = Promise.all([this._closing, closed]).then(() => {
|
|
8204
|
+
this.emit("file-closed", path, index);
|
|
8205
|
+
});
|
|
8206
|
+
stream.end();
|
|
8207
|
+
}
|
|
8208
|
+
};
|
|
8209
|
+
|
|
8210
|
+
// src/sinks/InMemorySink.ts
|
|
8211
|
+
var import_node_events9 = require("events");
|
|
8212
|
+
var InMemorySink = class extends import_node_events9.EventEmitter {
|
|
8119
8213
|
id;
|
|
8120
8214
|
samples;
|
|
8121
8215
|
_ended = false;
|
|
@@ -8178,6 +8272,7 @@ var RemoteTrackResolver = class {
|
|
|
8178
8272
|
observer.off("outbound-track-updated", onOutboundUpdated);
|
|
8179
8273
|
this._pendingInboundTracks.clear();
|
|
8180
8274
|
this._pendingOutboundTracks.clear();
|
|
8275
|
+
this._outboundTrackPublisherIds.clear();
|
|
8181
8276
|
});
|
|
8182
8277
|
observer.on("inbound-track-added", onInboundAdded);
|
|
8183
8278
|
observer.on("inbound-track-removed", onInboundRemoved);
|
|
@@ -8189,6 +8284,8 @@ var RemoteTrackResolver = class {
|
|
|
8189
8284
|
observedCall;
|
|
8190
8285
|
resolvers;
|
|
8191
8286
|
_publisherIdToOutboundTrack = /* @__PURE__ */ new Map();
|
|
8287
|
+
// The publisher id each outbound track was indexed under, so removal does not depend on its current attachments.
|
|
8288
|
+
_outboundTrackPublisherIds = /* @__PURE__ */ new Map();
|
|
8192
8289
|
_subscriberIdToInboundTrack = /* @__PURE__ */ new Map();
|
|
8193
8290
|
/**
|
|
8194
8291
|
* Tracks whose publisher id the strategy could not resolve **yet**.
|
|
@@ -8264,6 +8361,7 @@ var RemoteTrackResolver = class {
|
|
|
8264
8361
|
}
|
|
8265
8362
|
this._pendingOutboundTracks.delete(outboundTrack);
|
|
8266
8363
|
this._publisherIdToOutboundTrack.set(publisherId, outboundTrack);
|
|
8364
|
+
this._outboundTrackPublisherIds.set(outboundTrack, publisherId);
|
|
8267
8365
|
this.observedCall.unconsumedOutboundTracks.add(outboundTrack);
|
|
8268
8366
|
for (const observedClient of this.observedCall.observedClients.values()) {
|
|
8269
8367
|
for (const observedPeerConnection of observedClient.observedPeerConnections.values()) {
|
|
@@ -8278,7 +8376,8 @@ var RemoteTrackResolver = class {
|
|
|
8278
8376
|
}
|
|
8279
8377
|
_removeOutboundTrack(outboundTrack) {
|
|
8280
8378
|
this._pendingOutboundTracks.delete(outboundTrack);
|
|
8281
|
-
const publisherId = this.
|
|
8379
|
+
const publisherId = this._outboundTrackPublisherIds.get(outboundTrack);
|
|
8380
|
+
this._outboundTrackPublisherIds.delete(outboundTrack);
|
|
8282
8381
|
if (publisherId && this._publisherIdToOutboundTrack.get(publisherId) === outboundTrack) {
|
|
8283
8382
|
this._publisherIdToOutboundTrack.delete(publisherId);
|
|
8284
8383
|
}
|
|
@@ -8371,6 +8470,7 @@ function createP2pRemoteTrackResolverFactory() {
|
|
|
8371
8470
|
RTT_HISTOGRAM_NUMBER_OF_BUCKETS,
|
|
8372
8471
|
RemoteTrackResolver,
|
|
8373
8472
|
RemoteTrackResolverValidator,
|
|
8473
|
+
RollingJsonlFileSink,
|
|
8374
8474
|
SCORE_HISTOGRAM_BUCKET_WIDTH,
|
|
8375
8475
|
SCORE_HISTOGRAM_NUMBER_OF_BUCKETS,
|
|
8376
8476
|
SfuCongestionDetector,
|