ストーリー
モニタリング vs オブザーバビリティ
| 観点 | モニタリング | オブザーバビリティ |
|---|---|---|
| 目的 | 既知の問題を検知する | 未知の問題を調査・理解する |
| アプローチ | 事前定義のメトリクスとアラート | データの自由な探索と相関分析 |
| 質問 | 「システムは正常か?」 | 「なぜシステムは異常なのか?」 |
| データ | メトリクス中心 | メトリクス + ログ + トレース |
| 適用場面 | モノリス、シンプルなシステム | マイクロサービス、分散システム |
3つの柱(Three Pillars)
graph TD
Title["オブザーバビリティの3本柱"]
Title --- Metrics["メトリクス (Metrics)<br/>数値データ<br/><br/>・集約効率◎<br/>・コスト低<br/>・カーディナリティ制限<br/><br/>"何が起きているか""]
Title --- Logs["ログ (Logs)<br/>イベント記録<br/><br/>・詳細情報◎<br/>・コスト高<br/>・非構造化の場合<br/>検索困難<br/><br/>"詳細は何か""]
Title --- Traces["トレース (Traces)<br/>リクエストの経路追跡<br/><br/>・因果関係◎<br/>・コスト中<br/>・サンプリングが<br/>必要な場合がある<br/><br/>"どのサービスで起きたか""]
classDef title fill:#1a1a2e,stroke:#e94560,color:#fff
classDef pillar fill:#0d6efd,stroke:#0a58ca,color:#fff
class Title title
class Metrics,Logs,Traces pillar
各柱の特徴
| 柱 | 強み | 弱み | 主なツール |
|---|---|---|---|
| メトリクス | 集約が効率的、長期保存に適する | 詳細なコンテキストが欠ける | Prometheus, Datadog |
| ログ | 詳細なイベント情報を含む | 大量データでコストが高い | Loki, Elasticsearch |
| トレース | サービス間の因果関係が見える | サンプリングで一部が欠ける | Jaeger, Tempo |
3本柱の相関
graph TD
TraceID["Trace ID: abc-123"]
TraceID --> Metrics["メトリクス<br/>"エラー率が0.5%に上昇""]
TraceID --> Logs["ログ<br/>"Payment API:<br/>connection timeout<br/>to DB at 14:23:05""]
TraceID --> Traces["トレース<br/>"API Gateway →<br/>Payment Service (timeout 3.2s)<br/>→ DB (no response)""]
Metrics --- Correlate["Trace IDで3つを横断的に追跡"]
Logs --- Correlate
Traces --- Correlate
classDef traceId fill:#e94560,stroke:#c23050,color:#fff
classDef metrics fill:#0d6efd,stroke:#0a58ca,color:#fff
classDef logs fill:#198754,stroke:#146c43,color:#fff
classDef traces fill:#f5a623,stroke:#c47d10,color:#fff
classDef correlate fill:#6c757d,stroke:#495057,color:#fff
class TraceID traceId
class Metrics metrics
class Logs logs
class Traces traces
class Correlate correlate
OpenTelemetry入門
OpenTelemetryとは
OpenTelemetry(OTel)は、テレメトリデータ(メトリクス、ログ、トレース)の生成・収集・エクスポートのためのオープンソース標準です。
# OpenTelemetryの構成要素
components:
api:
description: "計装(Instrumentation)のためのインターフェース"
role: "アプリケーションコードにテレメトリの計装ポイントを定義"
sdk:
description: "APIの実装"
role: "テレメトリデータの処理、サンプリング、エクスポート"
collector:
description: "テレメトリデータの収集・加工・転送"
role: "ベンダー非依存のデータパイプライン"
exporters:
description: "バックエンドへのデータ送信"
destinations:
- Prometheus (メトリクス)
- Jaeger / Tempo (トレース)
- Loki / Elasticsearch (ログ)
OpenTelemetry Collectorのアーキテクチャ
graph LR
NodeApp["App (Node.js)"] --> Collector
PythonApp["App (Python)"] --> Collector
GoApp["App (Go)"] --> Collector
subgraph Collector["OpenTelemetry Collector"]
Receivers["Receivers"] --> Processors["Processors"] --> Exporters["Exporters"]
end
Collector --> Prometheus["Prometheus<br/>(メトリクス)"]
Collector --> Jaeger["Jaeger<br/>(トレース)"]
Collector --> Loki["Loki<br/>(ログ)"]
classDef app fill:#6c757d,stroke:#495057,color:#fff
classDef collector fill:#0d6efd,stroke:#0a58ca,color:#fff
classDef backend fill:#198754,stroke:#146c43,color:#fff
class NodeApp,PythonApp,GoApp app
class Receivers,Processors,Exporters collector
class Prometheus,Jaeger,Loki backend
Node.jsでのOpenTelemetry設定
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { Resource } from '@opentelemetry/resources';
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
const sdk = new NodeSDK({
resource: new Resource({
[ATTR_SERVICE_NAME]: 'payment-service',
[ATTR_SERVICE_VERSION]: '1.2.0',
'deployment.environment': process.env.NODE_ENV ?? 'development',
}),
// トレースエクスポーター
traceExporter: new OTLPTraceExporter({
url: 'http://otel-collector:4318/v1/traces',
}),
// メトリクスエクスポーター
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({
url: 'http://otel-collector:4318/v1/metrics',
}),
exportIntervalMillis: 15000,
}),
// 自動計装(HTTP, Express, pg, redis等)
instrumentations: [
getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-http': {
ignoreIncomingRequestHook: (req) => {
return req.url === '/health' || req.url === '/ready';
},
},
}),
],
});
sdk.start();
console.log('OpenTelemetry SDK started');
// グレースフルシャットダウン
process.on('SIGTERM', async () => {
await sdk.shutdown();
console.log('OpenTelemetry SDK shut down');
process.exit(0);
});
OpenTelemetry Collector設定
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 5s
send_batch_size: 1000
# リソース属性の追加
resource:
attributes:
- key: environment
value: production
action: upsert
# メモリ制限
memory_limiter:
check_interval: 5s
limit_mib: 512
spike_limit_mib: 128
exporters:
# Prometheusへのメトリクス送信
prometheus:
endpoint: 0.0.0.0:8889
namespace: otel
# Jaeger/Tempoへのトレース送信
otlp/tempo:
endpoint: tempo:4317
tls:
insecure: true
# Lokiへのログ送信
loki:
endpoint: http://loki:3100/loki/api/v1/push
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch, resource]
exporters: [otlp/tempo]
metrics:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [prometheus]
logs:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [loki]
OpenTelemetry vs ベンダー固有ソリューション
| 観点 | OpenTelemetry | ベンダー固有(Datadog等) |
|---|---|---|
| ロックイン | なし(オープン標準) | バックエンド変更が困難 |
| 自動計装 | 対応(主要フレームワーク) | 対応(より豊富な場合も) |
| 運用負荷 | Collectorの管理が必要 | SaaS型で運用不要 |
| コスト | OSS(インフラコストのみ) | ライセンス費用 |
| カスタマイズ | 高い自由度 | プロバイダの機能に制限 |
| コミュニティ | CNCF、活発な開発 | ベンダーサポート |
多くの組織では、OpenTelemetryでデータを収集し、バックエンドはDatadog/New Relic等のSaaSを使う「ハイブリッドアプローチ」が採用されています。
まとめ
| ポイント | 内容 |
|---|---|
| モニタリング vs オブザーバビリティ | 既知の問題検知 vs 未知の問題調査 |
| 3本柱 | メトリクス(数値)、ログ(イベント)、トレース(経路) |
| 相関分析 | Trace IDで3つの柱を横断的に追跡 |
| OpenTelemetry | テレメトリの収集・加工・送信のオープン標準 |
| Collector | ベンダー非依存のデータパイプライン |
チェックリスト
- モニタリングとオブザーバビリティの違いを説明できる
- 3本柱(メトリクス・ログ・トレース)の特徴と使い分けを理解した
- 3本柱のデータ相関の仕組み(Trace ID)を理解した
- OpenTelemetryの構成要素とアーキテクチャを把握した
- Node.jsでのOpenTelemetry設定を実装できる
次のステップへ
次は「Prometheus/Grafana」を深掘りします。Prometheusのアーキテクチャ、PromQLの応用、Grafanaのベストプラクティスを学びましょう。
推定読了時間: 40分