Skip to content

fix: resolve missing trace spans in embedded AdkWebServer#1183

Open
hemasekhar-p wants to merge 1 commit into
google:mainfrom
hemasekhar-p:adk-ui-trace-fix
Open

fix: resolve missing trace spans in embedded AdkWebServer#1183
hemasekhar-p wants to merge 1 commit into
google:mainfrom
hemasekhar-p:adk-ui-trace-fix

Conversation

@hemasekhar-p
Copy link
Copy Markdown
Contributor

Please ensure you have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

Problem:
When AdkWebServer is embedded as a child Spring Context, OpenTelemetry spans generated by the core Tracing utility is dropped, leaving the Dev UI's Trace tab completely empty. This occurs because the Dev UI correctly skips GlobalOpenTelemetry registration to avoid polluting the parent application's telemetry, but the core engine's Tracing utility is hardcoded to only pull from the global registry, resulting in a fallback No-Op tracer.

Solution:
Core: Added a thread-safe Tracing.setTracer() method in google-adk to allow external frameworks to inject a custom tracer.
Web: Updated OpenTelemetryConfig in google-adk-dev to automatically inject its isolated SDK tracer into the core engine upon bean creation.

Testing Plan

Manual End-to-End (E2E) Tests:

  1. Created a Spring Boot application EnterpriseAgentApplication configured as the parent context, launching AdkWebServer as a child context on port 8080.

  2. Disabled external OpenTelemetry exports in application.properties (management.otlp.tracing.export.enabled=false) to ensure strict isolation.

  3. Sent multiple prompts to the compiled agent.

  4. Opened the Trace tab in the left-hand navigation panel.

@hemasekhar-p
Copy link
Copy Markdown
Contributor Author

@krwc Please have a look into it.

Comment thread dev/src/main/java/com/google/adk/web/config/OpenTelemetryConfig.java Outdated
@damianmomotgoogle
Copy link
Copy Markdown
Contributor

I traced how same is achieved in Python ADK and Go ADK

  1. Go ADK Approach
    The Go implementation uses a Providers struct that acts as a configuration helper.
  • Mechanism: It provides a SetGlobalOtelProviders() method.
  • Behavior: This method calls the standard OTel otel.SetTracerProvider() and logglobal.SetLoggerProvider().
  • Philosophy: It doesn't store a tracer instance in a private variable within the library. Instead, it configures the global OpenTelemetry state, and the library then retrieves its tracer from that global state (using
    otel.GetTracerProvider().Tracer(...)).
  1. Python ADK Approach
    The Python implementation is even more integrated with the OpenTelemetry SDK.
  • Mechanism: It uses a maybe_set_otel_providers() function in telemetry/setup.py.
  • Behavior: This function calls trace.set_tracer_provider(). If a provider was already set globally by the user, the ADK respects it and avoids overriding.
  • Philosophy: Like Go, it does not provide a library-specific set_tracer method. It assumes that if you want to change the tracer, you should configure the global OpenTelemetry environment.
  1. Comparison with the Java PR (1183)
    Your proposed public static void setTracer(Tracer) in Java adds a library-specific static setter. While this is simple, it differs from the other languages in a few key ways:
  • Bypasses Global Registry: In Java, the standard way to configure tracing is GlobalOpenTelemetry.set(OpenTelemetry). Providing Tracing.setTracer(Tracer) creates a secondary path that only affects the ADK.
  • Potential Inconsistency: If a user sets a custom Tracer via your new method but also configures GlobalOpenTelemetry for the rest of their app, they might end up with fragmented traces or inconsistent configuration.
  • Inversion of Control: Python and Go lean into the "Global Registry" pattern. The library says, "I will use whatever is in the global registry," and provides a helper to put things there. Your Java proposal says, "I
    have my own slot for a tracer, please give it to me."

Recommendation
To align with the Python and Go ADK architectures and follow idiomatic OpenTelemetry Java patterns, you might consider:

  1. Rely on GlobalOpenTelemetry: The current implementation already defaults to GlobalOpenTelemetry.getTracer("gcp.vertex.agent"). Since this returns a lazy wrapper, users can simply call GlobalOpenTelemetry.set(...) at
    application startup, and the ADK will automatically pick up the custom configuration.

Would it work if we set GlobalOpenTelemetry.set(...) in ADK Web instead ?

@hemasekhar-p
Copy link
Copy Markdown
Contributor Author

@damianmomotgoogle, I have Refactored the code as per the review comments. could you please review?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web UI "Trace" tab is empty because Dev UI's OpenTelemetrySdk is never bridged into com.google.adk.telemetry.Tracing

3 participants