fix(otel): only set Scope.Transaction in SentrySpanProcessor when null#5337
fix(otel): only set Scope.Transaction in SentrySpanProcessor when null#5337tsushanth wants to merge 2 commits into
Conversation
| sut.OnStart(data!); | ||
|
|
||
| // Assert - the pre-existing transaction must still be on the scope | ||
| ITransaction? scopeTransaction = null; |
There was a problem hiding this comment.
issue: test was neither run nor built
- there is no
ITransactiontype - this project does not have Nullable Reference Types enabled
There was a problem hiding this comment.
Fixed — rewrote the test to use the real Hub instead of a mock IInternalScopeManager. The mock was eating ConfigureScope calls so the guard never ran. The test now captures the first transaction from sut._map and verifies scope.Transaction still points to it after the second OnStart.
| [Fact] | ||
| public void OnStart_WithExistingTransactionOnScope_DoesNotOverwriteExistingTransaction() |
There was a problem hiding this comment.
issue: test is ineffective
Currently, this test does not actually cover the modification, and does not cover the modified method SentrySpanProcessor.CreateRootSpan.
There was a problem hiding this comment.
@jamescrosswell I wonder if Mutation Testing could cover such issues early ... e.g. if we only run mutation tests on the changes per PR, and only via the test cases that cover the /src/ changes of the PR.
There was a problem hiding this comment.
That might be nice. It has to save us more effort than we spend maintaining CI to automate it. In the case of mutation tests that seems likely. Let's add an issue for prioritisation.
There was a problem hiding this comment.
Addressed in the same rewrite — the test now goes through the real Hub's ConfigureScope, so the null guard in CreateRootSpan actually runs.
| // Arrange - simulate a root OTel activity starting while another transaction is | ||
| // already on the scope (e.g. two overlapping root activities). The processor should | ||
| // not overwrite the existing transaction (see GH-5314). |
There was a problem hiding this comment.
thought: comments don't add additional value
IMO, the comments in this test apart from Arrange/Assert/Assert don't really add any additional value:
- Assert: the existing transaction is called
"Existing" - Act: the New Root Activity that is started is called
"NewRootActivity"- also: actually,
Actis missing for the Act portion of the test
- also: actually,
- Assert: the
becausestring parameter to the assertion describes
To me, the combination of Test-Name + Test-Logic + String-Parameters already describe what this test is covering and asserting.
There was a problem hiding this comment.
Plus the test itself is called OnStart_WithExistingTransactionOnScope_DoesNotOverwriteExistingTransaction...
There was a problem hiding this comment.
Removed the inline comments from the test.
| // Only set Scope.Transaction when it is currently null. Overwriting an existing | ||
| // transaction (which can happen when two root OTel activities overlap and neither is | ||
| // a child of the other) silently drops the previous transaction's scope context. | ||
| // See https://github.com/getsentry/sentry-dotnet/issues/5314 |
There was a problem hiding this comment.
suggestion: shorten comment
Although this comment does add value ... I find it a bit lengthy.
Perhaps we can shorten it a bit: for example: Only set Scope.Transaction when it is currently null is just describing the C# syntax in use.
There was a problem hiding this comment.
I think we could probably remove the comment entirely in this case... it's pretty apparent from the code what's going on.
| // Only set Scope.Transaction when it is currently null. Overwriting an existing | ||
| // transaction (which can happen when two root OTel activities overlap and neither is | ||
| // a child of the other) silently drops the previous transaction's scope context. | ||
| // See https://github.com/getsentry/sentry-dotnet/issues/5314 |
There was a problem hiding this comment.
question: do we want to add links to issues more aggressively? @jamescrosswell
Previously, we only added links to the respective GitHub issue, when the code isn't too obvious what it's trying to achieve in a rather complex flow ... or when the solution in place should be reviewed/revisited at some point in time when it is a workaround.
But it seems that Coding Agents like to add both a summary from the GitHub issue, as well as a link to the GitHub issue, and additionally describe the code semantics ahead.
In this case, I would prefer to either have a one-liner, or two/three words + link to the GitHub issue ... but both - to me - is a bit lengthy. To be fair, I might exaggerate "the problem" here a bit. What do you think?
There was a problem hiding this comment.
We get this for free from git blame (will identify the specific commit - relatively trivial to find the PR from there with a squash and merge as we're doing). When the code is particularly unintuitive and a full explanation in code comments isn't practical, it's worth linking to a PR description that provides a full explanation (make it clear we expect people will have to read the PR description to fully 'get it' in those cases).
For this piece of code, I don't think it's worth it though. We just don't want to overwrite previous/manually set values on the scope, which is obvious from the code.
|
Thank you very much, @tsushanth, for your contribution to the Sentry .NET SDK! |
| if (scope.Transaction is null) | ||
| { | ||
| scope.Transaction = transaction; | ||
| } |
There was a problem hiding this comment.
| if (scope.Transaction is null) | |
| { | |
| scope.Transaction = transaction; | |
| } | |
| scope.Transaction ??= transaction; |
There was a problem hiding this comment.
Thanks @tsushanth - did you forget to push your changes to remote maybe? I don't see them here...
Rewrite test to exercise CreateRootSpan directly via ScopeManager, use correct types, and remove noisy inline comments per review feedback.
8a3f87c to
8a20eba
Compare
|
Thanks for the detailed review @Flash0ver! Updated:
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8a20eba. Configure here.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5337 +/- ##
==========================================
+ Coverage 74.16% 74.20% +0.04%
==========================================
Files 508 509 +1
Lines 18353 18386 +33
Branches 3586 3600 +14
==========================================
+ Hits 13612 13644 +32
Misses 3869 3869
- Partials 872 873 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Sorry about the delay — was pushing to the wrong local branch name. Commits are now on the correct branch: |
|
thanks ... I'll take another look in the morning (CEST) |

Fixes #5314.
Problem
SentrySpanProcessor.OnStartcallsConfigureScopeunconditionally:When two root OTel activities overlap and neither is a child of the other, this silently overwrites whatever transaction was already on the scope with the new one. As the issue notes, the intuitive default is to not overwrite an existing transaction.
Fix
Add a null-check guard inside the
ConfigureScopelambda:Scope.Transactionis only set when it is currentlynull; an already-present transaction is left unchanged.Test
Added
OnStart_WithExistingTransactionOnScope_DoesNotOverwriteExistingTransactiontoSentrySpanProcessorTests: sets a transaction on the scope, starts a new root activity, callsOnStart, and asserts the scope still holds the original transaction.This is intentionally not bundled with #2399 (the
AutoSetScopeTransactionsopt-in), per the issue's notes.