JavaでgRPCサーバーを立ててX-RayのトレースIDを取ろうとしたらハマった話です。
何が起きたのか?
某所でgRPCの検証をしていてX-Rayでトレースした時に、 AWS公式の"incoming request"のやり方でAWSXRayServletFilterを使用してもトレースを取得できませんでした。
検証した環境は以下の通りです。
原因は何か?
ドキュメントを斜め読みしてAWSXRayServletFilterクラスを使えば良いのだなと思っていたのですが、 よくよく上記の公式のやり方を読んでみると HTTPリクエストをトレースするには(Java EEのServlet APIの)Filterクラスを使うよと記載があります。
Use a Filter to instrument incoming HTTP requests. When you add the X-Ray servlet filter to your application, the X-Ray SDK for Java creates a segment for each sampled request.
さらにgrpc-javaを調べてみると、サーバーサイド実装はNettyをベースにしています。
NettyはアプリケーションサーバーをJava EEのServlet APIを使わず実装しているため、 タイトル通りX-Ray SDKのAWSXRayServletFilterが使えないということが分かりました。
同じ問題はNetty実装のSpring WebFluxでもあるそうです。
どうやって解決するか?
調べた限り、トレースIDをリクエストヘッダーから取得してコンテキストに詰める独自のServerInterceptorを実装する方法しかないようです。
幸いにも下記のリンクに参考の実装がありました。 この通り実装したところ、トレースを取得してマネジメントコンソールのX-Ray Service Mapにトレースが表示されるようになりました。
ハマったら最初に公式ドキュメントを落ち着いて読むべし。
以上。