mcpField
L
logging

logging

github.com/codewithmukeshクラウド・DevOps7913.0k 回インストール12 週間前に更新
リポジトリ

logging について

.NET アプリケーションのログと可観測性を扱うスキルです。ヘルスエンドポイントや相関 ID、ログレベルの方針を説明し、Serilog と OpenTelemetry の設定は各専用スキルに委ねます。

主な機能

  1. 01稼働確認と準備状態のヘルスエンドポイント
  2. 02リクエスト処理を通じた相関 ID の伝播
  3. 03環境別のログレベル方針
  4. 04ログへの機密データ記録の回避

活用シーン

  1. 01サービスへのヘルスチェック追加
  2. 02下流呼び出しをまたぐリクエスト追跡
  3. 03環境に応じたログレベルの選択

インストール

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

$npx skills add https://github.com/codewithmukesh/dotnet-claude-kit --skill logging

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

詳細

ログ記録と可観測性

基本原則

  1. Serilog による構造化ログ記録 — すべてのログエントリは、書式化された文字列ではなく、名前付きプロパティを持つ構造化イベントです。これにより、検索、フィルタリング、アラートが可能になります。二段階ブートストラップ、AddSerilog()、シンク、エンリッチャーを含むすべての設定は serilog スキルにあります。このスキルにある UseSerilog() より AddSerilog() を使うというガイダンスが正式な指針です。
  2. 分散トレーシングには OpenTelemetry — トレースはサービス間のリクエストをつなぎ、メトリクスはシステムの健全性を時系列で追跡します。設定の詳細は opentelemetry スキルにあります。
  3. 運用準備状況の確認にはヘルスチェック — すべてのサービスで、ロードバランサーやオーケストレーター向けに /health エンドポイントを公開します。ライブネスとレディネスは別々の問いであり、エンドポイントも分けます。
  4. リクエストトレーシングには相関 ID — すべてのリクエストに一意の ID を割り当て、すべてのログエントリと下流サービスへの呼び出しに引き継ぎます。これにより、ユーザーからの問い合わせを、フィルタリングした 1 つのログストリームに対応付けられます。

パターン

各要素の連携方法
対象担当スキル
構造化アプリケーションログSerilog(AddSerilog())serilog
リクエストのサマリーログUseSerilogRequestLogging()serilog
トレース+メトリクス+OTLP エクスポートOpenTelemetry SDKopentelemetry
ヘルスチェックエンドポイント、相関 ID、ログレベルの方針このスキルlogging

まずログ記録を設定します(残りのデバッグにはログが必要です)。次にヘルスチェック、最後にトレーシングを設定します。

相関 ID
// Middleware to set correlation ID
public class CorrelationIdMiddleware(RequestDelegate next)
{
    private const string CorrelationIdHeader = "X-Correlation-Id";

    public async Task InvokeAsync(HttpContext context)
    {
        var correlationId = context.Request.Headers[CorrelationIdHeader].FirstOrDefault()
            ?? Guid.NewGuid().ToString();

        context.Items["CorrelationId"] = correlationId;
        context.Response.Headers[CorrelationIdHeader] = correlationId;

        using (LogContext.PushProperty("CorrelationId", correlationId))
        {
            await next(context);
        }
    }
}

// Program.cs — register early so every downstream log carries the ID
app.UseMiddleware<CorrelationIdMiddleware>();

ミドルウェアを使う理由:パイプラインの入口で一度プロパティを追加すれば、リクエストスコープ内のすべてのログイベントに付与されるため、呼び出し箇所ごとの設定は不要です。送信する HttpClient 呼び出しには、同じヘッダーを DelegatingHandler 経由で伝搬します(httpclient-factory スキルを参照)。

ヘルスチェック
// Program.cs
builder.Services.AddHealthChecks()
    .AddNpgSql(builder.Configuration.GetConnectionString("Default")!,
        name: "database", tags: ["ready"])
    .AddRedis(builder.Configuration.GetConnectionString("Redis")!,
        name: "redis", tags: ["ready"])
    .AddRabbitMQ(builder.Configuration.GetConnectionString("RabbitMq")!,
        name: "rabbitmq", tags: ["ready"]);

// Map endpoints
app.MapHealthChecks("/health/live", new HealthCheckOptions
{
    Predicate = _ => false // No dependency checks — just "am I running?"
});

app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("ready")
});

エンドポイントを 2 つ用意する理由:ライブネスの失敗は「再起動する」、レディネスの失敗は「トラフィックの送信を止める」という意味です。これらを混同すると、データベースの遅延によってアプリがループ状態で再起動します。

ログレベルの方針
レベル用途環境ごとの既定値
Debug診断の詳細、ペイロードのダンプ(本番環境では PII を含めない)Development のみ
Information注文の確定、ジョブの完了などのビジネスイベントDev と staging
Warning再試行の実行、フォールバックの使用など、回復可能な異常すべての環境 — 本番環境の既定値
Error対応が必要な失敗した操作すべての環境
Fatal/Criticalアプリの継続が不可能すべての環境

本番環境の既定値を Warning にする理由:規模が大きくなると、Information レベルのリクエストノイズはログストレージの費用を押し上げ、重要なシグナルを埋もれさせます。名前空間のオーバーライドを使って、本当に必要なビジネスイベントには Information を維持します(serilog スキルの MinimumLevel.Override パターンを参照)。

アンチパターン

機密データをログに記録しない
// BAD — logging credentials
logger.LogInformation("User logged in: {Email} with password {Password}", email, password);

// GOOD — log identifiers, never secrets or PII at Information level
logger.LogInformation("User {UserId} logged in", userId);
ヘルスチェックのタグを省略しない
// BAD — all checks run for liveness AND readiness
app.MapHealthChecks("/health");

// GOOD — separate liveness (am I running?) from readiness (can I serve traffic?)
app.MapHealthChecks("/health/live", new() { Predicate = _ => false });
app.MapHealthChecks("/health/ready", new() { Predicate = c => c.Tags.Contains("ready") });
担当スキルが提供する機能を再実装しない
// BAD — hand-rolling Serilog bootstrap here from memory
builder.Host.UseSerilog(...);  // legacy API — the serilog skill forbids this

// GOOD — load the serilog skill and use its two-stage AddSerilog() bootstrap
builder.Services.AddSerilog((services, lc) => lc.ReadFrom.Configuration(builder.Configuration)...);

判断ガイド

シナリオ推奨事項
アプリケーションのログ設定serilog を読み込む — AddSerilog() による二段階ブートストラップ
分散トレーシング/メトリクスopentelemetry を読み込む — OTLP エクスポーター
カスタムビジネスメトリクスIMeterFactory+カウンター/ヒストグラム(opentelemetry スキル)
リクエストトレーシング相関 ID ミドルウェア(このスキル)
コンテナーのヘルスチェック/health/live と /health/ready エンドポイント(このスキル)
ログストレージSeq(開発環境)、Elastic/Grafana/OTLP バックエンド(本番環境)
ログレベル開発環境では Debug、staging では Information、本番環境では Warning を既定値にする

コメント