本番環境でNode.jsアプリケーションを運用する際、適切なログ出力は障害調査やパフォーマンス分析に不可欠です。console.logによる簡易的なログ出力では、運用時の要件を満たすことができません。本記事では、console.logの限界を理解した上で、Node.jsの主要ロギングライブラリであるpinowinstonを使用した構造化ログの実装方法を解説します。ログレベルの設定からログローテーション、本番環境でのログ出力戦略まで、実運用に耐えうるロギングシステムの構築方法を習得できます。

前提条件

本記事の内容を実践するにあたり、以下の環境を前提としています。

項目 バージョン・要件
Node.js 20.x LTS以上
npm 10.x以上
OS Windows / macOS / Linux
エディタ VS Code(推奨)

事前に以下の知識を持っていることを前提としています。

  • JavaScriptの基礎知識
  • Node.jsの基本API理解(fspathなど)
  • npmによるパッケージ管理の基本

console.logの限界

Node.jsの標準出力であるconsole.logは、開発時のデバッグには便利ですが、本番運用では多くの課題があります。

console.logの問題点

1
2
3
4
5
// src/console-example.js
// 典型的なconsole.logによるログ出力
console.log('ユーザー登録処理を開始');
console.log('ユーザーID:', userId, 'メールアドレス:', email);
console.log('エラーが発生しました:', error);

上記のようなログ出力には、以下の問題があります。

問題点 説明
ログレベルがない エラー、警告、情報を区別できない
タイムスタンプがない いつ発生したログか分からない
構造化されていない ログ収集ツールでのパース・検索が困難
出力先の制御ができない ファイル出力やローテーションが困難
パフォーマンスへの影響 同期的な出力がアプリケーションをブロック

本番環境で求められるログ要件

運用に適したロギングシステムには、以下の要件が求められます。

flowchart TB
    subgraph 構造化ログの要件
        A[ログレベル制御] --> E[運用ログシステム]
        B[タイムスタンプ] --> E
        C[JSON形式出力] --> E
        D[ファイルローテーション] --> E
    end
    
    E --> F[ログ収集基盤]
    F --> G[Elasticsearch]
    F --> H[CloudWatch]
    F --> I[Datadog]
  1. ログレベル: 環境に応じてログ出力量を制御できる
  2. 構造化フォーマット: JSON形式でログ収集ツールと連携しやすい
  3. タイムスタンプ: 発生時刻を正確に記録する
  4. コンテキスト情報: リクエストIDやユーザーIDを付与できる
  5. 非同期出力: アプリケーションのパフォーマンスに影響を与えない

pinoによる高速構造化ログ

pinoは、Node.js向けの超高速ロガーです。他のロガーと比較して5倍以上高速であり、本番環境での使用に最適です。

pinoのインストール

1
npm install pino pino-pretty

pino-prettyは開発時にログを読みやすく整形するためのパッケージです。

基本的な使い方

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// src/pino-basic.js
import pino from 'pino';

// ロガーインスタンスの作成
const logger = pino({
  level: 'info'
});

// 各ログレベルでの出力
logger.trace('トレースログ - 最も詳細なログ');
logger.debug('デバッグログ - 開発時の詳細情報');
logger.info('情報ログ - 一般的な情報');
logger.warn('警告ログ - 注意が必要な状況');
logger.error('エラーログ - エラー発生時');
logger.fatal('致命的エラー - アプリケーション継続不能');

上記のコードを実行すると、以下のようなJSON形式でログが出力されます。

1
2
3
4
{"level":30,"time":1704603600000,"pid":12345,"hostname":"server-01","msg":"情報ログ - 一般的な情報"}
{"level":40,"time":1704603600001,"pid":12345,"hostname":"server-01","msg":"警告ログ - 注意が必要な状況"}
{"level":50,"time":1704603600002,"pid":12345,"hostname":"server-01","msg":"エラーログ - エラー発生時"}
{"level":60,"time":1704603600003,"pid":12345,"hostname":"server-01","msg":"致命的エラー - アプリケーション継続不能"}

pinoのログレベル

pinoは以下の6つのログレベルをサポートしています。数値が小さいほど詳細なログです。

ログレベル 数値 用途
trace 10 最も詳細なトレース情報
debug 20 デバッグ情報
info 30 一般的な情報
warn 40 警告
error 50 エラー
fatal 60 致命的エラー

設定したレベル以上のログのみが出力されます。例えばlevel: 'warn'と設定すると、warnerrorfatalのみが出力されます。

オブジェクトのログ出力

pinoでは、第1引数にオブジェクトを渡すことで、構造化されたデータをログに含められます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// src/pino-object.js
import pino from 'pino';

const logger = pino({ level: 'info' });

// ユーザー操作のログ
logger.info(
  { userId: 'user-123', action: 'login', ip: '192.168.1.1' },
  'ユーザーがログインしました'
);

// エラーのログ
const error = new Error('データベース接続エラー');
logger.error(
  { err: error, database: 'postgres', retryCount: 3 },
  'データベース接続に失敗しました'
);

出力結果は以下のようになります。

1
2
{"level":30,"time":1704603600000,"pid":12345,"hostname":"server-01","userId":"user-123","action":"login","ip":"192.168.1.1","msg":"ユーザーがログインしました"}
{"level":50,"time":1704603600001,"pid":12345,"hostname":"server-01","err":{"type":"Error","message":"データベース接続エラー","stack":"Error: データベース接続エラー\n    at ..."},"database":"postgres","retryCount":3,"msg":"データベース接続に失敗しました"}

子ロガー(Child Logger)

子ロガーを使用すると、特定のコンテキスト情報を継承したロガーを作成できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// src/pino-child.js
import pino from 'pino';

const logger = pino({ level: 'info' });

// リクエスト処理用の子ロガーを作成
function handleRequest(req) {
  const requestLogger = logger.child({
    requestId: req.id,
    method: req.method,
    path: req.path
  });

  requestLogger.info('リクエスト処理開始');
  
  // 処理中のログも自動的にrequestIdが付与される
  requestLogger.info({ userId: req.userId }, 'ユーザー認証完了');
  
  requestLogger.info('リクエスト処理完了');
}

// 使用例
handleRequest({
  id: 'req-abc123',
  method: 'POST',
  path: '/api/users',
  userId: 'user-456'
});

すべてのログにrequestIdmethodpathが自動的に付与されます。

開発環境でのpino-pretty

本番環境ではJSON形式が適していますが、開発時は読みやすい形式が便利です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// src/pino-dev.js
import pino from 'pino';

const isDevelopment = process.env.NODE_ENV !== 'production';

const logger = pino({
  level: isDevelopment ? 'debug' : 'info',
  transport: isDevelopment
    ? {
        target: 'pino-pretty',
        options: {
          colorize: true,
          translateTime: 'SYS:standard',
          ignore: 'pid,hostname'
        }
      }
    : undefined
});

logger.info({ userId: 'user-123' }, 'ユーザー情報を取得しました');

開発環境では以下のような読みやすい形式で出力されます。

[2026-01-07 12:00:00] INFO: ユーザー情報を取得しました
    userId: "user-123"

pinoでのファイル出力

pinoでファイルにログを出力するには、pino.transportを使用します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// src/pino-file.js
import pino from 'pino';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const logger = pino({
  level: 'info',
  transport: {
    targets: [
      // コンソール出力
      {
        target: 'pino/file',
        options: { destination: 1 }, // 1 = stdout
        level: 'info'
      },
      // ファイル出力
      {
        target: 'pino/file',
        options: {
          destination: path.join(__dirname, '../logs/app.log'),
          mkdir: true
        },
        level: 'info'
      },
      // エラーログは別ファイル
      {
        target: 'pino/file',
        options: {
          destination: path.join(__dirname, '../logs/error.log'),
          mkdir: true
        },
        level: 'error'
      }
    ]
  }
});

logger.info('アプリケーションが起動しました');
logger.error('エラーが発生しました');

pinoでのログローテーション

pinoでログローテーションを実現するには、pino-rollパッケージを使用します。

1
npm install pino-roll
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// src/pino-rotate.js
import pino from 'pino';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const logger = pino({
  level: 'info',
  transport: {
    target: 'pino-roll',
    options: {
      file: path.join(__dirname, '../logs/app'),
      frequency: 'daily',      // 日次ローテーション
      extension: '.log',
      mkdir: true,
      dateFormat: 'yyyy-MM-dd',
      limit: { count: 7 }      // 7日分保持
    }
  }
});

logger.info('ログローテーションが設定されました');

winstonによる柔軟なログ管理

winstonは、Node.jsで最も広く使用されているロギングライブラリです。柔軟な設定と豊富なトランスポート(出力先)のサポートが特徴です。

winstonのインストール

1
npm install winston

基本的な使い方

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// src/winston-basic.js
import winston from 'winston';

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  defaultMeta: { service: 'user-service' },
  transports: [
    new winston.transports.Console()
  ]
});

// 各ログレベルでの出力
logger.error('エラーが発生しました');
logger.warn('警告メッセージ');
logger.info('情報メッセージ');
logger.http('HTTPリクエスト');
logger.verbose('詳細情報');
logger.debug('デバッグ情報');
logger.silly('最も詳細な情報');

winstonのログレベル

winstonはnpmスタイルのログレベルをデフォルトで使用します。数値が小さいほど重要度が高いです。

ログレベル 数値 用途
error 0 エラー
warn 1 警告
info 2 一般的な情報
http 3 HTTPリクエスト
verbose 4 詳細情報
debug 5 デバッグ情報
silly 6 最も詳細な情報

フォーマットのカスタマイズ

winstonの強みは、フォーマットを柔軟にカスタマイズできる点です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// src/winston-format.js
import winston from 'winston';

const { combine, timestamp, json, errors, printf } = winston.format;

// JSON形式のロガー(本番環境向け)
const productionLogger = winston.createLogger({
  level: 'info',
  format: combine(
    timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
    errors({ stack: true }),
    json()
  ),
  defaultMeta: { service: 'api-server' },
  transports: [
    new winston.transports.Console()
  ]
});

// カスタム形式のロガー(開発環境向け)
const customFormat = printf(({ level, message, timestamp, ...metadata }) => {
  let msg = `${timestamp} [${level.toUpperCase()}]: ${message}`;
  if (Object.keys(metadata).length > 0) {
    msg += ` ${JSON.stringify(metadata)}`;
  }
  return msg;
});

const developmentLogger = winston.createLogger({
  level: 'debug',
  format: combine(
    timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
    customFormat
  ),
  transports: [
    new winston.transports.Console()
  ]
});

productionLogger.info('本番環境ログ', { userId: 'user-123' });
developmentLogger.info('開発環境ログ', { userId: 'user-123' });

本番環境での出力は以下のようになります。

1
{"level":"info","message":"本番環境ログ","service":"api-server","timestamp":"2026-01-07 12:00:00.000","userId":"user-123"}

開発環境での出力は以下のようになります。

2026-01-07 12:00:00 [INFO]: 開発環境ログ {"service":"api-server","userId":"user-123"}

複数のトランスポート

winstonでは、複数の出力先(トランスポート)を設定できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// src/winston-transports.js
import winston from 'winston';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const { combine, timestamp, json, errors, colorize, simple } = winston.format;

const logger = winston.createLogger({
  level: 'info',
  format: combine(
    timestamp(),
    errors({ stack: true }),
    json()
  ),
  defaultMeta: { service: 'api-server' },
  transports: [
    // エラーログはerror.logに出力
    new winston.transports.File({
      filename: path.join(__dirname, '../logs/error.log'),
      level: 'error'
    }),
    // すべてのログはcombined.logに出力
    new winston.transports.File({
      filename: path.join(__dirname, '../logs/combined.log')
    })
  ]
});

// 本番環境以外ではコンソールにも出力
if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: combine(
      colorize(),
      simple()
    )
  }));
}

logger.info('アプリケーションが起動しました');
logger.error('エラーが発生しました', { code: 'DB_ERROR' });

winstonでのログローテーション

winstonでログローテーションを実現するには、winston-daily-rotate-fileパッケージを使用します。

1
npm install winston-daily-rotate-file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// src/winston-rotate.js
import winston from 'winston';
import DailyRotateFile from 'winston-daily-rotate-file';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const { combine, timestamp, json, errors } = winston.format;

// 日次ローテーションのトランスポート設定
const fileRotateTransport = new DailyRotateFile({
  filename: path.join(__dirname, '../logs/app-%DATE%.log'),
  datePattern: 'YYYY-MM-DD',
  zippedArchive: true,    // 古いログをgzip圧縮
  maxSize: '20m',         // ファイルサイズ上限
  maxFiles: '14d',        // 14日分保持
  level: 'info'
});

// エラーログ専用のローテーション設定
const errorRotateTransport = new DailyRotateFile({
  filename: path.join(__dirname, '../logs/error-%DATE%.log'),
  datePattern: 'YYYY-MM-DD',
  zippedArchive: true,
  maxSize: '20m',
  maxFiles: '30d',        // エラーログは30日保持
  level: 'error'
});

// ローテーションイベントのハンドリング
fileRotateTransport.on('rotate', (oldFilename, newFilename) => {
  console.log(`ログファイルがローテーションされました: ${oldFilename} -> ${newFilename}`);
});

fileRotateTransport.on('error', (error) => {
  console.error('ログファイルエラー:', error);
});

const logger = winston.createLogger({
  level: 'info',
  format: combine(
    timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
    errors({ stack: true }),
    json()
  ),
  defaultMeta: { service: 'api-server' },
  transports: [
    fileRotateTransport,
    errorRotateTransport,
    new winston.transports.Console()
  ]
});

logger.info('ログローテーションが設定されました');

子ロガーの作成

winstonでも子ロガーを作成して、コンテキスト情報を継承できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// src/winston-child.js
import winston from 'winston';

const { combine, timestamp, json } = winston.format;

const logger = winston.createLogger({
  level: 'info',
  format: combine(timestamp(), json()),
  transports: [new winston.transports.Console()]
});

// リクエスト処理用の子ロガーを作成
function handleRequest(req) {
  const requestLogger = logger.child({
    requestId: req.id,
    method: req.method,
    path: req.path
  });

  requestLogger.info('リクエスト処理開始');
  requestLogger.info('ユーザー認証完了', { userId: req.userId });
  requestLogger.info('リクエスト処理完了');
}

handleRequest({
  id: 'req-abc123',
  method: 'POST',
  path: '/api/users',
  userId: 'user-456'
});

pinoとwinstonの比較

両ライブラリにはそれぞれ特徴があり、ユースケースによって選択が異なります。

観点 pino winston
パフォーマンス 非常に高速(他ロガーの5倍以上) 標準的な速度
設定の柔軟性 シンプル 非常に柔軟
トランスポート 基本的な出力先 豊富なプラグイン
学習コスト 低い やや高い
エコシステム 成長中 成熟している
ファイルサイズ 軽量 やや大きい
GitHub Stars 17.1k 24.3k
週間ダウンロード 約970万 約1,100万

選択の指針

flowchart TD
    A[ロガー選択] --> B{パフォーマンス最優先?}
    B -->|Yes| C[pino]
    B -->|No| D{複雑な出力設定が必要?}
    D -->|Yes| E[winston]
    D -->|No| F{既存プロジェクトとの互換性?}
    F -->|winston使用中| G[winston]
    F -->|新規プロジェクト| H[pino推奨]
  • pinoを選ぶべきケース: 高スループットが求められるAPI、マイクロサービス、シンプルな設定で済む場合
  • winstonを選ぶべきケース: 複雑なログ出力要件、多様なトランスポートが必要、既存エコシステムとの統合

本番環境でのログ出力戦略

本番環境でのログ運用には、いくつかの重要なポイントがあります。

環境別のログ設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// src/logger/index.js
import pino from 'pino';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

function createLogger() {
  const isDevelopment = process.env.NODE_ENV !== 'production';
  const logLevel = process.env.LOG_LEVEL || (isDevelopment ? 'debug' : 'info');

  const baseOptions = {
    level: logLevel,
    base: {
      service: process.env.SERVICE_NAME || 'app',
      version: process.env.APP_VERSION || '1.0.0',
      env: process.env.NODE_ENV || 'development'
    }
  };

  if (isDevelopment) {
    // 開発環境: 読みやすい形式でコンソール出力
    return pino({
      ...baseOptions,
      transport: {
        target: 'pino-pretty',
        options: {
          colorize: true,
          translateTime: 'SYS:standard',
          ignore: 'pid,hostname'
        }
      }
    });
  }

  // 本番環境: JSON形式でファイル出力
  return pino({
    ...baseOptions,
    transport: {
      targets: [
        {
          target: 'pino/file',
          options: { destination: 1 }, // stdout
          level: logLevel
        },
        {
          target: 'pino-roll',
          options: {
            file: path.join(__dirname, '../../logs/app'),
            frequency: 'daily',
            extension: '.log',
            mkdir: true,
            dateFormat: 'yyyy-MM-dd',
            limit: { count: 14 }
          },
          level: logLevel
        }
      ]
    }
  });
}

export const logger = createLogger();

リクエストログミドルウェア

HTTPリクエストのログを記録するミドルウェアを実装します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// src/middleware/request-logger.js
import { randomUUID } from 'node:crypto';
import { logger } from '../logger/index.js';

export function requestLogger(req, res, next) {
  const requestId = req.headers['x-request-id'] || randomUUID();
  const startTime = Date.now();

  // リクエストごとの子ロガーを作成
  req.logger = logger.child({
    requestId,
    method: req.method,
    path: req.url,
    userAgent: req.headers['user-agent']
  });

  req.logger.info('リクエスト受信');

  // レスポンス完了時のログ
  res.on('finish', () => {
    const duration = Date.now() - startTime;
    req.logger.info({
      statusCode: res.statusCode,
      duration: `${duration}ms`
    }, 'リクエスト完了');
  });

  // エラー発生時のログ
  res.on('error', (error) => {
    req.logger.error({ err: error }, 'レスポンスエラー');
  });

  next();
}

エラーログの設計

エラーログには、障害調査に必要な情報を含めます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// src/utils/error-logger.js
import { logger } from '../logger/index.js';

export function logError(error, context = {}) {
  const errorInfo = {
    err: {
      name: error.name,
      message: error.message,
      stack: error.stack,
      code: error.code
    },
    ...context
  };

  // エラーの種類に応じてログレベルを変更
  if (error.name === 'ValidationError') {
    logger.warn(errorInfo, 'バリデーションエラー');
  } else if (error.code === 'ECONNREFUSED') {
    logger.error(errorInfo, '外部サービス接続エラー');
  } else {
    logger.error(errorInfo, '予期しないエラー');
  }
}

// 使用例
try {
  await someOperation();
} catch (error) {
  logError(error, {
    operation: 'someOperation',
    userId: currentUser.id
  });
  throw error;
}

機密情報のマスキング

ログに機密情報を出力しないよう、リダクション(マスキング)を設定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// src/logger/secure-logger.js
import pino from 'pino';

const logger = pino({
  level: 'info',
  redact: {
    paths: [
      'password',
      'creditCard',
      'token',
      'authorization',
      '*.password',
      '*.creditCard',
      'user.email',
      'headers.authorization'
    ],
    censor: '[REDACTED]'
  }
});

// 機密情報がマスキングされる
logger.info({
  user: {
    id: 'user-123',
    email: 'test@example.com',  // [REDACTED]に置換
    password: 'secret123'       // [REDACTED]に置換
  },
  token: 'jwt-token-xxx'        // [REDACTED]に置換
}, 'ユーザー情報');

ログ収集基盤との連携

本番環境では、ログを中央集約型のログ収集基盤に送信することが一般的です。

flowchart LR
    A[Node.jsアプリ] -->|stdout| B[コンテナランタイム]
    B -->|JSON| C[Fluentd/Fluent Bit]
    C --> D[Elasticsearch]
    C --> E[CloudWatch Logs]
    C --> F[Datadog]
    
    D --> G[Kibana]
    E --> H[CloudWatch Insights]
    F --> I[Datadog Dashboard]

コンテナ環境では、標準出力(stdout)にJSON形式でログを出力し、ログドライバーやサイドカーコンテナで収集する方式が推奨されます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// src/logger/production.js
import pino from 'pino';

// コンテナ環境向けの設定
const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
  // 標準出力にJSON形式で出力
  // コンテナのログドライバーが収集
  base: {
    service: process.env.SERVICE_NAME,
    version: process.env.APP_VERSION,
    env: process.env.NODE_ENV
  },
  // タイムスタンプをISO形式で出力
  timestamp: pino.stdTimeFunctions.isoTime
});

export { logger };

まとめ

本記事では、Node.jsにおける構造化ログの実装方法を解説しました。

学んだこと

  1. console.logの限界: 本番環境では、ログレベル、タイムスタンプ、構造化フォーマットが必要
  2. pinoの特徴: 高速なJSON形式ログ出力、子ロガー、pino-prettyによる開発時の可読性向上
  3. winstonの特徴: 柔軟な設定、複数トランスポート、豊富なエコシステム
  4. ログローテーション: pino-rollやwinston-daily-rotate-fileによる日次ローテーション
  5. 本番環境戦略: 環境別設定、リクエストログ、機密情報のマスキング

次のステップ

  • ログ収集基盤(Elasticsearch + Kibana、CloudWatch Logs)との連携
  • 分散トレーシングの導入(OpenTelemetry)
  • アラート設定とログベースの監視

適切なロギングシステムを構築することで、障害調査の効率化とシステムの可観測性向上を実現できます。

参考リンク