Skip to content
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

Instrument Rack response bodies #1140

Merged
merged 4 commits into from
Jul 8, 2024
Merged

Instrument Rack response bodies #1140

merged 4 commits into from
Jul 8, 2024

Conversation

tombruijn
Copy link
Member

@tombruijn tombruijn commented Jul 2, 2024

Based on PR #1139

Instrument Rack response bodies

Instrument what happens when a Rack response body is read and closed. We instrument these events by wrapping the response body in the appropriate response body BodyWrapper subclass, depending on the response object type.

This change was previously sent in as PR #1037 and reverted in #1052. We saw issues with multiple requests reported in the same transaction. This problem occurred when there was an error in the middleware stack, and the BodyWrapper never closed the response body.

I've removed any transaction complete logic from the BodyWrapper in the original PR. We now have a Rack EventHandler that ensures the transaction is always closed per request, even when such an error scenario occurs again.

The only scenario in which we don't support this response body instrumentation is when no EventHandler is present in the middleware stack. This level of support is acceptable to me. We want people to use the EventHandler. Most of our automatic instrumentations are updated to add it to the middleware stack.

From the original commit: 7da96e7

Some work might be getting done within a Rack response body. For
example, when ActionController::Streaming is used, or when a Rack app
elects to stream a response.

The Rack SPEC doc defines the behavior in sufficient detail to wrap
this into the current AppSignal transaction.

Sadly, there is some work involved in supporting all the right
methods, so just "one-size-fits-all" wrapper will not quite work.

Closes #1099

Co-authored-by: Julik Tarkhanov me@julik.nl

Update StreamingListener to use AbstractMiddleware

Now that the AbstractMiddleware instruments response bodies, the StreamingListener has no special purpose anymore. It will now inherit from the AbstractMiddleware and be scheduled for removal.

Also removed the StreamWrapper class used previously by the StreamingListener. It was a private API that no one should have been using.

Deprecate StreamingListener middleware

Deprecate the StreamingListener now that it is almost identical to the AbstractMiddleware. Those couple differences are actually ones we don't want people to rely on, so deprecate it.

Don't instrument response bodies twice

If multiple rack instrumentation middleware are present in the middleware stack, don't instrument the response body multiple times.

Once it detects the response body is already a BodyWrapper subclass, pass it through without change.

@backlog-helper

This comment has been minimized.

1 similar comment
@backlog-helper
Copy link

backlog-helper bot commented Jul 8, 2024


This is a message from the daily scheduled checks.

New issue guide | Backlog management | Rules | Feedback

@tombruijn tombruijn changed the base branch from rack-instrumentation-middleware to main July 8, 2024 12:18
tombruijn and others added 4 commits July 8, 2024 14:25
Instrument what happens when a Rack response body is read and closed. We
instrument these events by wrapping the response body in the appropriate
response body BodyWrapper subclass, depending on the response object
type.

This change was previously sent in as PR #1037 and reverted in #1052. We
saw issues with multiple requests reported in the same transaction. This
problem occurred when there was an error in the middleware stack, and
the BodyWrapper never closed the response body.

I've removed any transaction complete logic from the BodyWrapper in the
original PR. We now have a Rack EventHandler that ensures the
transaction is always closed per request, even when such an error
scenario occurs again.

The only scenario in which we don't support this response body
instrumentation is when no EventHandler is present in the middleware
stack. This level of support is acceptable to me. We want people to use
the EventHandler. Most of our automatic instrumentations are updated to
add it to the middleware stack.

From the original commit: 7da96e7

> Some work might be getting done within a Rack response body. For
> example, when ActionController::Streaming is used, or when a Rack app
> elects to stream a response.
>
> The Rack SPEC doc defines the behavior in sufficient detail to wrap
> this into the current AppSignal transaction.
>
> Sadly, there is some work involved in supporting all the right
> methods, so just "one-size-fits-all" wrapper will not quite work.

Part of #1099

Co-authored-by: Julik Tarkhanov <me@julik.nl>
Now that the AbstractMiddleware instruments response bodies, the
StreamingListener has no special purpose anymore. It will now inherit
from the AbstractMiddleware and be scheduled for removal.

Also removed the StreamWrapper class used previously by the
StreamingListener. It was a private API that no one
should have been using.
Deprecate the StreamingListener now that it is almost identical to the
AbstractMiddleware. Those couple differences are actually ones we don't
want people to rely on, so deprecate it.
If multiple rack instrumentation middleware are present in the
middleware stack, don't instrument the response body multiple times.

Once it detects the response body is already a BodyWrapper subclass,
pass it through without change.
@tombruijn tombruijn merged commit 913c4fd into main Jul 8, 2024
117 checks passed
@tombruijn tombruijn deleted the instrument-responses branch July 10, 2024 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reapply rack response body instrumentation
2 participants