2025-09-02

pinoのロギングを (string, object) のインターフェースで呼び出したい

Node.jsのロガーライブラリの pino は以下のようなインターフェースでログ出力できる。

const pino = require('pino');
const logger = pino();

logger.info('string message');
logger.info({ message: 'json message' });
logger.info({ message: 'json message' }, 'string message');

見てもらえるとわかるように

に対応しているが、 第1引数が文字列で第2引数がオブジェクト(メタデータ・コンテキスト) には対応していない。

他の言語のロガーはだいたいこの方式に対応していたりするので、pinoもこのインターフェースに対応したい。ということで以下のような感じでカスタマイズできる。

import pino from "pino";

const logger = pino({
  hooks: {
    logMethod(inputArgs, method) {
      // 第1引数が文字列, 第2引数がオブジェクトの場合
      if (
        inputArgs.length === 2 &&
        typeof inputArgs[0] === "string" &&
        typeof inputArgs[1] === "object"
      ) {
        const msg = inputArgs[0];
        const context = inputArgs[1];
        // @ts-expect-error
        return method.apply(this, [{ ...context, msg }]);
      }
      // @ts-expect-error
      return method.apply(this, inputArgs);
    },
  },
});

これで

logger.info("string message", { userId: 123 });

という感じで呼び出すと

{"level":30,"time":1756819989743,"pid":27639,"hostname":"xxxx","userId":123,"msg":"string message"}

という感じな出力になる。