fix: name outbound HTTP client spans METHOD host/path for Datadog - #792
Merged
Conversation
otelhttp's default client formatter collapses outbound spans to bare GET/POST in Datadog. Format span names as METHOD host/path (no query), and drop the Shopware Admin client's redundant Internal HTTP spans so each request has one clear client span. Co-authored-by: Soner <github@shyim.de>
shyim
marked this pull request as ready for review
August 12, 2026 06:14
Contributor
Greptile SummaryThe PR adds a shared outbound HTTP span-name formatter and removes the redundant manual Shopware request span.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| api/internal/httputil/client.go | Wires the shared span-name formatter into every wrapped otelhttp transport. |
| api/internal/httputil/client_span_name.go | Adds host/path normalization and identifier grouping for outbound span names. |
| api/internal/httputil/client_span_name_test.go | Covers the formatter’s intended host, query, path, port, and identifier behavior. |
| api/internal/shopware/client.go | Removes the redundant manual span while preserving HTTP request and error behavior. |
Sequence Diagram
sequenceDiagram
participant Caller
participant HTTP as httputil client
participant OTel as otelhttp transport
participant Peer as Outbound service
Caller->>HTTP: Do(request)
HTTP->>OTel: RoundTrip with User-Agent
OTel->>OTel: ClientSpanName(method, request)
OTel->>Peer: Send request
Peer-->>OTel: Response
OTel-->>Caller: Response with one client span
Reviews (2): Last reviewed commit: "fix: bound HTTP client span resource car..." | Re-trigger Greptile
Collapse tenant/peer hosts to {host} (keep known shared hosts literal) and
replace UUID/numeric/long-hex path segments with {id} so Datadog resources
stay low-cardinality.
Co-authored-by: Soner <github@shyim.de>
|
Addressed Greptile’s cardinality note in 94bc08b: shared hosts stay literal; tenant/peer hosts collapse to |
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.
Problem
In Datadog production, ~520k+ worker spans / 6h collapse to
resource_name:GET(and similarly barePOST). Useful low-cardinality data is already on the spans ashttp.host+http.path_group(e.g. hostapi.shopware.com, path/pluginStore/pluginsByName), but Datadog’s resource name comes from the span name — and otelhttp’s default client formatter is effectively just the HTTP method.Root cause
httputil.wrapTransportwrapped outbound clients withotelhttp.NewTransport(base)and noWithSpanNameFormatter. The library default names client spans from the method alone (HTTP GET→ Datadog resourceGET).Separately, the Shopware Admin client started a manual Internal span named
method+" "+patharound each request. That duplicated the otelhttp client span and still showed up poorly in Datadog as a bare GET resource.Fix
httputil.ClientSpanNameand wire it viaotelhttp.WithSpanNameFormatterso outbound client spans are namedMETHOD host/pathapi.shopware.com,releases.shopware.com,store.shopware.com,raw.githubusercontent.com); other peers (per-shop Admin API, SSO IdPs, etc.) collapse to{host}{id}METHOD /pathwhen host is missing; empty path becomes/server.addressis already set by otelhttp’s client semconv — no extra attributes added.No HTTP behavior, timeout, SSRF, or User-Agent changes. No metrics-exporter work (separate task). DB span naming from #791 is untouched.