はじめに
開発中はconsole.logで十分だったのに、本番環境に出したとたん「いつ・どのレベルで・何が起きたログなのか」が全く追えなくなった経験はないでしょうか。ターミナルに流れるだけの文字列では、エラーログだけを抽出することも、ファイルに保存することも、外部の監視サービスに送ることもできません。
こうした悩みを解決してくれるのが、Node.js向けロギングライブラリのWinstonです。ログレベルの管理、複数の出力先への振り分け、フォーマットの統一までを一手に引き受けてくれます。この記事では、Winstonの特徴から実践的な使い方までを解説します。
Winstonとは
Winstonは、Node.js向けの多用途ロギングライブラリです。「あらゆる用途に対応できるシンプルで使いやすいロガーを」というコンセプトのもと開発されており、コンソール出力・ファイル保存・外部サービス連携といった複数の出力先(トランスポート)を、1つのロガーインスタンスで同時に扱えるのが最大の特徴です。
主な特徴
- 複数トランスポート対応 - コンソール、ファイル、HTTPなど、異なる出力先を組み合わせて同時に使える
- 柔軟なフォーマット - JSON形式やシンプルなテキスト形式など、用途に応じてログの見た目を自由に組み立てられる
- 細かいログレベル管理 -
errorからsillyまで7段階のレベルがあり、出力先ごとに「このレベル以上だけ記録する」といった制御ができる
インストール
npmまたはyarnでインストールできます。
npm install winston
yarn add winston
基本的な使い方
まずは最もシンプルな形で、ロガーを作成してみましょう。
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.Console({
format: winston.format.simple(),
}),
],
});
logger.info('サーバーを起動しました');
logger.warn('メモリ使用率が80%を超えています');
logger.error('データベース接続に失敗しました');
level: 'info'と指定した場合、error・warn・infoのログのみが出力され、より詳細なdebugやsillyは出力されません。ログレベルには次の7段階があり、数字が小さいほど優先度が高くなります。
{
error: 0, // 最も重要
warn: 1,
info: 2,
http: 3,
verbose: 4,
debug: 5,
silly: 6, // 最も重要度が低い
}
実践的なユースケース
実際のプロジェクトでは、開発時と本番時で出力先を切り替えるケースがよくあります。エラーログはファイルに保存しつつ、開発中はコンソールにも表示する構成を作ってみましょう。
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
defaultMeta: { service: 'user-service' },
transports: [
// エラーログ専用ファイル
new winston.transports.File({ filename: 'error.log', level: 'error' }),
// 全レベルのログをまとめて記録
new winston.transports.File({ filename: 'combined.log' }),
],
});
// 開発環境ではコンソールにも見やすい形式で出力
if (process.env.NODE_ENV !== 'production') {
logger.add(
new winston.transports.Console({
format: winston.format.simple(),
})
);
}
// アプリケーションのどこからでも同じロガーを使い回せる
function handleUserLogin(userId) {
logger.info('ユーザーがログインしました', { userId });
}
handleUserLogin('user-1234');
defaultMetaで指定した情報は全てのログに自動付与されるため、複数のサービスやモジュールが動く環境でも「どこから出たログか」をすぐに判別できます。またformat.combineでタイムスタンプとJSON化を組み合わせることで、そのままログ収集基盤に流し込める構造化ログになります。
まとめ
Winstonを使うことで、console.logだけでは実現できなかった「レベルごとの出し分け」「複数出力先への同時記録」「構造化されたフォーマット」を、少ないコードで実現できます。まずは今回紹介したシンプルな設定から始め、慣れてきたらトランスポートやフォーマットを増やして、自分のプロジェクトに合ったロギング基盤を組み立ててみてください。