オブザーバビリティとは
「オブザーバビリティ(Observability)」は、「Observe (観察する)」と「Ability (能力)」の組み合わせから示す通り、日本語では「可観測性」や「観察する能力」と翻訳されています。ではその概念は、いつ頃に登場したのでしょうか。
これは決して新しい概念ではなく、最初に提唱したのは「カルマンフィルター」で知られるRudolf E. Kálmán氏だと言われており、1960年に発表された「On the general theory of control systems(https://www.sciencedirect.com/science/article/pii/S1474667017700948?via%3Dihub)」に登場しています。
その意味は「システム内部の状態を外部出力の情報から推測できる度合いを示す指標」であり、もともとは「自己調整システムの制御理論」に関して言及された言葉でした。
現在IT業界で使われている「オブザーバビリティ」も、基本的な意味は同様です。
つまり「システムの状態に係る出力情報を調査することによって、システム内部の状態を推測、把握する能力」です。
オブザーバビリティを高める上で得られるメリット、期待できることは主に下記の 2 点です。
・システム状態の即時把握による、問題への迅速な初動対応
・ユーザーに対するサービスレベルの維持が容易になる
Open Telemetryとは
OpenTelemetry(オープンテレメトリー)は、マイクロサービスにおける性能や健全性を示す「テレメトリーデータ」を生成、管理するためのオープンソースのオブザーバビリティフレームワークです。
オブザーバビリティにおけるOpenTelemetryの役割は「データ収集基盤」として機能します。アプリケーションからテレメトリデータを収集し、監視バックエンドに送信することでオブザーバビリティを実現します。
テレメトリーデータとは
テレメトリーデータとは、システムやアプリケーションの動作状態を示すデータのことで、主にログ・メトリクス・トレースのことを指します。
Prometheusとは
Prometheus(プロメテウス)は、オープンソースの監視システムおよび時系列データベースです。主に、システムやアプリケーションのメトリクスを収集し、分析するために使用されます。
オブザーバビリティにおけるPrometheusの役割は「メトリクス収集」の基盤として機能します。
Grafanaとは
Grafanaはリアルタイムでデータを可視化・モニタリングを行ってくれるオープンソースの監視ソリューションです。
主な特徴は、多様なデータソースとの連携や、カスタマイズ可能なダッシュボードが挙げられます。オブザーバビリティにおけるGrafanaの役割は「可視化」の部分になります。テレメトリデータ(メトリクス、ログ、トレース)を表示することでシステムを統合的に把握することができます。
デモ構成図
デモは以下の構成になります。
ファイル構成
.
├── instrumentation.js
├── main.js
├── package-lock.json
├── package.json
├── docker-compose.yml
├── prometheus.yml
└── otel-collector-config.yml
デモ
計装するアプリ作成
まず必要なパッケージをインストールします。
npm i express @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/sdk-metrics @opentelemetry/exporter-metrics-otlp-grpc @opentelemetry/api
{
"name": "o11y",
"version": "1.0.0",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": "",
"type": "module",
"dependencies": {
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/auto-instrumentations-node": "^0.56.1",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.57.2",
"@opentelemetry/sdk-metrics": "^1.30.1",
"@opentelemetry/sdk-node": "^0.57.2",
"express": "^4.21.2"
}
}
次にOpenTelemetry SDKの設定を行います。
import { NodeSDK } from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
// OpenTelemetryのSDKを初期化する
const sdk = new NodeSDK({
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter(), // OTLPエンドポイントにテレメトリーデータを送信
}),
instrumentations: [
getNodeAutoInstrumentations(), // 自動計装を有効化
],
});
// SDKを起動することで自動で計装が開始される
sdk.start();
次にメトリクス生成を含めたExpressアプリを作成します。
import express from "express";
await import("./instrumentation.js");
import { metrics } from "@opentelemetry/api";
const app = express();
app.get("/", (req, res) => {
const meter = metrics.getMeter("test"); // プロバイダーからメーターを取得する。
const countMetric = meter.createCounter('metric.counter'); // 新しいカウンターメトリクスを作成する
countMetric.add(1); // カウントする
res.send("OK")
});
app.listen(3001, () => {
console.log("Server is running on port 3001");
});
OpenTelemetry Collector設定
receivers:
otlp:
protocols:
grpc:
endpoint: otel-collector:4317
http:
endpoint: otel-collector:4318
cors:
allowed_origins:
- "http://*"
- "https://*"
processors:
batch:
exporters:
prometheus:
endpoint: "0.0.0.0:8889" # すべてのインターフェースでリッスン
debug:
verbosity: detailed
extensions:
health_check:
service:
extensions: ["health_check"]
pipelines:
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheus, debug]
docker-compose.ymlの設定
services:
grafana:
image: grafana/grafana:11.4.0
container_name: grafana
ports:
- 3000:3000
prometheus:
image: prom/prometheus
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus.yml
command:
- "--config.file=/etc/prometheus.yml"
ports:
- "9090:9090"
otel-collector:
image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.116.1
container_name: otel-collector
volumes:
- ./otel-collector-config.yml:/etc/otel-collector-config.yml
command: ["--config=/etc/otel-collector-config.yml"]
ports:
- "8888:8888" # Prometheus metrics exposed by the collector
- "8889:8889" # Prometheus exporter metrics
- "13133:13133" # health_check extension
- "4317:4317" # OTLP gRPC receiver
- "4318:4318" # OTLP HTTP receiver
docker-compose.ymlの設定
global:
scrape_interval: 15s # デフォルトのインターバル時間。15秒間に1度スクレイピングする。
scrape_configs:
- job_name: "prometheus" # ジョブという単位で管理
scrape_interval: 5s # このジョブ特有の値
static_configs:
- targets: ["otel-collector:8889"]
実行
ターミナルを3つ開き、それぞれで以下のコマンドを実行します。
$ docker compose up
$ node main.js
$ curl http://localhost:3001
Grafanaダッシュボードでメトリクスを確認
Grafana (http://localhost:3000) にアクセスしてGrafanaのログイン画面を開きます。
初期ユーザー名とパスワードは共に「admin」です。
ログイン後は以下の画面になります。
次にGrafanaのデータソースにPrometheusを設定します。
サイドバーのData sourcesをクリックして、Prometheusを選択します。
次に赤枠箇所にDockerコンテナで実行しているPrometheusサーバーのURLを入力します。
「Save&test」をクリックして、成功すれば接続完了です。
ダッシュボードを作成します。
サイドバーのDashboards
をクリックして、Prometheusを選択します。
時間範囲を適切に設定して、Metricのプルダウンからmetric_counter_total
を選択します。
Prometheusのデータを可視化し、リクエスト数をダッシュボードで確認できます。