HAProxyを、サービス間の単なるブラックボックスとしてではなく、ディストリビューティッド(分散)トレーシングにおける接続されたホップとして確認できます。HAProxy 3.4以降には、ロードバランサーがディストリビューティッド(分散)トレーシングに直接参加できるようにするOpenTelemetryフィルターが含まれているため、New RelicはサービスマップでアプリケーションとHAProxyエンティティ間のサービス関係を自動的にマッピングできます — 手動での設定は必要ありません。
このページでは、トレースデータがNew Relicに到達するように、HAProxy OTelフィルター、そのエクスポーター、およびOTel Collectorを設定する方法について説明します。トレーシングが内部でどのように機能するか — HAProxyを介したW3Cトレースコンテキストの抽出と伝播 — については、以下の仕組みをご覧ください。
使い方
一般的な設定では、トラフィックは次のように流れます:
Instrumented app (frontend) → HAProxy (with OTel filter) → Instrumented app (backend)
- フロントエンドアプリケーションは、W3C
traceparentヘッダーを含むリクエストを送信します。 - HAProxyのOTelフィルターはトレースコンテキストを抽出し、リクエストのライフサイクルをカバーするスパンを作成して、バックエンドに転送されるリクエストに更新されたトレースコンテキストを注入します。
- バックエンドアプリケーションは、伝播されたトレースコンテキストとともにリクエストを受信し、トレースを継続します。
- フロントエンド、HAProxy、およびバックエンドは、スパンをOpenTelemetry Collectorにエクスポートし、OpenTelemetry CollectorはそれらをNew Relicに転送します。
New Relicは、これらの接続されたスパンを使用してCALLS関係を作成します:
- フロントエンドサービスがHAProxyエンティティを呼び出します
- HAProxyエンティティがバックエンドサービスを呼び出します
これらの関係は、サービスマップおよびマップエクスペリエンスで確認できます。
あなたが始める前に
HAProxy OTelフィルターは、次のようなW3Cトレースコンテキスト伝搬をサポートする任意のアプリケーションで機能します:
- OpenTelemetry SDKでインストゥルメントされたアプリケーション(任意の言語)
- OpenTelemetryの自動インストゥルメンテーション(Java、.NET、Python、Node.js)
- New Relic APMエージェント(Go、Java、.NET、Node.js、Python、Ruby、PHP)(ディストリビューティッド(分散)トレーシングが有効なもの)
計装アプローチを混在させることができます。たとえば、OTel SDKフロントエンドがHAProxyを介してNew Relic APMエージェントのバックエンドを呼び出すことができ、関係チェーンはNew Relicに正しく表示されます。
以下も用意されていることを確認してください:
ディストリビューティッド(分散)トレーシングの設定
ヒント
以下のトレースパイプラインは、ディストリビューティッド(分散)トレーシングに参加する任意のサービスで使用するのと同じ標準設定です — 手動の関連付け設定ではありません。トレースがアクティブになると、New Relicは接続されたスパンを自動的に検出し、サービスの関連付けを作成します。関連付けを表示するために追加の設定は必要ありません。
haproxy.cfgのfrontendセクションにfilter opentelemetryディレクティブを追加します。これにより、HAProxyに受信したrequestsへOTelフィルターを適用するように指示します:
default_backend app_servers
filter opentelemetry id otel config /etc/haproxy/otel.cfg
configパラメーターは、スパン、コンテキスト伝搬、およびエクスポーター設定を定義する別のOTelフィルター設定ファイルを指します。
statsフロントエンドはHAProxy statsエンドポイントを有効にし、OTel Collectorのhaproxyreceiverはこれを使用してパフォーマンスメトリクスを収集します。必要に応じて、バインドアドレスとポートを調整します。
OTelフィルター設定ファイルを作成します(たとえば、/etc/haproxy/otel.cfg):
otel-instrumentation otel-inst
config /etc/haproxy/otel.yml default
scopes client_session_start
scopes frontend_http_request
scopes backend_http_request
scopes client_session_end
scopes server_session_start
scopes server_session_end
otel-scope client_session_start
extract "-ctx" use-headers
span "HAProxy session" parent "-ctx" root
otel-event on-client-session-start
otel-scope frontend_http_request
span "Frontend HTTP request" parent "HAProxy session" kind server
attribute "http.method" method
attribute "http.target" path
otel-event on-frontend-http-request
otel-scope backend_http_request
span "Backend HTTP request" parent "Frontend HTTP request" kind client
finish "Frontend HTTP request"
inject "-ctx" use-headers
otel-event on-backend-http-request
otel-scope client_session_end
finish "Backend HTTP request"
otel-event on-client-session-end
otel-scope server_session_start
span "Server session" parent "HAProxy session"
otel-event on-server-session-start
span "HTTP response" parent "Server session"
attribute "http.status_code" status
otel-event on-http-response
otel-scope server_session_end
otel-event on-server-session-end
この設定は以下のことを行います:
- 受信したW3C
traceparentヘッダー(extract "-ctx" use-headers)を抽出し、HAProxyスパンを呼び出し元サービスのトレースにリンクします。 - セッション開始、フロントエンドリクエスト処理、バックエンドリクエスト転送、レスポンス処理、セッション終了など、リクエストのライフサイクル全体のスパンを作成します。
- バックエンド(
inject "-ctx" use-headers)に送信されるrequestsに更新されたトレースコンテキストを挿入し、ダウンストリームサービスがトレースを継続できるようにします。 - requests(
rate-limit 100.0)の100%をトレースします。高スループット環境でトレース量を減らすには、この値を調整します。
重要
haproxy.cfgのfilter opentelemetryディレクティブのidの値は、otel.cfgのセクション名(たとえば、[otel])と一致する必要があります。
OTelフィルター設定の完全なリファレンスについては、『HAProxy OTelトレースのドキュメント』を参照してください。
フィルターエクスポーターの設定ファイルを作成します(たとえば、/etc/haproxy/otel.yml)。これにより、HAProxy OTelフィルターにトレースデータの送信先を指示します:
endpoint: "http://localhost:4317/v1/traces"
- service.name: "YOUR_HAPROXY_SERVICE_NAME"
scope_name: "HAProxy OTel filter"
exporters: exporter_traces
processors: processor_batch
providers: provider_traces
YOUR_HAPROXY_SERVICE_NAMEを、このHAProxyインスタンスを識別する名前に変更します(例:haproxy-prod-lb)。
service.name は、ディストリビューティッド(分散)トレーシングに参加するすべてのサービスを識別する標準のOpenTelemetryリソース属性です — HAProxyだけではありません。OTelでインストゥルメントされたすべてのアプリケーションは(OTEL_SERVICE_NAMEを介して)これを設定し、すべてのNew Relic APMエージェントには同等のもの(app_name)があります。これがない場合でも、トレースは引き続き正しくフローして接続されますが、スパンはUIでunknown_serviceとして表示されるため、識別が困難になります。詳細については、OpenTelemetryリソースのベストプラクティスをご覧ください。
これはHAProxyインスタンスごとに1回限りの設定です。新しいバックエンドまたはフロントエンドアプリケーションを追加する場合、このファイルを変更する必要はありません — 関連付けはトレースコンテキスト伝搬を通じて自動的に形成されます。
エクスポーターは、gRPC経由でトレースをlocalhost:4317に送信します。そこではOTel Collectorがリッスンしています。コレクターが別のホストで実行されている場合は、endpointを調整してください。
HAProxy OTelフィルターからトレースを、HAProxy statsエンドポイントからメトリクスを受信し、それらをNew Relicに転送するようにOTel Collectorを設定します。
endpoint: "http://127.0.0.1:8404/stats"
value: "http://127.0.0.1:8404/stats"
endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}
api-key: ${env:NEW_RELIC_LICENSE_KEY}
processors: [resourcedetection, resource/haproxy, batch]
processors: [resourcedetection, resource/haproxy, batch]
このコレクター設定には、2つのパイプラインが含まれています:
- トレースパイプライン:HAProxy OTelフィルターおよびインストゥルメントされたアプリケーションから、gRPC(ポート4317)またはHTTP(ポート4318)経由でOTLPトレースデータを受信します。これは、New RelicにOTLPデータを送信するすべてのサービスで使用するのと同じ標準のトレースパイプラインです。
- メトリクスパイプライン:
haproxyreceiverを使用して、HAProxyのstatsエンドポイントからパフォーマンスメトリクス(1秒あたりのセッション数、リクエスト率、バックエンドのヘルス)を収集します。これらのメトリクスにより、New Relicにゴールデンメトリクスを持つHAProxyエンティティが作成されます。
両方のパイプラインは以下のプロセッサを共有します:
resourcedetection:OpenTelemetryエコシステム全体でホストを識別するために使用される標準のリソース属性であるhost.nameとhost.idを追加します。resource/haproxy:このHAProxyインスタンスを識別し、New Relicの同じHAProxyエンティティの下でメトリクスとトレースデータをリンクするhaproxy.addr属性を追加します。
http://127.0.0.1:8404/statsの値は、HAProxyの公式ドキュメントで使用されている従来のHAProxy統計アドレスであり、ステップ1のhaproxy.cfgと一致します。これは、HAProxyインスタンスごとの1回限りの静的な値です。バックエンドおよびフロントエンドのアプリケーションを追加または削除する場合、コレクターの設定を変更する必要はありません — 関係はトレースコンテキスト伝搬を通じて自動的に形成されます。統計エンドポイントが異なるアドレス、ポート、またはURIを使用している場合にのみ、haproxyレシーバーのendpointおよびresource/haproxyの値を調整してください — 両方は常に一致する必要があります。
必要な環境変数を設定し、コレクターを起動(または再起動)します:
$export NEW_RELIC_LICENSE_KEY="YOUR_LICENSE_KEY"
$export OTEL_EXPORTER_OTLP_ENDPOINT="YOUR_NEWRELIC_OTLP_ENDPOINT"
$sudo systemctl restart otelcol-contrib
YOUR_LICENSE_KEYをに置き換えます。OTLPエンドポイントについては、New Relic OTLPエンドポイントの設定を参照してください。
OTelフィルターの設定を読み込むには、HAProxyを再起動します:
$sudo systemctl restart haproxy
重要
HAProxyバイナリにはOTelフィルターが含まれている必要があります。unknown keyword 'filter'やunknown keyword 'opentelemetry'のようなエラーが表示される場合、HAProxyビルドにはフィルターが含まれていません。互換性のあるディストリビューションについては、HAProxy OTelインストレーションガイドを参照してください。
サービスの関連付けの表示
HAProxyとコレクターが稼働したら、インストゥルメントされたアプリケーションを通じてトラフィックを生成します。数分後、データがNew Relicに到着していることを確認します:
FROM Span SELECT count(*)
WHERE service.name = 'YOUR_HAPROXY_SERVICE_NAME'
FROM Metric SELECT count(*)
WHERE metricName LIKE 'haproxy.%'
トレースデータが流れ始めると、New RelicはサービスとHAProxyエンティティ間のCALLS関係を自動的に作成します。関係が表示されるまでに最大10分かかります。
関連付けを表示するには、次の手順に従います:
- one.newrelic.com > All capabilities > All entitiesに移動します。
- HAProxyエンティティまたはインストゥルメントされたサービスのいずれかを検索します。
- エンティティを選択して、そのサマリーページを開きます。
- Service mapをクリックして、エンティティ関係グラフを表示します。
フロントエンドサービスがHAProxyに接続され、HAProxyがバックエンドサービスに接続されていることが表示されるはずです:
[Frontend app] → CALLS → [HAProxy] → CALLS → [Backend app]
NRQLを使用して関連付けをクエリすることもできます:
FROM Relationship SELECT *
WHERE source.entityName = 'YOUR_HAPROXY_SERVICE_NAME'
OR target.entityName = 'YOUR_HAPROXY_SERVICE_NAME'
トラブルシューティング
以下の起動エラーを確認してください:
- フィルターサポートの欠落:
unknown keyword 'filter'またはunknown keyword 'opentelemetry'が表示される場合、HAProxyバイナリにOTelフィルターが含まれていません。HAProxy OTelインストレーションガイドを参照してください。 - 設定ファイルが見つからない:
unable to load OTel configurationが表示される場合、filter opentelemetryディレクティブのconfigパスが正しく、ファイルが存在することを確認してください。パスはHAProxyの作業ディレクトリからの相対パスです。 - 共有ライブラリのエラー:OTelフィルターには、OpenTelemetry C++ SDK共有ライブラリが必要です。それらがインストールされており、検出可能であることを確認してください(たとえば、
LD_LIBRARY_PATHまたはldconfig経由で)。
順番に次の確認を行ってください:
- HAProxyがエラーなしで起動したことを確認してください:
sudo journalctl -u haproxy -n 50 --no-pager - OTelフィルターがロードされていることを確認してください。HAProxyのログで、
filter、opentelemetry、またはotelが記載されているエラーを探してください。 - OTel Collectorが実行されており、
otel.ymlで指定されたポートでリッスンしていることを確認します: sudo ss -tlnp | grep 4317 - コレクターのログでエラーを確認します:
sudo journalctl -u otelcol-contrib -n 50 --no-pager otel.ymlエクスポーターのエンドポイントが、コレクターのgRPCリスナーアドレスと一致することを確認してください。
以下の考えられる原因を確認してください:
最初のスパンが到着してから関係が表示されるまで、最大10分お待ちください。
インストゥルメントされたアプリケーションがコレクターを通じてトレースを送信していることを確認してください。関係を形成するには、HAProxyスパンとアプリケーションスパンの両方がNew Relicに到達する必要があります。
フロントエンドアプリケーションがW3C traceparentヘッダーを伝搬していることを確認してください。トレースコンテキスト伝搬がない場合、HAProxyスパンは呼び出し元のサービスに接続されません。
resourcedetectionプロセッサとresource/haproxyプロセッサの両方がコレクターのトレースパイプラインに含まれていることを確認してください。HAProxyエンティティの識別には、host.idおよびhaproxy.addr属性が必要です。
メトリクスパイプラインがhaproxyレシーバーで実行されていることを確認してください。メトリクスパイプラインはHAProxyエンティティを作成します — これがない場合、HAProxyは専用のHAProxyエンティティではなく、一般的なサービスとして表示されます。
HAProxyスパンとアプリケーションスパンの両方がトレースIDを共有していることを確認するクエリ:
FROM Span SELECT uniques(service.name)
SELECT uniques(trace.id) FROM Span
WHERE service.name = 'YOUR_HAPROXY_SERVICE_NAME'
SINCE 10 minutes ago LIMIT 5
アプリケーションのサービス名と並んで、HAProxyのサービス名が表示されるはずです。
以下の考えられる原因を検討してください:
- すべてのサービスのスパンデータが同じアカウントに到達するように、インストゥルメントされた各アプリケーションからのトレースを同じOTel Collector経由で(または直接New Relicに)送信します。
- New Relic APMエージェントを使用しているアプリケーションの場合は、ディストリビューティッド(分散)トレーシングが有効になっており、エージェントが接続されていることを確認してください。
- OTel SDKアプリケーションの場合は、OTLPエクスポーターがコレクターに送信するように構成されていることを確認してください。
- トラフィック量が少ないサービスの関係は表示されるまでに時間がかかる場合があるため、しばらくお待ちください。
次のステップ