NGINX 1.25.3以降には、Webサーバーに直接ディストリビューティッド(分散)トレーシングのサポートを追加するネイティブのOpenTelemetryモジュールであるngx_otel_moduleが含まれています。
ngx_otel_moduleをインストゥルメントされたアプリケーションと組み合わせると、New Relicはトレースをエンドツーエンドで接続し、サービスとNGINXエンティティの間にサービス関係を作成します。これらの関係はサービスマップに表示され、Webサーバーまたはリバースプロキシをトラフィックがどのように流れるかを可視化します。
使い方
一般的な設定では、トラフィックは次のように流れます:
Instrumented app (client) → NGINX (with ngx_otel_module) → Instrumented app (backend)
- クライアントアプリケーションは、W3C
traceparentヘッダーを含むリクエストを送信します。 - NGINXの
ngx_otel_moduleはトレースコンテキストを抽出し、リクエストのスパンを作成して、アップストリームのバックエンドにプロキシされるリクエストに更新されたトレースコンテキストを挿入します。 - バックエンドアプリケーションは、伝播されたトレースコンテキストとともにリクエストを受信し、トレースを継続します。
- すべてのスパン(クライアント、NGINX、およびバックエンドからのもの)はOpenTelemetry Collectorにエクスポートされ、そこでNGINXスパンにNGINXアイデンティティが付与されてNew Relicに転送されます。
New Relicは、これらの接続されたスパンを使用してCALLS関係を作成します:
- クライアントサービス CALLS NGINXエンティティ
- NGINXエンティティ CALLS バックエンドサービス
コレクターはNGINXメトリクスが使用するものと同じnginx.deployment.nameおよびnginx.server.endpointアイデンティティをスタンプするため、NGINXスパンはNGINXメトリクスと同じNGINXSERVERエンティティに解決されます。これらの関係は、サービスマップおよびマップエクスペリエンスで確認できます。
互換性
ngx_otel_module 以下を含む、W3Cトレースコンテキスト伝搬をサポートするすべてのアプリケーションに対応しています:
- OpenTelemetry SDKでインストゥルメントされたアプリケーション(任意の言語)
- OpenTelemetryの自動インストゥルメンテーション(Java、.NET、Python、Node.js、Go)
- New Relic APMエージェント(Go、Java、.NET、Node.js、Python、Ruby、PHP)(ディストリビューティッド(分散)トレーシングが有効なもの)
計装アプローチを混在させることができます。たとえば、OTel SDKクライアントはNGINXを介してNew Relic APMエージェントのバックエンドを呼び出すことができ、リレーションシップチェーンはNew Relicに正しく表示されます。
あなたが始める前に
以下のものを用意してください:
ディストリビューティッド(分散)トレーシングの設定
ヒント
以下のトレースパイプラインは、ディストリビューティッド(分散)トレーシングに参加するすべてのサービスで使用するのと同じ標準設定です。手動でのリレーションシップの設定ではありません。トレーシングがアクティブになると、New Relicは接続されたスパンを自動的に検出し、サービスのリレーションシップを作成します。
モジュールをロードし、nginx.confでトレーシングを有効にします。トップレベル(メインコンテキスト)にload_moduleディレクティブを追加し、httpコンテキスト内にOpenTelemetryディレクティブを追加します:
load_module modules/ngx_otel_module.so;
otel_service_name nginx-server;
otel_trace_context propagate;
proxy_pass http://backend_app;
この設定:
- OpenTelemetryモジュール(
load_module)をロードします。 localhost:4317(otel_exporter)でリッスンしているコレクターに、OTLP/gRPC経由でスパンをエクスポートします。- すべてのリクエスト(
otel_trace on)に対してスパンを作成します。高スループット環境でトラフィックのサブセットをトレースするには、onの代わりにotel_traceを変数(たとえば、split_clientsによって駆動されるもの)に設定します。 - トレースコンテキスト(
otel_trace_context propagate)を伝播します:これにより、受信したtraceparentヘッダーを抽出し(NGINXスパンを呼び出し元のサービスにリンクします)、更新されたコンテキストをアップストリームに送信されるrequestsに注入します(ダウンストリームサービスがトレースを継続できるようにします)。
特定の仮想ホストまたはルートのみをトレースしたい場合は、otel_trace onおよびotel_trace_contextディレクティブをserverまたはlocationブロックごとに設定することもできます。
ディレクティブの完全なリファレンスについては、ngx_otel_moduleのドキュメントを参照してください。
OTel Collectorを設定して、ngx_otel_moduleからトレースを受信し、NGINXスタブステータスエンドポイントからメトリクスを受信し、両方にNGINX IDを付与して、New Relicに転送します。
endpoint: <YOUR_STUB_STATUS_ENDPOINT>
- key: nginx.server.endpoint
value: "<YOUR_STUB_STATUS_ENDPOINT>"
- key: nginx.deployment.name
value: "<YOUR_DEPLOYMENT_NAME>"
- set(attributes["nginx.display.name"], Concat(["server", attributes["nginx.deployment.name"]], ":"))
- set(attributes["nginx.display.name"], Concat(["server", attributes["nginx.deployment.name"]], ":"))
endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}
api-key: ${env:NEW_RELIC_LICENSE_KEY}
processors: [resourcedetection, resource/nginx, transform/nginx_traces, batch]
processors: [resourcedetection, resource/nginx, transform/nginx_metrics, batch]
このコレクター設定には、2つのパイプラインが含まれています:
- トレースパイプライン:
ngx_otel_moduleおよびインストゥルメントされたアプリケーションから、gRPC(ポート4317)またはHTTP(ポート4318)経由でOTLPトレースデータを受信します。これは、New RelicにOTLPデータを送信するすべてのサービスで使用するのと同じ標準のトレースパイプラインです。 - メトリクスパイプライン:
nginxreceiverを使用して、NGINXスタブステータスエンドポイントからパフォーマンスメトリクス(接続、requests)を収集します。これらのメトリクスにより、New Relicにゴールデンメトリクスを備えたNGINXエンティティが作成されます。
両方のパイプラインは以下のプロセッサを共有します:
resourcedetection:OpenTelemetryエコシステム全体でホストを識別するために使用される標準リソース属性であるhost.idを追加します。resource/nginx:nginx.server.endpointとnginx.deployment.nameを追加します。これら2つの属性は、NGINXエンティティのアイデンティティを形成します。これらを両方のパイプラインに適用することで、NGINXのスパンとメトリクスは、重複したサービスエンティティではなく、同じNGINXSERVERエンティティに解決されるようになります。transform/nginx_*:わかりやすいエンティティ名としてnginx.display.nameを追加します。
重要
resource/nginxのnginx.server.endpointの値と、nginxレシーバーのendpointは同一である必要があります。nginx.deployment.nameとともに、これらはNGINXSERVERエンティティのアイデンティティを形成します。これは、NGINXインスタンスごとの1回限りの静的な値です。バックエンドおよびクライアントアプリケーションを追加または削除する際、コレクターの設定を変更する必要はありません。トレースコンテキスト伝搬を通じて、関係が自動的に形成されます。
必要な環境変数を設定し、コレクターを起動(または再起動)します:
$export NEW_RELIC_LICENSE_KEY="<YOUR_LICENSE_KEY>"
$export OTEL_EXPORTER_OTLP_ENDPOINT="<YOUR_NEWRELIC_OTLP_ENDPOINT>"
$sudo systemctl restart nrdot-collector
<YOUR_LICENSE_KEY>をに置き換えます。OTLPエンドポイントについては、New Relic OTLPエンドポイントの設定を参照してください。
設定をテストし、NGINXをリロードしてOpenTelemetryモジュールをロードします:
$sudo systemctl reload nginx
重要
load_moduleディレクティブは、指定されたパスにngx_otel_module.soファイルが存在し、NGINXのバージョンと一致していることを必要とします。unknown directive "otel_exporter"またはモジュールのロードエラーが表示される場合、モジュールがインストールされていないか、ロードされていません。NGINXのバージョンに対応するnginx-module-otelパッケージをインストールし、load_moduleのパスを確認してください。
NGINXとコレクターが実行されたら、インストゥルメントされたアプリケーションを通じてトラフィックを生成します。数分後、データがNew Relicに到着していることを確認します:
FROM Span SELECT count(*)
WHERE nginx.deployment.name = '<YOUR_DEPLOYMENT_NAME>'
FROM Metric SELECT count(*)
WHERE metricName LIKE 'nginx.%'
トレースデータが流れ始めると、New RelicはサービスとNGINXエンティティの間にCALLS関係を自動的に作成します。関係が表示されるまでに最大10分かかります。
関係を表示するには:
one.newrelic.com > All capabilities > All entitiesに移動します。
NGINXエンティティ、またはインストゥルメントされたサービスのいずれかを検索します。
エンティティを選択して、そのサマリーページを開きます。
Service mapをクリックして、エンティティ関係グラフを表示します。
クライアントサービスがNGINXに接続され、NGINXがバックエンドサービスに接続されていることが確認できます:
[Client app] → CALLS → [NGINX] → CALLS → [Backend app]
NRQLを使用して関連付けをクエリすることもできます:
FROM Relationship SELECT *
WHERE source.entityName = '<YOUR_NGINX_DISPLAY_NAME>'
OR target.entityName = '<YOUR_NGINX_DISPLAY_NAME>'
トラブルシューティング
- NGINXがエラーなしでリロードされたことを確認します:
sudo nginx -tおよび sudo journalctl -u nginx -n 50 --no-pager ngx_otel_moduleがロードされていることを確認します。unknown directive "otel_exporter"エラーは、モジュールがロードされていないことを意味します。load_moduleのパスを確認し、NGINXのバージョンに対応するnginx-module-otelがインストールされていることを確認してください。- OTel Collectorが実行されており、
otel_exporterのポートでリッスンしていることを確認します: sudo ss -tlnp | grep 4317 - コレクターのログでエラーを確認します:
sudo journalctl -u nrdot-collector -n 50 --no-pager otel_exporterエンドポイントがコレクターのgRPCリスナーアドレスと一致していることを確認します。
最初のスパンが到着してから関係が表示されるまで、最大10分お待ちください。
インストゥルメントされたアプリケーションがコレクターを通じてトレースを送信していることを確認します。関係が形成されるには、NGINXのスパンとアプリケーションのスパンの両方がNew Relicに到達する必要があります。
クライアントアプリケーションがW3Cのtraceparentヘッダーを伝搬していることを確認してください。トレースコンテキスト伝搬がない場合、NGINXのスパンは呼び出し元のサービスに接続されません。
resourcedetectionプロセッサとresource/nginxプロセッサの両方がコレクタートレースパイプラインに含まれていることを確認します。NGINXスパンがNGINXSERVERエンティティに解決されるには、nginx.server.endpointおよびnginx.deployment.name属性が必要です。
otel_trace_context propagateが設定されていることを確認してください(extractまたはinject単独ではなく)。NGINXを経由するエンドツーエンドのコンテキストフローには、propagateが必要です。
NGINXとアプリケーションの両方のスパンがトレースIDを共有していることを確認するクエリ:
FROM Span SELECT uniques(service.name)
SELECT uniques(trace.id) FROM Span
WHERE nginx.deployment.name = '<YOUR_DEPLOYMENT_NAME>'
SINCE 10 minutes ago LIMIT 5
アプリケーションのサービス名と並んで、NGINXサービスが表示されるはずです。
resource/nginxプロセッサが(メトリクスパイプラインだけでなく)トレースパイプラインで実行されていることを確認してください。これがないと、NGINXスパンにnginx.deployment.name/nginx.server.endpointが欠落し、NGINXSERVERエンティティに解決されるのではなく、汎用サービスとして合成されます。nginxレシーバーとresource/nginxプロセッサでnginx.server.endpointの値が完全に同一であること、およびnginx.deployment.nameがNGINXメトリクスで使用される値と一致していることを確認します。エンティティのIDは、これら2つの値の組み合わせです。一致しない場合、異なるエンティティが生成されます。- メトリクスパイプラインも実行します。NGINXSERVERエンティティのゴールデンメトリクスは
nginxreceiverから取得されます;これがない場合、NGINXはトレース経由で引き続き表示されますが、メトリクスは表示されません。
- すべてのサービスのスパンデータが同じアカウントに届くように、各インストゥルメントされたアプリケーションは、同じOTel Collectorを経由して(または直接New Relicに)トレースを送信する必要があります。
- New Relic APMエージェントを使用しているアプリケーションの場合は、ディストリビューティッド(分散)トレーシングが有効になっており、エージェントが接続されていることを確認してください。
- OTel SDKアプリケーションの場合は、OTLPエクスポーターがコレクターに送信するように構成されていることを確認してください。
- さらに時間をおいてください。トラフィック量が少ないサービスのリレーションシップは、表示されるまでに時間がかかる場合があります。
次のステップ