File Coverage

blib/lib/OpenTracing/Tracer.pm
Criterion Covered Total %
statement 63 111 56.7
branch 7 24 29.1
condition 11 24 45.8
subroutine 20 31 64.5
pod 7 18 38.8
total 108 208 51.9


line stmt bran cond sub pod time code
1             package OpenTracing::Tracer;
2              
3 3     3   69480 use strict;
  3         13  
  3         78  
4 3     3   13 use warnings;
  3         5  
  3         125  
5              
6             our $VERSION = '1.003'; # VERSION
7             our $AUTHORITY = 'cpan:TEAM'; # AUTHORITY
8              
9 3     3   410 no indirect;
  3         989  
  3         12  
10 3     3   614 use utf8;
  3         16  
  3         12  
11              
12             =encoding utf8
13              
14             =head1 NAME
15              
16             OpenTracing::Tracer - application tracing
17              
18             =head1 DESCRIPTION
19              
20             This provides the interface between the OpenTracing API and the tracing service(s)
21             for an application.
22              
23             Typically a single process would have one tracer instance.
24              
25             =cut
26              
27 3     3   415 use OpenTracing::Process;
  3         49  
  3         94  
28 3     3   393 use OpenTracing::Span;
  3         7  
  3         76  
29 3     3   408 use OpenTracing::SpanProxy;
  3         39  
  3         100  
30              
31 3     3   24 use List::Util qw(min);
  3         6  
  3         325  
32 3     3   19 use Scalar::Util qw(refaddr);
  3         3  
  3         140  
33 3     3   15 use Time::HiRes ();
  3         5  
  3         78  
34              
35 3     3   924 use Log::Any qw($log);
  3         15309  
  3         21  
36              
37             =head1 METHODS
38              
39             =cut
40              
41             sub new {
42 3     3 0 138 my ($class, %args) = @_;
43 3   50     27 $args{span_completion_callbacks} ||= [];
44 3         10 bless \%args, $class
45             }
46              
47             =head2 process
48              
49             Returns the current L.
50              
51             =cut
52              
53             sub process {
54 1     1 1 518 my ($self) = @_;
55              
56             # Handle forks
57 1 50 33     7 if($self->{process} and $self->{process}->pid != $$) {
58 0         0 delete $self->{process};
59             }
60              
61 1   33     5 $self->{process} //= do {
62 1         484 require Net::Address::IP::Local;
63 1         7796 OpenTracing::Process->new(
64             pid => $$,
65             ip => Net::Address::IP::Local->public_ipv4,
66             'tracer.version' => 'perl-OpenTracing-' . __PACKAGE__->VERSION,
67             );
68             }
69             }
70              
71             =head2 is_enabled
72              
73             Returns true if this tracer is currently enabled.
74              
75             =cut
76              
77 8   100 8 1 33 sub is_enabled { shift->{is_enabled} //= 0 }
78              
79             =head2 enable
80              
81             Enable the current tracer.
82              
83             =cut
84              
85 1     1 1 1714 sub enable { shift->{is_enabled} = 1 }
86              
87             =head2 disable
88              
89             Disable the current tracer.
90              
91             =cut
92              
93 0     0 1 0 sub disable { shift->{is_enabled} = 0 }
94              
95             =head2 spans
96              
97             Returns an arrayref of L instances.
98              
99             =cut
100              
101             sub spans {
102             shift->{spans}
103 1     1 1 5 }
104              
105             =head2 span_list
106              
107             Returns a list of L instances.
108              
109             =cut
110              
111             sub span_list {
112 0   0 0 1 0 (shift->{spans} //= [])->@*
113             }
114              
115             =head2 add_span
116              
117             Adds a new L instance to the pending list, if
118             we're currently enabled.
119              
120             =cut
121              
122             sub add_span {
123 4     4 1 18 my ($self, $span) = @_;
124 4 100       17 return $span unless $self->is_enabled;
125 2         7 push $self->{spans}->@*, $span;
126 2         9 Scalar::Util::weaken($span->{batch});
127 2         3 $span
128             }
129              
130             sub span {
131 4     4 0 931 my ($self, %args) = @_;
132 4   66     35 $args{operation_name} //= (caller 1)[3];
133             $self->add_span(
134             my $span = OpenTracing::Span->new(
135             tracer => $self,
136             parent => $self->{current_span},
137 4         39 %args
138             )
139             );
140 4         12 $self->{current_span} = $span;
141 4         29 return OpenTracing::SpanProxy->new(span => $span);
142             }
143              
144 0     0 0 0 sub current_span { shift->{current_span} }
145              
146             sub finish_span {
147 4     4 0 11 my ($self, $span) = @_;
148 4         25 $log->tracef('Finishing span %s', $span);
149 4 100 66     51 undef $self->{current_span} if $self->{current_span} and refaddr($self->{current_span}) == refaddr($span);
150              
151 4 100       15 return $span unless $self->is_enabled;
152 2   100     5 push @{$self->{finished_spans} //= []}, $span;
  2         10  
153 2         15 $_->($span) for $self->span_completion_callbacks;
154 2         5 return $span;
155             }
156              
157             sub add_span_completion_callback {
158 0     0 0 0 my ($self, $code) = @_;
159 0         0 push $self->{span_completion_callbacks}->@*, $code;
160 0         0 return $self;
161             }
162              
163             sub remove_span_completion_callback {
164 0     0 0 0 my ($self, $code) = @_;
165 0         0 my $addr = Scalar::Util::refaddr($code);
166 0         0 my $data = $self->{span_completion_callbacks};
167             # Essentially extract_by from List::UtilsBy
168 0         0 for(my $idx = 0; ; ++$idx) {
169 0 0       0 last if $idx > $#$data;
170 0 0       0 next unless Scalar::Util::refaddr($data->[$idx]) == $addr;
171 0         0 splice @$data, $idx, 1, ();
172             # Skip the $idx change
173 0         0 redo;
174             }
175 0         0 return $self;
176             }
177              
178             sub span_completion_callbacks {
179             shift->{span_completion_callbacks}->@*
180 2     2 0 7 }
181              
182             sub inject {
183 0     0 0   my ($self, $span, %args) = @_;
184 0   0       $args{format} //= 'text_map';
185 0 0         if($args{format} eq 'text_map') {
186             return {
187 0           map {; $_ => $span->$_ } qw(id parent_id operation_name start_time finish_time),
  0            
188             }
189             } else {
190             die 'unknown format ' . $args{format}
191 0           }
192             }
193              
194             sub span_for_future {
195 0     0 0   my ($self, $f, %args) = @_;
196 0           my $span = $self->span(
197             operation_name => $f->label,
198             %args,
199             );
200             $f->on_ready(sub {
201 0     0     $span->tag(
202             'future.state' => $f->state
203             );
204 0           $span->finish;
205 0           undef $f;
206 0           undef $span
207 0           });
208 0           return $span;
209             }
210              
211             sub extract {
212 0     0 0   my ($self, $data, %args) = @_;
213 0   0       $args{format} //= 'text_map';
214 0 0         if($args{format} eq 'text_map') {
215 0           return OpenTracing::Span->new(%$data);
216             } else {
217             die 'unknown format ' . $args{format}
218 0           }
219             }
220              
221             sub extract_finished_spans {
222 0     0 0   my ($self, $count) = @_;
223 0 0         if(!defined($count)) {
    0          
224 0           $count = 10;
225             } elsif(!$count) {
226 0           $count = @{$self->{finished_spans}};
  0            
227             }
228 0           return splice @{$self->{finished_spans}}, 0, min(0 + @{$self->{finished_spans}}, $count);
  0            
  0            
229             }
230              
231             =head2 DESTROY
232              
233             Triggers callbacks when the batch is discarded. Normally used by the transport
234             mechanism to ensure that the batch is sent over to the tracing endpoint.
235              
236             =cut
237              
238             sub DESTROY {
239 0     0     my ($self) = @_;
240 0 0         return if ${^GLOBAL_PHASE} eq 'DESTRUCT';
241             my $on_destroy = delete $self->{on_destroy}
242 0 0         or return;
243 0           $self->$on_destroy;
244 0           return;
245             }
246              
247             1;
248              
249             __END__