-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26 from jobindex/mojo-template-integration
Mojo::Template integration
- Loading branch information
Showing
4 changed files
with
160 additions
and
2 deletions.
There are no files selected for viewing
This file contains 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 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,65 @@ | ||
package Sentry::Integration::MojoTemplate; | ||
use Mojo::Base 'Sentry::Integration::Base', -signatures; | ||
|
||
use Try::Tiny; | ||
use Sentry::Util 'around'; | ||
|
||
has tracing => 1; | ||
has fix_stacktrace => 1; | ||
|
||
sub setup_once ($self, $add_global_event_processor, $get_current_hub) { | ||
around( | ||
'Mojo::Template', | ||
render => sub ($orig, $mojo_template, @args) { | ||
my $hub = $get_current_hub->(); | ||
my $parent_span = $self->tracing && $hub->get_current_scope->get_span; | ||
my $output; | ||
$hub->with_scope(sub ($scope) { | ||
my $namespace = $mojo_template->namespace; | ||
|
||
my $span; | ||
if ($parent_span) { | ||
$span = $parent_span->start_child({ | ||
op => 'mojo.template', | ||
description => $mojo_template->name, | ||
data => { | ||
compiled => $mojo_template->compiled ? 'yes' : 'no', | ||
}, | ||
}); | ||
$scope->set_span($span); | ||
} | ||
|
||
try { | ||
$output = $orig->($mojo_template, @args); | ||
if ($self->fix_stacktrace && ref $output && $output->isa('Mojo::Exception')) { | ||
_fix_template_stack_frames($namespace, $output); | ||
} | ||
} finally { | ||
$span->finish() if $span; | ||
}; | ||
}); | ||
return $output; | ||
} | ||
); | ||
} | ||
|
||
sub _fix_template_stack_frames($namespace, $exc) { | ||
for my $frame ($exc->frames->@*) { | ||
# Frames coming from Mojo templates will have their module set to | ||
# $namespace which is not very useful since it will be the same for all | ||
# templates. Additionally, if using Mojolicious::Plugin::EPRenderer, the | ||
# namespace will contain a hash value, which means it will mess up issue | ||
# grouping. | ||
# Remove module and subroutine from the frame so that Sentry falls back | ||
# to using the filename in the UI and for grouping. | ||
if ($frame->[0] && $frame->[0] eq $namespace && $frame->[1]) { | ||
$frame->[0] = ''; # module | ||
$frame->[3] = ''; # subroutine | ||
} elsif ($frame->[3]) { | ||
# Remove namespace from subroutine name | ||
$frame->[3] =~ s/^${namespace}:://; | ||
} | ||
} | ||
} | ||
|
||
1; |
This file contains 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 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,84 @@ | ||
use Mojo::Base -strict, -signatures; | ||
|
||
use Mojo::File; | ||
# curfile missing in Mojolicious@^8. The dependency shall not be updated for | ||
# the time being. For this reason `curfile` is duplicated for now. | ||
# use lib curfile->sibling('lib')->to_string; | ||
# See https://github.com/mojolicious/mojo/blob/4093223cae00eb516e38f2226749d2963597cca3/lib/Mojo/File.pm#L36 | ||
use lib Mojo::File->new(Cwd::realpath((caller)[1]))->sibling('lib')->to_string; | ||
|
||
use Mojo::Template; | ||
use Sentry::Hub; | ||
use Sentry::Integration::MojoTemplate; | ||
use Sentry::Tracing::Span; | ||
use Sentry::Util qw(restore_original); | ||
use Test::Spec; | ||
|
||
describe 'Sentry::Integration::MojoTemplate' => sub { | ||
my $integration; | ||
my $hub; | ||
|
||
before each => sub { | ||
$hub = Sentry::Hub->new; | ||
|
||
$integration = Sentry::Integration::MojoTemplate->new( | ||
tracing => 1, | ||
fix_stacktrace => 1, | ||
); | ||
|
||
$integration->setup_once(sub { }, sub {$hub}); | ||
}; | ||
|
||
after each => sub { | ||
restore_original 'Mojo::Template', 'render'; | ||
}; | ||
|
||
it 'creates a span when rendering template' => sub { | ||
my $scope = $hub->get_current_scope; | ||
my $span = Sentry::Tracing::Span->new(); | ||
$scope->set_span($span); | ||
|
||
my $mt = Mojo::Template->new(name => 'tmpl foo'); | ||
$mt->render('foo'); | ||
|
||
is scalar $span->spans->@*, 1; | ||
my %tmpl_span = $span->spans->[0]->%*; | ||
is $tmpl_span{description}, 'tmpl foo'; | ||
is $tmpl_span{op}, 'mojo.template'; | ||
is_deeply $tmpl_span{data}, { compiled => 'no' }; | ||
}; | ||
|
||
it 'fixes stacktrace' => sub { | ||
$integration->fix_stacktrace(1); | ||
my $scope = $hub->get_current_scope; | ||
my $span = Sentry::Tracing::Span->new(); | ||
$scope->set_span($span); | ||
|
||
my $mt = Mojo::Template->new(name => 'tmpl foo', namespace => 'Mojo::Template::Sandbox::deadbeef'); | ||
my $output = $mt->render('<% die "boom"; %>'); | ||
|
||
is ref $output, 'Mojo::Exception'; | ||
my ($module, $filename, undef, $subroutine) = $output->frames->[0]->@*; | ||
is $module, ''; | ||
is $filename, 'tmpl foo'; | ||
is $subroutine, ''; | ||
}; | ||
|
||
it 'does not fix stacktrace when fix_stacktrace is false' => sub { | ||
$integration->fix_stacktrace(0); | ||
my $scope = $hub->get_current_scope; | ||
my $span = Sentry::Tracing::Span->new(); | ||
$scope->set_span($span); | ||
|
||
my $mt = Mojo::Template->new(name => 'tmpl foo', namespace => 'Mojo::Template::Sandbox::deadbeef'); | ||
my $output = $mt->render('<% die "boom"; %>'); | ||
|
||
is ref $output, 'Mojo::Exception'; | ||
my ($module, $filename, undef, $subroutine) = $output->frames->[0]->@*; | ||
is $module, 'Mojo::Template::Sandbox::deadbeef'; | ||
is $filename, 'tmpl foo'; | ||
is $subroutine, 'Mojo::Template::__ANON__'; | ||
}; | ||
}; | ||
|
||
runtests; |