|
| 1 | +import { mkdirSync } from 'fs' |
| 2 | +import path, { dirname } from 'path' |
| 3 | +import { pino } from 'pino' |
| 4 | + |
| 5 | +let logPath: string | undefined = undefined |
| 6 | +let pinoLogger: any = undefined |
| 7 | + |
| 8 | +const loggingLevels = ['info', 'debug', 'warn', 'error', 'fatal'] as const |
| 9 | +type LogLevel = (typeof loggingLevels)[number] |
| 10 | + |
| 11 | +function initPinoLoggerWithPath(path: string): void { |
| 12 | + if (path === logPath) return // nothing to do |
| 13 | + |
| 14 | + logPath = path |
| 15 | + mkdirSync(dirname(path), { recursive: true }) |
| 16 | + |
| 17 | + // ────────────────────────────────────────────────────────────── |
| 18 | + // pino.destination(..) → SonicBoom stream, no worker thread |
| 19 | + // ────────────────────────────────────────────────────────────── |
| 20 | + const fileStream = pino.destination({ |
| 21 | + dest: path, // absolute or relative file path |
| 22 | + mkdir: true, // create parent dirs if they don’t exist |
| 23 | + sync: false, // set true if you *must* block on every write |
| 24 | + }) |
| 25 | + |
| 26 | + pinoLogger = pino( |
| 27 | + { |
| 28 | + level: 'debug', |
| 29 | + formatters: { |
| 30 | + level: (label) => ({ level: label.toUpperCase() }), |
| 31 | + }, |
| 32 | + timestamp: () => `,"timestamp":"${new Date().toISOString()}"`, |
| 33 | + }, |
| 34 | + fileStream, // <-- no worker thread involved |
| 35 | + ) |
| 36 | +} |
| 37 | + |
| 38 | +function log(level: LogLevel, data: any, msg?: string, ...args: any[]): void { |
| 39 | + if ( |
| 40 | + process.env.CODEBUFF_GITHUB_ACTIONS !== 'true' && |
| 41 | + process.env.NEXT_PUBLIC_CB_ENVIRONMENT !== 'test' |
| 42 | + ) { |
| 43 | + const projectRoot = path.join(__dirname, '..') |
| 44 | + const logTarget = path.join(projectRoot, 'debug', 'evals.log') |
| 45 | + |
| 46 | + initPinoLoggerWithPath(logTarget) |
| 47 | + } |
| 48 | + |
| 49 | + if (pinoLogger !== undefined) { |
| 50 | + pinoLogger[level]({ data }, msg, ...args) |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +/** |
| 55 | + * Wrapper around Pino logger. |
| 56 | + * |
| 57 | + * To also send to Posthog, set data.eventId to type AnalyticsEvent |
| 58 | + * |
| 59 | + * e.g. logger.info({eventId: AnalyticsEvent.SOME_EVENT, field: value}, 'some message') |
| 60 | + */ |
| 61 | +export const logger: Record<LogLevel, pino.LogFn> = Object.fromEntries( |
| 62 | + loggingLevels.map((level) => { |
| 63 | + return [ |
| 64 | + level, |
| 65 | + (data: any, msg?: string, ...args: any[]) => |
| 66 | + log(level, data, msg, ...args), |
| 67 | + ] |
| 68 | + }), |
| 69 | +) as Record<LogLevel, pino.LogFn> |
0 commit comments