この記事は New Relic Advent CalendarC# Advent Calendarの3日目のエントリです。

分散トレーシング

最近では1つのサービスを複数のアプリケーションから構成するシステムも多くなり、エンドユーザーからの1つのリクエストが1つのアプリケーションで完結するのではなく、複数のアプリケーションで処理されるケースも増えてきました。そのようなアプリケーション群の依存関係を可視化したのがService Mapと呼ばれる機能であり、1つのリクエストがどのアプリケーションでどのように処理されたか”一筆書き”のようにトレースするのが分散トレーシングと呼ばれる機能です。今回はNew Relicの分散トレーシングの機能を、ASP.NET Coreの3つのアプリで試してみたいと思います。なお、New Relicの分散トレーシングはNew Relic APMがサポートしているプログラミング言語であれば異なる言語間でも利用できます。

今回作った3つのアプリのService Mapはこのような関係になっています。

  • WebPortal: Webページを持ったいわゆる普通のWebアプリ。ASP.NET Core Razorページ。
  • PromoService: HTTP Rest APIを持ったAPIアプリ。ASP.NET Core。

    gRPC Service: gRPCでのAPIエンドポイントを持ったアプリ。ASP.NET Core + gRPC。

  • WebPortalはHTTP REST APIでPromoServiceを呼び出します。さらにPromoServiceはgRPCでgRPC Serviceを呼び出します。先ほどのService Mapでこれらの呼び出し関係が可視化できていることがわかります。

この時ある一つのWebPortalへのHTTPリクエストがPromoService、gRPC Serviceを呼び出した分散トレーシングはNew Relicではこのように見えます。一つ一つの処理の区切りがSpanでそれぞれ開始時間と終了時間(および経過時間)の情報があります。Spanは木構造のように1つのルートSpanから子供が生えています。

New Relicの分散トレーシングのUIの説明についてはこちらに詳細があります。

https://docs.newrelic.co.jp/docs/understand-dependencies/distributed-tracing/get-started/how-new-relic-distributed-tracing-works

また、OpenTracingが定義している情報もありますので合わせてご参照ください。

https://opentracing.io/docs/overview/what-is-tracing/

分散トレーシングのセットアップ

New Relicで分散トレーシングを利用するにはAPM Proも契約が必要です。さらに各言語のAgentで分散トレーシングが利用できる新しめのバージョンを利用し、設定で有効にする必要があります。

https://docs.newrelic.co.jp/docs/understand-dependencies/distributed-tracing/enable-configure/enable-distributed-tracing

.NET Coreアプリの場合、8.6.45.0以上のバージョンで分散トレーシングは設定ファイルもしくは環境変数などで有効にします。

アプリ間で呼び出したアプリのSpanと呼び出されたアプリのSpanが関連付けられるには条件があり、それを満たさない場合は手動での設定が必要な場合もあります。リクエストヘッダーを利用することが多いため、単純なHTTP呼び出しであれば多くの場合自動的に関連づけられます。.NET Coreの場合、HttpClientを用いた呼び出しや、.NET Core 3で導入されたgRPCの呼び出しは標準で関連づけられます。つまり、分散トレーシングのセットアップが完了すればアプリ側は特段手を入れる必要はありません。

分散トレーシングをみてみる

それでは分散トレーシングを少し深くみていきましょう。動かしたコードの通信部分はgistにおいています。

https://gist.github.com/tanaka-takayoshi/e5d0d287e55b2b5ea2ccc83f689b4549

WebPortalからPromoServiceへのHTTP呼び出しは単純なHttpClientを使った呼び出しで、トレーシングのために余計なコードは必要ありません。なお、運用環境ではHttpClientFactoryを使って耐久性のある方法を考慮するのが良いでしょう。

該当箇所のトレーシングを見る際に「Display in-process spans for this service」のトグルスイッチをONにしましょう。

するとこのようにプロセス内のSpanが展開されます。ここで、「promoservice - Stream/GET」がHTTP呼び出し側のSpanで「Promo/Verify/{code}」が呼び出されたアプリ側でのSpanになります。色が変わることでアプリが変わったことを指しています。

特定のSpanを選択すると、Performance, Attributes,Detailsが表示されます。

次にPromoServiceからRPCServiceへのgRPCの呼び出しをみてみましょう。

 

該当するトレースはこう表示されています。先ほどと同じようにPromoServiceが紫色でRPCServiceが群青色で表h時されています。

3つのアプリの順番で呼び出している単純な例を説明してきました。さて、最初の画面の右上に「See Logs」というリンクがあります。これは12/1のエントリでも紹介しているLogs in Contextの機能で、このトレーシングに関するログを表示できます。

今回このアプリはkubernetes上で全て動いていますが、その場合、アプリからは標準出力に出力すると、あとはkubernetes用のLog転送プラグインを設定するだけでこのプレビュー機能が利用できます。

まとめ

このようにNew Relicでの.NET Coreアプリの分散トレーシングはエージェントのインストールと分散トレーシングの有効化を行うだけで設定できました。.NET Core 3でサポートされたgRPC呼び出しもサポートしています。さらに、今回は触れませんでしたが、AWS Lambdaのコードを呼び出した場合に、Lamdba側のトレーシングも分散トレーシングに含めることができます。ぜひ一度ご利用いただき、使い勝手をフィードバックいただけばと思います。

 

New Relic の全機能はこちらから無料アカウントでお試しいただけます。

無料トライアル