import { type PerformanceEntry } from 'node:perf_hooks'; import type { AppendableSink } from './wal.js'; /** * Encoder that converts PerformanceEntry to domain events. * * Pure function that transforms performance entries into domain events. * Should be stateless, synchronous, and have no side effects. * Returns a readonly array of encoded items. */ export type PerformanceEntryEncoder = (entry: PerformanceEntry) => readonly F[]; /** * Default threshold for triggering queue flushes based on queue length. * When the queue length reaches (maxQueueSize - flushThreshold), * a flush is triggered to prevent overflow. This provides a buffer zone * before hitting the maximum queue capacity. */ export declare const DEFAULT_FLUSH_THRESHOLD = 20; /** * Default maximum number of items allowed in the queue before entries are dropped. * This acts as a memory safety limit to prevent unbounded memory growth * in case of sink slowdown or high-frequency performance entries. */ export declare const DEFAULT_MAX_QUEUE_SIZE = 10000; /** * Validates the flush threshold configuration to ensure sensible bounds. * * The flush threshold must be positive and cannot exceed the maximum queue size, * as it represents a buffer zone within the queue capacity. * * @param flushThreshold - The threshold value to validate (must be > 0) * @param maxQueueSize - The maximum queue size for comparison (flushThreshold <= maxQueueSize) * @throws {Error} If flushThreshold is not positive or exceeds maxQueueSize */ export declare function validateFlushThreshold(flushThreshold: number, maxQueueSize: number): void; /** * Configuration options for the PerformanceObserverSink. * * @template T - The type of encoded performance data that will be written to the sink */ export type PerformanceObserverOptions = { /** * The sink where encoded performance entries will be written. * Must implement the AppendableSink interface for handling the encoded data. */ sink: AppendableSink; /** * Function that encodes raw PerformanceEntry objects into domain-specific types. * This transformer converts Node.js performance entries into application-specific data structures. * Returns a readonly array of encoded items. */ encodePerfEntry: PerformanceEntryEncoder; /** * Whether to enable buffered observation mode. * When true, captures all performance entries that occurred before observation started. * When false, only captures entries after subscription begins. * * @default true */ captureBufferedEntries?: boolean; /** * Threshold for triggering queue flushes. * Flushes occur in two scenarios: * 1. When queue length reaches (maxQueueSize - flushThreshold) * 2. When the number of items added since last flush reaches flushThreshold * Larger values provide more buffer space before hitting capacity limits. * * @default DEFAULT_FLUSH_THRESHOLD (20) */ flushThreshold?: number; /** * Maximum number of items allowed in the queue before new entries are dropped. * Acts as a memory safety limit to prevent unbounded growth during sink slowdown. * * @default DEFAULT_MAX_QUEUE_SIZE (10000) */ maxQueueSize?: number; /** * Name of the environment variable to check for debug mode. * When the env var is set to 'true', encode failures create performance marks for debugging. * * @default 'CP_PROFILER_DEBUG' */ debugEnvVar?: string; }; /** * A sink implementation that observes Node.js performance entries and forwards them to a configurable sink. * * This class provides a buffered, memory-safe bridge between Node.js PerformanceObserver * and application-specific data sinks. It handles performance entry encoding, queue management, * and graceful degradation under high load conditions. * * Performance entries flow through the following lifecycle: * * - Queued in Memory 💾 * - Items stored in queue (`#queue`) until flushed * - Queue limited by `maxQueueSize` to prevent unbounded growth * - Items remain in queue if sink is closed during flush * * - Successfully Written 📤 * - Items written to sink and counted in `getStats().written` * - Queue cleared after successful batch writes * * - Item Disposition Scenarios 💥 * - **Encode Failure**: ❌ Items lost when `encode()` throws. Creates perf mark if debug env var (specified by `debugEnvVar`) is set to 'true'. * - **Sink Write Failure**: 💾 Items stay in queue when sink write fails during flush * - **Sink Closed**: 💾 Items stay in queue when sink is closed during flush * - **Proactive Flush Throws**: 💾 Items stay in queue when `flush()` throws during threshold check * - **Final Flush Throws**: 💾 Items stay in queue when `flush()` throws at end of callback * - **Buffered Flush Throws**: 💾 Items stay in queue when buffered entries flush fails * - **Queue Overflow**: ❌ Items dropped when queue reaches `maxQueueSize` * * @template T - The type of encoded performance data written to the sink * @implements {Observer} - Lifecycle management interface * @implements {Buffered} - Queue statistics interface */ export declare class PerformanceObserverSink { #private; /** * Creates a new PerformanceObserverSink with the specified configuration. * * @param options - Configuration options for the performance observer sink * @throws {Error} If flushThreshold validation fails (must be > 0 and <= maxQueueSize) */ constructor(options: PerformanceObserverOptions); /** * Returns whether debug mode is enabled for encode failures. * * Debug mode is determined by the environment variable specified by `debugEnvVar` * (defaults to 'CP_PROFILER_DEBUG'). When enabled, encode failures create * performance marks for debugging. * * @returns true if debug mode is enabled, false otherwise */ get debug(): boolean; /** * Returns current queue statistics for monitoring and debugging. * * Provides insight into the current state of the performance entry queue, * useful for monitoring memory usage and processing throughput. * * @returns Object containing all states and entry counts */ getStats(): { isSubscribed: boolean; queued: number; dropped: number; written: number; maxQueueSize: number; flushThreshold: number; addedSinceLastFlush: number; buffered: boolean; }; /** * Encodes a raw PerformanceEntry using the configured encoder function. * * This method delegates to the user-provided encoder function, allowing * transformation of Node.js performance entries into application-specific types. * * @param entry - The raw performance entry to encode * @returns Readonly array of encoded items */ encode(entry: PerformanceEntry): readonly T[]; /** * Starts observing performance entries and forwarding them to the sink. * * Creates a Node.js PerformanceObserver that monitors 'mark' and 'measure' entries. * The observer uses a bounded queue with proactive flushing to manage memory usage. * When buffered mode is enabled, any existing buffered entries are immediately flushed. * If the sink is closed, items stay in the queue until reopened. * */ subscribe(): void; /** * Flushes all queued performance entries to the sink. * * Writes all currently queued encoded performance entries to the configured sink. * If the sink is closed, flush is a no-op and items stay in the queue until reopened. * The queue is always cleared after flush attempt, regardless of success or failure. */ flush(): void; /** * Stops observing performance entries and cleans up resources. * * Performs a final flush of any remaining queued entries, then disconnects * the PerformanceObserver and releases all references. * * This method is idempotent - safe to call multiple times. */ unsubscribe(): void; /** * Checks whether the performance observer is currently active. * * Returns true if the sink is subscribed and actively observing performance entries. * This indicates that a PerformanceObserver instance exists and is connected. * * @returns true if currently subscribed and observing, false otherwise */ isSubscribed(): boolean; }