-
Notifications
You must be signed in to change notification settings - Fork 621
Fix the behavioural defects found in the OpenTelemetry tracing review #1978
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
lukebakken
wants to merge
13
commits into
main
Choose a base branch
from
fix/gh-1967-opentelemetry-tracing
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
24eb68f
Document the OpenTelemetry tracing review findings
lukebakken 84e3dc4
Fix the behavioural defects found in the tracing review
lukebakken e905388
Address the code review of the tracing fixes
lukebakken a93b47e
Dedupe exception events on the publish failure path (#1967)
danielmarbach 55c43e3
Apply all three SetActivityError signals consistently
danielmarbach 67c6ca7
Do not record caller-initiated cancellation as an error
danielmarbach 122f762
Strengthen failure-recording test assertions and pin publish parenting
danielmarbach 50566ef
Test that caller cancellation is not recorded as a publish failure
lukebakken 54076d4
Correct a stale inline comment in the cancellation test
lukebakken 9424ba3
Restore two fixes reverted by the rebase onto main
lukebakken 0cee52b
Correct the Stable-attribute claim and cite the governing spec
lukebakken 74bf6d8
Document why a handled publish exception is still recorded as `Error`
lukebakken e200050
Document the release-note sweep in RELEASE.md
lukebakken File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,17 +97,33 @@ private async ValueTask BasicPublishCoreAsync<TMethod, TProperties>( | |
| RateLimitLease? lease = | ||
| await MaybeAcquirePublisherConfirmationLockAsync(cancellationToken) | ||
| .ConfigureAwait(false); | ||
| /* | ||
| * The send activity is declared out here, rather than inside the try | ||
| * below, so the catch can record the failure on it. With the `using` | ||
| * scoped to the inner try the span was already disposed by the time | ||
| * the catch ran, so no publish failure was ever reported: the span | ||
| * ended status=Unset with no exception event, which tracing backends | ||
| * read as a successful publish. See issue #1967. | ||
| */ | ||
| using Activity? sendActivity = RabbitMQActivitySource.PublisherHasListeners | ||
| ? RabbitMQActivitySource.BasicPublish(routingKey, exchange, body.Length, basicProperties) | ||
| : default; | ||
| /* | ||
| * Tracks the exception (if any) already recorded on sendActivity by the | ||
| * catch below, so the finally's confirmation-await catch does not record | ||
| * the same instance twice. When MaybeHandleExceptionWithEnabledPublisherConfirmations | ||
| * faults the confirm TCS, the finally's await re-raises that exception; | ||
| * without this guard a publish whose send failed (e.g. on a closed | ||
| * connection) recorded the same exception twice. See issue #1967. | ||
| */ | ||
| Exception? recordedSendError = null; | ||
| try | ||
| { | ||
| publisherConfirmationInfo = MaybeStartPublisherConfirmationTracking(); | ||
|
|
||
| await MaybeEnforceFlowControlAsync(cancellationToken) | ||
| .ConfigureAwait(false); | ||
|
|
||
| using Activity? sendActivity = RabbitMQActivitySource.PublisherHasListeners | ||
| ? RabbitMQActivitySource.BasicPublish(routingKey, exchange, body.Length, basicProperties) | ||
| : default; | ||
|
|
||
| ulong publishSequenceNumber = publisherConfirmationInfo?.PublishSequenceNumber ?? 0; | ||
|
|
||
| BasicProperties? props = PopulateBasicPropertiesHeaders(basicProperties, sendActivity, publishSequenceNumber); | ||
|
|
@@ -125,6 +141,34 @@ await ModelSendAsync(in cmd, in props, body, bodyOwner, cancellationToken) | |
| } | ||
| catch (Exception ex) | ||
| { | ||
| /* | ||
| * Caller-initiated cancellation is not a publish failure, so it is | ||
| * not recorded on the span. Confirmation tracking still needs the | ||
| * cleanup below (faulting the TCS, decrementing the sequence number), | ||
| * which is why this is an inline guard rather than a `when` filter: | ||
| * a filter that skipped this catch would skip the cleanup too. | ||
| * See issue #1967. | ||
| */ | ||
| bool isCallerCancellation = | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why a separate local instead of having the condition in the Same below. |
||
| ex is OperationCanceledException && cancellationToken.IsCancellationRequested; | ||
| if (!isCallerCancellation) | ||
| { | ||
| sendActivity.SetActivityError(ex); | ||
| recordedSendError = ex; | ||
| } | ||
|
|
||
| /* | ||
| * "Handled" here means the exception was routed onto the publisher | ||
| * confirmation task, not that it was swallowed: the finally below | ||
| * awaits that task and re-raises the same instance to the caller. So | ||
| * recording the error above is correct even when exceptionWasHandled | ||
| * is true - the publish failed and the caller sees it, just through | ||
| * the confirmation channel rather than a throw from here. This is not | ||
| * the spec's "handled or retried and completed gracefully" exemption, | ||
| * which is for operations that recover; a faulted publish never does. | ||
| * Every path that records Error is one the caller observes as a | ||
| * failure. See issue #1967. | ||
| */ | ||
| bool exceptionWasHandled = | ||
| MaybeHandleExceptionWithEnabledPublisherConfirmations(publisherConfirmationInfo, ex); | ||
| if (!exceptionWasHandled) | ||
|
|
@@ -135,8 +179,30 @@ await ModelSendAsync(in cmd, in props, body, bodyOwner, cancellationToken) | |
| finally | ||
| { | ||
| MaybeReleasePublisherConfirmationLock(lease); | ||
| await MaybeEndPublisherConfirmationTrackingAsync(publisherConfirmationInfo, cancellationToken) | ||
| .ConfigureAwait(false); | ||
|
|
||
| /* | ||
| * This await is the one that surfaces a nack or an unroutable | ||
| * mandatory publish (PublishException), so it is a publish failure | ||
| * like any other and belongs on the span. It cannot simply be | ||
| * wrapped by the catch above, because it runs in the finally: the | ||
| * confirmation is only awaited once the send has been issued. | ||
| */ | ||
| try | ||
| { | ||
| await MaybeEndPublisherConfirmationTrackingAsync(publisherConfirmationInfo, cancellationToken) | ||
| .ConfigureAwait(false); | ||
| } | ||
| catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) | ||
| { | ||
| // Caller-initiated cancellation during the confirmation await is | ||
| // not a publish failure. See issue #1967. | ||
| throw; | ||
| } | ||
| catch (Exception ex) when (!ReferenceEquals(ex, recordedSendError)) | ||
| { | ||
| sendActivity.SetActivityError(ex); | ||
| throw; | ||
| } | ||
| } | ||
| } | ||
| finally | ||
|
|
||
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
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find the choice of this name confusing. I would call it something like connectionActivity