feat(tt): tag server spans with _dd.tt.extraction_sources from RC patterns#11376
Draft
labbati wants to merge 4 commits into
Draft
feat(tt): tag server spans with _dd.tt.extraction_sources from RC patterns#11376labbati wants to merge 4 commits into
labbati wants to merge 4 commits into
Conversation
Adds the TransactionTrackingPatterns util (hand-rolled glob matcher with a single volatile snapshot, zero allocations on the empty fast path), wires the new optional 'tt_extraction_patterns' field through the APM_TRACING remote-config DTO and DynamicConfig snapshot, exposes a Config static fallback (always empty for now) and adds the InstrumentationTags TT_EXTRACTION_SOURCES constant. No tagging behaviour yet \u2014 only the configuration plumbing and the compiled-pattern snapshot publication. tag: ai generated
Adds the HttpServerDecorator.forEachRequestHeaderName extension point (no-op default) and a guarded tagging block in onRequest. When the TransactionTrackingPatterns snapshot is non-empty the server span gets a single _dd.tt.extraction_sources tag whose value is a deterministic CSV of matching header / query-string parameter names, sorted within each source bucket (headers first, then qs) and lowercased. Fast path on the empty snapshot is a single volatile read + isEmpty() check, no allocation. A negative unit test asserts no tag is set when the pattern list is empty. tag: ai generated
Overrides forEachRequestHeaderName in the javax-servlet 2.2 and 3.0 decorators using HttpServletRequest.getHeaderNames(), so Spring WebMVC running on top of any javax-servlet container (Tomcat, Jetty, etc.) emits the _dd.tt.extraction_sources tag transparently. Adds a Spring WebMVC 5.3 integration test (MockMvc) covering mixed header/qs matches and asserting absence of the tag when the pattern list is empty. The InstrumentationSpecification MOCK_DSM_TRACE_CONFIG now implements the new TraceConfig.getTransactionTrackingExtractionPatterns() with an empty list so the test infrastructure still compiles. tag: ai generated
tag: ai generated tag: no release note
Contributor
|
❌ New Groovy Files Detected Please avoid introducing new
Instead, rewrite the new file(s) in Java / JUnit. See the How to Test With JUnit Guide for more details. If this PR needs an exception, add the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Tag inbound HTTP server spans with
_dd.tt.extraction_sourceslisting the names of request headers and query-string parameters that match a remote-config-driven pattern list. Intended as the agent-side groundwork for the "transaction tracking made easy" workflow on the DSM side.While the pattern list is empty (default), this feature is inert: a single volatile read +
isEmpty()check on the request hot path, no allocations, no tag.How
tt_extraction_patterns(List<String>) on the existingAPM_TRACINGdynamic-config product. Wired throughTracingConfigPoller.LibConfig→DynamicConfig→TraceConfig. No new RC product.internal-apiclassTransactionTrackingPatterns. Hand-rolled*-glob (nojava.util.regex): segment walker on*-split chunks, lowercased once at compile time, snapshot held in avolatile List<...>. Multiple*per pattern allowed; case-insensitive on the candidate name.HttpServerDecorator.onRequest(...)now calls a newforEachRequestHeaderName(REQUEST, Consumer<String>)extension point (default no-op) when the pattern snapshot is non-empty. Matching header names and matching query-string parameter names are collected and emitted as a CSV under_dd.tt.extraction_sources:header:<lowercased-name>/qs:<lowercased-name>, deduplicated per source bucket, sorted alphabetically within each bucket, headers first then qs (deterministic for log-based aggregation and test assertions).javax-servlet-3.0andjavax-servlet-2.2) overrideforEachRequestHeaderNameviaHttpServletRequest#getHeaderNames(), so Spring WebMVC (3.1 / 5.3 / 6.0) and other servlet-based stacks (Tomcat, Jetty, Undertow when used via servlet) get this transparently. Non-servlet stacks (Netty, Vert.x, WebFlux, …) fall back to the no-op default until per-decorator overrides are added — to be tracked separately.Pattern syntax is intentionally minimal:
*is the only metacharacter (zero-or-more chars). No?, no character classes.Why APM_TRACING
Per the design doc, this is the simplest route: zero new wiring on the agent side and zero new product binding on the backend side (the field is additive JSON). Migration to a dedicated
APM_TT_*product is a code-only change for the agent and a small overlap window on the backend, deferrable until customer demand for independent targeting materialises.Tests
TransactionTrackingPatternsTest(JUnit5,internal-api): literal /*-prefix /*-suffix /*-middle / multi-*/ case-insensitivity / no-match / empty.TracingConfigPollerTest(JUnit5,dd-trace-core): RC update with the field propagates and clears; absent field leaves config untouched.HttpServerDecoratorTtExtractionTest(Spock,agent-bootstrap): mock decorator subclass with canned header names + URL with query string asserts tag presence, exact CSV ordering, source-prefixing, and absence when patterns are empty (fast-path correctness).TtExtractionSpringBootTest(Spock,spring-webmvc-5.3): full Spring Boot test app, real request through Tomcat, asserts_dd.tt.extraction_sourceson the resulting server span and asserts absence when patterns are empty.Targeted Gradle commands (all green locally — see commits for the exact list):
Rollout / kill switch
No agent-side feature flag. The feature is inert until the backend pushes a non-empty
tt_extraction_patterns. Backend can target by org / service / env / canary; pushing an empty list at any time disables the feature on the next snapshot.Plan deviations from the design doc
(Surfaced for reviewer awareness; documented in detail in the implementation report.)
APM_TRACINGDTO uses Moshi, not Jackson; I followed the existing pattern (@Json(name = "tt_extraction_patterns")).jakarta-servlet-5.0server decorator in this repo — jakarta server flavours live in per-container modules (Tomcat-10, Jetty-11+, Liberty-23, …) and each uses container-specific request types. Out of scope for this PR; falls back to the no-op default. Tracked as a follow-up.InstrumentationTagsactually lives ininternal-api, notagent-bootstrap; the new constant lives in the real file.ConfigDefaultsconstant — there is no env-var / system-property fallback in v1 (deferred to v2), so the constant would be dead code.internal-apihas nojmhsource set. Empty-pattern fast-path correctness is exercised by the negative tests at every layer.Span tag spec
_dd.tt.extraction_sourcesheader:<lower>andqs:<lower>entries; sorted alphabetically within source; headers firstheader:authorization,header:x-customer-id,qs:order_idSet only when at least one match is found. Absent otherwise.