mcpField
S
structured-logging-standardizer

structured-logging-standardizer

github.com/patricio0312rev開発63258 回インストール41 週間前に更新
リポジトリ

structured-logging-standardizer について

一貫性があり、検索や関連付けが可能なログを実装する開発スキルです。ログスキーマ、リクエスト ID ミドルウェア、標準ロガーの例を示します。

主な機能

  1. 01構造化ログスキーマの定義
  2. 02リクエスト ID の生成または再利用
  3. 03レスポンスヘッダーへのリクエスト ID 設定
  4. 04標準ロガーの提供
  5. 05一貫したフィールド名でコンテキストを記録

活用シーン

  1. 01サービス間のログ形式の統一
  2. 02リクエストとログエントリーの関連付け
  3. 03構造化フィールドによるログ検索
  4. 04サービス名や環境情報のログへの付加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/patricio0312rev/skills --skill structured-logging-standardizer

インストール後、Claude Code で/structured-logging-standardizerを入力して読み込まれたか確認します。

詳細

構造化ログ標準化ツール

一貫性があり、クエリ可能で、相関関係を追跡できるログを実装します。

ログスキーマ

interface LogEntry {
  timestamp: string; // ISO 8601
  level: "debug" | "info" | "warn" | "error" | "fatal";
  message: string;
  service: string;
  environment: string;

  // Request context
  requestId?: string;
  traceId?: string;
  userId?: string;

  // Additional context
  [key: string]: any;
}

リクエスト ID ミドルウェア

import { v4 as uuidv4 } from "uuid";

app.use((req, res, next) => {
  // Generate or use existing request ID
  req.id = req.headers["x-request-id"] || uuidv4();

  // Add to response headers
  res.setHeader("x-request-id", req.id);

  // Store in async local storage
  asyncLocalStorage.run(new Map(), () => {
    asyncLocalStorage.getStore()?.set("requestId", req.id);
    next();
  });
});

// Logger with request context
const logger = pino({
  mixin() {
    return {
      requestId: asyncLocalStorage.getStore()?.get("requestId"),
    };
  },
});

標準化されたロガー

class StandardLogger {
  private logger = pino();

  info(message: string, context?: Record<string, any>) {
    this.logger.info(
      {
        ...this.getContext(),
        ...context,
      },
      message
    );
  }

  error(message: string, error?: Error, context?: Record<string, any>) {
    this.logger.error(
      {
        ...this.getContext(),
        ...context,
        error: {
          message: error?.message,
          stack: error?.stack,
          name: error?.name,
        },
      },
      message
    );
  }

  private getContext() {
    return {
      requestId: asyncLocalStorage.getStore()?.get("requestId"),
      userId: asyncLocalStorage.getStore()?.get("userId"),
    };
  }
}

ベストプラクティス

// ✅ DO: Structured fields
logger.info({ userId: '123', action: 'purchase', amount: 99.99 }, 'Purchase completed');

// ❌ DON'T: String interpolation
logger.info(\`User 123 purchased for $99.99\`);

// ✅ DO: Consistent field names
logger.info({ duration_ms: 150 }, 'Request completed');

// ❌ DON'T: Inconsistent naming
logger.info({ durationMs: 150 }, 'Request done');

出力チェックリスト

  • リクエスト ID ミドルウェア
  • 構造化ログスキーマ
  • 相関 ID
  • 標準化されたロガー
  • 文書化されたベストプラクティス ENDFILE

コメント