docker-composeでOpenTelemetryに入門してみる for Laravel
Social Databank Advent Calendar 2025 の10日目です。
こんにちは、zinです🦑
APMの機運が高まってきたので、まずは開発環境でログ・トレース・メトリクスを確認できる環境を作ってみました。
まだ動作イメージが持てる程度の理解度ですが、これから育てていこうという気持ちと共に記事にしてみました。
サンプルコードはこちらに置いてあります。
構成するコンポーネント
今回の環境では、以下のコンポーネントをdocker-composeで起動します。
OpenTelemetry Collector
テレメトリデータ(ログ、トレース、メトリクス)を受信し、適切なバックエンドに振り分ける中継役です。アプリケーションからはこのCollectorにデータを送信するだけで済むため、バックエンドの変更がアプリケーションに影響しません。
Grafana
可視化のためのダッシュボードです。Loki、Prometheus、Tempoからデータを取得して、統合的に確認できます。
Prometheus
メトリクス(CPU使用率、メモリ使用量、HTTPリクエスト数など)を時系列で保存するデータベースです。
Loki
ログを保存するデータベースです。Grafana Labsが開発しており、Grafanaとの連携が非常にスムーズです。
Tempo
分散トレーシングのデータを保存するデータベースです。HTTPリクエストの流れを追跡できます。
データの流れ
今回の構成では、以下のような流れでデータが処理されます。
Laravelアプリケーション
↓
OpenTelemetry Collector
├→ Prometheus (メトリクス)
├→ Loki (ログ)
└→ Tempo (トレース)
↓
Grafana (可視化)
Laravelアプリケーションは、すべてのテレメトリデータをOpenTelemetry Collectorに送信します。Collectorは受け取ったデータの種類に応じて、適切なバックエンド(Prometheus、Loki、Tempo)に振り分けます。
OpenTelemetry Collectorの設定
otel/config.yamlで、Collectorの動作を定義します。
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
exporters:
prometheus:
endpoint: 0.0.0.0:8889
otlp:
endpoint: tempo:4317
tls:
insecure: true
otlphttp/loki:
endpoint: http://loki:3100/otlp
tls:
insecure: true
service:
pipelines:
metrics:
receivers: [ otlp ]
exporters: [ prometheus ]
traces:
receivers: [ otlp ]
exporters: [ otlp ]
logs:
receivers: [ otlp ]
exporters: [ otlphttp/loki ]
Laravel側の設定
1. PHP拡張のインストール
DockerfileでOpenTelemetry PHP拡張をインストールします。
RUN pecl install opentelemetry \
&& docker-php-ext-enable opentelemetry
この拡張により、PHPアプリケーションからOpenTelemetryの機能を利用できるようになります。
2. Composerパッケージのインストール
composer.jsonに以下のパッケージを追加します。
{
"require": {
"open-telemetry/exporter-otlp": "^1.3",
"open-telemetry/opentelemetry-auto-guzzle": "^1.2",
"open-telemetry/opentelemetry-auto-laravel": "^1.4",
"open-telemetry/opentelemetry-auto-psr18": "^1.1",
"open-telemetry/sdk": "^1.10"
}
}
3. 環境変数の設定
docker-compose.ymlで、LaravelコンテナにOpenTelemetry関連の環境変数を設定します。
# SDK有効化
OTEL_SDK_DISABLED: "false"
OTEL_PHP_AUTOLOAD_ENABLED: "true"
# サービス情報
OTEL_SERVICE_NAME: laravel-app
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=dev,service.version=dummy
# エンドポイント設定
OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4318
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: http://otel-collector:4318/v1/logs
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: http://otel-collector:4318/v1/metrics
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: http://otel-collector:4318/v1/traces
# 各種シグナルのエクスポーター指定
OTEL_LOGS_EXPORTER: otlp
OTEL_METRICS_EXPORTER: otlp
OTEL_TRACES_EXPORTER: otlp
4. カスタムメトリクスの送信(オプション)
自動計装だけでなく、アプリケーション固有のメトリクスを送信したい場合は、独自のメトリクスサービスを実装できます。
MetricsServiceの実装
app/Telemetry/MetricsService.phpを作成し、OpenTelemetryのMeterProviderをラップします。
ServiceProviderに登録する方法はここでは割愛します。
<?php
namespace App\Telemetry;
use Closure;
use OpenTelemetry\API\Metrics\CounterInterface;
use OpenTelemetry\API\Metrics\MeterInterface;
use OpenTelemetry\SDK\Metrics\MeterProvider;
use OpenTelemetry\SDK\Metrics\MeterProviderFactory;
class MetricsService
{
private string $prefix;
private MeterProvider $meterProvider;
private MeterInterface $meter;
private array $counters = [];
public function __construct(string $prefix)
{
$this->prefix = $prefix;
$this->meterProvider = (new MeterProviderFactory)->create();
$this->meter = $this->meterProvider->getMeter($prefix);
}
public function forceFlush(): void
{
$this->meterProvider->forceFlush();
}
public function increment(
string $name,
float|int $value = 1,
array $attributes = []
): void {
$metricName = "{$this->prefix}.{$name}";
if (!isset($this->counters[$metricName])) {
$this->counters[$metricName] = $this->meter->createCounter($metricName);
}
$this->counters[$metricName]->add($value, $attributes);
}
}
使用例
ミドルウェアやコントローラーで簡単に使えます。
// HTTPリクエスト数をカウント(ルート別)
\Metrics::increment('http_request_count', attributes: [
'uri' => \Route::getCurrentRoute()->uri,
]);
この実装により、自動計装では取得できないビジネス固有のメトリクスを送信できるようになります。
動かしてみる
1. コンテナの起動
初回はLaravelコンテナのビルドとComposerの依存関係インストールに時間がかかります(5〜10分程度)。
docker compose up -d
2. Laravelアプリケーションにアクセス
サンプルで以下3つのエンドポイントを用意しています。いずれもLaravelのwelcomeページが表示されます。
Grafanaで確認するためにたくさんアクセスしておきましょう。
- http://localhost:8000
-
http://localhost:8000/db
- 裏で適当なクエリを投げている
-
http://localhost:8000/http
- 裏でexample.comにアクセスしている
3. Grafanaでデータを確認
ある程度データが溜まったらブラウザで http://localhost:3000/dashboards にアクセスします。
- ユーザー名:
admin - パスワード:
password
Default APMというダッシュボードが作られているので、開きます。
まだGrafana力がヨワヨワなため見た目はご愛嬌ですが、ログ・トレース・メトリクスが届いていることは確認できました。
おわりに
ひとまずdocker-composeを使って自動計装や独自のメトリクス定義を動かす方法がわかりました。
OpenTelemetryでできることはもっとたくさんあるので道半ばといったところですが、今後理解が深まってきたら続編記事を出したいと思います。
Discussion