nginxのログデータを更に深堀り: New RelicのLogs in Contextでトレースとログを関連付ける方法

:::note info
最新のアップデートの詳細はこちら。　[New Relic アップデート一覧](https://newrelic.com/jp/blog/nerdlog/new-relic-update "New Relic アップデート一覧")
:::

# はじめに
　[こちらの記事](https://qiita.com/MarthaS/items/14da436b6bce5e7d7759)では、OpenTelemetry を使用して nginx のテレメトリデータを収集し、New Relic でそのデータを可視化する方法を紹介しました。

https://qiita.com/MarthaS/items/14da436b6bce5e7d7759

　ただ、New Relic の分散トレーシングをフル活用するためには、まだまだ設定が不足しています。この記事では、New Relic　の Logs in Context を使って nginx のログとトレース情報を関連付けてトランザクションごとのログを確認できるようにする方法を紹介します。Logs in Context については、こちらのブログを参考にしてください。

https://newrelic.com/jp/blog/how-to-relic/logs-in-context-for-all-new-relic-agents

![Logs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/8a8a7d6a-d143-caf9-2233-a5c95b0c239d.png)

# nginx のログをNew Relicに連携する
　今回は、nginx のログをfluent bit 経由で New Relic へ連携していきます。
　まず、Fluentd Forward Protocol を使って　OpenTelemetry Collector　がログを受信できるように設定を変更します。
```diff_yaml:otel-config.yml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
+ fluentforward:
+ endpoint: 0.0.0.0:8006
processors:
  batch:

exporters:
  otlp:
    endpoint: https://otlp.nr-data.net:4317
    headers:
      api-key: ${NEW_RELIC_LICENSE_KEY} # New Relicのライセンスキーを環境変数に設定

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp]
    logs:
-     receivers: [otlp]
+     receivers: [otlp, fluentforward]
      processors: [batch]
      exporters: [otlp]
```
次に nginx から OpenTelemetry Collector にログが出力されるようにDocker Composeの定義ファイルを変更します。
```diff:docker-compose.yml
  # nginx
  web:
      container_name: nginx_web
      platform: 'linux/amd64'
      build:
        context: .
        dockerfile: ./containers/nginx.dockerfile
      ports:
          - "8080:80"
      depends_on:
          - php
+     logging:
+       driver: "fluentd"
+       options:
+         # OpenTelemetry Collector のポート　８００６　を宛先に設定
+         fluentd-address: localhost:8006
+         # 起動時に接続を確立的無くても　container　は起動する設定
+         fluentd-async-connect: "true"
```
```diff:docker-compose.yml
  # OpenTelemetry Collector
  otel-collector:
    container_name: otel-collector
    platform: 'linux/amd64'
    image: otel/opentelemetry-collector-contrib:0.83.0
    restart: always
    command: ["--config=/etc/otel-config.yml", ""]
    volumes:
      - ./otel-config.yml:/etc/otel-config.yml
    environment:
        # 環境変数でNew Relicのライセンスキーを設定
        - NEW_RELIC_LICENSE_KEY
+   # fluentforward で受信するためのポートを公開
+   ports:
+       - "8006:8006"
```
　ここまでの設定で nginx のログを New Relic へ連携されます。それでは、New Relic Logs で連携されたログを確認してみましょう。

![logs-without-servicename.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/2a660768-00ac-4224-f740-55594c2139fb.png)
　New Relicにコンテナ名：nginx_webのログが連携されていることが確認できました。OpenTelemetry Collector経由でログを転送しているため、newrelic.source に ``api.logs.otlp`` が設定されています。
　ログの詳細を確認してみましょう。
![logs-detail-without-servicename.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/4dcd8e29-1d05-9dc9-e88a-f9840912fec5.png)
　JSON形式でログを転送しているため key-value 形式で表示されます。また、アプリケーションやインフラのエンティティとゴルが関連付けられていれば、画像の赤枠の位置にエンティティーへのリンクが表示されています。しかし、現状表示されていないため、ログとアプリケーション nginx-php-proxy が関連付ける必要があります。
　関連付けができていないため、下記の画像のように New Relic APM の Logs のメニューを開いてもデータが表示されません。
![apm-logs-without-servicename.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/23b2c231-e6d7-69c2-f49d-c243bdc94ecf.png)


# nginx のログをトレース情報と関連付けてNew Relicで表示する
　ログをアプリケーションと関連付けるには、ログの metadata に``service.name``を設定する必要があります。詳細は[こちらの公式ドキュメント](https://docs.newrelic.com/jp/docs/more-integrations/open-source-telemetry-integrations/opentelemetry/best-practices/opentelemetry-best-practices-logs/#log-correlation)を参考にしてください。

https://docs.newrelic.com/jp/docs/more-integrations/open-source-telemetry-integrations/opentelemetry/best-practices/opentelemetry-best-practices-logs/#log-correlation

　さらに、アプリケーションのトレース情報とログを関連付ける場合には、ログの metadata に ``trace.id``、 ``span.id``を設定する必要があります。詳細は[こちらの公式ドキュメント](https://docs.newrelic.com/jp/docs/more-integrations/open-source-telemetry-integrations/opentelemetry/view-your-data/opentelemetry-logs-page/)を参考にしてください。

https://docs.newrelic.com/jp/docs/more-integrations/open-source-telemetry-integrations/opentelemetry/view-your-data/opentelemetry-logs-page/

　この内容に合わせて nginx のログ出力設定を変更していきます。
```diff_conf:nginx.conf
    log_format json escape=json '{"time": "$time_iso8601",'
                                '"host": "$remote_addr",'
                                '"vhost": "$host",'
                                '"user": "$remote_user",'
                                '"status": "$status",'
                                '"protocol": "$server_protocol",'
                                '"method": "$request_method",'
                                '"path": "$request_uri",'
                                '"req": "$request",'
                                '"size": "$body_bytes_sent",'
                                '"reqtime": "$request_time",'
                                '"apptime": "$upstream_response_time",'
                                '"user_agent": "$http_user_agent",'
                                '"forwardedfor": "$http_x_forwarded_for",'
                                '"forwardedproto": "$http_x_forwarded_proto",'
-                               '"referrer": "$http_referer"}';
+                               '"referrer": "$http_referer",'
+                               '"service.name": "nginx-php-proxy",'
+                               '"trace.id": "$opentelemetry_trace_id",'
+                               '"span.id": "$opentelemetry_span_id"}';
```
　この変更で nginx のログを New RelicのUI上で nginx-php-proxy のエンティティとトレース情報に関連付けることができています。Dockerを再構築して結果を確認していきましょう。

まずは、nginx-php-proxy のエンティティとの関連付けを確認します。nginx-php-proxy の APM のメニューから Logs 開いて連携されているログを確認しましょう。
![apm-logs-with-servicename.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/f0cb1793-ea42-51d2-0fea-495da660b9d1.png)
　service.name がログのメタデータに含まれているため、ログが APM の画面上で確認できるようになっています。
　ログの詳細も確認してみましょう。下記のようにログの詳細画面で Service や Distributed Trace　の情報が確認できるようになっています。画面上の ``/index.php``のリンクから APM の Distributed Tracing　の画面へ遷移できます。このリンクから Distributed Tracing　の画面を開いてトレース情報に関連付けられたログを確認していきましょう。
![apm-logs-detail-with-servicename.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/e9efbed1-af09-ff56-a475-3cb0b59d4fbd.png)
　このように Distributed Tracing の画面が表示されます。次に Logs のタブからこのトレースに関連付けられたログを確認していきます。
![apm-dt-with-servicename.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/da5be8f5-10b7-4c32-9df5-ab2c3a0e7146.png)
　下記が Logs のタブで表示した画面です。今回は、nginx のログのみが表示されていますが、同一トレース内でアプリケーションのログが出力されている場合はこちらに表示されます。
![apm-dt-logs-with-servicename.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/0968f6f8-3aae-b71e-e9dc-ee9f4c1b4c94.png)

# 参考情報
　この記事では nginx の計装をメインで説明したため、バックエンドのアプリケーションは簡易なものでした。実際のアプリケーションでは、以下のような表示になります。
![スクリーンショット 2023-09-03 22.25.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/f26399c3-251d-5abc-9f77-3835fe56cddb.png)
![スクリーンショット 2023-09-03 22.25.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/824af227-4bbd-1209-6a75-3cfad1829d0f.png)
　
# まとめ
　この記事の中で、OpenTelemetry を使用して nginx のトレース情報とログを収集し、New Relic の Logs　in Context でそのデータを関連付けて可視化する方法を解説しました。
　これにより、nginx のログデータを効果的に収集し、New Relic での可視化を実現することができます。特に、分散トレーシングを有効にすることで、トランザクション単位のログを明確に把握することができるようになりました。nginx のログは、システムの問題の発見・対応に役立つ重要な作業です。OpenTelemetry と New Relic を組み合わせることで、これらの作業を効率的に行うことができます。
　試してみたいという方は、今回紹介した OpenTelemetry と New Relic の連携は、永久無償ライセンスでも利用できます。是非永久無償ライセンスを[こちら](https://newrelic.com/jp/sign-up-japan)から試して見てください。

https://newrelic.com/jp/sign-up-japan

:::note info
最新のアップデートの詳細はこちら。　[New Relic アップデート一覧](https://newrelic.com/jp/blog/nerdlog/new-relic-update "New Relic アップデート一覧")
:::