-
Notifications
You must be signed in to change notification settings - Fork 120
Guard blocks handed to the transaction #1544
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
Merged
unflxw
merged 2 commits into
wip-otel-rework
from
fix-transaction-block-exception-safety
Jul 16, 2026
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| bump: patch | ||
| type: fix | ||
| --- | ||
|
|
||
| Complete the transaction even when a block handed to it raises. The error block passed to `Appsignal.set_error`, `Appsignal.send_error`, and `Appsignal.report_error`, as well as the internal `after_create` and `before_complete` hooks, are user code that can raise. Until now such an exception propagated out of transaction creation or completion, which surfaced the error in unrelated code and could leave the transaction unfinished. These blocks are now run defensively: the failure is logged, naming the error and where the block was defined, and creation and completion carry on. |
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
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.
Would you want to differentiate between the three different handlers that now have the source set to 'error'?
Like so for example:
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'd like for it to be meaningful to the customer -- so
send_error/set_error/report_error, but that information is lost at this point in the call tree. I could try and pass it down, or I could try to show all three names for readability.As far as we're concerned, in terms of our ability to debug it, we should get which one of
internal_set_errororreport_errors_as_duplicatesit was that caused it from the backtrace itself, so that information is never lost. The method name in the error is for the customer, for them to be able to debug what it is they're doing in a block that caused it to error.What does concern me, though, is that you mentioned it's called three different times. I think some of those are redundant with each other -- if
internal_set_errorcalls its block withcall_transaction_block, thenreport_errors_as_duplicatesdoes not need to call its block withcall_transaction_blockfrom inside a block passed tointernal_set_error. Thank you for flagging that.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.
Following up on this: I went with wrapping at the entry point.
Each error block is now wrapped once, where user code hands it in, instead of at every place it later runs. That fixed the redundancy I mentioned. The duplicate-transaction path no longer wraps a block from inside a block passed to
internal_set_error. It calls the already-wrapped block directly.It also recovered the customer-facing name.
send_errorandreport_errorpass their own name when they wrap the block, so the log names the call the customer made rather than an internal method.set_erroris left out on purpose, because its block runs inline at the call site, so a failure there already surfaces to the caller.The
after_createandbefore_completehooks are the one exception. They can be registered either with a block or by pushing a method onto the set, so there is no single entry point to wrap them at. They keep their guard where they run.