🌲

Next.jsでPinoを使う

2022/10/22に公開

Pino というロガーが速くていい感じそうだったので使ってみたら、pino-pretty とNext.jsとの相性(?)でハマり、日英両言語ともあまり知見がなくてつらかったので共有します。

TL; DR

  • Programmatic Integration は使わない方がいい
  • dev のnpmコマンドを以下のように変更する
    package.json
    "dev": "FORCE_COLOR=true next dev | pino-pretty -tc",
    

前提

  • pino 8.7.0
  • pino-pretty 9.1.1
  • next 12.2.5

症状

まず、導入は普通に

yarn add pino pino-pretty

loggerのラッパーを書いて (参考: Programmatic Integration)

logger.ts
export const logger = pino({
  level: process.env.NODE_ENV === 'development' ? 'debug' : 'info',
  transport: {
    target: 'pino-pretty'
  }
})

呼び出してみると

logger.info('hello')
error - Error: unable to determine transport target for "pino-pretty"

なぜか初回だけエラーが出ます。2回目以降の呼び出しはエラーなしにちゃんとprettyされたログが出るようです。

ちなみに、

logger.ts
export const logger = pino({
  level: 'debug',
  transport: {
    target: 'pino-pretty'
  }
})

こうすると、初回もエラーになることなくprettyされます。なんだこれは…

try-catchで無理矢理初回エラーを握りつぶそうかとも思いましたが、このNextアプリはVercelにデプロイするつもりで、Functionは実行するたびに初回になると思うので却下(試してはいませんが)。
まあバックエンドに蓄積されるのはprettyされていないログでもいいかなと思うので、Devサーバーの出力だけCLIでprettyすることにしました。

まずは素朴に

package.json
"dev": "next dev | pino-pretty"

として yarn dev してみますが、ログだけでなくNextの出力も全部無色になってしまいました。

ググってみると、ドンピシャな discussion が見つかり、この通りに書き換えると色がついた!
ここから必要なところだけ抜き出して、

package.json
"dev": "FORCE_COLOR=true next dev | pino-pretty -tc",

これで完成!

ちょっと調査したこと

ぼくが諦め悪くProgrammatic Integrationでいけないかと考えていた結果もここに供養しておきます。

まず、NODE_ENVlevel を分岐しなければ正常に動くあたり、若干の処理遅延がライブラリに影響を及ぼしているのかな、と考えました。
pinoのtransport.targetの実装が副作用マシマシなのかな?などと思いましたが、どうやらNode標準の modulecreateRequire をそのまま使っているように見えます。

もしかしたら createRequire がNext.jsやtscあたりと相性悪いのかな?と思っています。

GitHubで編集を提案

Discussion