第2章 単純構成:OpenTelemetry SDK と Jaeger v2 によるトレース構築
本章では、OpenTelemetry SDK から分散トレーシングシステム「Jaeger v2」へ直接トレースデータを送信する最小構成を構築します。中間サーバー(Collector)を挟まず、手元の開発マシンで手軽に動作確認できる手順を解説します。
アーキテクチャの概要
最小構成のデータフローは以下の通りです。
+-----------------------+
| Python アプリケーション |
| (OpenTelemetry SDK) |----+
+-----------------------+ |
| OTLP (gRPC: 4317 / HTTP: 4318)
+-----------------------+ |
| C# アプリケーション |----+
| (OpenTelemetry SDK) | |
+-----------------------+ v
+--------------------+
| Jaeger v2 |
| - OTLP Receiver |
| - UI (:16686) |
+--------------------+
Jaeger v2 は、OpenTelemetry Collector のフレームワークを基盤として再構築された新世代の Jaeger です。従来の独自プロトコル(Thrift など)に代わり、OTLP(ポート 4317 / 4318)を第一級の受信口として標準サポートしています。
Jaeger v2 の起動(Docker Compose)
作業用ディレクトリを用意し、Jaeger v2 を起動するための docker-compose.yaml を作成します。
services:
jaeger:
image: jaegertracing/jaeger:2.3.0
container_name: jaeger-v2
ports:
- "16686:16686" # Jaeger UI
- "4317:4317" # OTLP gRPC 受信ポート
- "4318:4318" # OTLP HTTP 受信ポート
environment:
- METRICS_STORAGE_TYPE=memory
以下のコマンドを実行してコンテナを起動します。
docker compose up -d
起動後、ブラウザで http://localhost:16686 にアクセスすると、Jaeger の Web UI が表示されます。
Python によるトレース送信実装
Python の OpenTelemetry SDK を使用し、Jaeger へトレースを直接送信するコードを作成します。
必要なパッケージのインストール
仮想環境を作成し、必要なライブラリをインストールします。
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp
送信スクリプト(trace_sample.py)
以下のスクリプトは、親スパン(Parent Span)と子スパン(Child Span)を作成し、属性(Attributes)やイベントを付加して送信します。
import time
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# 1. サービス名などのリソース情報を定義
resource = Resource.create(
attributes={
"service.name": "order-service-python",
"service.version": "1.0.0",
"deployment.environment": "development",
}
)
# 2. TracerProvider を作成し、OTLP エクスポーターを登録
provider = TracerProvider(resource=resource)
# Jaeger v2 の gRPC エンドポイント (localhost:4317) を指定
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint="localhost:4317", insecure=True)
)
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
# 3. トレーサーを取得
tracer = trace.get_tracer("order-service-tracer")
def process_order(order_id: str):
# 親スパンの開始
with tracer.start_as_current_span("create_order") as parent_span:
parent_span.set_attribute("order.id", order_id)
parent_span.set_attribute("customer.vip", True)
time.sleep(0.1)
# 子スパンの開始
with tracer.start_as_current_span("validate_inventory") as child_span:
child_span.set_attribute("item.sku", "ITEM-9981")
child_span.set_attribute("item.quantity", 2)
time.sleep(0.05)
child_span.add_event("在庫の引き当てに成功しました")
with tracer.start_as_current_span("charge_payment") as child_span:
child_span.set_attribute("payment.method", "credit_card")
child_span.set_attribute("payment.amount", 3500)
time.sleep(0.08)
print(f"注文処理が完了しました: {order_id}")
if __name__ == "__main__":
process_order("ORD-2026-001")
# バッファされたスパンを確実にフラッシュして終了
provider.shutdown()
スクリプトの実行
python trace_sample.py
C# によるトレース送信実装
.NET では、ランタイム組み込みの System.Diagnostics.ActivitySource と OpenTelemetry .NET SDK を組み合わせてトレースを送信します。
プロジェクトの作成とパッケージ追加
.NET 8 または .NET 10 を想定したコンソールアプリケーションを作成します。
dotnet new console -n OtelSampleCSharp
cd OtelSampleCSharp
dotnet add package OpenTelemetry
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
送信プログラム(Program.cs)
Program.cs を以下のように記述します。
using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
const string serviceName = "payment-service-csharp";
const string serviceVersion = "1.0.0";
// 1. .NET 組み込みの ActivitySource を定義
var activitySource = new ActivitySource(serviceName, serviceVersion);
// 2. OpenTelemetry TracerProvider を構築
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.ConfigureResource(resource => resource.AddService(
serviceName: serviceName,
serviceVersion: serviceVersion,
serviceInstanceId: Environment.MachineName))
.AddSource(serviceName)
// Jaeger v2 の gRPC エンドポイント (http://localhost:4317) を指定
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("http://localhost:4317");
options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
})
.Build();
// 3. 業務処理を実行し、スパン(Activity)を生成
ProcessPayment("PAY-2026-8871", 5200);
void ProcessPayment(string paymentId, decimal amount)
{
// 親スパンの開始
using (var parentActivity = activitySource.StartActivity("ProcessPayment"))
{
parentActivity?.SetTag("payment.id", paymentId);
parentActivity?.SetTag("payment.amount", amount);
Thread.Sleep(100);
// 子スパンの開始
using (var authActivity = activitySource.StartActivity("AuthorizeCard"))
{
authActivity?.SetTag("card.brand", "Visa");
Thread.Sleep(60);
authActivity?.AddEvent(new ActivityEvent("カード与信枠を確保しました"));
}
using (var settleActivity = activitySource.StartActivity("SettleTransaction"))
{
settleActivity?.SetTag("settlement.currency", "JPY");
Thread.Sleep(80);
}
}
Console.WriteLine($"決済処理が完了しました: {paymentId}");
}
プログラムの実行
dotnet run
Jaeger UI でのトレース確認
- ブラウザで
http://localhost:16686を開きます。 - 左メニューの Service ドロップダウンをクリックします。
order-service-pythonまたはpayment-service-csharpが表示されていることを確認し、選択します。- Find Traces ボタンをクリックします。
- 検索結果一覧からトレースをクリックすると、タイムライン形式で各スパンの親子関係、実行所要時間、付与した属性(Tags)やイベントが表示されます。