Disclaimer: This article was written by AI and may contain inaccuracies or errors.
Table of contents
はじめに
Node.js で高速なロギングライブラリとして知られている Pino は、本番環境でのパフォーマンスを重視して JSON 形式でログを出力します。
しかし、開発中にこの JSON ログをターミナルで見るのは少し読みづらいものです。
{
"level": 30,
"time": 1761276937425,
"pid": 3115,
"hostname": "runsc",
"msg": "Starting application"
}
このような JSON の羅列を眺めるよりも、もっと読みやすい形式で表示できたら便利です。
そこで登場するのが pino-pretty です。このライブラリは、Pino が出力する JSON ログを開発者にとって読みやすい形式に整形してくれます。
今回、実際に動かして試してみたので、その体験をレポートします。
pino-pretty とは
pino-pretty は、ndjson(改行区切りの JSON)形式のログを人間が読みやすい形式に変換してくれるフォーマッターです。Pino のログ専用に設計されており、ログレベルや タイムスタンプなどを考慮した整形を行ってくれます。
主な特徴
- 読みやすいフォーマット - JSON を構造化されたテキストに変換
- カラー表示 - ログレベルごとに色分けして表示
- 柔軟な設定 - タイムスタンプのフォーマット、表示するフィールドなどをカスタマイズ可能
- 複数の使い方 - CLI パイプ、transport、stream など様々な方法で利用できる
- エラーの特別扱い - エラーオブジェクトのスタックトレースを見やすく表示
用途
公式ドキュメントでも明記されていますが、pino-pretty は 開発環境での使用を想定 しています。本番環境では、パフォーマンスを重視して JSON のまま出力し、ログ収集システムで処理することが推奨されています。
セットアップ
pino-pretty のインストール方法はいくつかあります。
グローバルインストール
CLI ツールとして使う場合:
npm install -g pino-pretty
開発用依存関係として
プロジェクトごとに管理する場合(推奨):
npm install --save-dev pino pino-pretty
または
pnpm install --save-dev pino pino-pretty
実際に試してみる
実際にどのように動作するか確かめるため、いくつかのパターンで試してみました。
1. transport として使う(Pino v7+)
最もシンプルな方法は、Pino の transport 機能を使う方法です。
// basic-usage.js
const pino = require("pino");
const logger = pino({
transport: {
target: "pino-pretty",
options: {
colorize: true,
},
},
});
// 様々なログレベル
logger.trace("This is a trace message");
logger.debug("This is a debug message");
logger.info("This is an info message");
logger.warn("This is a warning message");
logger.error("This is an error message");
logger.fatal("This is a fatal message");
// 追加データと一緒にログ
logger.info({ user: "john", id: 123 }, "User logged in");
// エラーをログ
const error = new Error("Something went wrong!");
logger.error({ err: error }, "An error occurred");
// カスタムフィールド
logger.info(
{
requestId: "req-001",
method: "GET",
url: "/api/users",
duration: 45,
},
"HTTP request completed"
);
このコードを実行すると、以下のような出力が得られます:
[03:35:29.337] INFO (2698): This is an info message
[03:35:29.337] WARN (2698): This is a warning message
[03:35:29.337] ERROR (2698): This is an error message
[03:35:29.337] FATAL (2698): This is a fatal message
[03:35:29.426] INFO (2698): User logged in
user: "john"
id: 123
[03:35:29.426] ERROR (2698): An error occurred
err: {
"type": "Error",
"message": "Something went wrong!",
"stack":
Error: Something went wrong!
at Object.<anonymous> (/tmp/pino-pretty-test/my-test-app/basic-usage.js:25:15)
at Module._compile (node:internal/modules/cjs/loader:1706:14)
...
}
[03:35:29.427] INFO (2698): HTTP request completed
requestId: "req-001"
method: "GET"
url: "/api/users"
duration: 45
ログレベルごとに色分けされ(実際のターミナルでは色がつきます)、オブジェクトのフィールドがインデントされて見やすく表示されます。エラーのスタックトレースも整形されています。
2. CLI パイプとして使う
従来の方法として、標準の Pino ロガーの出力をパイプする使い方もあります。
// cli-usage.js
const pino = require("pino");
const logger = pino();
logger.info("Starting application");
logger.info(
{ database: "postgresql", host: "localhost", port: 5432 },
"Database connected"
);
logger.warn({ memory: "80%" }, "High memory usage detected");
logger.info({ users: 42, active: 38 }, "Active users summary");
logger.error(
{ code: "ECONNREFUSED", attempt: 3 },
"Failed to connect to service"
);
logger.info("Application shutting down");
このコードを pino-pretty なしで実行すると、JSON がそのまま出力されます:
$ node cli-usage.js
{"level":30,"time":1761276937425,"pid":3115,"hostname":"runsc","msg":"Starting application"}
{"level":30,"time":1761276937426,"pid":3115,"hostname":"runsc","database":"postgresql","host":"localhost","port":5432,"msg":"Database connected"}
{"level":40,"time":1761276937426,"pid":3115,"hostname":"runsc","memory":"80%","msg":"High memory usage detected"}
これを pino-pretty にパイプすると:
$ node cli-usage.js | npx pino-pretty
[03:35:44.243] INFO (3532): Starting application
[03:35:44.244] INFO (3532): Database connected
database: "postgresql"
host: "localhost"
port: 5432
[03:35:44.244] WARN (3532): High memory usage detected
memory: "80%"
[03:35:44.244] INFO (3532): Active users summary
users: 42
active: 38
[03:35:44.244] ERROR (3532): Failed to connect to service
code: "ECONNREFUSED"
attempt: 3
[03:35:44.244] INFO (3532): Application shutting down
JSON がきれいに整形され、ログの内容が把握しやすくなりました。
3. カスタム設定を使う
pino-pretty は様々な設定オプションを提供しています。タイムスタンプのフォーマットや表示フィールドをカスタマイズできます。
// custom-config.js
const pino = require("pino");
const logger = pino({
transport: {
target: "pino-pretty",
options: {
colorize: true,
translateTime: "SYS:yyyy-mm-dd HH:MM:ss",
ignore: "pid,hostname",
levelFirst: true,
},
},
});
logger.info("Custom formatted message");
logger.info({ userId: 100, action: "login" }, "User action tracked");
logger.warn(
{ temperature: 85, threshold: 80 },
"Temperature threshold exceeded"
);
logger.error({ code: 404, path: "/api/missing" }, "Resource not found");
実行結果:
INFO [2025-10-24 03:35:52]: Custom formatted message
INFO [2025-10-24 03:35:52]: User action tracked
userId: 100
action: "login"
WARN [2025-10-24 03:35:52]: Temperature threshold exceeded
temperature: 85
threshold: 80
ERROR [2025-10-24 03:35:52]: Resource not found
code: 404
path: "/api/missing"
設定によって出力フォーマットが変わりました:
translateTimeでタイムスタンプの形式を変更ignoreで pid と hostname を非表示にlevelFirstでログレベルを先頭に配置
主な設定オプション
pino-pretty には 40 以上の設定オプションがありますが、特によく使いそうなものをいくつか紹介します。
表示関連
colorize: カラー表示の有効化(デフォルト: false)levelFirst: ログレベルを先頭に表示(デフォルト: false)hideObject: オブジェクトを非表示(デフォルト: false)singleLine: 全てを1行で表示(デフォルト: false)
タイムスタンプ関連
translateTime: タイムスタンプを人間が読みやすい形式に変換'HH:MM:ss.l': デフォルト(ローカルタイムゾーン)'UTC:yyyy-mm-dd HH:MM:ss': UTC 時刻'SYS:yyyy-mm-dd HH:MM:ss': システムのタイムゾーン
フィルタリング関連
ignore: 指定したキーを非表示(例:'pid,hostname')include: 指定したキーのみ表示minimumLevel: 指定レベル以下のログを非表示
メッセージフォーマット
messageFormat: メッセージの表示形式をカスタマイズ- 例:
'{levelLabel} - {pid} - url:{req.url}'
- 例:
良かった点
1. 開発体験の向上
JSON の羅列を読むよりも、整形された形式の方が圧倒的に読みやすいです。特にオブジェクトのフィールドがインデントされて表示されるのは、ログの内容を素早く把握するのに役立つと感じました。
2. 色分けによる視認性
ログレベルごとに色が変わるので、WARNING や ERROR がすぐに目に入ります。大量のログが流れる中でも、重要な情報を見逃しにくくなると思います。
3. 柔軟な使い方
transport として組み込む方法と、パイプで使う方法の両方が用意されています。既存のコードを変更せずに使いたい場合はパイプ、新規プロジェクトや本格的に導入したい場合は transport、という使い分けができます。
4. エラー表示の工夫
エラーオブジェクトのスタックトレースが見やすく整形されます。開発中のデバッグ作業が楽になると感じました。
5. カスタマイズ性
タイムスタンプのフォーマットや表示フィールドなど、細かくカスタマイズできます。チームやプロジェクトの好みに合わせて調整できるのは良いと思います。
6. シンプルな導入
設定なしでも動作するため、まず試してみることができます。必要に応じて徐々にカスタマイズしていけるのは学習コストが低くて助かります。
気づいた点
1. 開発環境専用
公式ドキュメントにも明記されていますが、本番環境での使用は推奨されていません。フォーマット処理のオーバーヘッドがあるため、本番では JSON のまま出力することが想定されています。
この点は制限というよりも、適切な使い分けを促すための設計思想だと感じます。
2. transport のパフォーマンス
transport として組み込んだ場合、ログ出力のたびにフォーマット処理が走ります。開発環境では問題になりませんが、大量のログを出力する場合は、パイプ方式の方がパフォーマンスが良いかもしれません。
3. カスタムフォーマットの学習
messageFormat などの高度なカスタマイズを行う場合は、少し学習が必要です。ただし、基本的な使い方だけなら特に学ぶべきことは少ないので、必要になってから調べても十分だと思います。
まとめ
私が感じたこと
pino-pretty は、開発時のログの読みやすさを劇的に改善してくれるツールだと感じました。特に以下の点が印象的でした:
- 即座に効果を実感できる - 導入してすぐに読みやすさが向上する
- 開発体験重視の設計 - 本番と開発で使い分ける思想が明確
- 柔軟な使い方 - パイプでも transport でも使える
どんな場合に使えそうか
以下のような場面で特に有用だと思います:
- 開発中のデバッグ - ログの内容を素早く把握したい
- ローカル開発環境 - ターミナルでログを確認しながら作業する
- 複雑なオブジェクトをログに含める場合 - インデント表示が役立つ
- 複数人での開発 - 統一されたフォーマットでログを見たい
逆に、以下のような場合は不要かもしれません:
- 本番環境 - JSON のまま出力してログ収集システムに送る
- ログをファイルに出力する場合 - 機械処理しやすい JSON の方が適している
- 超高速なロギングが必要な場合 - フォーマット処理のオーバーヘッドを避けたい
個人的な感想
実際に動かしてみて、JSON ログと整形されたログの読みやすさの差を体感できたのは良かったです。特に、エラーオブジェクトのスタックトレースがきれいに表示される点は、ドキュメントを読むだけでは伝わりにくい部分だと思いました。
開発中のログの読みづらさに悩んでいる方や、Pino を使い始めた方には、ぜひ試してみることをお勧めします。
参考リンク
検証環境
本記事で使用したパッケージのバージョン:
- pino: 10.1.0
- pino-pretty: 13.1.2
- Node.js: 20.x
pino-pretty を実際に試してみて、開発時のログの読みやすさが大きく向上することが分かりました。
この記事が、Node.js でのロギングを改善したい方の参考になれば幸いです。