UNPKG

lever-ui-logger

Version:

Zero-dependency logging library with optional EventBus integration. Built-in PII redaction, multiple transports, and comprehensive logging capabilities.

362 lines 11.2 kB
/** * SendBeacon transport for efficient telemetry data transmission * * Provides efficient batching, offline support, and automatic retry capabilities * for sending telemetry data to remote endpoints using the sendBeacon API with * fetch fallback for maximum compatibility. * * @example * ```typescript * import { SendBeaconTransport } from '@nuanced-labs/lever-ui-logger'; * * const transport = new SendBeaconTransport({ * endpoint: 'https://api.example.com/telemetry', * batchSize: 100, * flushInterval: 10000, * authToken: 'your-api-token', * enableOfflineStorage: true * }); * * // Use with logger * const logger = createLogger(eventBus, { * transports: [transport] * }); * ``` */ import type { LogEventData } from '../logger/types.js'; import { BaseTransport } from './transport-interface.js'; import { type TokenProvider } from './secure-token-handler.js'; /** * Telemetry envelope metadata structure for wrapping log events * * Contains session and user context along with the batch of log events * being transmitted to the telemetry endpoint. */ export interface TelemetryEnvelope { /** Unique session identifier */ sessionId: string; /** Optional user identifier */ userId?: string; /** User agent string */ userAgent: string; /** Browser/client timezone */ timezone: string; /** Timestamp of the envelope creation */ timestamp: number; /** Array of log events */ events: LogEventData[]; /** Number of events in this batch */ eventCount: number; /** Total size in bytes (estimated) */ sizeBytes: number; } /** * Configuration options for SendBeacon transport * * @example * ```typescript * const config: SendBeaconTransportConfig = { * endpoint: 'https://api.example.com/logs', * batchSize: 50, * flushInterval: 5000, * maxPayloadSize: 64 * 1024, * authToken: () => getAuthToken(), * enableOfflineStorage: true, * rateLimitPerMinute: 1000 * }; * ``` */ export interface SendBeaconTransportConfig { /** Transport name */ name?: string; /** Endpoint URL for sending telemetry */ endpoint: string; /** Maximum batch size (number of events) */ batchSize?: number; /** Flush interval in milliseconds */ flushInterval?: number; /** Maximum payload size in bytes (default ~64KB for sendBeacon) */ maxPayloadSize?: number; /** Enable offline storage */ enableOfflineStorage?: boolean; /** Storage key prefix for offline logs */ storageKeyPrefix?: string; /** Maximum retry attempts */ maxRetries?: number; /** Initial retry delay in milliseconds */ retryDelay?: number; /** Authentication token or function to get token */ authToken?: string | TokenProvider; /** Enable secure token handling (default: true) */ enableSecureTokenHandling?: boolean; /** Custom headers for requests */ headers?: Record<string, string>; /** Enable compression if available */ enableCompression?: boolean; /** Session ID generator function */ sessionIdGenerator?: () => string; /** User ID provider function */ userIdProvider?: () => string | undefined; /** Rate limit: max events per minute */ rateLimitPerMinute?: number; /** Enable automatic page lifecycle handling */ enableLifecycleHandling?: boolean; } /** * SendBeacon transport for efficient telemetry transmission * * High-performance transport that uses the sendBeacon API when available, * falling back to fetch with keepalive. Provides intelligent batching, * offline storage, retry logic, and lifecycle management. * * Features: * - Automatic batching with size and time-based flushing * - sendBeacon API with fetch fallback * - Offline storage with localStorage * - Exponential backoff retry logic * - Rate limiting and abuse prevention * - Page lifecycle event handling * - Bearer token authentication * - Circular reference protection * * @example * ```typescript * const transport = new SendBeaconTransport({ * endpoint: 'https://telemetry.example.com/logs', * batchSize: 100, * flushInterval: 10000, * authToken: 'bearer-token', * enableOfflineStorage: true, * userIdProvider: () => getCurrentUserId() * }); * ``` */ export declare class SendBeaconTransport extends BaseTransport { private readonly transportConfig; private readonly secureTokenHandler; private readonly userIdProvider?; private eventQueue; private flushTimer?; private sessionId; private rateLimitCounter; private rateLimitResetTime; private isOnline; private retryQueue; private lifecycleHandlersAttached; /** * Create a new SendBeacon transport instance * * @param config - Configuration options for the transport * @param config.endpoint - Required endpoint URL for telemetry data * @param config.batchSize - Maximum events per batch (default: 50) * @param config.flushInterval - Flush interval in milliseconds (default: 5000) * @param config.maxPayloadSize - Maximum payload size in bytes (default: 64KB) * @param config.authToken - Authentication token or provider function * @param config.enableOfflineStorage - Enable localStorage fallback (default: true) * @param config.rateLimitPerMinute - Rate limit events per minute (default: 1000) * * @example * ```typescript * const transport = new SendBeaconTransport({ * endpoint: 'https://api.example.com/telemetry', * batchSize: 25, * flushInterval: 3000, * authToken: async () => await getApiToken(), * userIdProvider: () => user.id * }); * ``` */ constructor(config: SendBeaconTransportConfig); /** * Write a log event to the transport * * Adds the event to the batching queue and triggers immediate flush * if batch size or payload size limits are reached. Events are * subject to rate limiting. * * @param event - The log event to write * * @example * ```typescript * transport.write({ * level: 'info', * message: 'User logged in', * timestamp: Date.now(), * component: 'auth', * context: { userId: '123' }, * args: [] * }); * ``` */ write(event: LogEventData): void; /** * Flush all pending events immediately * * Sends all queued events and retry events in optimally-sized batches. * Respects payload size limits and creates multiple batches if necessary. * Automatically handles online/offline state and retry logic. * * @returns Promise that resolves when all events have been processed * * @example * ```typescript * // Manually flush before page unload * window.addEventListener('beforeunload', async () => { * await transport.flush(); * }); * ``` */ flush(): Promise<void>; /** * Close the transport and clean up resources * * Performs a final flush of all pending events, clears timers, * removes event listeners, saves any remaining events to * offline storage if enabled, and securely disposes of token handler. * * @returns Promise that resolves when cleanup is complete * * @example * ```typescript * // Clean shutdown * await transport.close(); * ``` */ close(): Promise<void>; /** * Check if immediate flush is needed */ private shouldFlushImmediately; /** * Create batches respecting size limits */ private createBatches; /** * Send a batch of events */ private sendBatch; /** * Send payload using sendBeacon or fetch with keepalive * * Attempts to use navigator.sendBeacon first for optimal performance, * then falls back to fetch with keepalive flag. Automatically handles * payload size limits and browser compatibility. * * @param payload - JSON string payload to send * @returns Promise resolving to true if send was successful * * @internal */ private sendPayload; /** * Build request headers with secure token handling */ private buildHeaders; /** * Create telemetry envelope with metadata and sanitized events * * Wraps log events in a telemetry envelope containing session context, * user information, and environment metadata. Automatically sanitizes * events to handle circular references and serialization issues. * * @param events - Array of log events to include in envelope * @returns Promise resolving to complete telemetry envelope * * @internal */ private createEnvelope; /** * Handle send failure with retry logic */ private handleSendFailure; /** * Setup online/offline status monitoring */ private setupOnlineStatusMonitoring; /** * Setup page lifecycle event handlers */ private setupLifecycleHandlers; /** * Remove lifecycle event handlers */ private removeLifecycleHandlers; /** * Save events to offline storage */ private saveOfflineEvents; /** * Load events from offline storage */ private loadOfflineEvents; /** * Get events from offline storage */ private getOfflineEvents; /** * Clear offline storage */ private clearOfflineEvents; /** * Check rate limit */ private checkRateLimit; /** * Start flush timer */ private startFlushTimer; /** * Clear flush timer */ private clearFlushTimer; /** * Estimate size of event(s) in bytes */ private estimateEventSize; /** * Get a secure replacer function for handling circular references and sensitive data */ private getCircularReplacer; /** * Sanitize event data for safe logging * * @param event - Event data to sanitize * @returns Sanitized event data safe for logging */ private sanitizeEventForLogging; /** * Generate a unique session ID */ private static generateSessionId; } /** * Create a SendBeacon transport with default configuration * * Factory function that creates a new SendBeacon transport instance * with the provided configuration. Provides a convenient way to * create transports without using the constructor directly. * * @param config - Transport configuration options * @returns New SendBeacon transport instance * * @example * ```typescript * import { createSendBeaconTransport } from '@nuanced-labs/lever-ui-logger'; * * const transport = createSendBeaconTransport({ * endpoint: 'https://api.example.com/telemetry', * batchSize: 100, * flushInterval: 10000, * authToken: process.env.API_TOKEN, * enableOfflineStorage: true, * rateLimitPerMinute: 500 * }); * * // Use with logger * const logger = createLogger(eventBus, { * transports: [transport] * }); * ``` */ export declare function createSendBeaconTransport(config: SendBeaconTransportConfig): SendBeaconTransport; //# sourceMappingURL=sendbeacon-transport.d.ts.map