Spring (Boot) with micrometer(-tracing) nicely propagate traceparent
from an HTTP request header into traceId/spanId withing the app (MDC, etc). However, no traceparent header is included in the Spring (Boot) controller response (corresponding to that request).
While that feature could be implemented with the Filter
, after a discussion with @jonatan-ivanov on Micrometer's Slack, I propose to have this available as a feature in (Reactive) Spring Web.
For backward compatibility, it could be initially available as opt-in, however, for a request with traceparent
, it is natural to have it included also in a corresponding response.
Comment From: jonatan-ivanov
I think this feature can be useful for clients who want to report issues against application they call, e.g.: an error or a slow response. This information for example can be added to error messages on UIs so that it can be much simpler to troubleshoot issues when users report it.
Also, it's important to call out that headers in the response is not necessary for context propagation, I think this feature is more similar to log correlation (traceId/spanId in log entries). Because of this, it is not a must to send back the traceparent
header, also users can use other propagation formats, not necessarily W3C (traceparent
) but sending back the tracing information in some format (or letting the user define that format) would be really nice.
Comment From: jonatan-ivanov
A related feature to this could be adding the tracing information to ProblemDetails
/error response (as the article suggests above).
Comment From: arung0wda
Is this feature available? How do I use it?
Comment From: jonatan-ivanov
Right now it is not, you need to implement it, there is an example in the PR description.
Here's another one, this is what I'm doing to add the trace info to the ProblemDetails
(only for error response): CommonExceptionHandler.
Comment From: bclozel
Given the nature of the Observation
API, we can't get the current traceId when the observation scope is started. Getting the current span requires the Tracer
instance. Exposing the Tracer
type on the ServerHttpObservationFilter
class would make micrometer-tracing
a required dependency and would cause many issues in Spring Framework and Spring Boot.
We could also consider a separate Servlet Filter for this, but the filter implementation would be very straightforward and the filter would need to be configured after the observation filter.
I have decided to introduce a protected method onScopeOpened
that can be used by types extending ServerHttpObservationFilter
. A typical implementation would do the following:
public class TraceIdObservationFilter extends ServerHttpObservationFilter {
private final Tracer tracer;
public TraceIdObservationFilter(Tracer tracer, ObservationRegistry observationRegistry) {
super(observationRegistry);
this.tracer = tracer;
}
@Override
protected void onScopeOpened(Observation.Scope scope, HttpServletRequest request,
HttpServletResponse response) {
Span currentSpan = this.tracer.currentSpan();
if (currentSpan != null) {
response.setHeader("X-Trace-Id", currentSpan.context().traceId());
}
}
}
I'll create a follow-up issue in Spring Boot to auto-configure this use case.
Comment From: bclozel
See https://github.com/spring-projects/spring-boot/issues/40857