UNPKG

logs-interceptor-node14

Version:

High-performance, production-ready log interceptor for Node.js 14 applications with Loki integration

172 lines (147 loc) 6.11 kB
/** * Preload script for logs-interceptor * This file automatically initializes the logs interceptor when loaded via NODE_OPTIONS */ (function() { 'use strict'; // Only run if we're not already in a preload context if (global.__LOGS_INTERCEPTOR_PRELOADED) { return; } global.__LOGS_INTERCEPTOR_PRELOADED = true; try { // Load the main module const logsInterceptor = require('./dist/index.js'); // Check for required environment variables const url = process.env.LOGS_INTERCEPTOR_URL; const tenantId = process.env.LOGS_INTERCEPTOR_TENANT_ID; const appName = process.env.LOGS_INTERCEPTOR_APP_NAME; const enabled = process.env.LOGS_INTERCEPTOR_ENABLED; const debug = process.env.LOGS_INTERCEPTOR_DEBUG === 'true'; // Early exit if disabled if (enabled === 'false') { if (debug) { console.log('[logs-interceptor] Preload: Disabled by LOGS_INTERCEPTOR_ENABLED=false'); } return; } // Check if we have minimum required config if (!url || !tenantId || !appName) { if (debug) { console.log('[logs-interceptor] Preload: Missing required environment variables'); console.log('[logs-interceptor] Required: LOGS_INTERCEPTOR_URL, LOGS_INTERCEPTOR_TENANT_ID, LOGS_INTERCEPTOR_APP_NAME'); console.log('[logs-interceptor] Found:', { url: !!url, tenantId: !!tenantId, appName: !!appName }); } return; } if (debug) { console.log('[logs-interceptor] Preload: Starting initialization...'); } // Parse additional config from environment const config = { transport: { url: url, tenantId: tenantId, authToken: process.env.LOGS_INTERCEPTOR_AUTH_TOKEN, timeout: parseInt(process.env.LOGS_INTERCEPTOR_TIMEOUT) || 5000, compression: process.env.LOGS_INTERCEPTOR_COMPRESSION !== 'false' }, appName: appName, environment: process.env.LOGS_INTERCEPTOR_ENVIRONMENT || process.env.NODE_ENV || 'production', version: process.env.LOGS_INTERCEPTOR_VERSION || '1.0.0', // Buffer settings buffer: { maxSize: parseInt(process.env.LOGS_INTERCEPTOR_BUFFER_SIZE) || 100, flushInterval: parseInt(process.env.LOGS_INTERCEPTOR_FLUSH_INTERVAL) || 5000, maxMemoryMB: parseInt(process.env.LOGS_INTERCEPTOR_MAX_MEMORY_MB) || 50 }, // Filter settings filter: { levels: process.env.LOGS_INTERCEPTOR_LOG_LEVEL ? process.env.LOGS_INTERCEPTOR_LOG_LEVEL.split(',').map(l => l.trim()) : ['debug', 'info', 'warn', 'error', 'fatal'], samplingRate: parseFloat(process.env.LOGS_INTERCEPTOR_SAMPLING_RATE) || 1.0, sanitize: process.env.LOGS_INTERCEPTOR_SANITIZE !== 'false' }, // Features interceptConsole: process.env.LOGS_INTERCEPTOR_INTERCEPT_CONSOLE !== 'false', preserveOriginalConsole: process.env.LOGS_INTERCEPTOR_PRESERVE_CONSOLE !== 'false', debug: debug, silentErrors: process.env.LOGS_INTERCEPTOR_SILENT_ERRORS === 'true' }; // Parse labels if provided if (process.env.LOGS_INTERCEPTOR_LABELS) { try { if (process.env.LOGS_INTERCEPTOR_LABELS.startsWith('{')) { config.labels = JSON.parse(process.env.LOGS_INTERCEPTOR_LABELS); } else { // Parse "key1=value1,key2=value2" format config.labels = {}; const pairs = process.env.LOGS_INTERCEPTOR_LABELS.split(','); for (const pair of pairs) { const [key, ...valueParts] = pair.split('='); if (key && valueParts.length > 0) { config.labels[key.trim()] = valueParts.join('=').trim(); } } } } catch (error) { if (debug) { console.warn('[logs-interceptor] Failed to parse labels:', error.message); } } } // Initialize the interceptor const interceptor = logsInterceptor.init(config); // Store global reference global.__logsInterceptor = interceptor; if (debug) { console.log('[logs-interceptor] Preload: Successfully initialized!'); console.log(`[logs-interceptor] App: ${config.appName}`); console.log(`[logs-interceptor] Environment: ${config.environment}`); console.log(`[logs-interceptor] Loki URL: ${config.transport.url}`); console.log(`[logs-interceptor] Console interception: ${config.interceptConsole ? 'enabled' : 'disabled'}`); } // Send initialization log interceptor.info('logs-interceptor initialized via preload', { method: 'preload', appName: config.appName, environment: config.environment, nodeVersion: process.version, platform: process.platform, pid: process.pid, uptime: process.uptime() }); // Setup graceful shutdown const gracefulShutdown = async (signal) => { if (debug) { console.log(`[logs-interceptor] Preload: Graceful shutdown (${signal})`); } try { await interceptor.flush(); await interceptor.destroy(); if (debug) { console.log('[logs-interceptor] Preload: Cleanup completed'); } } catch (error) { if (debug) { console.error('[logs-interceptor] Preload: Cleanup error:', error.message); } } }; process.on('SIGTERM', () => gracefulShutdown('SIGTERM')); process.on('SIGINT', () => gracefulShutdown('SIGINT')); } catch (error) { const debug = process.env.LOGS_INTERCEPTOR_DEBUG === 'true'; console.error('[logs-interceptor] Preload failed:', error.message); if (debug) { console.error('[logs-interceptor] Stack trace:', error.stack); console.error('[logs-interceptor] Environment variables:', { LOGS_INTERCEPTOR_URL: process.env.LOGS_INTERCEPTOR_URL, LOGS_INTERCEPTOR_TENANT_ID: process.env.LOGS_INTERCEPTOR_TENANT_ID, LOGS_INTERCEPTOR_APP_NAME: process.env.LOGS_INTERCEPTOR_APP_NAME }); } // Don't crash the process, just log the error } })();