Next.jsのOpenTelemetry対応を試してみた
Hi, Splunkでオブザーバビリティ製品の導入支援担当をしている @katzchang です。SplunkはOpenTelemetryに貢献している企業の一つであり、Splunk Observabilityでも、導入するエージェントはOpenTelemetryベースのものを案内していたりします。そんな中で、Next.jsのドキュメントサイトの中でOpenTelemetry対応に関する記載があることを知ったので、試してみました。
ドキュメントに沿って計装を加えつつ、Splunk Observabilityにトレースデータを送って、どのように見えるかを見てみましょう。
Hello, Next.js!
とりあえず、Next.jsのアプリケーションを動かしましょう。ちょうど公式サイトにサンプルプロジェクトの起動が書いてあったので、この通りに進めていきます。
全部入りの「Automatic Installation」もあるのですが、ここはシンプルに「Manual Installation」の方を試していきます。
npm install next@latest react@latest react-dom@latest
しつつ、指定されたように、 package.json
, app/layout.tsx
, app/page.tsx
ファイルをそれぞれ作り、アプリケーションを起動します。
npm run dev
ブラウザーで http://<IPアドレス>:3000 を開くと、ハローワールドが成功したことがわかります。
では、ここにOpenTelemetryの設定を加えていくわけですが、そのまえに、OpenTelemetry Collectorをセットアップしていきましょう。
Installing OpenTelemetry Collector
OpenTelemetry Collectorは、ローカルホストなどでテレメトリデータを受け取りつつ、任意の送り先に送るサービスで、アダプターのような役割をします。OpenTelemetryの各言語エージェントは、デフォルトの動作として、テレメトリーデータを localhost:4317 に送るような動作になっています。OpenTelemetry Collectorはそのポートでデータを受け取りつつ、指定した送り先に送るという格好です。
https://github.com/signalfx/splunk-otel-collector/blob/main/docs/architecture.md
Splunk Observabilityを使う場合は、Data Management > + Add Integrationに進み、LinuxやKubernetesなどお好みの環境に応じてOpenTelemertry Collectorのセットアップをします。こんなスクリプトを実行すると、1-2分後にはサービスが動く状態になります。
curl -sSL https://dl.signalfx.com/splunk-otel-collector.sh > /tmp/splunk-otel-collector.sh \
&& sudo sh /tmp/splunk-otel-collector.sh --realm <YOUR_REALM> -- <YOUR_INGEST_TOKEN> --mode agent --without-fluentd --deployment-environment Next.js
OpenTelemetry Collectorは単にアダプターであるだけではなく、情報を追加したり、送りたくない情報を削除したり、テレメトリーデータに対して様々な加工ができるようになっています。Splunk Observabilityでは deployment.environment
属性が指定されていると色々便利なので、追加していきましょう。
/etc/otel/collector/agent_config.yaml
を開くと、様々な設定がデフォルトで有効になっています。その中から、 processor
> resource/add_environment
の箇所のコメントを外して、属性値に好みの値を指定します。ここでは Next.js
とでもしてみましょう。
# Optional: The following processor can be used to add a default "deployment.environment" attribute to the logs and
# traces when it's not populated by instrumentation libraries.
# If enabled, make sure to enable this processor in the pipeline below.
resource/add_environment:
attributes:
- action: insert
value: Next.js
key: deployment.environment
さらに、 services
> pipelines
> traces
> processors
で、 resource/add_environment
の記述を加えましょう(コメントを外すだけでOKです)。
pipelines:
traces:
receivers: [jaeger, otlp, smartagent/signalfx-forwarder, zipkin]
processors:
- memory_limiter
- batch
- resourcedetection
- resource/add_environment
ここまで編集がおわったら、サービスを再起動しましょう。
sudo service splunk-otel-collector restart
動作が怪しければ、sudo service splunk-otel-collector status
したり、 journalctl -u splunk-otel-collector
したりして、動作を確かめてみてください。
Optimizaing with OpenTelemetry
ではいよいよ、このドキュメントに沿って、OpenTelemetryを使えるようにしてみましょう。
まずは、otelモジュールをインストールします。
npm install @vercel/otel
@vercel/otel
サービス名を取ってきたりOTelモジュールを読み込ませているだけのシンプルなモジュールのようです。詳しくは https://github.com/vercel/otel を眺めてみてください。
インストールが終わったら、ディレクトリ直下に next.config.js
ファイルを作り、設定を足しましょう。Next.jsでのOpenTelemetry対応は現在experimentalな機能であり、明示的にフラグを立てる必要があるとドキュメントにあるので、従ってみます。
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
instrumentationHook: true,
},
}
module.exports = nextConfig
変更箇所は以上です。上述の通り、エクスポート先はデフォルトで localhost:4317 であり、OpenTelemetry Collectorがすでにそのポートで受け付けるようになっています。
ここまでが終わったら、再びアプリケーションを起動してみます。
npm run dev
トレースデータを見てみる
まずは、OpenTelemtry Collectorがスパンを受信して送信できているかを見てみましょう。OpenTelemetry Collector自身も、さまざまなテレメトリデータを出力して、状況把握ができるようになっています。
まずは、ブラウザで http://<YOUR_IP_ADDRESS>:3000 をなんどか開いてみます。そして、Dashboards > OpenTelemetry Collector ダッシュボードを開いて、今動かしているCollectorにしぼりつつ、最下部のSpanチャートを見てみましょう。アクセスしたタイミングでのトゲがあれば、おそらく動いていると言えるでしょう。
では実際にトレースデータを見てみます。 APMのUIを開いて、Environmentなどで絞り込みつつ、Next.jsサンプルアプリケーションの情報を探してみます。
UIをたどると、トレーススパンの状況や、エンドポイントごとのパフォーマンス、REDメトリクスなど、各種情報が集まっていることがわかります。
まとめ
いかがでしたか?
OpenTelemetryのエコシステムでは、計装をオブザーバビリティ製品ベンダーに頼ることなく、フレームワークやミドルウェアが積極的にサポートすることももちろん可能になります。そうすることで、フレームワークの事情に応じた独自のテレメトリーデータを出力しつつ、それを送ったり可視化したり分析したりする部分は既存のソリューションを組み合わせて使うことが簡単にできるようになります。
OpenTelemetryに対応したバックエンドは、JaegerなどのOSSソリューションだけではなく、Splunkを始めとした商用ソリューションなど、様々な選択があり、状況によって使っていきましょう!
Discussion