UNPKG

@pulzar/core

Version:

Next-generation Node.js framework for ultra-fast web applications with zero-reflection DI, GraphQL, WebSockets, events, and edge runtime support

172 lines 5.22 kB
import pino from "pino"; import { AsyncLocalStorage } from "async_hooks"; const requestContext = new AsyncLocalStorage(); // Create transport configuration based on environment function createTransport() { const isDev = process.env.NODE_ENV === "development"; const isTest = process.env.NODE_ENV === "test"; if (isTest) { return { target: "pino/file", options: { destination: "/dev/null" }, }; } if (isDev) { return { target: "pino-pretty", options: { colorize: true, translateTime: "HH:MM:ss Z", ignore: "pid,hostname", messageFormat: "{msg}", hideObject: false, singleLine: false, crlf: false, }, }; } // Production: JSON output with optional Loki transport const transports = [ { target: "pino/file", options: { destination: 1 }, // stdout }, ]; // Add Loki transport if configured if (process.env.LOKI_URL) { transports.push({ target: "pino-loki", options: { batching: true, interval: 5000, host: process.env.LOKI_URL, basicAuth: process.env.LOKI_AUTH ? { username: process.env.LOKI_USERNAME || "", password: process.env.LOKI_PASSWORD || "", } : undefined, labels: { service: process.env.SERVICE_NAME || "pulzar-app", environment: process.env.NODE_ENV || "production", }, }, }); } return transports.length > 1 ? transports : transports[0]; } // Default logger configuration const defaultOptions = { level: process.env.LOG_LEVEL || "info", name: process.env.SERVICE_NAME || "pulzar-app", transport: createTransport(), timestamp: pino.stdTimeFunctions.isoTime, base: { env: process.env.NODE_ENV || "development", version: process.env.SERVICE_VERSION || "1.0.0", }, formatters: { level: (label) => ({ level: label }), log: (object) => { const context = requestContext.getStore(); if (context) { return { ...object, ...context }; } return object; }, }, serializers: { err: pino.stdSerializers.err, error: pino.stdSerializers.err, req: pino.stdSerializers.req, res: pino.stdSerializers.res, }, redact: { paths: [ "password", "token", "authorization", "cookie", "*.password", "*.token", "*.authorization", "*.cookie", ], remove: true, }, }; // Create the main logger instance export const logger = pino(defaultOptions); // Context management functions export function setRequestContext(context) { requestContext.enterWith(context); } export function getRequestContext() { return requestContext.getStore(); } export function withRequestContext(context, fn) { return requestContext.run(context, fn); } // Child logger factory export function createChildLogger(bindings, options) { const mergedOptions = { ...defaultOptions, ...options }; return pino(mergedOptions).child(bindings); } // Request logger for Fastify export function createRequestLogger(requestId, userId) { return logger.child({ requestId, userId, }); } // Performance logger export function logPerformance(operation, startTime, metadata) { const duration = performance.now() - startTime; logger.info({ operation, duration: `${duration.toFixed(2)}ms`, ...metadata, }, `Performance: ${operation} completed in ${duration.toFixed(2)}ms`); } // Error logger with stack trace export function logError(error, context, message) { logger.error({ err: error, ...context, }, message || error.message); } // Structured logging helpers export const log = { trace: (obj, msg) => logger.trace(obj, msg), debug: (obj, msg) => logger.debug(obj, msg), info: (obj, msg) => logger.info(obj, msg), warn: (obj, msg) => logger.warn(obj, msg), error: (obj, msg) => logger.error(obj, msg), fatal: (obj, msg) => logger.fatal(obj, msg), // Simple message logging message: { trace: (msg) => logger.trace(msg), debug: (msg) => logger.debug(msg), info: (msg) => logger.info(msg), warn: (msg) => logger.warn(msg), error: (msg) => logger.error(msg), fatal: (msg) => logger.fatal(msg), }, }; // Graceful shutdown export async function flushLogger() { return new Promise((resolve, reject) => { logger.flush((err) => { if (err) { reject(err); } else { resolve(); } }); }); } // Export the pino instance directly for advanced usage export { pino }; export default logger; //# sourceMappingURL=logger.js.map