Skip to content

fix(tracing): Propagate the span of the hub passed to the Guzzle middleware - #2289

Merged
Litarnus merged 5 commits into
getsentry:masterfrom
RaphaelFakhri:fix/guzzle-trace-headers-hub
Oct 22, 2026
Merged

Litarnus merged 5 commits into
getsentry:masterfrom
RaphaelFakhri:fix/guzzle-trace-headers-hub

Conversation

@RaphaelFakhri

@RaphaelFakhri RaphaelFakhri commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

fix(tracing): Propagate the span of the hub passed to the Guzzle middleware

Description

GuzzleTracingMiddleware::trace() accepts a hub and starts the http.client span on it, but it built the sentry-trace and baggage headers with getTraceparent() and getBaggage(), which always read SentrySdk::getCurrentHub(). When the given hub is not the current hub, the outgoing request carried the trace of another hub, and the downstream service continued a trace that does not contain the http.client span.

getTraceparent() and getBaggage() now accept an optional hub and fall back to the current hub. Both functions use that hub consistently, and the middleware passes its hub to them.

The existing tests set the given hub as the current hub, so they did not cover this case. The new tests use two different hubs.

Issues

Reminders

@Litarnus

Litarnus commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Thanks for the PR! I think it would be easier to update the top level functions to take a $hub = null parameters. Then the change would boil down to

function getTraceparent(HubInterface $hub = null): string
{
    $hub = $hub ?? SentrySdk::getCurrentHub();
    // the rest
}

same for getBaggage

edit: I noticed we call SentrySdk::getCurrentHub() twice in there, so this would also be a good opportunity to use $hub consistently

Pass the Guzzle middleware hub to both functions instead of reading the
span directly, and use the given hub consistently inside them.
@RaphaelFakhri

Copy link
Copy Markdown
Contributor Author

@Litarnus Thanks, that is simpler. The PR now takes that approach:

  • getTraceparent() and getBaggage() accept an optional ?HubInterface $hub = null, fall back to SentrySdk::getCurrentHub(), and use $hub for the span lookup too.
  • GuzzleTracingMiddleware passes its hub to both functions.
  • A new FunctionsTest::testTraceHeadersUseTheGivenHub covers the functions directly, and the existing middleware test stays.

Both tests fail without the source change and pass with it. The unit suite passes (2007 tests).

CHANGELOG.md is not touched, since it is updated during releases.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c8a01c8. Configure here.

Comment thread src/functions.php
@Litarnus

Copy link
Copy Markdown
Collaborator

The CI is unrelated to your changes, the recent PHP vulnerability seem to have changed behaviour around OOM. I will fix it in a different PR and merge it here

Litarnus and others added 2 commits October 22, 2026 11:39
When the given hub has no span, getBaggage() builds the header from the
scope's propagation context, which read the current hub's options. Pass
the hub to PropagationContext::toBaggage() so the fallback uses it too.

@Litarnus Litarnus left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, thank you for fixing this

@Litarnus
Litarnus merged commit ee96b73 into getsentry:master Oct 22, 2026
50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GuzzleTracingMiddleware sends the trace headers of the current hub instead of the given hub

2 participants