四つのシグナルは同じ成熟度にありません
障害が起きたからといって、まずログ検索窓を開く理由はありません。サービス全体でエラーがどこまで広がったかがわからなければメトリクスが先です。特定の要求が複数のサービスをまたいで失敗したのならトレースのほうが速く進みます。例外が出た時点でアプリケーションがどんな状態だったかを見る必要があればログが要り、CPUやメモリを実際に消費した関数を探すならプロファイルが答えに近くなります。
したがって最初に見るシグナルは「自分たちの道具が何をよく見せるか」ではなく「いまの症状がどの形の失敗か」で決めます。この記事は何を利用者の失敗として測るかを定義し直しません。それは利用者導線とSLI設計で先に決めます。ここでは失敗が検知されたあと、四つのどこから調査を始め、どの条件で次へ移るかを扱います。
四つのシグナルがいま同じ成熟度にあるわけではありません。OpenTelemetryではTracesがAPI・SDK・OTLPのすべてでStableです。MetricsはSignalとAPI・データモデル・OTLPがStableである一方、SDK全体と言語別の実装状況は混在しています。LogsもSignal・Bridge API・SDK・OTLPはStableで、言語別のAppenderと実装範囲は異なります。[1]
Profilesは事情が違います。2026年3月にPublic Alphaへ入り、CollectorおよびeBPF Profiling Agentとの連携は進みましたが、Concepts文書はいまもAlphaと表示し、OTLP ProfilesはDevelopment状態です。OpenTelemetryのAlpha警告によれば、Critical Production Workloadの必須依存として前提にしてはなりません。[2] プロファイリング技法そのものが新しいという意味ではなく、規格と生態系の相互運用支援がまだ成熟の途上にあるという意味です。
この差はシグナル選択に影響します。プロファイルが最もよく答える問いがあっても、いまのRuntimeとBackendが必要なProfile TypeとCorrelationを支えていなければ、既存の言語Profilerや別の診断手段を併せて検討します。
各シグナルがよく答える問いは重なりません
OpenTelemetryも四つの守備範囲を同じように分けます。Metricsはシステム水準の状態、Logsは個別の事象、Tracesは分散した要求の経路、Profilesは資源を消費したコードを示します。[1] Metricsは多数の測定値を時間区間ごとの統計に集約します。Tracesは個別の要求の生存期間とContextをつなぎます。
下の表は右側の列こそ重要です。あるシグナルが答えられない問いをそのシグナルで掘り続けると、調査時間が延び、偶然の相関を原因と取り違えやすくなります。
シグナル | よく答える問い | 答えにくい問い |
|---|---|---|
| Metrics | いつから異常か。どれだけの要求・インスタンス・利用者が影響を受けたか。エラー率・遅延分布・Queue Depth・CPU・メモリはどう変わったか | 特定の要求はなぜ失敗したか。どの関数がCPUを消費したか。失敗時点の業務状態は何だったか |
| Logs | どんな事象が発生したか。どの例外・入力分類・状態遷移・再試行結果が記録されたか | 問題は全体の何割か。複数サービスにまたがる因果経路は何か。記録されていない事象が起きなかったと証明できるか |
| Traces | 一つの要求がどのサービス・DB・外部APIを通ったか。どのSpanで失敗または遅延したか。非同期処理と元の要求はどうつながるか | どの関数がCPU・Heapを消費したか。問題は全トラフィックでどれほど頻繁か。計装されていない内部状態で何が起きたか |
| Profiles | どの関数と呼び出しスタックがCPU、Heap、Allocation、Lock・I/O待ちを消費したか | 利用者への影響範囲はどれほどか。要求はどの外部サービスを通ったか。いまの環境が必要なProfile Typeを実際に支えているか |
監視から復旧・改善までつながる運用 — サービス指標とアラートを基準に対応し、変更履歴と事後報告を次の改善につなげます。
障害の種類が最初のシグナルを決めます
下の表のFirst Signalは、すべての環境で固定された正解ではありません。いまわかっている症状だけで調査範囲を最も早く狭める既定の出発点です。
このマトリクスをMetrics → Logs → Traces → Profilesという単一の階段に変えると、問題が戻ってきます。特定の利用者の要求一件が失敗したのなら、全体のMetricsを走査するよりそのTraceが速く進みます。逆に「今朝からサービスがおおむね遅い」という報告だけなら、任意のTrace一件を開くより遅延分布と影響Serviceを先に見るほうが賢明です。
同じUser-visible Errorでも、一件の事象か集団的な変化かで最初のシグナルが分かれます。「決済要求ABCが失敗した」のように具体的な識別子があれば、Traceでどのspanが最初のエラーを出したかを見るほうが速く進みます。失敗Spanを見つけたあと同じtrace_idとspan_idを持つログへ移れば、当時の例外と業務状態が現れます。一方「決済エラーが普段より多い」という症状は集計の問題です。まずMetricsでエラー率がいつから上がったか、特定のRoute・地域・配布バージョン・Instanceに偏ったかを絞り、そのうえで代表的な失敗要求をTraceに選びます。
障害種別 | いま見えている症状 | First Signal | Next Signal | 移行条件と注意点 |
|---|---|---|---|---|
| User-visible Error | 特定の要求・利用者導線が失敗 | Trace | Logs → Metrics | 要求IDがなくエラー率の急増だけが見えるならMetricsで範囲から確定する |
| Latency | サービス全体または一部の要求が遅い | Metrics | Traces → Profiles または Logs | 遅い要求のTrace IDが既にあればTraceから始める。単一Process内の時間が長ければProfileへ移る |
| Resource Saturation | CPU・メモリ・Thread・Connection・Queueが上限に接近 | Metrics | Profiles → Logs または Traces | 資源を消費したコードにはProfile、飽和の結果として失敗した要求はTrace・Logsで確認する |
| Intermittent Failure | 一部の要求だけが不規則に失敗 | Trace または構造化Logs | Logs ↔ Traces → Metrics | 失敗要求がTraceに残っていなければCorrelation IDを持つLogsから始める |
| External Dependency | 外部API・DB・Queue・DNSなど遠隔依存を疑う | Trace | Dependency Metrics → Logs | Traceが遠隔境界を示さないならClient計装とContext伝播を先に点検する |
| Distributed Request Failure | 複数サービスにまたがる一つの要求が途中で失敗 | Trace | 失敗SpanのLogs → Metrics | 最後にエラーを出したサービスと最初の原因サービスを区別する |
| Code Hotspot | 特定のコードが遅い、またはCPU費用が大きいと疑う | Profile | Trace → Metrics | 利用者の経路とつなぐにはTrace、影響の大きさを見るにはMetricsが要る |
| Memory / CPU anomaly | CPU急増、Memory増加、OOM、GC圧迫 | Metrics | Profiles → Logs → Traces | Profile Typeの対応を確認する。OOM・Restart・GCはLogs、影響要求はTracesでつなぐ |
| Background Job | Queue滞留、処理遅延、重複・欠落・失敗した処理 | Metrics | Traces / Span Links → Logs | Job IDがあればLogsやTraceから始めてよい。Producer と Consumer のContextをつながないと元の要求を追えない |
| Unknown symptom | 「サービスがおかしい」以外の手がかりがほぼない | Metrics | Trace または Logs → 必要ならProfiles | Metricsは原因を確定する道具ではなく次の問いを選ぶ地図である |
遅延と資源飽和は範囲・経路・コードの順で狭めます
サービス全体が遅くなったのなら、Metricsが四つを切り分けます。全要求が遅いのか特定のRouteだけか、平均だけが動いたのか上位の遅延帯が厚くなったのか、特定のService・Instance・配布バージョンに偏ったのか、CPU・メモリ・Queue・Connectionといった資源の変化と同じ時点かです。
範囲を狭めたあとは、Traceで遅い要求の時間がどのSpanに留まったかを見ます。外部API呼び出しが長ければDependencyの問題へ移り、DB Spanが長ければQueryとConnectionの状態を見ます。長い時間が単一Process内のSpanに残っていれば、そこでProfileが役に立ちます。On-CPU ProfileはCPUを消費した関数、Off-CPU ProfileはLockやI/Oを待った位置、Heap・Allocation Profileはメモリを占有または反復確保したコード経路を探すのに使います。対応するProfile TypeはRuntimeとProfilerごとに異なります。[2]
Traceは「どの区間が遅かったか」を示しますが、その区間の中のどの関数がCPUを使ったかまで自動では答えません。Profileはその逆です。関数水準の消費は示しますが、そのコードが実際の利用者要求全体でどれほど大きな問題だったかは、MetricsとTraceなしには判断しにくくなります。
資源飽和も同じです。CPU 95%、Connection Pool 100%、Queue Depthの急増は重要な手がかりですが、それ自体が最初の原因を証明しません。遅くなった外部呼び出しを待つ間にWorkerとConnectionが縛られていたのかもしれず、再試行の急増がCPUとQueueを同時に押し上げたのかもしれません。そのためResource Saturationでは、Metricsでまず飽和した資源と時点を見つけ、次のシグナルは問いによって分かれます。誰がCPUとメモリを消費したかはProfiles、どの要求が資源を長く占有したかはTraces、OOM・Restart・GC・Connection Timeoutが実際に起きたかはLogs、影響が全要求のどれほどかはMetricsが答えます。資源チャート一枚でインスタンスを増設するより、飽和が原因か結果かを見分けてこそ同じ障害が繰り返されません。
間欠障害と分散要求は一件の保存で解けます
間欠障害は全体のMetricsで薄まりやすいものです。特定の利用者、特定のTenant、特定の入力の組み合わせ、一部のInstanceだけで失敗するなら、正常な要求と失敗した要求を比べる識別子が要ります。失敗した要求がTraceに残っていれば、経路とSpan Attributeを正常な要求と比べます。Traceがなければ、構造化Logsで要求ID、Job ID、配布バージョン、Instance、結果コードのような安定したFieldから事象を探します。ここでいう構造化ログはJSONで出力したログではなく、Field名・型・意味が一貫したログを指します。[1] 一件の差を見つけたあとで初めて、Metricsに戻って同じ条件の発生率を計算します。原因を見つけたつもりで、実際にはごく少数の要求の偶然の性質だけを見ていないかを確かめるためです。
分散システムでは、最後のエラーを記録したサービスが最初の原因とは限りません。上流のサービスが下流APIの応答を待ってTimeoutを出したのかもしれず、下流の再試行がQueueとConnectionを枯渇させた結果かもしれません。Traceは要求がサービス・DB・外部APIを通った経路と各Spanの時間をつなぎます。OpenTelemetryはW3C Trace Contextのtraceparentを既定の伝播方式として使い、Trace IDとParent Spanの情報をサービス境界の向こうへ渡します。[3] 非同期処理はSpan LinkやProducer・Consumer Spanで元の要求と後続処理を因果的につなぎます。ただし外部サービスへ内部Contextを無条件に渡してはなりません。信頼しない外部境界では入ってくるTrace Headerを検証または除去し、出ていくContextが内部構造を不必要に露出しないかを見ます。Baggageには利用者の資格情報、API Key、個人情報を入れません。
背景処理はHTTP応答が終わったあとに始まることもあれば、ProducerがJobを作ってから長く経ってConsumerが処理することもあります。そのため単一要求のParent-Child関係だけでは足りません。Queue全体が滞る症状なら、まずMetricsでEnqueue・Completion・Failure Rate、Queue Depth、Oldest Job Age、Retry・Dead-letterの増加、Consumer数と処理量、特定のJob Type・Tenant・バージョンへの偏りを見ます。特定のJob一件を追うにはProducer SpanとConsumer Span、Span Link、Job IDが要ります。Logsには状態遷移と再試行理由を残しつつ、Traceとつなぐ Context がなければなりません。OpenTelemetryはProducer Spanを非同期Jobの生成、Consumer Spanをその後の実処理として区別します。[1]
集めることよりシグナル間を移動できることが重要です
四つのシグナルがすべてあっても、互いに異なる名前と識別子を使えば、障害中は事実上四つの孤立したデータ保管庫になります。必要なのは一枚の画面よりCorrelation Contractです。
OpenTelemetryのすべてのシグナルはResourceとつながることができ、同じResource Identityは同一のService・Process・Instanceから出たシグナルを行き来する基準点になります。MetricsとTracesはExemplarで集計値の代表測定とTrace ID・Span IDをつなぎます。LogsはアクティブなTrace ContextをLog Recordへ注入します。[1] ProfilesもRequest ContextとResource Contextの両方との接続を目指しますが、現在はAlphaのため実際のEnd-to-end対応は組み合わせごとに確認します。[2]
Metric Labelに毎要求のTrace IDを入れる方式でCorrelationを実装してはなりません。Metricsは固有のAttribute組み合わせごとに別々の集計状態を保つため、User ID、Raw URL、Trace IDのように値の種類が増え続けるAttributeはCardinalityとメモリ費用を大きく押し上げます。個別のTraceとつなぐときはMetric Dimensionを増やす代わりに、Exemplarのような接続構造を使います。
すべてのシグナルを常に集める必要もありません。可観測性の目的は四種類のデータを漏れなく買い集めて保存することではなく、繰り返し答えるべき運用上の問いを妥当な費用と危険度で解くことです。単一Processで動き外部呼び出しの少ない単純な処理は、基本のMetricsと構造化Logsで足ります。逆に複数のサービスとQueueを通る重要な利用者導線は、Tracesがなければ原因Serviceを見つけるのに時間がかかります。CPU・メモリ費用が中心の処理サービスはProfilesの価値が大きい一方、対応状況と収集Overhead、データ保存、Symbolization、Backend互換性を先に検証します。新しいシグナルの導入可否は六つの問いで決めます。どの障害の問いを現在のデータで答えられないか、その問いはどれほど頻繁で利用者の被害はどれほど大きいか、新しいシグナルが実際に調査範囲を狭めるか、既存のシグナルとつなぐContextを作れるか、収集量・Cardinality・保存費用・個人情報の危険を制御できるか、言語・Runtime・Agent・Collector・Backendが必要な機能を実際に支えるかです。四つ目のシグナルを追加するより、既存の二つの間にtrace_id、Resource、Deployment Versionを一貫して通すことが先である場合が多くあります。
移動経路 | 必要なContext | 何が可能になるか |
|---|---|---|
| Metrics → Traces | Exemplar、共通Resource、時間区間 | 遅延・エラーHistogramの代表測定値から実際の要求Traceへ移動 |
| Traces → Logs | trace_id、span_id、共通Timestamp | 失敗Spanから同じ実行Contextの例外・状態ログへ移動 |
| シグナル間のResource移動 | service.name、service.instance.id、環境・バージョン・Region | 同じService・Instance・Deploymentが出した別のシグナルを照会 |
| Traces → Profiles | Trace・Span Context または同一Resource・時間区間 | 遅いSpanとその時点で実行されたコードスタックを接続 |
| Producer → Background Job | Span Link、Job・Message ID、Producer・Consumer Context | 元の要求と後で実行された非同期処理を接続 |
障害中は次の問いが詰まったときにシグナルを替えます
実務ではすべてのタブを順に開くのではなく、いまのシグナルが次の問いに答えられなくなった時点で移ります。順序は五段階です。
まず症状の形を分類します。一件の要求か、集団的変化か、資源異常か、コード費用か。次にFirst Signalで時間と範囲を削ります。Service、Route、Instance、Job Type、Dependency、Deployment Versionまで絞ります。続いて具体的な識別子を確保します。Trace ID、Span ID、Job ID、Resource Identity、代表Exemplarを探します。そして次の問いに合うシグナルへ移ります。事象の詳細な状態はLogs、要求の経路はTraces、コードの資源消費はProfiles、発生率と影響範囲はMetricsで確認します。最後に緩和行動に必要な証拠を残します。原因の推定だけを書かず、どのシグナルと識別子で確認したか、影響を受けた範囲と配布バージョンは何かを書きます。
障害分析の速さを決めるのはシグナルの数ではありません。メトリクスは範囲を示し、トレースは経路をつなぎ、ログは事象を説明し、プロファイルはコードの資源消費を明らかにします。しかしこの順序は固定された階段ではありません。最初のシグナルはいつも、いま見ている失敗の形から始まります。



