モチベーション
OpenTelemetry でトレースを取得するにあたって、設定は環境変数で行い、基本的には自動計装にまかせつつ、自動計装で取れない(外部通信を行っていない)ところにだけ手動でspanを追加したかった。
方法
Java OpenTelemetry agentによる自動計装 でjavaagent、OTELの設定をする
export JAVA_TOOL_OPTIONS="-javaagent:path/to/opentelemetry-javaagent.jar"
export OTEL_SERVICE_NAME="your-service-name"
アプリケーションコード内のトレースを取得したい箇所で
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 現在のスコープのSpanを取得、attributeをセットすることもできる
Span.current().setAttribute("url.path", req.getRequestURI());
// ... トレースを取得したい区間
// サブメソッドにspanオブジェクトを渡す必要は特にない
childMethod();
}
private void childMethod() {
// 自動計装によって初期化されているグローバルオブジェクトからTracerを取得
Tracer tracer = GlobalOpenTelemetry.getTracer(SERVICE_NAME);
// ネストしたspanを作成
Span parentSpan = tracer.spanBuilder("childMethod").startSpan();
try (Scope parentScope = parentSpan.makeCurrent()) {
Span span = tracer.spanBuilder("sub1").startSpan();
// ... トレースを取得したい区間1
span.end();
span = tracer.spanBuilder("sub2").startSpan();
// ... トレースを取得したい区間2
span.end();
} finally {
parentSpan.end();
}
}
APIハンドラーでは、自動計装によりSpanが作成されているのでそれを使う。
よくわかっていなかったが、 Scope scope = span.makeCurrent()
をすると scope.close()
するまでは Context.current()
や Span.current()
で現在のcontextを取得できるので、別メソッドを呼び出すときにSpanオブジェクトを渡す必要はない。