@observertc/observer-js 1.3.0-rc.5 → 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 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
@@ -7236,6 +7236,74 @@ declare class JsonlFileSink<T = ClientSample> extends EventEmitter implements Si
7236
7236
  /** Build a JSONL file sink for a single path. */
7237
7237
  declare function createJsonlFileSink<T = ClientSample>(options: JsonlFileSinkOptions<T>): JsonlFileSink<T>;
7238
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
+
7239
7307
  declare interface InMemorySink {
7240
7308
  on<E extends keyof SinkEvents>(event: E, listener: (...args: SinkEvents[E]) => void): this;
7241
7309
  once<E extends keyof SinkEvents>(event: E, listener: (...args: SinkEvents[E]) => void): this;
@@ -7262,4 +7330,4 @@ declare function createInMemorySink(samples?: ClientSample[]): InMemorySink;
7262
7330
  declare function createDefaultMediasoupRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
7263
7331
  declare function createP2pRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
7264
7332
 
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 };
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
@@ -7236,6 +7236,74 @@ declare class JsonlFileSink<T = ClientSample> extends EventEmitter implements Si
7236
7236
  /** Build a JSONL file sink for a single path. */
7237
7237
  declare function createJsonlFileSink<T = ClientSample>(options: JsonlFileSinkOptions<T>): JsonlFileSink<T>;
7238
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
+
7239
7307
  declare interface InMemorySink {
7240
7308
  on<E extends keyof SinkEvents>(event: E, listener: (...args: SinkEvents[E]) => void): this;
7241
7309
  once<E extends keyof SinkEvents>(event: E, listener: (...args: SinkEvents[E]) => void): this;
@@ -7262,4 +7330,4 @@ declare function createInMemorySink(samples?: ClientSample[]): InMemorySink;
7262
7330
  declare function createDefaultMediasoupRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
7263
7331
  declare function createP2pRemoteTrackResolverFactory(): RemoteTrackResolverFactory;
7264
7332
 
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 };
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,
@@ -8119,9 +8120,96 @@ var TrendTester = class {
8119
8120
  }
8120
8121
  };
8121
8122
 
8122
- // src/sinks/InMemorySink.ts
8123
+ // src/sinks/RollingJsonlFileSink.ts
8124
+ var fs2 = __toESM(require("fs"));
8123
8125
  var import_node_events8 = require("events");
8124
- var InMemorySink = class extends import_node_events8.EventEmitter {
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 {
8125
8213
  id;
8126
8214
  samples;
8127
8215
  _ended = false;
@@ -8382,6 +8470,7 @@ function createP2pRemoteTrackResolverFactory() {
8382
8470
  RTT_HISTOGRAM_NUMBER_OF_BUCKETS,
8383
8471
  RemoteTrackResolver,
8384
8472
  RemoteTrackResolverValidator,
8473
+ RollingJsonlFileSink,
8385
8474
  SCORE_HISTOGRAM_BUCKET_WIDTH,
8386
8475
  SCORE_HISTOGRAM_NUMBER_OF_BUCKETS,
8387
8476
  SfuCongestionDetector,