File Coverage

blib/lib/OpenTracing/WrapScope.pm
Criterion Covered Total %
statement 105 105 100.0
branch 41 44 93.1
condition 7 8 87.5
subroutine 21 21 100.0
pod 3 3 100.0
total 177 181 97.7


line stmt bran cond sub pod time code
1             package OpenTracing::WrapScope;
2             our $VERSION = 'v0.103.0';
3 13     13   8804103 use strict;
  13         134  
  13         435  
4 13     13   77 use warnings;
  13         25  
  13         370  
5 13     13   76 use warnings::register;
  13         26  
  13         1591  
6 13     13   622 use B::Hooks::EndOfScope;
  13         11242  
  13         137  
7 13     13   1001 use Carp qw/croak/;
  13         25  
  13         628  
8 13     13   85 use List::Util qw/uniq/;
  13         27  
  13         779  
9 13     13   488 use OpenTracing::GlobalTracer;
  13         11188  
  13         90  
10 13     13   1537 use PerlX::Maybe;
  13         2471  
  13         143  
11 13     13   7057 use Sub::Info qw/sub_info/;
  13         94563  
  13         97  
12              
13             { # transparent caller, stolen from Hook::LexWrap
14 13     13   453 no warnings 'redefine';
  13         29  
  13         6897  
15             *CORE::GLOBAL::caller = sub (;$) {
16 394   100 394   5430190253 my ($height) = ($_[0]||0);
17 394         712 my $i=1;
18 394         594 my $name_cache;
19 394         612 while (1) {
20             my @caller = CORE::caller() eq 'DB'
21 698 100       4549 ? do { package DB; CORE::caller($i++) }
  10         42  
22             : CORE::caller($i++);
23 698 100       1839 return if not @caller;
24 682 100       1371 $caller[3] = $name_cache if $name_cache;
25 682 100       1467 $name_cache = $caller[0] eq __PACKAGE__ ? $caller[3] : '';
26 682 100 100     2382 next if $name_cache || $height-- != 0;
27 378 100       2208 return wantarray ? @_ ? @caller : @caller[0..2] : $caller[0];
    100          
28             }
29             };
30             }
31              
32             sub import {
33 14     14   5792 shift; # __PACKAGE__
34 14         39 my $target_package = caller;
35              
36 14         39 my ($use_env, @subs, @files);
37 14         98 while (my (undef, $arg) = each @_) {
38 22 100       75 if ($arg eq '-env') {
    100          
39 2         6 $use_env = 1;
40             }
41             elsif ($arg eq '-file') {
42 2 50       7 my (undef, $next) = each @_ or last;
43 2 100       12 push @files, ref $next eq 'ARRAY' ? @$next : $next;
44             }
45             else {
46 18         45 push @subs, _qualify_sub($arg, $target_package);
47             }
48             }
49 14 50 66     53 if ($use_env and $ENV{OPENTRACING_WRAPSCOPE_FILE}) {
50 2         14 push @files, split ':', $ENV{OPENTRACING_WRAPSCOPE_FILE};
51             }
52 14         38 push @subs, map { _load_sub_spec($_) } map { glob } @files;
  7         29  
  6         344  
53              
54 14     14   168 on_scope_end { install_wrapped(uniq @subs) };
  14         10284  
55              
56 14         2074 return;
57             }
58              
59             sub install_wrapped {
60 17     17 1 1579 foreach my $sub (@_) {
61 36         105 my $full_sub = _qualify_sub($sub, scalar caller);
62              
63 36 100       156 if (not defined &$sub) {
64 2         76 warnings::warn "Couldn't find sub: $sub";
65 1         32 next;
66             }
67              
68 13     13   114 no strict 'refs';
  13         36  
  13         514  
69 13     13   89 no warnings 'redefine';
  13         28  
  13         8609  
70 34         98 *$sub = wrapped(\&$sub);
71             }
72 16         73 return;
73             }
74              
75             sub wrapped {
76 34     34 1 70 my ($coderef) = @_;
77 34         102 my $info = sub_info($coderef);
78              
79             return sub {
80 42     42   28187 my ($call_package, $call_filename, $call_line) = caller(0);
81 42         220 my $call_sub = (caller(1))[3];
82 42         434 my $tracer = OpenTracing::GlobalTracer->get_global_tracer;
83             my $scope = $tracer->start_active_span(
84             "$info->{package}::$info->{name}",
85             tags => {
86             'source.subname' => $info->{name},
87             'source.file' => $info->{file},
88             'source.line' => $info->{start_line},
89             'source.package' => $info->{package},
90 42         802 maybe
91             'caller.subname' => $call_sub,
92             'caller.file' => $call_filename,
93             'caller.line' => $call_line,
94             'caller.package' => $call_package,
95             },
96             );
97              
98 42         61744 my $result;
99 42         94 my $wantarray = wantarray; # eval will have its own
100 42         141 my $ok = eval {
101 42 100       128 if (defined $wantarray) {
102 4 100       23 $result = $wantarray ? [&$coderef] : &$coderef;
103             }
104             else {
105 38         147 &$coderef;
106             }
107 41         8602 1;
108             };
109 42 100       151 $scope->get_span->add_tag(error => $@) unless $ok;
110 42         380 $scope->close();
111              
112 42 100       6224 die $@ unless $ok;
113 41 100       552 return if not defined wantarray;
114 4 100       71 return wantarray ? @$result : $result;
115 34         4392 };
116             }
117              
118             sub _qualify_sub {
119 54     54   212 my ($sub, $pkg) = @_;
120 54 100       326 return $sub if $sub =~ /'|::/;
121 16         74 return "${pkg}::$sub";
122             }
123              
124             sub _load_sub_spec {
125 9     9   37 my ($filename) = @_;
126              
127 9 50       352 open my $fh_subs, '<', $filename or die "$filename: $!";
128              
129 9         26 my @subs;
130 9         184 while (<$fh_subs>) {
131 17         47 chomp;
132 17 100       137 croak "Unqualified subroutine: $_" if !/'|::/;
133 16         119 push @subs, $_;
134             }
135 8         79 close $fh_subs;
136              
137 8         64 return @subs;
138             }
139              
140             sub wrap_from_file {
141 2     2 1 2519 my ($filename) = @_;
142 2         6 install_wrapped( _load_sub_spec($filename) );
143 1         4 return;
144             }
145              
146              
147             1;