ロギング&可観測性
すべての3つのサービス(Web、MCP、CtraderCliNode)はSerilogでstdoutにコンパクトJSONとしてログ — コンテナランタイムとログコレクタ(Loki、ELK、CloudWatch、Azure Log Analytics、Datadog)が構造化イベントを直接取り込み、フリーテキスト解析不要。
パイプライン
- Sink 1 — コンソール(コンパクトJSON)。
RenderedCompactJsonFormatter;各eventは完全なOpenTelemetryリソースIDを持ち運ります —service.name(cmind-web/cmind-mcp/cmind-node-agent/cmind-copy-agent)、service.version、service.namespace(cmind)、deployment.environment— plustrace_id/span_idは周囲のActivity(ActivityEnricher)とLogContextスコープから。 Trace idsによりCloudWatch Logs InsightsとAzure Log Analyticsがlog↔traceをピボットできます コレクタがデプロイされていなくても可能です。 - Sink 2 — OTLP(オプション)。
OTEL_EXPORTER_OTLP_ENDPOINT設定時、ログは同等のリソース属性でOTLP上也export alongside OpenTelemetry metricsとtraces(ASP.NET Core、HttpClient、ランタイム計装)AddAppTelemetryから。 - Sink 3 — Azure Monitor(オプション)。
APPLICATIONINSIGHTS_CONNECTION_STRING設定時、トレースとメトリクスはApplication Insightsにネイティブにexport(AddAzureMonitorTraceExporter/AddAzureMonitorMetricExporter) — コレクタなし。以下参照cloud-nativeセクション。 - ソース生成メッセージ。 アプリログは安定した
EventIdを持つ強く型付けされたLogMessages拡張機能を使用(Core/Logging/LogMessages.cs) — 而非 ad-hocILogger.LogInformation。 - リクエストロギング。
UseSerilogRequestLogging()はHTTPリクエストごとに1つの構造化サマリーをemits(メソッド、パス、ステータス、経過ms)。
設定
レベルはappsettings.jsonのSerilogセクションでサービスごとに調整可能(ReadFrom.Configuration経由で読み取り)、例:
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": { "Microsoft.AspNetCore": "Warning", "Microsoft.EntityFrameworkCore": "Warning" }
}
}
}
起動時に環境変数でオーバーライド、例:Serilog__MinimumLevel__Default=Debug。
コレクタへのShipping
1つenv varをサービスごとに設定、OTLPエンドポイントを指す:
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
- Helm:
--set observability.otlpEndpoint=http://otel-collector:4317。 - Compose / cloud: 各サービスにenv varを追加。
コレクタから、トレース↔ログ相関を维持しながらバックエンドにファンアウト(Tempo/Jaegerトレース、Prometheusメトリクス、Lokiログ)。
Cloud-nativeバックエンド(追加のコレクタ不要)
両方の管理されたデプロイメントは箱から出してすぐにネイティブ可観測性スタックに接続されます — OTLPコレクタ不要。
Azure — Application Insights + Log Analytics
deploy/azure/main.bicepはワークスペースベースのApplication Insightsコンポーネントをプロビジョニングし、その接続文字列をWebとMCPにAPPLICATIONINSIGHTS_CONNECTION_STRINGとして渡します。結果:
- トレース + メトリクスがApp Insightsにネイティブにフロー(Application Map、ライブメトリクス、エンドツーエンドトランザクション検索)、
trace_idで相関。 - ログ(stdoutのコンパクトJSON)はContainer Apps
appLogsConfiguration経由で同じLog Analyticsワークスペースに着地 ThereforeAppTraces/ContainerAppConsoleLogs_CLがtrace idで結合。 - オプションのotlpEndpoint Bicep paramを追加でコレクタにもファンアウトするように設定。
Log Analyticsでクエリログ(Log_sのJSONライン):
ContainerAppConsoleLogs_CL
| extend log = parse_json(Log_s)
| where log.["service.name"] == "cmind-web"
| project TimeGenerated, level = log["@l"], msg = log["@m"], trace_id = log.trace_id
AWS — X-Ray + CloudWatch(ADOT sidecar)
deploy/aws/main.tfは各FargateタスクでAWS Distro for OpenTelemetry(ADOT)コレクタをsidecarとして実行。AppはOTLPをhttp://localhost:4317にexport; sidecarは以下をshipします:
- トレース → AWS X-Ray(
awsxrayexporter)、 - メトリクス → CloudWatch(
awsemf、namespacecmind、ロググループ/ecs/<prefix>/metrics)。 - ログは
awslogsdriverとしてコンパクトJSONでstay; CloudWatch Logs InsightsはJSONフィールドを自動発見因此filter/statsontrace_id、service.name、@lなどを使用。
タスクロール(aws_iam_role.task)はAWSXRayDaemonWriteAccess + CloudWatchAgentServerPolicyを運ぶ。
CloudWatch Logs Insightsでログをクエリ:
fields @timestamp, @l, @m, trace_id, `service.name`
| filter `service.name` = "cmind-web"
| sort @timestamp desc
ヘルスエンドポイント(プローブでも使用)
| エンドポイント | サービス | 意味 |
|---|---|---|
/alive | Web | ライブネス — プロセスのみ。 |
/health | Web | 準備完了 — データベースチェックを含む。 |
/version | Web、MCP | 商品 + プロトコルバージョン(MCPライブネス/準備完了)。 |
すべて的环境(previously Devのみ)でマッピング Therefore Kubernetesとcloudプローブが本番で動作します。