wy471x opened a new pull request, #7655:
URL: https://github.com/apache/shenyu/pull/7655

   ### Summary
   
   Records what the gateway knows about a traced request, so that a trace 
carries the routing decision and the failure of the request instead of a bare 
span. This is the second task of #7566.
   
   Make sure that:
   
   - [X] You have read the [contribution 
guidelines](https://shenyu.apache.org/community/contributor-guide).
   - [X] You submit test cases (unit or integration tests) that back your 
changes.
   - [X] Your local test passed `./mvnw clean install 
-Dmaven.javadoc.skip=true`.
         Run here for the touched modules and their dependencies: `mvn -pl 
shenyu-plugin/shenyu-plugin-tracing,shenyu-plugin/shenyu-plugin-api,shenyu-web 
-am install` with checkstyle, RAT and tests enabled (BUILD SUCCESS). The full 
repository build was not run locally, CI covers it.
   
   ### Changes:
   
   1. `SpanAttributesBuilder` (new, 
`shenyu-plugin/shenyu-plugin-tracing/.../SpanAttributesBuilder.java:63,79,107`) 
— builds the span name and records the request and outcome attributes. Only 
bounded values are recorded: the route comes from the metadata of the matched 
api, the context path from the exchange once the chain has run, and the status 
code from the response or from the exception the gateway answered the request 
with. The request path and the query string are left out, and the status 
description of a failure is limited to its type; the exception event keeps the 
message and the stack trace, as the OpenTelemetry convention defines.
   2. `TracingPlugin` (`.../TracingPlugin.java:78,103`) — keeps the span 
lifecycle: continues the inbound context or starts a new trace, starts the 
`SERVER` span per subscription, stores the context, exposes the trace id and 
ends the span once with the terminal signal. The recording logic moved to the 
builder, which leaves the plugin with a single responsibility.
   3. `ShenyuWebHandler.handle` and `after` 
(`shenyu-web/.../ShenyuWebHandler.java:114,129,138`) — the chain timing now 
runs with the terminal signal of the request instead of while the chain is 
assembled. The reported cost is the duration of the request and the gateway 
span already exists, so its trace id can be read; previously the timing was 
logged before the subscription, which is early for both. 
`Constants.CHAIN_START_TIME` is only read and written by this handler.
   4. `TraceIdUtils` (new, 
`shenyu-plugin/shenyu-plugin-api/.../utils/TraceIdUtils.java:41`) and 
`ShenyuPlugin.after` (`.../ShenyuPlugin.java:150,153`) — the plugin timing log 
prints the real span trace id instead of the WebFlux log prefix, and falls back 
to the log prefix while no span is active, for example when tracing is disabled.
   5. `TracingConstants` (`.../TracingConstants.java:68,74`) — the attributes 
which have a semantic convention key are named after it (`http.request.method`, 
`http.route`, `http.response.status_code`), and the gateway specific ones use a 
`shenyu.` prefix. The upstream host is recorded as `shenyu.upstream.host`, 
because the server of a gateway span is the gateway itself, not the upstream.
   6. Span naming — the name is `{method} {route}` as the http conventions ask 
for, where the route is the path the client registered, so the name does not 
grow with the request path. A request which did not match a registered api is 
named by its method only.
   7. Outcome handling — a 5xx response is an error span while a 4xx response 
is not, as the http conventions ask for. A failure records the exception and 
reports the timeout outcome, which covers the `408` a retried request is 
answered with, the `504` which wraps a timeout of an upstream call, and a 
timeout which is only visible in the cause chain of a status exception. A 
failure whose status is a client error keeps the span status unset, like the 
same status answered by a response, while a timeout stays an error span whether 
it is reported by a status or by an exception, because the gateway or the 
upstream ran out of time. The error type is recorded exactly when the request 
is an error span, so that it can be used to count failures without counting 
client errors, and a timeout answered by a response is reported like one which 
surfaced as an exception. A request which the client cancelled is marked with 
an attribute. The outcome is written in one place and the span is ended exactl
 y once, even when recording the outcome fails.
   
   ### Test Cases:
   
   - `TracingSpanLifecycleTest` (14 tests) — success, client error, client 
error answered by an exception, client error only visible in the cause chain, 
server error, thrown exception, timeout, the timeout exception of a protocol 
plugin, the timeout wrapped into a `504`, the timeout only visible in the cause 
chain, the timeout answered by a `504` response, the timeout answered by a 
`408` response, the retried request answered with `408`, and cancellation. Each 
case asserts that the exporter sees exactly one span for the request, plus the 
status and the attributes of that path.
   - `TracingSpanAttributesTest` (8 tests) — the request attributes, the guard 
which keeps the request path out of the route method attribute of the http like 
protocols, the route and the span name taken from the registered api, the 
method only name without a registered api, the context path read once the chain 
has run with the ShenyuContext fallback, the upstream host and the selector id 
once the request is routed with a closed set assertion over every attribute the 
gateway records, and a closed set which may not contain the request path or the 
query string.
   - `TracingPluginTest` (18 tests, extended) and `TraceContextExtractorTest` 
(18 tests) — the inbound span behaviour and the W3C header handling of the 
first task, with the span name assertion updated to the route based name.
   - `TraceIdUtilsTest` (2 tests) — the trace id of a traced request and the 
log prefix fallback.
   - `ShenyuWebHandlerTest` (9 tests, 3 new) — the chain timing is read with 
the terminal signal rather than while the chain is assembled, a request which 
is subscribed again is not reported again, and a logback appender proves that 
both the chain timing log and the plugin timing log carry the span trace id 
which a plugin exposed while the request was subscribed.
   
   ### Verification
   
   - `mvn -pl 
shenyu-plugin/shenyu-plugin-tracing,shenyu-plugin/shenyu-plugin-api,shenyu-web 
-am install` → BUILD SUCCESS, module tests: tracing 58, plugin-api 3, 
shenyu-web 96, no failures.
   - checkstyle 0 violations and `apache-rat:check` Unapproved 0 for the three 
modules.
   - `mvn -pl shenyu-bootstrap -am install -DskipTests` → BUILD SUCCESS, which 
checks that the tracing plugin and the core handler still integrate with the 
gateway build.
   - Not covered by this change: outbound context injection (#7616), OTLP 
export, sampling and Java agent coexistence (#7612), the integration test and 
documentation (#7617).
   
   Fixes #7613
   Part of #7566
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to