Class TraceContextResponseProcessor
- All Implemented Interfaces:
ResponseProcessor
traceparent and, when present,
tracestate) so a client calling this server can read the resulting trace identifiers back
off the response.
How it works
A TracerHook bridge (e.g. the OpenTelemetry bridge in juneau-rest-server-tracing-otel)
renders the W3C traceparent / tracestate values from the server-started span
context at span-start time — the only point where
that context is reliably active — and stashes them as the request attributes
ATTR_TRACEPARENT / ATTR_TRACESTATE. This processor runs later, during response
rendering (after the span scope has already closed), reads those stashed strings, and writes them
as response headers.
This capture-at-span-start / write-at-response-time split is deliberate: the framework opens and
closes the tracing scope around the @RestOp handler in
RestOpInvoker.invokeOp(RestOpSession), which completes before response processors
run, so Span.current() is no longer valid here. Keeping the rendered values on the request
also keeps this processor free of any OpenTelemetry (or other tracer) dependency — it works
with any TracerHook bridge that populates the two attributes.
Off-by-default behavior
The first action in process(RestOpSession) is a single request-attribute read. When no
non-no-op TracerHook ran for the request, no ATTR_TRACEPARENT attribute is present
and the processor returns ResponseProcessor.NEXT immediately with no allocations — matching the
off-by-default, zero-cost contract of the observability hooks. Registration of this processor is
itself gated on RestContext.responseTraceparent (default true); setting it to
false keeps the processor out of the chain entirely.
Already-committed responses
If the response has already been committed (for example a streaming / SSE handler that flushed its
headers before returning), the headers can no longer be set. In that case the processor logs a
FINE message and skips the write — it never throws.
See Also:
- Since:
- 10.0.0
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringRequest-attribute key under which aTracerHookbridge stashes the rendered, non-empty W3Cbaggagevalue.static final StringRequest-attribute key under whichRestOpInvokerstashes the activeScopefor the duration of one@RestOphandler invocation.static final StringRequest-attribute key under which aTracerHookbridge stashes the rendered W3Ctraceparentvalue (e.g.static final StringRequest-attribute key under which aTracerHookbridge stashes the rendered W3Ctracestatevalue (a comma-separatedkey=valuelist).Fields inherited from interface org.apache.juneau.rest.server.processor.ResponseProcessor
FINISHED, NEXT, RESTART -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionintprocess(RestOpSession opSession) Process this response if possible.
-
Field Details
-
ATTR_TRACEPARENT
Request-attribute key under which aTracerHookbridge stashes the rendered W3Ctraceparentvalue (e.g.00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01) for this processor to emit as a response header.- See Also:
-
ATTR_TRACESTATE
Request-attribute key under which aTracerHookbridge stashes the rendered W3Ctracestatevalue (a comma-separatedkey=valuelist). Only set when the active trace state is non-empty.- See Also:
-
ATTR_BAGGAGE
Request-attribute key under which aTracerHookbridge stashes the rendered, non-empty W3Cbaggagevalue.Unlike
ATTR_TRACEPARENT/ATTR_TRACESTATE, this processor does not read this attribute and never emits abaggageresponse header from it —baggageis stashed purely so a dated MCP adapter can echo it into a successful result's_meta(added in a later task). Ordinary HTTP response-header behavior fortraceparent/tracestateis unaffected by this constant's existence.- Since:
- 10.0.0
- See Also:
-
ATTR_SCOPE
Request-attribute key under whichRestOpInvokerstashes the activeScopefor the duration of one@RestOphandler invocation.Populated only on the active-tracer path — see the no-tracer fast-path contract documented on
TracerHook— and cleared once that invocation's synchronous or deferred observability lifecycle closes the scope. A dated MCP adapter running inside the handler already resolves this sameRestRequestthrough its own request-scopedBeanStoreentry; reading this attribute off that request lets it callScope.recordRpcError(int, String)before returning a JSON-RPC error response — a JSON-RPC error is dispatched over HTTP200, so it never otherwise reachesScope.setStatusCode(int)with anything but the adapter's uniform success status.- Since:
- 10.0.0
- See Also:
-
-
Constructor Details
-
TraceContextResponseProcessor
public TraceContextResponseProcessor()
-
-
Method Details
-
process
Description copied from interface:ResponseProcessorProcess this response if possible.- Specified by:
processin interfaceResponseProcessor- Parameters:
opSession- The HTTP call.- Returns:
- One of the following codes:
0 - The processor could not handle the request.1 - The processor was able to fully handle the request.2 - The processor was able to partially handle the request by replacing the output. The response processors should start over.
- Throws:
IOException- If low-level exception occurred on output stream.
Results in aHttpServletResponse.SC_INTERNAL_SERVER_ERRORerror.BasicHttpException- If some other exception occurred.
Can be used to provide an appropriate HTTP response code and message.
-