7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「OpenTelemetry...?」

7
Last updated at Posted at 2026-06-08

OpenTelemetry ... ?

ドキュメントのタイトル欄に打ち込んだその文字列を、浅井はじっと見つめていた。仮タイトルとして打ち込んだはずなのに、もう一時間書き直せていない。

──いや、ちゃんとしたタイトルつけろよ。

研修レポートの提出期限は明後日。テーマは「OpenTelemetry について、OJT を通して理解したことを自分の言葉でまとめる」。三日前に上司から渡された課題だ。公式デモを動かして、ダッシュボードを眺めて、社内ドキュメントを読んで、ハンズオンをこなして、そして今、画面の前で固まっている。

OJT で動かしたデモはすごかった。

e-commerce のサンプルアプリ。注文を一回投げると、Jaeger に span が時系列でずらりと流れていく。Grafana のサービスマップが点滅して、リクエスト数、エラーレート、p99 レイテンシーが綺麗にグラフ化される。「なんか、すごいな」と思った。誰が見ても多分「すごい」と思う。

けどレポートに「なんか、すごかったです」とは書けない。

浅井はキーボードに指を置いた。置いただけで動かない。書き出しを何度か試みて、何度か Cmd+A、Delete を繰り返した結果、画面に残っているのは仮タイトルだけだった。

──何を書けばいいんだ、これ

動かしたツールの説明はメモに書いてある。トレースとは、メトリクスとは、ログとは。SDK と Collector の違い。そういったことは書いてある。書いてある、けど、それをまとめるのはたぶんダメだ。「自分の言葉で」とわざわざ書かれているその言葉がいま、ない。

──OpenTelemetry って、一体誰が嬉しいんだろう。

ふと、そんな問いが浮かんだ。

浮かんでしまうと、それしか考えられなくなった。

デモで span が流れていくのを見た時、自分は別に嬉しくはなかった。「ふーん、こうやって繋がってるんだ」とは思った。でもそれは嬉しいわけじゃない。

前職は、世界がもっと閉じてた。自分が書いて、自分でデプロイして、おかしくなったら自分のログを読む。ローカルで開発するとき print デバッグで届かないところは、デバッガーをアタッチすれば足りた。デプロイしたログで足りない時はログを追加してデプロイした。サービスというのは、そういう距離感で回ってた。

span が流れて、ダッシュボードが点滅して、それで誰がどんな顔で嬉しいのか、その絵が描けない。

「うーん...」

思わず声が漏れた。

「...先輩、何唸ってるんですか」

顔を上げると、怜がコーヒーのカップを二つ持ってすぐ近くに立っていた。片方をこちらに差し出してくる。

「あ、ありがとう」

受け取ったカップは思ったより温かかった。

「悩んでる顔してましたよ。遠くからでも」

隣の椅子を引いて、当たり前みたいに座る。当たり前じゃない、と浅井は思った。たぶんこれは、わざわざ来てくれたんだ。

前職を辞めて転職活動でくすぶっていた頃、ここに引っ張ってくれたのも怜だった。同じ大学の後輩にメンターをしてもらっている、というのが今の自分の正確な立場で、それを情けないと思う余裕も、まだない。

怜は浅井のディスプレイをちらりと見て、しばらく無言だった。それから控えめに言った。

「...タイトル、それでいくんですか」

「い、行かない、行かない。仮、仮だから」

「一時間くらい仮ですよね、それ」

「...なんで知ってんの」

「さっき廊下を通った時から、同じ画面でした」

浅井は黙った。

怜はそれ以上突っ込まずに、自分のコーヒーを一口飲んで、ノートパソコンの隣に置く。

浅井は少し迷ってから、思い切って聞いてみた。

「...あの、変なこと聞いていい?」

「どうぞ」

「OpenTelemetry って、結局、誰が嬉しいんだろう...?」

我ながら間の抜けた質問だと思った。一週間 OJT を受けてきた人間が、研修担当のメンターに向かって投げる問いじゃない。提出期限は明後日だ。

──しまった、馬鹿だと思われたかも。

恐る恐る怜の顔を窺った。

でも怜は、目をぱちりと瞬かせただけだった。

それから、ふっと柔らかく笑った。

「私が、嬉しいです」

「...え」

「あと、夜中に叩き起こされる、世界中の運用の人たち」

浅井は反射でカップを口に運ぼうとして、その手を止めた。

怜は別に冗談を言っているわけではないらしかった。

「...どういうこと?」

怜は自分のコーヒーをしばらく見つめてから、ゆっくり口を開いた。

「ちょっと、私の話していいですか」

「うん」

「去年、ある顧客先で深夜にアラートが鳴ったんですよ」

浅井は姿勢を直した。

「決済サービスの p99 が、じわじわ伸びていて。エラーじゃないんです。エラーは出てない。レスポンスは返ってる。ただ遅い。クライアントから『最近重い』って問い合わせが来始めて、それでようやく気付いた」

「...あー」

「先輩、その顔、わかりますね?」

「わかる。一番嫌なやつだ」

「そうです。一番嫌なやつです」

怜は少しだけ姿勢を緩めて、コーヒーを一口飲んだ。

「ログ、見たんですよ。決済サービスのログ。何も出てない。普通にリクエストが処理されてる。INFO のログが綺麗に並んでるだけ」

「うん」

「メトリクスも見ました。CPU、メモリ、コネクション数、全部正常。なんなら、決済サービス自体のレスポンスタイムも、内部的には速いんです」

「えっ、じゃあ何が遅いの?」

「そう。それが、ログとメトリクスだけ見ててもわからないんです」

浅井は思わず身を乗り出していた。

「決済サービスは、内側では速い。でもユーザーから見ると遅い。ってことは、間に何かがある」

「...あー」

「で、その時、私、トレースを開いたんです」

怜の声がほんの少しだけ低くなった。語り口が引き締まる。

「リクエスト一本のトレースを引っ張ってきて、span の連なりを上から眺めていったら、決済サービスの手前にいる認証用のサイドカーで、ものすごく時間を食ってた。証明書のリフレッシュ処理で待ちが入っていて、たまにブロックされてたんです」

「うわ」

「決済サービスの中だけ見てたら絶対わからない。認証サイドカーのログは別の場所に出てる。メトリクスも別。でもトレースを見たら、ぜんぶ繋がってた」

浅井は何も言えなかった。

言えないまま、span が時系列でずらりと流れていく、デモで見た Jaeger の画面を思い出していた。あの時、自分は「ふーん、こうやって繋がってるんだ」としか思わなかった。

怜はふっと笑って言った。

「あの時、私、本気でトレースに『ありがとう』って思いました。変な話ですけど」

「...いや、全然変じゃないと思う」

運用の人ってこうやってトラブルシューティングするんだ、と思った。

自分の中になかった景色だった。

怜はその「変じゃない」を、ちゃんと受け取ったみたいだった。

でもそれ以上は触らずに、コーヒーをまた一口飲んだ。

浅井の中で、聞きたいことがひとつ形を持ち始めていた。

「...あのさ」

「はい」

「なんで、トレースだと、それが見えたんだろう」

言ってから、ちょっと首を傾げた。

「ログには出てなかった、メトリクスにも出てなかった、でもトレースには出てた。何が違ったんだろう」

言いながら、気付いた。

「...いやごめん、当たり前か。トレースってそういうものだもんね」

ちょっと恥ずかしくなって、コーヒーに視線を落とした。

怜はちょっとだけこちらを見ていた。

「いえ、いい質問だと思いますよ、先輩」

「えっ」

「私からも質問してみてもいいですか?」

「え、いいけど」

「なんで当たり前なんですかね?」

「え、いや...」

浅井は止まった。

「えっと、トレースって、要するに、サービスをまたぐためのものだから...」

「うん」

「ログとかメトリクスは、それぞれのサービスの中で完結してる。でもトレースは、サービスを横断してる。一本のリクエストが、どこを通ったか、繋がって見える」

言ってから、自分の中で何かが繋がる感覚があった。

「あ。繋がってるから、わかった?」

怜がちょっとだけ目を細めた。

「そうです。それがトレースの本体ですね。繋がってる

「で、その『繋がってる』が、具体的にどういう仕組みで成り立ってるか。ハンズオン、触りましたよね」

「触った。リクエスト一本ごとにユニークな ID が振られて、それが下流のサービスに伝わっていく、ってやつ」

「そうです。それです。同じ ID が貼ってあるから、繋がる

怜が立ち上がった。

「ちょっと、そこのボード借りていいですか」

「あ、うん」

浅井もコーヒーを持って後を追った。フロアの隅、申し訳程度に置かれている小さなホワイトボードの前で、怜がマーカーを取った。

それから三つの四角を並べて、矢印で繋いだ。

CleanShot 2026-06-08 at 15.13.33@2x.png

「ここをリクエストが通っていく時に、A の中で出る span も、B の中のログも、C で出るメトリクスも、ぜんぶ同じトレースのIDを抱えるように相関させることができるんです」

「うん」

「だから後からこのトレースのIDで引けば、『この一本のリクエストの間に何が起きてたか』を、サービスを横断してひとまとめに眺められる」

「...あー」

浅井は何度か頷いた。自分の中でようやく少し、絵が描けた気がした。

怜はしばらくボードを眺めてから、マーカーを持ち直した。

3つのテレメトリ

「『全部同じ ID が貼ってあるから後から拾える』、あれがなんでそんなに大事なのか。テレメトリの歴史を、ちょっとだけ振り返ってみましょう」

「あ、聞きたい」

怜はボードの余白に、三本の柱を並べて書いた。

CleanShot 2026-06-08 at 12.28.23@2x.png

「観測のためのデータ、テレメトリって言うんですけど、その代表がこの三つ」

「うん」

「で、これ、もともとぜんぶ別々に発展してきたんです。別の時代、別の人たちが、別の問題を解こうとして」

「別々に?」

「ログはいちばん古い。syslog って機構が 80 年代から Unix と一緒にあって、長いこと grep と tail で読む世界でした」

「聞いたことある」

「対してメトリクスはネットワーク機器の監視から始まってます。90 年代に MRTG とか RRDtool っていう、回線の帯域を可視化するツールが大元。そこから Nagios、Graphite、Prometheus と世代が積み重なってる」

「Prometheus は知ってる」

「トレースはさらに若い。Google が 2010 年に出した Dapper っていう論文がスタート地点。そこから Twitter の Zipkin、Uber の Jaeger と続いて、今のかたちになってます」

「...十五年ちょっと?」

「そうです、ぜんぜん新しい」

「えっ、トレースってそんな最近なんだ」

「最近です。だからログとトレースって、もう生まれた時代も現場も全然違う。データの形も、保存の仕方も、見るためのツールも、ぜんぶ別系統で発展した」

「あー...」

「で、ここが問題で。本番で障害が起きると、運用の人は、ログ用のツール、メトリクス用のツール、トレース用のツール、ぜんぶ別のものを開いて、別の画面で突き合わせる」

「えっ、別の画面?」

「別の画面です」

「どうやって突き合わせるの?」

「時刻とあとはそれぞれのメトリクスの属性を見て、それを頼りに」

浅井は想像しただけでげんなりした。

「『午前三時二十五分から三十分の間に何かあったらしい』って当たりをつけて、ログを開いて、エラーが出てる行から request_id を一個拾うじゃないですか。それをメトリクスのダッシュボードのフィルタに貼って、同じリクエストの周辺で何が起きてたか見て。今度はその時刻の host 名で別のログに絞り直して、ってやっていく」

「...夜中三時に」

「夜中三時に、やってたんですよ。頭フル回転させて、手で繋ぎ込んでるんです。ただ、これって全部、人間が頭の中で『同じ出来事』を組み立て直してるだけなんです。データそのものは、繋がってない」

しんどいな、と思った。

怜が伝わったみたいに、うんうんと頷いた。

そしてコーヒーを一口飲んだ。

「仮に、これらのテレメトリを特定の SaaS にまとめて管理したとしても、データが別々の論理で生まれてる限り、それをただまとめるだけだと、データ同士を繋ぎ込むのは結局人間なんですよ。ログにはログの世界の属性、メトリクスにはメトリクスの世界の属性、トレースにはトレースの世界の属性があって、それぞれの世界で完結したものがただ画面に並んでるだけ。画面が一つになっただけで、繋ぎ込む人間の脳の負担は変わらない」

「...なるほど」

「OpenTelemetry って、まさにこういう問題意識から発展してきたんですよ」

コンテキスト

怜は、さっき書いた三本の柱の下に、もう一段、長い箱を書き足した。

CleanShot 2026-06-08 at 12.29.23@2x.png

「三本の柱の下に、コンテキスト っていう共通の土台を敷く」

「コンテキスト...」

「リクエストがサービス A から B、C と流れていく時に、コンテキストっていう情報が一緒に運ばれていく。で、その流れの中で出るログも、span も、メトリクスも、ぜんぶこの共通のコンテキストの上で生まれる

「...」

「つまり、生まれた瞬間から、自分がどのリクエストの話なのか、自分がどのサービスの話なのかを知ってる。後から人間が突き合わせるんじゃなくて、最初から繋がる仕組みがデータに埋め込まれてる」

浅井はボードの図をじっと見た。

トレース、メトリクス、ログ、それぞれ歴史も思想も違うものが、コンテキストという同じ土台の上に立っている。

全部に同じトレースのID が貼ってあるから、後から拾い集めて並べられる、っていう先輩の理解。あれは、コンテキストという土台の上で起きてる現象の、いちばん分かりやすい姿なんですよ。要はトレースって、テレメトリを繋ぎ合わせるっていう考え方をもとにしてるんです。そして、こうやって、別々の場所で生まれたデータを、後から繋いで読めるようにすること。これには名前があります」

怜は、コンテキストの図の隣に書いた。

correlation

「コリレーション...?」

「日本語では、相関ですね」

浅井はその二文字をじっと見た。さっき自分が手に入れた絵が、ようやく名前を持った気がした。

「別々のところで生まれた別々のものを、後から繋いで読めるようにすること。これを相関と呼びます」

怜はボードから目を上げた。

「私が深夜、トレースに『ありがとう』って思った時、本当にありがたかったのは、トレースそのものというより、その裏にあった、相関、だったんです」

浅井はふと想像してしまった。

深夜のオフィス、薄暗い中でディスプレイいっぱいに広がった span の連なりを眺めて、ちょっと安心したみたいに、心の中で「ありがとう」と呟いている怜を。

「...先輩、何ニヤニヤしてるんですか」

「え」

── しまった、頬が緩んでいたらしい

「気持ち悪いです」

そう言って怜が目を細めた。

「ご、ごめんなさい...」

怜は小さく息を吐いてから、何事もなかったみたいにボードに視線を戻した。

「で、ここからがちょっと面白い話なんですけど」

「OpenTelemetry における相関って、実は種類があるんです。オライリーの『入門 OpenTelemetry』という本で使われている概念なんですけど」

浅井は、ボードに書かれた「correlation」の文字に視線を戻した。

「種類?」

「ふたつ、あります」

怜はマーカーを取って、ボードの上にサラサラと絵を描いた。

CleanShot 2026-06-08 at 13.18.41@2x.png

ハードコンテキスト

「まず、ハードコンテキストから」

怜はハードコンテキスト、と書いてある方の四角を指した。

「これは、因果関係を運ぶ情報です。さっき先輩が言ってくれた『全部に同じトレース ID が貼ってある』、あれがまさにハードコンテキスト」

「うん」

「で、これがコンポーネントをまたいで運ばれていく仕組みのことを、Context Propagation って呼びます。コンテキストを伝搬させる、っていう意味です」

「ぷ、プロパゲーション」

なんかかっこいい

「リクエストがサービス A から B に渡る瞬間、A の中で組み立てたコンテキストを B に渡す必要がある。HTTP リクエストならヘッダーに、gRPC ならメタデータに、メッセージキューならメッセージのヘッダーに乗せる。どのプロトコルでも『次に渡す』ってのは、抽象的には同じ動作なんですよ」

「あ、それ、ハンズオンでやった気がする。HTTP ヘッダーに勝手に乗っかってくやつ」

「そうです。HTTP の場合は W3C Trace Context っていう仕様で、ヘッダーの名前とフォーマットが決まってます」

「...あれ、そんな名前だったんだ」

「アプリのコードは、自分で trace_id を運ぶ必要がない。SDK と Propagator が勝手に運んでくれる」

「うん」

「これがハードコンテキストの中心です。システムが機械的に、処理の流れにそって運ぶ因果情報。だからハード」

「うん」

怜はマーカーを持ち直して、その先をこちらに向けた。

「はい、ここで先輩に質問です!」

「え、なに、いきなり」

「コンテキストってなんだったか、自分の言葉で説明してみてください」

「えーっ、無茶振りじゃん」

「無茶振りです」

平然とそう言って、怜は待っていた。

浅井は少し焦りつつ、頭の中で図をなぞった。さっき自分で思い浮かべた絵が、ちゃんとまだ残っていた。

「えっと...一番下に、コンテキストっていう土台があって。リクエストが流れてくると、そこにいろんな情報が乗る。trace_id とか、ユーザーのID とか」

「うん」

「で、その上に立ってる、トレース、メトリクス、ログ、ぜんぶに、その情報が同時に伝搬していく」

「うん」

「で、そのコンテキストがサービスをまたいで運ばれていく仕組みが、Context Propagation」

浅井は息を継いだ。

「で、合ってる?」

「合ってます」

怜が満足そうに頷いた。

「お見事です、先輩」

「あ、よかった」

「では、その上で、もう一個考えてみてほしいんですけど」

怜はマーカーの先で、Logs/Metrics/Tracing の枠を順番に指した。

「コンテキストがこの三つ全部の下に共通でいる、ってことは。ハードコンテキストで、ログとトレースも自動で繋がる、ってことになりませんか?」

浅井は考えた。考えるまでもなかった。

「あ、コンテキストの中の trace_id が、ログにも一緒に乗っかってれば、後から繋げる」

「そういうことです」

怜は嬉しそうに笑った。

LogRecord, Exemplar

「OpenTelemetry には、LogRecord っていう、ログのための共通のデータモデルが定義されています。ログ一行を表す箱、みたいなものです。タイムスタンプとか、本文とか、severity とか、属性とか、まあ普通のログが持ってる情報が入ってる。で、その箱の中に、trace_id と span_id が一級の項目として最初から用意されてる

「...なるほど」

「アプリの中で、active な span がある時にログを吐くと、OTelのログ連携や自動計装が有効なら、 LogRecord の trace_id と span_id を埋めてくれる。だから後から、その span に紐づくログだけを綺麗に引ける」

「...ってことは、メトリクスも、同じように繋がる?」

怜が楽しそうに笑った。

「はい。メトリクスにもちゃんと仕組みがあって。Exemplar って言います」

「い、イグザンプラーっ!」

やっぱり、なんかかっこいい

「Exemplar を使うと、集約されたメトリクスのデータポイントに、その集約の中に含まれる代表的な測定値をサンプルとして添えることができるんです。OTel の SDK はこの測定値が active な span の中で記録されていた場合に、trace_id や span_id も一緒に保持できます。だから、レイテンシーヒストグラムで一番遅いバケットを見た時、そこに残っていた代表サンプルのトレースへ飛ぶことができるんです」

「メトリクスを見て、『この遅いやつは何だったんだ』って思った瞬間に、その遅いリクエストを代表するようなトレースに飛べる」

「そういうことです」

浅井は少し考えた。

「...じゃあ、その逆もできる? トレースから、関連するメトリクスを引っ張ってくる、みたいな」

「うーん、それは、二つの話が混ざってるんですよ」

「二つ?」

「先輩が今言った『関連するメトリクス』には、たぶん二通りあって。一つは、同じサービスの、同じ時間帯の、同じエンドポイントのメトリクスを引く方向。これは普通にできます。span に乗ってる属性でメトリクスを絞り込めばいいだけだから。たとえばバックエンド側で service.name="checkout"http.route="/api/orders" という条件を使って同じサービス・同じエンドポイントのメトリクスへ絞りこむことができる」

「あー、確かに。そうか」

「もう一つが、そのリクエスト自身が、どのメトリクスのデータポイントに混ざったかを辿る方向。これが、原理的に取れないんです」

「...どう違うの?」

「メトリクスって、集約されたデータじゃないですか。リクエスト一万本のレスポンスタイムを束ねて『p99 は 230ms でした』って数字を出してる」

「うん」

「だから、一本のリクエストは一個のメトリクスに対応しない。一本一本のリクエストは、集約の中に溶けてしまうんです」

「あー...」

「Exemplar は、ヒストグラムのバケットに『このバケットを代表する測定値』を残しておく仕組み。だから、代表値がトレース・スパンの情報を持っている場合は、メトリクスからトレースに飛べる。でも、自分が投げた span から『自分はどのバケットに入ったか』は辿れない。集約っていう操作は、情報を捨てる操作だから。捨てた情報は戻らない」

集約という操作が情報を捨ててる以上、戻せないものは戻せない。テレメトリの種類によって、相関の効き方には差があるんだ。

「で、さっきの話の続きなんですけど。ExemplarやLogRecordって要するに、トレースの『繋がってる』を、ログとメトリクスにも拡張してきてるんです。trace_id っていう一本の鍵が、トレースの中では span 同士を繋ぎ、ログでは LogRecord の trace_id / span_id として残せる。メトリクスでは、通常のデータポイント全部にのるわけではないけれど、Exemplar として残った代表サンプルからトレースへ飛べる。3つのテレメトリはコンテキストを起点にそれぞれのやり方で相関することができるんです」

浅井はボードを見上げた。

コンテキストという土台。その上に並ぶ、三本の柱。

trace_id は、リクエストごとにコンテキストに乗る。トレースでは span 同士を繋ぐ。ログでは、LogRecord の trace_id / span_id として残せる。メトリクスでは通常のデータポイント全部に乗るわけではないけれど、Exemplar として残った代表サンプルが trace/span 情報を持てることがある。

だから三本の柱は、同じコンテキストを起点に、それぞれのやり方で相関できる。

「トレースが span 同士を繋ぐのを拡張して、別の種類の異なるテレメトリ間同士で繋ぎ合わせることができるんだ」

ぼそり、と口に出してしまった。

それを聞いた怜が嬉しそうに頷いた。

「そうです。LogRecord も Exemplar も、別々に作られた橋じゃなくて、Context Propagation によって繋ぎ合わせられるように作られてるんです」

「な、なるほどっ...!」

感心している浅井を見て、怜がニコッとした。

ソフトコンテキスト

それからコーヒーを一口飲んで、もう一つの四角を指した。

「で、もう一つが、ソフトコンテキスト。これは、ハードと違って、人間が意味を乗せるための層です」

浅井は少し首を傾げた。

「意味のために?」

「たとえば、私が深夜に決済サービスの障害を追ってた時、トレースを見て『認証サイドカーが遅い』ってわかった。でもその時、もう一つ知りたかったことがあって」

「何」

「『遅いのは、特定のお客さんだけか? 全員か?』。全員が遅いなら、サービス全体の問題。特定のお客さんだけなら、その人のデータとか、フィーチャーフラグとか、別の角度から見ないといけない」

「ふむふむ...」

「だから span に『どのお客さんのリクエストか』っていう情報が一緒に乗っかってると、すごく嬉しい」

「うん」

「で、その『お客さん ID』みたいな情報は、システムが勝手に運んでくれません。誰かが、ここに乗せる、ってコードに書く。」

「うん」

「ハードコンテキストは因果関係を機械的に運ぶ。ソフトコンテキストは、人間が後から『これで切り分けたい』って思った切り口を、データに乗せておく」

「なるほど」

「乗せ方はいろいろあって。span に直接 attribute として書くこともあれば、サービスをまたいで運びたい時のために Baggage っていう仕組みもあります。Context Propagation に荷物を乗せて運ぶ、みたいなイメージ」

怜はマーカーで Baggage と書き足してから、少し間を置いた。

「で、ここで一つだけ補足させてください」

セマンティック規約

「うん」

「今のところソフトコンテキストって、結局『データに属性を乗せる』って話じゃないですか」

「だね」

その属性に何の名前をつけるか、は、ずっと書く人の自由だったんですよ。お客さんの ID を customer_id って書く人もいれば、user.id って書く人もいる。uid って書く人もいる。意味はだいたい同じなのに、名前が全部違う。これだと、別チームのサービスと突き合わせようとした時に、属性の名前が違うから、横断して引けない」

「あー、それは...しんどい」

「しんどいんです。だから OpenTelemetry には、もう一段の仕組みがあって。こういう情報はこういう名前で表しましょう、っていう共通の語彙を、業界全体で決めてるんです」

「決めてる...?」

「サービスの名前を表すなら service.name。HTTP のメソッドなら http.request.method。データベースの種類なら db.system.name。Kubernetes のポッド名なら k8s.pod.name、ノード名なら k8s.node.name

「アプリの話もインフラの話も?」

「ぜんぶ、です。アプリからインフラまで、いろんな層で共通の語彙が用意されてる。これを セマンティック規約(Semantic Conventions) って呼びます」

浅井はその名前を、頭の中で何度か繰り返した。

機械の話を聞いていたつもりだった。でも、その下で、ずっと人間が決めてた。アプリ固有の意味も、共通の語彙も、結局は人が選んだ名前だ。

言ってることはまぁわかる。けど、それが「すごく嬉しい」レベルでピンと来ているかと言われると、正直自信がなかった。

「あの、先輩」

顔を上げると、怜がこちらをまっすぐ見ていた。

目が明らかに輝いていた。

「先月、ある顧客先で SLO アラートが鳴ったんですよ。あるサービスのエラー率がいきなりしきい値を超えたんです」

早口だった。

「うん」

「トレースを見たら、特定の数件のリクエストが軒並み内部エラーで死んでた。下流の DB への問い合わせが軒並みタイムアウトしてる。で、共通点を探すわけです。同じユーザーじゃない。同じエンドポイントでもない。Baggage として伝搬していた値や、そこから span attribute にコピーしていた値もバラバラで原因の切り口にはなりませんでした」

「...コンテキストの中に、原因が見つからなかったってこと?」

「そう、そうです」

「ハードコンテキストをどれだけ辿っても見つからない。ソフトコンテキストの方も、アプリ側はバラバラ」

「DB が悪いのかと思って DB 側のメトリクスを見たんですけど、これがまた健康なんですよ。負荷も低い、スロークエリも出てない。なんなら、同じクエリでも、生き残ってるリクエストの方は数 ms で返ってきてる

「えっ」

「同じクエリが、片方は速くて、片方はタイムアウトする。DB から見ると、どっちのリクエストも同じ顔をしてるのに」

浅井は姿勢を直した。

「で、頭を冷やして、別の角度から span を眺め直したんです」

「別の角度」

浅井は少し考えた。さっきまでの話が頭の中で動いていた。

「えっと... Baggage で伝搬している値が手がかりにならなくて、トレースにハードコンテキストで相関するテレメトリからも原因が見つけられなかったんだよね...あとはメトリクスに異常がないかを見て Exampler から相関するトレースを探すとか...?」

怜は静かに首を振った。

「それじゃ、無理だったんですよ」

「えっ」

「先輩はなんでだと思います?」

ハードコンテキスト。リクエストごとに振られて、サービスをまたいで運ばれていく ID。リクエスト本人が、自分で持ってる情報。

──リクエスト本人が、持ってる情報。

「...リクエストって、自分の身の回りのことしか知らないんだ」

「うん」

「自分がどのサービスを通って、どのユーザーから来たか、までは知ってる。けど、自分を動かしてる側のことまでは、知らない」

「うん」

「...インフラ?」

怜が嬉しそうに頷いた。

k8s.node.name ── その span を吐いたプロセスが動いてたノードの名前 ── がぜんぶ同じだったんです」

「...同じノード」

「そう。死んでたリクエスト、ぜんぶ同じノードで動いてたんです

「あ」

「で、そのノードで他に何が動いてるか調べたら、別チームのバッチ job の pod が同居してて。日次の集計処理の結果を、オブジェクトストレージに数十 GB を並列でぶん投げてる最中だったんです」

「...」

「ノードの NIC のエグレス帯域が完全に飽和して、うちの pod から外に出ていく通信が、軒並み TX キューで待たされてた。DB は健康で、いつも通り待ち構えてるのに、こっちからのパケットがそもそも届いてない。タイムアウトもするわけです」

「うわ」

「うちのチームのダッシュボード、自分たちの pod のメトリクスしか映してないんですよ。同居してる他チームのバッチなんて、最初から視界の外。インフラ側のアラートも鳴ってなかった。ノードの CPU もメモリもディスクも全部余裕。NIC の帯域だけが、ぴったり詰まってた

「あー...」

「リクエスト本人は、自分が乗ってるノードを誰と共有してるかなんて、知らないんですよ。Context Propagation に乗って運ばれてくる情報じゃない。ハードコンテキストでは、絶対に捉えられない原因だったんです」

怜がマーカーの先で、ボードのコンテキストの図を指した。

「アプリの span と、ノードのインフラメトリクスは、Context Propagation で繋がってないんですよ。別々の場所で別々のタイミングで生まれる」

「うん」

「でも両方に k8s.node.name っていう同じ名前の属性が乗ってた。ここがポイントで。両方にノード名が乗ってる、ってだけじゃ足りなかったんです。両方が、同じ k8s.node.name で書いてくれてたから、串刺せた」

怜はそこまで言って、マーカーを持ち直した。

ボードに向き直り、今説明したことの絵を描いた。

CleanShot 2026-06-08 at 15.49.18@2x.png

「先輩、多分さっきまでは、セマンティック規約の嬉しさがピンと来てなかったですよね」

「あ、うん」

バレてた

「私がセマンティック規約について、一番伝えたかったのってたぶんここなんです。セマンティクスって、ソフトコンテキストと別の話じゃないんですよ」

「え」

セマンティクスは、ソフトコンテキストを『構築する』ためのものなんです」

「構築する...?」

「ただ属性を乗せるだけだとその情報は自分の中で閉じる。アプリケーション特有の情報だけ、自分のチームの中だけなら、属性の名前は何でもいいかもしれません。でも、別チームのサービスや、自分が書いてない SDK の中や、インフラを観測してる側まで含めて、横断して切り分けたい瞬間が来る」

「うん」

「そこで、名前が揃ってないと、ソフトコンテキストはテレメトリ同士をつなぐ橋にならない

「あー...」

「だから、セマンティクスが、横断できるソフトコンテキストを構築する。私はいつもこういう考え方をしてます」

怜は話しながら追加の絵を描き足して、描き終わった後にそれをマーカーの裏でとんとんと叩いた。

CleanShot 2026-06-08 at 13.20.31@2x.png

「Context Propagation だけだと、見えない世界がある。アプリと、インフラと、サービスの内側と外側を、ぜんぶ繋ぐためには、セマンティクスが構築するソフトコンテキストが、本当にありがたいんです」

怜の声がもう完全に上ずってた。

「で、なんで両方に同じ k8s.node.name が乗ってたか、っていうと、実は、アプリも、インフラを観測してる側も、それぞれ自分のコードでノード名を取ってきてるわけじゃなくて、Collector の側で取って来るようにできるんです。Collector って、SDK から受け取ったテレメトリを加工して保存先に転送するためのミドルウェアなんですけど、その中には resourcedetection とか k8sattributes のような processor があって、その設定に従って、Kubernetes のメタデータを Resource attributes として attach することができるんです。アプリの span も、インフラのメトリクスも、同じ Collector を通るから、両方に k8s.node.nameを揃って...」

怜はそこで急に止まった。

──あ、と気付いた顔だった。

怜はこほん、と咳払いをした。

「...すみません、ちょっと語っちゃいました」

言ってから、ほんの少し目を逸らした。

──こういうことか。

何かがすとんと自分の中に落ちた気がした。

ハードコンテキストは、リクエストの因果を機械的に運ぶ。ソフトコンテキストは、人間と社会が「これで切りたい」って思った切り口を、データに乗せる。そして、セマンティクスが、その切り口の名前を横断で揃えてくれることで、ソフトコンテキストが、テレメトリを相関させる橋を架けられるようになる

三つが噛み合って初めて、深夜のオフィスで、たった一人の人間が、アプリの span と、インフラのメトリクスを、同じ k8s.node.name で串刺すことができた。

怜が「ありがとう」って思ったのは、たぶん、その三つ全部に対してだ。

OpenTelemetry の Vision

怜はコーヒーを一口飲んだ。

少し落ち着いたみたいだった。

「最後に、OpenTelemetryの世界観について少しだけ触れさせてください」

「世界観」

浅井はなんとなく姿勢を直した。

「OpenTelemetryには vision っていう、自分たちが目指してる世界を文章にしたものがあって。五つ書かれてるんです」

怜はホワイトボードの空いたところに、五行書いた。

Telemetry should be easy
Telemetry should be universal
Telemetry should be vendor-neutral
Telemetry should be loosely coupled
Telemetry should be built-in

「テレメトリは、簡単であるべき。普遍であるべき。ベンダー中立であるべき。疎結合であるべき。組み込まれているべき」

「...五つ並べると、なんか強いな」

「ですよね」

怜は universal の文字を、マーカーの後ろでとんとんと叩いた。

「で、今日の話の根っこは、ぜんぶここなんですよ。プロトコルとセマンティックコンベンションを、言語をまたいで、シグナルの種類をまたいで、統一する。三本の柱が同じContextの土台の上に立つのも、service.nameとかk8s.node.nameで属性を揃えるのも、ぜんぶこれの話で、残りはこの上に乗ってる。easyは計装が楽でデフォルトでそれっぽく動く、built-inはライブラリやランタイムに最初から計装が組み込まれていく、どっちもエンドユーザーが楽になる方向。で」

怜はvendor-neutralとloosely coupledの二つを、マーカーで軽く囲った。

「私が今日いちばん最後に話したいのが、残りの二つの組み合わせ方なんです。ベンダーニュートラルは構造の話で、vision本文にはっきり書いてあって。『テレメトリの収集とストレージ・分析を密結合させてきたことが、業界のイノベーションを阻害してきた』って。昔は計装SDKもデータの形も保存方法もベンダーごとに全部違って、移行したくなったらぜんぶ書き直し」

「あー、それは嫌だ」

「嫌なんですよ。だからOpenTelemetryは、データを生むところと、保存・分析するところを構造的に分けた。OTLPっていう共通プロトコルで、トレースもメトリクスもログも同じプロトコルで流せる。で、疎結合の方はもう一段違う話で、OpenTelemetry自身が『これが正解』って押し付けない、っていう約束なんです。SDKだけ使ってもいい、Collectorだけ使ってもいい、観測の世界で何が勝ち筋かを選ばない。この二つが合わさるとすごく効くんですよ。ベンダーニュートラルでデータの縛りが構造的に解けて、その上でOpenTelemetry自身も勝者を選ばない。だから、その上の世界では、何が正解かを各社が真剣に競っていい状態になる。たとえばCharity Majorsって、Honeycombっていう会社をやってる人が、『高カーディナリティのワイドイベントを列指向で持つべきだ』っていう強い思想を持ってる。一方でGrafana LabsのLGTMスタックは、Loki・Tempo・Mimirで三本柱をそれぞれ別々に最適化したストレージで持つ立場。ほとんど真逆に見えますよね。でも、どっちが正解かを決める必要はあんまりないんです。観測データって本番で何かあった瞬間の前後、つまり最近のデータにこそ価値が集中しやすい。だから他のツールに移るコストが構造的に低くて、データがそもそも人質になりにくい。昔は誰かの思想に乗っかった瞬間、データもその人の都合に縛られてたのが、今はそれが解けてる。」

怜はそこで一拍置いた。

「だから私、観測のデータは、ユーザーのものになる、と思うんですよ」

「ユーザーのもの」

「自分たちで生み出して、好きな保存先に流す。気に入らなければ別に移せる。その上に立てる思想も自分で選べる。オブザーバビリティが、誰かの製品の名前じゃなくて、みんなで作る共通基盤になっていく方向に進んでる。私、それが結構いいなって思ってて」

浅井はしばらく黙ってボードを眺めた。

コンテキストという土台。その上に三つのシグナル。それらを繋ぐハードコンテキスト。人間たちが決めた意味を運ぶソフトコンテキスト。loosely coupled な世界。

──前職、これ、要らなかったんだよな。

ふと、思った。

自分で書いて、自分でデプロイして、自分のログを読んで。span がサービスをまたぐ話も、ノードがメモリ枯渇する話も、自分の関心の外側にあった。

でも。

前職で、隣の島にいた人の顔が浮かんだ。

一人だけ、SRE と呼ばれていた人。穏やかな声で話す、ベテランの人。浅井が書いたサービスが、どのノードで、どんな顔をして動いていたか。深夜にアラートが鳴った時、何が起きていたか。あの人はたぶん、ぜんぶ知っていた。

自分の関心が、サービスの中しか向いていなかった頃。あの人はずっと、その外側を見ていた。

──あの人、きっとこういう問題を見てたんだ。

p99 がじわじわ伸びてる、特定のノードだけメモリが枯渇してる。リクエストの中身だけではない、その下でアプリケーションが乗るインフラ。本番環境の向こうから、アプリケーションの先にいるユーザー体験までを含めた大きな世界。

自分の世界が小さかったから観測の道具が要らなかったんじゃない。誰かが代わりに、その大きい世界を引き受けてくれていたから、自分の世界が小さく見えていただけだった。

──あの人が見ていた景色。そして、怜が見ている景色。

ちょっとだけ、見えた気がした。

「先輩?」

「...なんか今なら書けそうかも」

「レポート?」

「うん」

怜がふっと笑った。

「よかった」

浅井は少し迷ってから言った。

「ご飯行かない? 今日助かったし、奢るよ」

怜が目をぱちりと瞬かせて、コーヒーカップを置いた。

「先輩」

「うん?」

「私、奢られるの好きじゃないんですよ」

「えっ」

「割り勘で行きましょう」

「あ、はい」

立ち上がった怜が、マーカーをトレーに戻した。

「お腹空きました」

「うん、行こうか」

浅井はノートパソコンを閉じる前に、もう一度タイトル欄を見た。

「OpenTelemetry...?」

帰ってきたら書き直そう。

たぶん今度こそ書ける。

参考書籍

  • Ted Young、Austin Parker 著、山口 能迪 訳 入門 OpenTelemetry ― 現代的なオブザーバビリティシステムの構築と運用
7
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?