H4ad / nodejs-logging-proposal

3 stars 0 forks source link

Signature of log method #8

Closed H4ad closed 5 months ago

H4ad commented 6 months ago

Ref: https://github.com/nodejs/node/issues/49296#issuecomment-2135160646

Basically, should we use something like golang, that does by pair of key-value?

util.format is something to avoid since it generates unstructured log.

What other libraries does?

H4ad commented 6 months ago

Ecosystem

Pino

interface LogFn {
    // TODO: why is this different from `obj: object` or `obj: any`?
    /* tslint:disable:no-unnecessary-generics */
    <T extends object>(obj: T, msg?: string, ...args: any[]): void;
    (obj: unknown, msg?: string, ...args: any[]): void;
    (msg: string, ...args: any[]): void;
}

Ref: https://github.com/pinojs/pino/blob/main/pino.d.ts#L316

Winston

// used on .log
interface LogMethod {
  (level: string, message: string, callback: LogCallback): Logger;
  (level: string, message: string, meta: any, callback: LogCallback): Logger;
  (level: string, message: string, ...meta: any[]): Logger;
  (entry: LogEntry): Logger;
  (level: string, message: any): Logger;
}

// used on .info, .warn, etc....
interface LeveledLogMethod {
  (message: string, callback: LogCallback): Logger;
  (message: string, meta: any, callback: LogCallback): Logger;
  (message: string, ...meta: any[]): Logger;
  (message: any): Logger;
  (infoObject: object): Logger;
}

Ref: https://github.com/winstonjs/winston/blob/master/index.d.ts#L79-L93

Log4js

log(level: Level | string, ...args: any[]): void;

info(message: any, ...args: any[]): void;
// repeated for other levels

Ref: https://github.com/log4js-node/log4js-node/blob/master/types/log4js.d.ts#L436

Bunyan

 * Usages:
 *    log.<level>()  -> boolean is-trace-enabled
 *    log.<level>(<Error> err, [<string> msg, ...])
 *    log.<level>(<string> msg, ...)
 *    log.<level>(<object> fields, <string> msg, ...)

Ref: https://github.com/trentm/node-bunyan/blob/master/lib/bunyan.js#L1056-L1060

Roarr

// printf style
export type Logger =
  (
    context: MessageContext,
    message: string,
    c?: SprintfArgument,
    d?: SprintfArgument,
    e?: SprintfArgument,
    f?: SprintfArgument,
    g?: SprintfArgument,
    h?: SprintfArgument,
    i?: SprintfArgument,
    k?: SprintfArgument
  ) => void |
  (
    message: string,
    b?: SprintfArgument,
    c?: SprintfArgument,
    d?: SprintfArgument,
    e?: SprintfArgument,
    f?: SprintfArgument,
    g?: SprintfArgument,
    h?: SprintfArgument,
    i?: SprintfArgument,
    k?: SprintfArgument
  ) => void;

Ref: https://github.com/gajus/roarr?tab=readme-ov-file#api

Signale

export type LoggerFunction = (...message: any[]) => void;

Ref: https://github.com/klaudiosinani/signale/blob/master/types/signale.d.ts#L49

H4ad commented 6 months ago

Based on the suggestions, I think the most common signature will be:

export interface LogMethod {
    (level: string, obj: unknown, msg?: string, ...args: any[]): void;
    (level: string, msg: string, ...args: any[]): void;
}

export interface LogLevelMethod {
    (obj: unknown, msg?: string, ...args: any[]): void;
    (msg: string, ...args: any[]): void;
}
H4ad commented 5 months ago

I will not add .log method, so I will keep the same signature of pino.