 
 Next.js で OpenTelemetry を使用した計装を行う
この記事では Next.js で OpenTelemetry を使用した計装を行う方法について紹介します。Next.js では `instrumentation.ts` ファイルを使用して監視ツールやログツールの計装を設定できます。
OpenTelemetry は Observability のフレームワークであり、トレース・メトリクス・ログなどのテレメトリーデータを作成、管理するためのツールキットです。OpenTelemetry はベンダーに依存しない形で標準化されたプロトコルとツールを提供していることが特徴です。
Next.js では instrumentation.ts ファイルを使用することで、監視やログツールの計装を設定できます。また、Next.js ではアプケーションのパフォーマンスを計測できるように、render route, fetch, resolve page component といったいくつかのスパンが自動で計装されるようになっています。
この記事では、Next.js で OpenTelemetry を使用した計装を行う方法について紹介します。
OpenTelemetry パッケージのインストール
初めに Next.js のプロジェクトを作成しましょう。以下のコマンドを実行します。
npx create-next-app@latest next-otel続いて OpenTelemetry で計装を行うために必要なパッケージをインストールします。いくつかの Node.js 向けの SDK が提供されていますが、 Next.js 向けにすぐに利用できるように @vercel/otel パッケージが用意されているので、これを使用します。
npm install @vercel/otelプロジェクトのルートディレクトリに instrumentation.ts ファイルを作成します。instrumentation.ts ファイルで register 関数を export すると、Next.js のサーバーインスタンスが初期化される際に 1 度だけ呼び出されます。
import { registerOTel } from '@vercel/otel';
 
export function register() {
  registerOTel({ serviceName: "next-otel" });
}register 関数では registerOtel 関数を呼び出すことで、OpenTelemetry の計装を設定が完了します。オプションの serviceName は OpenTelemetry の Resource Semantic Conventions で定義されている service.name 属性に対応しています。service.name 属性はテレメトリデータの送信元のサービス名を表す元として規約で定義されています。
監視バックエンドへの送信
Next.js 側で軽装されたテレメトリデータを収集するために、OpenTelemetry Collector を使用できます。OpenTelemetry Collector は、複数のバックエンドに送信するためのミドルウェアです。アプリケーションから直接バックエンドに送信するのではなく、OpenTelemetry Collector を経由して送信することで、アプリケーションはバックエンドのことを意識する必要がなくなります。
テレメトリデータを収集するための監視バックエンドとして、Jaeger と Prometheus を使用します。 Jaeger はトレースデータを、Prometheus はメトリクスデータをそれぞれ収集します。
docker-compose.yml Otel Collector, Jaeger, Prometheus を起動するための設定ファイルを作成します。構成ファイルは以下のレポジトリを参考にしています。
version: "2"
services:
  # Jaeger
  jaeger-all-in-one:
    image: jaegertracing/all-in-one:latest
    restart: always
    ports:
      - "16686:16686"
      - "14268"
      - "14250"
 
  # Zipkin
  zipkin-all-in-one:
    image: openzipkin/zipkin:latest
    restart: always
    ports:
      - "9411:9411"
 
  # Collector
  otel-collector:
    image: otel/opentelemetry-collector-contrib
    restart: always
    command: ["--config=/etc/otel-collector-config.yaml"]
    volumes:
      - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
    ports:
      - "1888:1888" # pprof extension
      - "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
      - "55679:55679" # zpages extension
    depends_on:
      - jaeger-all-in-one
      - zipkin-all-in-one
 
  prometheus:
    container_name: prometheus
    image: prom/prometheus:latest
    restart: always
    volumes:
      - ./prometheus.yaml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"
 続いて otel-collector-config.yaml ファイルを作成します。このファイルでは、OpenTelemetry Collector の設定を記述します。
receivers:
  otlp:
    protocols:
      grpc:
      http:
 
exporters:
  prometheus:
    endpoint: "0.0.0.0:8889"
    const_labels:
      label1: value1
 
  logging:
 
  zipkin:
    endpoint: "http://zipkin-all-in-one:9411/api/v2/spans"
    format: proto
 
  jaeger:
    endpoint: jaeger-all-in-one:14250
    tls:
      insecure: true
 
processors:
  batch:
 
extensions:
  health_check:
  pprof:
    endpoint: :1888
  zpages:
    endpoint: :55679
 
service:
  extensions: [pprof, zpages, health_check]
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [logging, zipkin, jaeger]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [logging, prometheus]
 最後に Prometheus の設定ファイル prometheus.yml を作成します。
scrape_configs:
  - job_name: 'otel-collector'
    scrape_interval: 10s
    static_configs:
      - targets: ['otel-collector:8889']
      - targets: ['otel-collector:8888']以下のコマンドで Docker コンテナを起動します。
docker compose up -d監視バックエンドにはそれぞれ以下の URL でアクセスできます。
- Jaeger: http://localhost:16686
- Prometheus: http://localhost:9090
リクエストの計装
Next.js アプリケーションを起動し http://localhost:3000 にアクセスし、サーバーにリクエストが来た際に OpenTelemetry で計装されたデータが監視バックエンドに送信されることを確認します。
npm run devJeager の UI にアクセスし、トレースデータが表示されていることを確認しましょう。Service のセレクトボックスで registerOTel で指定した serviceName が選択できます。この next-otel を選択すると、Next.js アプリケーションのトレースデータが表示されます。正常に動作している場合には、GET /{pathname} のようなラベルがついたルートサーバースパンが表示されます。

それぞれのトレースデータをクリックすると、リクエストの詳細情報を確認できます。

Next.js でデフォルトで提供されている各スパンについては、以下のドキュメントを参照してください。
まとめ
- Next.js では instrumentation.tsファイルを使用して監視ツールやログツールの計装を設定できる- register()関数を export することで、サーバーインスタンスが初期化される際に 1 度だけ呼び出される
 
- Next.js ではデフォルトでいくつかのスパンが自動で計装される
- @vercel/otelパッケージを使用の- registerOTel関数を使用することで、細かな設定をせずとも OpenTelemetry の計装を開始できる
- OpenTelemetry Collector を使用することで、複数のバックエンドにテレメトリデータを送信できる
- Jaeger と Prometheus を使用して、トレースデータとメトリクスデータを収集する


 
  
 