Next.jsでPinoを使う
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)
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されたログが出るようです。
ちなみに、
export const logger = pino({
level: 'debug',
transport: {
target: 'pino-pretty'
}
})
こうすると、初回もエラーになることなくprettyされます。なんだこれは…
try-catchで無理矢理初回エラーを握りつぶそうかとも思いましたが、このNextアプリはVercelにデプロイするつもりで、Functionは実行するたびに初回になると思うので却下(試してはいませんが)。
まあバックエンドに蓄積されるのはprettyされていないログでもいいかなと思うので、Devサーバーの出力だけCLIでprettyすることにしました。
まずは素朴に
"dev": "next dev | pino-pretty"
として yarn dev
してみますが、ログだけでなくNextの出力も全部無色になってしまいました。
ググってみると、ドンピシャな discussion が見つかり、この通りに書き換えると色がついた!
ここから必要なところだけ抜き出して、
"dev": "FORCE_COLOR=true next dev | pino-pretty -tc",
これで完成!
ちょっと調査したこと
ぼくが諦め悪くProgrammatic Integrationでいけないかと考えていた結果もここに供養しておきます。
まず、NODE_ENV
で level
を分岐しなければ正常に動くあたり、若干の処理遅延がライブラリに影響を及ぼしているのかな、と考えました。
pinoのtransport.targetの実装が副作用マシマシなのかな?などと思いましたが、どうやらNode標準の module
の createRequire
をそのまま使っているように見えます。
もしかしたら createRequire
がNext.jsやtscあたりと相性悪いのかな?と思っています。
Discussion