Skip to content

fix(middleware): connection_drop_prevention_handler loses tracing context and amplifies panics - #5611

Open
dimazzq92 wants to merge 2 commits into
macro-inc:mainfrom
dimazzq92:main
Open

fix(middleware): connection_drop_prevention_handler loses tracing context and amplifies panics#5611
dimazzq92 wants to merge 2 commits into
macro-inc:mainfrom
dimazzq92:main

Conversation

@dimazzq92

Copy link
Copy Markdown

Summary

While exploring the architecture in crates/macro_middleware/src/lib.rs, I noticed an observability bug in the connection_drop_prevention_handler. This middleware wraps mutating requests in tokio::task::spawn to prevent database operations from being aborted if the client drops the connection.

By moving the request execution into a new tokio task without explicit instrumentation, this inadvertently introduces two problems:

  1. Loss of Tracing/Logging Context: tokio::task::spawn does not inherit the current thread-local tracing::Span. Any logs (tracing::info!, error!, etc.) emitted downstream inside the request handler are completely orphaned. They lose the request_id, user context, and path set by outer middleware layers, making production debugging very difficult for POST/PUT requests.
  2. Panic Amplification: Using .unwrap() on the JoinHandle means that if the inner handler panics, the JoinError::Panic is unwrapped, causing the middleware itself to panic. This bypasses normal Axum panic-handling layers and abruptly kills the connection, rather than returning a clean HTTP 500.

Proposed Fix

  1. Use .instrument(tracing::Span::current()) from the tracing crate to explicitly pass the span into the spawned task.
  2. Handle the JoinError gracefully, mapping it to a 500 response.

This PR implements these fixes, ensuring that network drops won't cancel the query, while keeping production observability intact and safely converting task panics to standard 500s.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b39e3e62-d9d9-4d05-ac2c-9fe0e8e978b2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of failures during mutating requests.
    • Panics and cancelled operations are now logged and return an HTTP 500 response instead of causing the request to fail unexpectedly.
    • Added improved request execution tracing for better diagnostics.

Walkthrough

Mutating request handlers now execute in instrumented Tokio tasks. Successful task results return their HTTP responses. Task panics and cancellations are logged and converted into empty HTTP 500 responses. Other request methods retain direct execution.

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title uses conventional commit syntax and describes the fix, but it is 94 characters and exceeds the 72-character limit. Shorten the title to 72 characters or fewer while preserving the main fix, for example: "fix(middleware): preserve tracing and handle task panics".
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the tracing-context and panic-handling changes in the middleware.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
crates/macro_middleware/src/lib.rs (1)

28-33: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use a structured JoinError field.

Lines 30 and 32 render err inside the message. Keep the distinct messages, but record err as the error field so tracing backends can index it consistently.

Proposed change
- tracing::error!("Request handler panicked: {:?}", err);
+ tracing::error!(error = ?err, "Request handler panicked");
...
- tracing::error!("Request handler task was cancelled: {:?}", err);
+ tracing::error!(error = ?err, "Request handler task was cancelled");

As per coding guidelines, log errors using tracing::error!(error=?e, "error msg") rather than interpolating the error into the message.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/macro_middleware/src/lib.rs` around lines 28 - 33, Update the Err
handling in the request-handler task join flow to keep the distinct panic and
cancellation messages while passing the JoinError as a structured `error` field
to `tracing::error!`. Remove the interpolated `err` formatting from both log
messages and use debug-field recording consistent with the project’s logging
convention.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/macro_middleware/src/lib.rs`:
- Around line 28-33: Update the Err handling in the request-handler task join
flow to keep the distinct panic and cancellation messages while passing the
JoinError as a structured `error` field to `tracing::error!`. Remove the
interpolated `err` formatting from both log messages and use debug-field
recording consistent with the project’s logging convention.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 56d728fe-c524-4100-9a9e-1a70360016d0

📥 Commits

Reviewing files that changed from the base of the PR and between f15a6aa and cac3fc1.

📒 Files selected for processing (1)
  • crates/macro_middleware/src/lib.rs

Comment thread crates/macro_middleware/src/lib.rs Outdated
Ok(response) => response,
Err(err) => {
if err.is_panic() {
tracing::error!("Request handler panicked: {:?}", err);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

prefer

Suggested change
tracing::error!("Request handler panicked: {:?}", err);
tracing::error!(error=?err, "request handler panicked");

Comment thread crates/macro_middleware/src/lib.rs Outdated
if err.is_panic() {
tracing::error!("Request handler panicked: {:?}", err);
} else {
tracing::error!("Request handler task was cancelled: {:?}", err);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

prefer

Suggested change
tracing::error!("Request handler task was cancelled: {:?}", err);
tracing::error!(error=?err, "request handler task was cancelled");

@whutchinson98 whutchinson98 self-assigned this Aug 13, 2026
@dimazzq92

Copy link
Copy Markdown
Author

Applied the suggested structured tracing format (error=?err). Thanks for the review!

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.

2 participants