「アプリが遅い」
「どこで失敗したのか分からない」
そんな悩みを抱えたことはありませんか?
この記事では、モダンな分散システムの必需品である OpenTelemetry を使い、トレース・メトリクス・ログを一括で収集・可視化する方法をハンズオン形式で解説します。JavaScript 初心者の方でも実践できるように、Docker Compose を中心に構築手順をまとめました。
OpenTelemetryとは何か?可観測性の基本
可観測性(Observability)は「システムの内部状態を外部から推測できる能力」です。OpenTelemetry は CNCF がホストするオープンソース規格で、分散トレーシング・メトリクス・ログの収集を標準化します。
従来は Zipkin、Prometheus、Fluentd など個別ツールを組み合わせる必要がありましたが、OpenTelemetry を使えば統一的なフォーマットと API で ワンストップ に実装可能です。結果として、障害解析のリードタイム短縮や運用コスト削減につながります。
トレース・メトリクス・ログを統合する理由
サービス遅延の原因は、コードバグ・リソース枯渇・ネットワーク輻輳(ふくそう)など多岐にわたります。
※輻輳(ふくそう):ある場所やシステムにモノや情報が集中し、混雑した状態になること
トレースだけでは呼び出し経路は追えますが、CPU やメモリ使用率までは把握できません。メトリクスだけでは関数単位の遅延を捕捉できません。ログだけでは関連イベントを時系列でつなげるのが困難です。
統合観測 によって、三つのデータを相互参照しながら根本原因を特定するフローを実現できます。
OpenTelemetryのアーキテクチャとコンポーネント
OpenTelemetry は大きく分けて Instrumentation、SDK、Collector の三層で構成されます。Instrumentation は各言語ランタイムやフレームワークにフックを追加し、自動的にスパンやメトリクスを生成します。
SDK は生成したデータをバッファリングし、Exporter を通じて Collector や外部ストレージへ送信します。Collector は受信したデータを一度バッチ処理し、Jaeger、Prometheus、OTLP など複数フォーマットに変換・転送します。
SDKとCollectorの役割
SDK はアプリケーションプロセスの一部として動作し、最小限のオーバーヘッドで計測データを生成します。一方 Collector は別プロセスまたはサイドカーとして動作し、データの集約・サンプリング・変換を担当します。Collector を経由させることで、アプリケーションを再デプロイせずに Exporter を切り替えられる利点があります。
Instrumentationライブラリの選択
主要言語(Java、Go、Python、JavaScript など)ごとに自動計測ライブラリが提供されています。たとえば Node.js の場合、@opentelemetry/auto-instrumentations-node
を導入するだけで Express、MySQL、gRPC など幅広いモジュールのスパンが自動生成されます。まずは自動計測で全体像を把握し、必要に応じて startSpan()
で手動スパンを追加するのが一般的です。
ハンズオン環境構築:Docker Composeで始める
以下のハンズオンでは、サンプル API サーバー(Node.js + Express)と OpenTelemetry Collector、Jaeger、Prometheus、Grafana を Docker Compose でまとめて起動します。ローカル PC に Docker がインストールされていれば 10 分ほどでセットアップ可能です。
準備するツールと前提条件
- Docker Desktop(v24 以上)
- Git(サンプルリポジトリを clone するため)
- macOS または WSL2 環境の Windows 10/11
次のコマンドでリポジトリを取得し、コンテナを一括起動します。
# 公式OpenTelemetryデモを使用(推奨)
git clone https://github.com/open-telemetry/opentelemetry-demo.git
cd opentelemetry-demo
docker compose up -d
# または、シンプルなNode.js例を使用
git clone https://github.com/SigNoz/opentelemetry-nodejs-example.git
cd opentelemetry-nodejs-example
docker compose up -d
ブラウザで http://localhost:16686
(Jaeger UI)にアクセスし、サンプル API を呼び出すとトレースが表示されるはずです。
サンプルアプリケーションにトレーシングを組み込む
Node.js の index.js
で以下のようにトレーサーを初期化します。
// tracing.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
const sdk = new NodeSDK({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'sample-api',
}),
instrumentations: [getNodeAutoInstrumentations()],
});
あとは node -r ./tracing.js index.js
で起動すれば自動計測が始まります。
シャットダウン処理について
運用環境では、プロセス終了時に sdk.shutdown()
を呼び、送信し切れていないスパンを flush するようにしておくと安全です。
process.on('SIGTERM', () => {
sdk.shutdown()
.then(() => console.log('Tracing terminated'))
.catch((err) => console.error('Error terminating tracing', err))
.finally(() => process.exit(0));
});
データの可視化:JaegerとPrometheus+Grafanaの活用
トレース可視化には Jaeger、メトリクスには Prometheus と Grafana が定番です。Grafana では Tempo データソースを追加するとトレースとメトリクスをダッシュボード上でクロスリンクできます。Prometheus 側で Exemplar を有効化し、Tempo データソースと紐付けることでスパン⇔メトリクスを相互ジャンプできます。
JaegerとZipkinの比較表
項目 | Jaeger | Zipkin |
---|---|---|
開発元 | CNCF (Uber) | OpenZipkin Community |
ストレージ | Elasticsearch / Cassandra / OpenSearch(開発用途は Badger) | MySQL / Cassandra / Elasticsearch |
UI機能 | 時系列スパン分析、サービス依存関係グラフ | タイムラインビュー、依存関係グラフ |
OpenTelemetryサポート | OTLP natively | 変換レイヤ経由(OTLP → Zipkin v2 形式) |
推奨ユースケース | Kubernetes + Elasticsearch環境 | 軽量検証やレガシーシステム |
ベストプラクティス:パフォーマンスとコストの最適化
大量のトレースを無差別に送信するとネットワーク帯域とストレージ使用量が急増します。まずは サンプリング(ParentBased(TraceIdRatioBased)
など)で 1〜10% 程度に抑え、エラー時のみフルサンプリングする戦略が有効です。(tail‑based sampling で実現)メトリクスは解像度を 10 秒→60 秒に落とすだけでも保存コストを大幅に削減できます。Collector の batch
Processor で一括送信し、Exporter 側で gzip 圧縮を有効にするとなお良いでしょう。
よくある落とし穴とトラブルシューティング
- トレースが表示されない:SDK の
service.name
が未設定だと Jaeger UI 上でフィルタに掛からないことがあります。 - メトリクスが欠損する:Collector のリソース不足でキューが溢れている可能性があります。
memory_limiter
を導入し、メモリ上限を引き上げてください。 - ログとトレースの関連付け:W3C Trace Context (
traceparent
) をログ側に埋め込むことで相互検索が容易になります。
まとめと次のステップ
OpenTelemetry を導入することで、トレース・メトリクス・ログを統合的に扱える可観測性プラットフォームを短時間で構築できます。まずは自動計測で全体の挙動を掴み、課題が見えたら手動スパンやカスタムメトリクスを追加していきましょう。
次のステップとして、クラウドマネージドの Azure Monitor や Google Cloud Operations と組み合わせ、スケールアウトにも対応した運用基盤を目指すと、障害対応や性能改善のスピードがさらに向上します。