UNPKG

bktide

Version:

Command-line interface for Buildkite CI/CD workflows with rich shell completions (Fish, Bash, Zsh) and Alfred workflow integration for macOS power users

114 lines 4.36 kB
import fs from 'node:fs'; import path from 'node:path'; import { pino } from 'pino'; import { XDGPaths } from '../utils/xdgPaths.js'; const logDir = XDGPaths.getAppLogDir('bktide'); fs.mkdirSync(logDir, { recursive: true }); const logFile = path.join(logDir, 'cli.log'); // Check for debug flag early, before Commander parses options. // Pino transports filter at initialization time (worker threads with immutable config), // so we need to know the level before creating the logger. const debugFlagPresent = process.argv.some(arg => arg === '--debug' || arg === '-d'); const effectiveLevel = debugFlagPresent ? 'debug' : (process.env.LOG_LEVEL || 'info'); export const logger = pino({ level: effectiveLevel, customLevels: { console: 80 }, transport: { targets: [ // Direct console output (no pretty formatting) { target: 'pino-pretty', level: 'console', options: { colorize: false, useOnlyCustomProps: true, sync: true, minimumLevel: 'console', ignore: 'level,time,pid,hostname', errorProps: 'err,error,stack,message,code,details' } }, // Debug output with pretty formatting (to stderr) { target: 'pino-pretty', level: effectiveLevel, // Only show when --debug or LOG_LEVEL enables it options: { destination: 2, // stderr - keeps debug separate from stdout for JSON/Alfred colorize: true, sync: true, translateTime: 'HH:MM:ss.l', ignore: 'time,pid,hostname', errorProps: 'err,error,stack,message,code,details' } }, // JSON file output for detailed logging { target: 'pino/file', level: 'trace', options: { destination: logFile, mkdir: true, sync: false } } ], dedupe: true }, serializers: { err: pino.stdSerializers.err, error: pino.stdSerializers.err, stack: (stack) => stack, details: (details) => details } }); // Convenience re-exports for existing codebases export const { info, warn, error, debug, trace, fatal } = logger; /** * Changes the logging level of the current logger instance. * Note: This only affects the logger threshold, not transport filtering. * For debug output to stderr, use --debug flag or LOG_LEVEL env var at startup. * @param level The new log level to set */ export function setLogLevel(level) { logger.level = level; } /** * Helper function to measure and log execution time of async functions * @param label Description of the operation being timed * @param fn Function to execute and time * @param level Log level to use for output (defaults to 'debug') * @returns Result of the function execution */ export async function timeIt(label, fn, level = 'debug') { const start = process.hrtime.bigint(); try { return await fn(); } finally { const end = process.hrtime.bigint(); const duration = Number(end - start) / 1_000_000; // Convert to milliseconds switch (level) { case 'trace': logger.trace({ duration }, `${label} completed in ${duration.toFixed(2)}ms`); break; case 'debug': logger.debug({ duration }, `${label} completed in ${duration.toFixed(2)}ms`); break; case 'info': logger.info({ duration }, `${label} completed in ${duration.toFixed(2)}ms`); break; case 'warn': logger.warn({ duration }, `${label} completed in ${duration.toFixed(2)}ms`); break; case 'error': logger.error({ duration }, `${label} completed in ${duration.toFixed(2)}ms`); break; case 'fatal': logger.fatal({ duration }, `${label} completed in ${duration.toFixed(2)}ms`); break; } } } //# sourceMappingURL=logger.js.map