技术架构
オブザーバビリティの3本柱:Traces、Metrics、Logs
マイクロサービスとクラウドネイティブアーキテクチャにおいて、オブザーバビリティはシステムの振る舞いを理解するために不可欠です。
オブザーバビリティ ≠ モニタリング。モニタリングは既知の問題の検出、オブザーバビリティは未知の問題の探索。
| 柱 | 目的 | 典型的なシナリオ |
|---|---|---|
| Traces | リクエストの完全なライフサイクル | クロスサービスコールチェーン追跡 |
| Metrics | 定量化されたシステム指標 | パフォーマンス監視、キャパシティプランニング |
| Logs | 離散的なイベント記録 | エラー調査、監査 |
OpenTelemetryは、CNCFのインキュベーティングプロジェクトで、3つのシグナルを統一的に収集するベンダーニュートラルなAPI、SDK、ツールを提供します。
OpenTelemetryアーキテクチャ:SDK、Collector、Exporter
3層アーキテクチャにより、収集とエクスポートの分離を実現:
アプリケーション層 SDK (Java/Go/Node)
↓ OTLP(gRPC/HTTP)
OTel Collector (受信→処理→エクスポート)
↓
バックエンド (Jaeger/Prometheus/Elasticsearch)
| レイヤー | コンポーネント | 責務 | デプロイ |
|---|---|---|---|
| SDK | OpenTelemetry SDK | 自動/手動インストルメンテーション | プロセス内 |
| Collector | OTel Collector | テレメトリデータの受信、処理、ルーティング | スタンドアロン |
| Exporter | OTLP Exporter | バックエンドへのデータエクスポート | Collector内 |
Java Agent自動インストルメンテーション:ゼロコード侵入
JVM引数を1つ追加するだけで、Spring Boot、HTTPクライアント、JDBC、Redisなどを自動追跡:
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=order-service \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=otlp \
-Dotel.exporter.otlp.endpoint=http://collector:4317 \
-jar my-app.jar
主要設定
| 設定 | デフォルト | 説明 |
|---|---|---|
otel.service.name |
unknown | サービス名 |
otel.traces.exporter |
otlp | Traceエクスポーター |
otel.traces.sampler |
parentBased_alwaysOn | サンプリング戦略 |
自動インストルメンテーション対応範囲
| コンポーネント | 自動Trace | 自動Metrics |
|---|---|---|
| Spring Web MVC/WebFlux | ✅ | ✅ |
| RestTemplate/WebClient | ✅ | ✅ |
| JDBC / R2DBC | ✅ | ✅ |
| Redis (Lettuce/Jedis) | ✅ | ✅ |
| Kafka | ✅ | ✅ |
分散トレーシング実践
コールチェーン例
[OrderService] POST /api/orders
├── [InventoryService] POST /api/inventory/deduct
├── [PaymentService] POST /api/payments/charge
└── [NotificationService] CONSUME payment-success
W3C Trace Context伝播
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067bf0bc902b7-01
カスタムSpanとAttributes
@Service
public class OrderService {
private final Tracer tracer;
public OrderResult createOrder(CreateOrderRequest request) {
Span span = tracer.spanBuilder("order.create")
.setAttribute("order.userId", request.getUserId())
.setAttribute("order.productCount", request.getItems().size())
.startSpan();
try (Scope scope = span.makeCurrent()) {
OrderResult result = doCreateOrder(request);
span.setAttribute("order.id", result.getOrderId());
return result;
} catch (Exception e) {
span.recordException(e);
span.setStatus(StatusCode.ERROR, e.getMessage());
throw e;
} finally {
span.end();
}
}
}
Metrics収集:Counter、Histogram、Gauge
| タイプ | セマンティクス | 集約方式 | ユースケース |
|---|---|---|---|
| Counter | 増加のみのカウント | Sum | リクエスト総数、エラー総数 |
| Histogram | 値の分布統計 | Histogram | リクエストレイテンシ |
| Gauge | 現在の瞬時値 | Last Value | アクティブ接続数 |
Meter meter = meterProvider.meterBuilder("payment-service").build();
LongCounter requestCounter = meter.counterBuilder("payment.requests.total")
.setDescription("Total payment requests")
.build();
LongHistogram latencyHistogram = meter.histogramBuilder("payment.request.duration")
.setUnit("ms")
.ofLongs()
.build();
Collectorデプロイメントモード
| モード | メリット | デメリット | ユースケース |
|---|---|---|---|
| Sidecar | 隔離性が良い | リソースコスト大 | 大規模K8s |
| DaemonSet | リソース効率が良い | 単一障害点リスク | 一般推奨 |
| Gateway | 集中管理 | ネットワークホップ増 | マルチクラスター |
Collector設定
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
send_batch_size: 1024
timeout: 5s
exporters:
otlp/jaeger:
endpoint: jaeger:4317
prometheusremotewrite:
endpoint: http://prometheus:9090/api/v1/write
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp/jaeger]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheusremotewrite]
サンプリング戦略:ヘッドベース vs テールベース
ヘッドベースサンプリング
otel.traces.sampler=parentbased_traceidratio
otel.traces.sampler.arg=0.1
シンプルで効率的だが、エラーリクエストを見逃す可能性あり。
テールベースサンプリング
processors:
tail_sampling:
decision_wait: 10s
sampling_policies:
- name: errors-policy
type: status_code
status_code:
status_codes: [ERROR]
- name: slow-policy
type: latency
latency:
threshold_ms: 1000
- name: fallback-policy
type: probabilistic
probabilistic:
sampling_percentage: 10
推奨:本番環境ではテールベースサンプリングを使用し、エラーと遅いリクエストの100%可視性を確保。
フロントエンドRUM統合
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
const exporter = new OTLPTraceExporter({
url: 'https://collector.example.com/v1/traces',
});
const provider = new WebTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.register();
フロントエンドのHTTPリクエストが自動的に
traceparentヘッダーを運び、ブラウザからバックエンドまでのエンドツーエンドのトレーシングを実現。
Prometheus + Grafanaのクラシックスタック
OpenTelemetry SDK → OTel Collector → Prometheus → Grafana
→ Jaeger/Tempo → Grafana
主要メトリクス
| パネル | PromQL | アラート閾値 |
|---|---|---|
| リクエストレート | rate(http_server_request_total[5m]) |
>10000 |
| P99レイテンシ | histogram_quantile(0.99, rate(http_server_duration_bucket[5m])) |
>500ms |
| エラーレート | rate(http_server_request_total{status=~"5.."}[5m]) / rate(http_server_request_total[5m]) |
>1% |
RED原則:Rate、Errors、Duration — サービスモニタリングの3つのゴールデンシグナル。
まとめ
オブザーバビリティは贅沢品ではなく、マイクロサービスアーキテクチャの必需品である。 オブザーバビリティがなければマイクロサービスはブラックボックス、OpenTelemetryがあればシステムの振る舞いを完全に把握できる。
ブラウザローカルツールを無料で試す →
#OpenTelemetry#可观测性#分布式追踪#Metrics#日志