-
Notifications
You must be signed in to change notification settings - Fork 60
fix(logger): migrate to winston for simpler executable support #1808
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e1ee9ed
6a9f309
bd66719
3759362
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # Verifies lint, formatting, types, audit, and other static checks pass. | ||
| name: check | ||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| ref: | ||
| required: true | ||
| type: string | ||
|
|
||
| jobs: | ||
| check: | ||
| runs-on: codebuild-agentcore-e2e-${{ github.run_id }}-${{ github.run_attempt }} | ||
| permissions: | ||
| contents: read | ||
| steps: | ||
| - uses: actions/checkout@v7 | ||
| with: | ||
| ref: ${{ inputs.ref }} | ||
| persist-credentials: false | ||
| - uses: oven-sh/setup-bun@v2 | ||
| - run: bun install --frozen-lockfile | ||
| - run: bun run lint:check | ||
| if: always() | ||
| - run: bun run format:check | ||
| if: always() | ||
| - run: bun run typecheck | ||
| if: always() | ||
| - run: bun audit | ||
| if: always() |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import pino from "pino"; | ||
| import winston from "winston"; | ||
| import DailyRotateFile from "winston-daily-rotate-file"; | ||
| import { type AsyncLogger, type LoggerBindings, type LogLevel } from "./types"; | ||
|
|
||
| export interface FileLoggerConfig { | ||
|
|
@@ -9,54 +10,62 @@ export interface FileLoggerConfig { | |
| logLevel: LogLevel; | ||
| } | ||
|
|
||
| function wrapPinoLogger(pinoLogger: pino.Logger): AsyncLogger { | ||
| function wrapWinstonLogger( | ||
| winstonLogger: winston.Logger, | ||
| transport: DailyRotateFile, | ||
| bindings: LoggerBindings, | ||
| ): AsyncLogger { | ||
| const log = | ||
| (level: pino.Level) => | ||
| (level: string) => | ||
| (...args: string[]) => | ||
| pinoLogger[level](args.join(" ")); | ||
| winstonLogger.log(level, args.join(" "), bindings); | ||
|
|
||
| return { | ||
| debug: log("debug"), | ||
| info: log("info"), | ||
| warn: log("warn"), | ||
| error: log("error"), | ||
| child: (bindings) => wrapPinoLogger(pinoLogger.child(bindings)), | ||
| // we convert pino's flush method that accepts a callback into a promise to make it easier to work with. | ||
| // Note: we also treat flush as best-effort and swallow errors | ||
| flush: () => new Promise<void>((resolve) => pinoLogger.flush(() => resolve())), | ||
| child: (childBindings) => | ||
| wrapWinstonLogger(winstonLogger, transport, { ...bindings, ...childBindings }), | ||
| end: () => | ||
| new Promise<void>((resolve) => { | ||
| transport.on("finish", resolve); | ||
| // note: we prefer close over end since close calls end on the stream internally: https://github.com/winstonjs/winston-daily-rotate-file/blob/a1a4668cfea77476cd6a4a11f038c2aac9d10741/daily-rotate-file.js#L201-L207 | ||
| if (transport.close) transport.close(); | ||
| }), | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * Creates a logger that writes structured JSON to a rotating file. | ||
| * | ||
| * @param config - Logger configuration (file path, rotation limits, level). | ||
| * @returns A {@link AsyncLogger} that writes to a rotating file via pino. | ||
| * @returns A {@link AsyncLogger} that writes to a rotating file via winston. | ||
| */ | ||
| export function createFileLogger(config: FileLoggerConfig): AsyncLogger { | ||
| const maxSizeInMB = config.maxSizeInMB ?? 10; | ||
| const maxFileCount = config.maxFileCount ?? 5; | ||
| const maxSizeInMB = config.maxSizeInMB ?? 5; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the new behavior is that it rotates the file each day or when the size cap it hit. Before we rotated only when the size limit was hit. This swap ensures we maintain roughly the past 10 days but still no more than 50MB. |
||
| const maxFileCount = config.maxFileCount ?? 10; | ||
| const bindings = config.bindings ?? {}; | ||
| return wrapPinoLogger( | ||
| pino({ | ||
| level: config.logLevel, | ||
| base: undefined, // omit pid and hostname | ||
| formatters: { | ||
| level(label) { | ||
| return { level: label }; | ||
| }, | ||
| }, | ||
| transport: { | ||
| target: "pino-roll", | ||
| options: { | ||
| extension: ".log", | ||
| dateFormat: "yyyy-MM-dd'T'HH-mm-ss", | ||
| // Rotate when file reaches {maxSizeInMB} MB, and start deleting once we have {maxFileCount} files | ||
| size: `${maxSizeInMB}m`, | ||
| limit: { count: maxFileCount }, | ||
| file: config.filePath, | ||
| mkdir: true, | ||
| }, | ||
| }, | ||
| }), | ||
| ).child(bindings); | ||
|
|
||
| const transport = new DailyRotateFile({ | ||
| filename: `${config.filePath}-%DATE%`, | ||
| extension: ".log", | ||
| datePattern: "YYYY-MM-DD", | ||
| maxSize: `${maxSizeInMB}m`, | ||
| maxFiles: maxFileCount, | ||
| createSymlink: false, | ||
| }); | ||
|
|
||
| const jsonFormat = winston.format.printf((info) => { | ||
| const { level, message, ...rest } = info; | ||
| return JSON.stringify({ level, msg: message, time: Date.now(), ...rest }); | ||
| }); | ||
|
|
||
| const logger = winston.createLogger({ | ||
| level: config.logLevel, | ||
| format: jsonFormat, | ||
| transports: [transport], | ||
| }); | ||
|
|
||
| return wrapWinstonLogger(logger, transport, bindings); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to top-level to ensure that logger/io init failures are logged to console.