-
Notifications
You must be signed in to change notification settings - Fork 7
Open
Description
Because the sentry integrations are global, they don't play nicely out of the box with async; in my project at work i've written my own sentry plugin around this one that uses Syntax::Keyword::Dynamically and Future::AsyncAwait to solve this, relevant bits below -
$app->hook(
around_action => sub ($next, $c, $action, $last) {
my $req = $c->req;
my $scope = $c->stash('_sentry_scope');
my $transaction = $c->stash('_sentry_transaction');
unless ($scope) {
# eliminate any non-request scopes, b/c memory leaks for the lose
Sentry::Hub->get_current_hub->reset;
Sentry::SDK->configure_scope(sub ($new_scope) {
my $transaction = Sentry::SDK->start_transaction({
name => $c->match->endpoint->to_string // '/',
op => 'http.server',
request => {
url => $req->url->to_abs->to_string,
method => $req->method,
query => $req->url->query->to_hash,
headers => { pairgrep { $a ne 'Cookie' } $req->headers->to_hash->%* }
},
$self->continue_from_headers($req->headers)->%*
});
$new_scope->set_span($transaction);
$c->stash(_sentry_scope => $scope = $new_scope);
$c->stash(_sentry_transaction => $transaction);
});
}
# save our scope for this dynamic context
dynamically Sentry::Hub->get_current_hub->{scopes} = [$scope];
# turn on breadcrumbs for this dynamic context
dynamically Sentry::Integration->get_integration('DBI')->{breadcrumbs} = 1;
dynamically Sentry::Integration->get_integration('MojoUserAgent')->{breadcrumbs} = 1;
return $next->() if $c->tx->is_websocket;
# always returns a promise
$self->handle_action($c, $next, $last);
# break the dispatch chain, but the action handler may actually continue it
return $last;
}
);and the call to handle_action is
async sub handle_action ($self, $c, $next_hook, $last) {
# we must hold onto the $tx here, b/c the req may get cancelled while await-ing
my $tx;
try {
$tx = $c->render_later->tx;
my $fin = $next_hook->();
$fin = await $fin if blessed $fin and $fin->can('AWAIT_IS_READY');
# we need to delay to avoid an infinite loop
Mojo::IOLoop->next_tick(sub {
$c->continue if $fin && !$last;
});
} catch ($err) {
$c->reply->exception($err);
Sentry::SDK->capture_exception($err) if $c->res->is_server_error;
} finally {
if ($last) {
my $transaction = $c->stash('_sentry_transaction');
if (defined $c->stash('sentry_tracing')) {
$transaction->sampled($c->stash('sentry_tracing'));
}
$transaction->set_http_status($c->res->code) if $c->res->code;
$transaction->finish();
}
}
}Would be happy to open a PR, just wanna know if the dependencies are acceptable for the scope of this project.
Metadata
Metadata
Assignees
Labels
No labels