diff --git a/packages/logger/src/utils/format.ts b/packages/logger/src/utils/format.ts index 21e2521c5796..2340876a371e 100644 --- a/packages/logger/src/utils/format.ts +++ b/packages/logger/src/utils/format.ts @@ -1,5 +1,5 @@ import winston from "winston"; -import {isEmptyObject} from "@lodestar/utils"; +import {LodestarError, isEmptyObject} from "@lodestar/utils"; import {LoggerOptions, TimestampFormatCode} from "../interface.js"; import {logCtxToJson, logCtxToString, LogData} from "./json.js"; import {formatEpochSlotTime} from "./timeFormat.js"; @@ -88,7 +88,14 @@ function humanReadableTemplateFn(_info: {[key: string]: any; level: string; mess str += `[${infoString}] ${info.level.padStart(infoPad)}: ${info.message}`; if (info.context !== undefined && !isEmptyObject(info.context)) str += " " + logCtxToString(info.context); - if (info.error !== undefined) str += " - " + logCtxToString(info.error); + if (info.error !== undefined) { + str += + // LodestarError is formatted in the same way as context, it is either appended to + // the log message (" ") or extends existing context properties (", "). For any other + // error, the message is printed out and clearly separated from the log message (" - "). + (info.error instanceof LodestarError ? (isEmptyObject(info.context) ? " " : ", ") : " - ") + + logCtxToString(info.error); + } return str; } diff --git a/packages/logger/test/fixtures/loggerFormats.ts b/packages/logger/test/fixtures/loggerFormats.ts index fffaaf9ea2f0..563f3094882d 100644 --- a/packages/logger/test/fixtures/loggerFormats.ts +++ b/packages/logger/test/fixtures/loggerFormats.ts @@ -71,10 +71,27 @@ export const formatsTestCases: (TestCase | (() => TestCase))[] = [ id: "error with metadata", opts: {module: "test"}, message: "foo bar", + context: {}, + error: error, + output: { + human: `[test] \u001b[33mwarn\u001b[39m: foo bar code=SAMPLE_ERROR, data=foo=bar\n${error.stack}`, + json: '{"context":{},"error":{"code":"SAMPLE_ERROR","data":{"foo":"bar"},"stack":"$STACK"},"level":"warn","message":"foo bar","module":"test"}', + }, + }; + }, + + () => { + const error = new LodestarError({code: "SAMPLE_ERROR", data: {foo: "bar"}}); + error.stack = "$STACK"; + return { + id: "error and log with metadata", + opts: {module: "test"}, + message: "foo bar", + context: {meta: "data"}, error: error, output: { - human: `[test] \u001b[33mwarn\u001b[39m: foo bar - code=SAMPLE_ERROR, data=foo=bar\n${error.stack}`, - json: '{"error":{"code":"SAMPLE_ERROR","data":{"foo":"bar"},"stack":"$STACK"},"level":"warn","message":"foo bar","module":"test"}', + human: `[test] \u001b[33mwarn\u001b[39m: foo bar meta=data, code=SAMPLE_ERROR, data=foo=bar\n${error.stack}`, + json: '{"context":{"meta":"data"},"error":{"code":"SAMPLE_ERROR","data":{"foo":"bar"},"stack":"$STACK"},"level":"warn","message":"foo bar","module":"test"}', }, }; },