File Coverage

blib/lib/OpenTracing/Role/Tracer.pm
Criterion Covered Total %
statement 122 185 65.9
branch 19 74 25.6
condition 5 18 27.7
subroutine 37 40 92.5
pod 5 6 83.3
total 188 323 58.2


line stmt bran cond sub pod time code
1             package OpenTracing::Role::Tracer;
2              
3             our $VERSION = 'v0.86.1';
4              
5 9     9   1434949 use syntax qw/maybe/;
  9         184586  
  9         41  
6              
7 9     9   31003 use Moo::Role;
  9         13627  
  9         55  
8 9     9   7889 use MooX::HandlesVia;
  9         10407  
  9         52  
9 9     9   4987 use MooX::Should;
  9         33157  
  9         68  
10              
11 9     9   888 use Carp;
  9         23  
  9         503  
12 9     9   52 use List::Util qw/first/;
  9         20  
  9         1032  
13 9     9   4366 use OpenTracing::Types qw/ScopeManager Span SpanContext is_Span is_SpanContext/;
  9         1196631  
  9         84  
14 9     9   16078 use Ref::Util qw/is_plain_hashref/;
  9         5185  
  9         774  
15 9     9   4190 use Role::Declare::Should -lax;
  9         11487  
  9         100  
16 9     9   561323 use Try::Tiny;
  9         24  
  9         621  
17 9     9   4695 use Types::Common::Numeric qw/PositiveOrZeroNum/;
  9         247240  
  9         93  
18 9     9   8121 use Types::Standard qw/ArrayRef CodeRef Dict HashRef InstanceOf Maybe Object Str Undef/;
  9         31  
  9         50  
19 9     9   32077 use Types::TypeTiny qw/TypeTiny/;
  9         47  
  9         107  
20              
21             our @CARP_NOT;
22              
23             has scope_manager => (
24             is => 'ro',
25             should => ScopeManager,
26             reader => 'get_scope_manager',
27             default => sub {
28             require 'OpenTracing::Implementation::NoOp::ScopeManager';
29             return OpenTracing::Implementation::NoOp::ScopeManager->new
30             },
31             );
32              
33             sub get_active_span {
34 0     2 1 0 my $self = shift;
35            
36 0 100       0 my $scope_manager = $self->get_scope_manager
37             or croak "Can't get a 'ScopeManager'";
38            
39 9 50       9401 my $scope = $scope_manager->get_active_scope
40             or return;
41            
42 2         1384 return $scope->get_span;
43             }
44              
45             sub start_active_span {
46 2     5 1 45 my $self = shift;
47 2 100       259 my $operation_name = shift
48             or croak "Missing required operation_name";
49 1         160 my $opts = { @_ };
50            
51             my $finish_span_on_close =
52             exists( $opts->{ finish_span_on_close } ) ?
53             !! delete $opts->{ finish_span_on_close }
54             : !undef
55 5 100       10293 ; # use 'truthness' of param if provided, or set to 'true' otherwise
56            
57 5         17 my $span = $self->start_span( $operation_name => %$opts );
58            
59 5         14 my $scope_manager = $self->get_scope_manager();
60 5         20 my $scope = $scope_manager->activate_span( $span,
61             finish_span_on_close => $finish_span_on_close
62             );
63            
64 5         23 return $scope
65             }
66              
67             sub start_span {
68 5     2 1 629 my $self = shift;
69            
70 5 100       525 my $operation_name = shift
71             or croak "Missing required operation_name";
72 5         432 my $opts = { @_ };
73            
74 2         2841 my $start_time = delete $opts->{ start_time };
75 2         9 my $ignore_active_span = delete $opts->{ ignore_active_span };
76 2         10 my $child_of = delete $opts->{ child_of };
77 2         5 my $tags = delete $opts->{ tags };
78            
79 2 0 0     5 $child_of //= $self->get_active_span()
80             unless $ignore_active_span;
81            
82 2         4 my $context;
83            
84 2 50       4 $context = $child_of
85             if is_SpanContext($child_of);
86            
87 2 0       13 $context = $child_of->get_context
88             if is_Span($child_of);
89            
90 2 0       82 $context = $context->new_clone->with_trace_id( $context->trace_id )
91             if is_SpanContext($context);
92            
93 2 0       10 $context = $self->build_context( )
94             unless defined $context;
95            
96 2         8 my $span = $self->build_span(
97             operation_name => $operation_name,
98             context => $context,
99            
100             maybe
101             child_of => $child_of,
102            
103             maybe
104             start_time => $start_time,
105            
106             maybe
107             tags => $tags,
108             );
109             #
110             # we should get rid of passing 'child_of' or the not exisitng 'follows_from'
111             # these are merely helpers to define 'references'.
112            
113 2         10 return $span
114             }
115              
116              
117              
118             sub extract_context {
119 2     3 1 18 my $self = shift;
120 2         70 my $carrier = shift;
121 2         231 my $context = shift;
122            
123 3         2463 my $context_formatter =
124             $self->_first_context_formatter_for_carrier( $carrier );
125            
126 3         6 my $formatter = $context_formatter->{extractor};
127 3         5 return $self->$formatter( $carrier );
128             }
129              
130              
131              
132             sub inject_context {
133 3     9 1 17 my $self = shift;
134 3         7 my $carrier = shift;
135 3         7 my $context = shift;
136            
137 9         8233 my $context_formatter =
138             $self->_first_context_formatter_for_carrier( $carrier );
139            
140 9   0     16 $context //= $self->get_active_context();
141 9 0       15 return $carrier unless defined $context;
142 9         45 my $formatter = $context_formatter->{injector};
143 9         41 return $self->$formatter( $carrier, $context );
144             }
145              
146              
147              
148             # XXX this is not a OpenTracing API method
149             #
150             sub get_active_context {
151 9     0 0 503 my $self = shift;
152            
153 6 0       12 my $active_span = $self->get_active_span
154             or return;
155            
156 6         54 return $active_span->get_context
157             }
158              
159              
160              
161 9         58 use constant ContextFormatter => Dict[
162             type => TypeTiny,
163             injector => CodeRef,
164             extractor => CodeRef,
165 9     9   9465 ];
  9         21  
166              
167              
168              
169             has context_formatters => (
170             is => 'rw',
171             should => ArrayRef[ContextFormatter],
172             handles_via => 'Array',
173             handles => {
174             register_context_formatter => 'unshift',
175             known_context_formatters => 'elements',
176             },
177             default => \&_default_context_formatters,
178             );
179              
180             sub _default_context_formatters {
181             [
182             {
183             type => Undef,
184 0     0   0 injector => sub {undef },
185 0     0   0 extractor => sub {undef },
186             },
187             {
188             type => ArrayRef,
189 0     2   0 injector => sub {shift->inject_context_into_array_reference(@_) },
190 0     1   0 extractor => sub {shift->extract_context_from_array_reference(@_)},
191             },
192             {
193             type => HashRef,
194 0     2   0 injector => sub {shift->inject_context_into_hash_reference(@_) },
195 2     1   8 extractor => sub {shift->extract_context_from_hash_reference(@_) },
196             },
197             {
198             type => InstanceOf['HTTP::Headers'],
199 1     2   4 injector => sub {shift->inject_context_into_http_headers(@_) },
200 2     1   7 extractor => sub {shift->extract_context_from_http_headers(@_) },
201             },
202 1     20   4 ]
203             }
204              
205             sub _first_context_formatter_for_carrier {
206 2     12   13 my $self = shift;
207 1         4 my $carrier = shift;
208            
209 12     36   28 my $context_formatter = first { $_->{type}->check($carrier) }
210 20         138391 $self->known_context_formatters;
211            
212 12         17 my $type = ref($carrier) || 'Scalar';
213 12 0       251 croak "Unsupported carrier format [$type]"
214             unless defined $context_formatter;
215            
216 36         974 return $context_formatter
217             }
218              
219              
220              
221             instance_method extract_context_from_array_reference(
222             ArrayRef $carrier,
223 9 0   9   84042 ) :ReturnMaybe(SpanContext) {};
  9 0       36  
  9 0       110  
  0 0       0  
  0         0  
  0         0  
  9         24178  
  9         33  
  12         250  
  12         29  
224              
225             instance_method extract_context_from_hash_reference(
226             HashRef $carrier,
227 9 0   9   46 ) :ReturnMaybe(SpanContext) {};
  0 0       0  
  0         0  
  0         0  
  0         0  
  9         13755  
  9         23  
  9         37  
  12         27  
228              
229             instance_method extract_context_from_http_headers(
230             Object $carrier,
231 0 0       0 ) :ReturnMaybe(SpanContext) {
  0 0       0  
  0         0  
  9         18316  
  9         23  
232 9         41 ( InstanceOf['HTTP::Headers'] )->assert_valid( $carrier )
233 0     9   0 };
  0         0  
  0         0  
234              
235             instance_method inject_context_into_array_reference(
236             ArrayRef $carrier,
237             Maybe[ SpanContext ] $span_context = undef,
238 0 0   9   0 ) :Return(ArrayRef) {};
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
239              
240             instance_method inject_context_into_hash_reference(
241             HashRef $carrier,
242             Maybe[ SpanContext ] $span_context = undef,
243 0 0   9   0 ) :Return(HashRef) {};
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  9         15732  
244              
245             instance_method inject_context_into_http_headers(
246             Object $carrier,
247             Maybe[ SpanContext ] $span_context = undef,
248 0 0       0 ) :Return(InstanceOf['HTTP::Headers']) {
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  9         16515  
249 9         103 ( InstanceOf['HTTP::Headers'] )->assert_valid( $carrier )
250 9     9   20 };
  9         37  
  0         0  
251              
252              
253             instance_method build_span (
254             Str :$operation_name,
255             SpanContext :$context,
256             Maybe[ SpanContext | Span ] :$child_of,
257             Maybe[ PositiveOrZeroNum ] :$start_time,
258             Maybe[ HashRef[Str] ] :$tags,
259 9 0 0 9   51 ) :Return (Span) { };
  0 50 33     0  
  0 100 100     0  
  0 50 33     0  
  0 100       0  
  0 50       0  
  0         0  
  0         0  
  9         252015  
  9         29  
  9         61  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
260              
261              
262             instance_method build_context (
263             %span_context_args,
264 9 100       11852 ) :Return (SpanContext) {
  9         21  
  9         156  
  0         0  
265 0         0 ( HashRef[Str] )->assert_valid( { %span_context_args } );
266 0     9   0 };
  0         0  
  0         0  
267              
268              
269             BEGIN {
270             # use Role::Tiny::With;
271 0     9   0 with 'OpenTracing::Interface::Tracer'
272             }
273              
274              
275              
276             1;