File Coverage

blib/lib/OpenTracing/Role/Tracer.pm
Criterion Covered Total %
statement 122 185 65.9
branch 19 74 25.6
condition 4 9 44.4
subroutine 37 40 92.5
pod 5 6 83.3
total 187 314 59.5


line stmt bran cond sub pod time code
1             package OpenTracing::Role::Tracer;
2              
3             our $VERSION = 'v0.86.0';
4              
5 9     9   1374140 use syntax qw/maybe/;
  9         175735  
  9         43  
6              
7 9     9   29906 use Moo::Role;
  9         12481  
  9         69  
8 9     9   7959 use MooX::HandlesVia;
  9         9698  
  9         64  
9 9     9   4849 use MooX::Should;
  9         32866  
  9         59  
10              
11 9     9   888 use Carp;
  9         22  
  9         502  
12 9     9   54 use List::Util qw/first/;
  9         21  
  9         1031  
13 9     9   4043 use OpenTracing::Types qw/ScopeManager Span SpanContext is_Span is_SpanContext/;
  9         523792  
  9         73  
14 9     9   14957 use Ref::Util qw/is_plain_hashref/;
  9         13951  
  9         720  
15 9     9   3966 use Role::Declare::Should -lax;
  9         10730  
  9         67  
16 9     9   1162111 use Try::Tiny;
  9         28  
  9         693  
17 9     9   5284 use Types::Common::Numeric qw/PositiveOrZeroNum/;
  9         235529  
  9         1332  
18 9     9   9644 use Types::Standard qw/ArrayRef CodeRef Dict HashRef InstanceOf Maybe Object Str Undef/;
  9         1268  
  9         57  
19 9     9   34527 use Types::TypeTiny qw/TypeTiny/;
  9         45  
  9         1363  
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       9063 my $scope = $scope_manager->get_active_scope
40             or return;
41            
42 2         1336 return $scope->get_span;
43             }
44              
45             sub start_active_span {
46 2     5 1 43 my $self = shift;
47 2 100       576 my $operation_name = shift
48             or croak "Missing required operation_name";
49 1         104 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       10280 ; # use 'truthness' of param if provided, or set to 'true' otherwise
56            
57 5         38 my $span = $self->start_span( $operation_name => %$opts );
58            
59 5         14 my $scope_manager = $self->get_scope_manager();
60 5         27 my $scope = $scope_manager->activate_span( $span,
61             finish_span_on_close => $finish_span_on_close
62             );
63            
64 5         24 return $scope
65             }
66              
67             sub start_span {
68 5     2 1 600 my $self = shift;
69            
70 5 100       530 my $operation_name = shift
71             or croak "Missing required operation_name";
72 5         413 my $opts = { @_ };
73            
74 2         2604 my $start_time = delete $opts->{ start_time };
75 2         7 my $ignore_active_span = delete $opts->{ ignore_active_span };
76 2         8 my $child_of = delete $opts->{ child_of };
77 2         4 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         5 my $context;
83            
84 2 50       4 $context = $child_of
85             if is_SpanContext($child_of);
86            
87 2 0       14 $context = $child_of->get_context
88             if is_Span($child_of);
89            
90 2 0       83 $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 19 my $self = shift;
120 2         76 my $carrier = shift;
121 2         220 my $context = shift;
122            
123 3         2433 my $context_formatter =
124             $self->_first_context_formatter_for_carrier( $carrier );
125            
126 3         7 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         9 my $context = shift;
136            
137 9         8197 my $context_formatter =
138             $self->_first_context_formatter_for_carrier( $carrier );
139            
140 9   33     17 $context //= $self->get_active_context();
141 9 0       14 return $carrier unless defined $context;
142 9         41 my $formatter = $context_formatter->{injector};
143 9         39 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 451 my $self = shift;
152            
153 6 0       12 my $active_span = $self->get_active_span
154             or return;
155            
156 6         17 return $active_span->get_context
157             }
158              
159              
160              
161 9         62 use constant ContextFormatter => Dict[
162             type => TypeTiny,
163             injector => CodeRef,
164             extractor => CodeRef,
165 9     9   9963 ];
  9         27  
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   7 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   6 extractor => sub {shift->extract_context_from_http_headers(@_) },
201             },
202 1     20   3 ]
203             }
204              
205             sub _first_context_formatter_for_carrier {
206 2     12   18 my $self = shift;
207 1         4 my $carrier = shift;
208            
209 12     36   23 my $context_formatter = first { $_->{type}->check($carrier) }
210 20         139121 $self->known_context_formatters;
211            
212 12   100     22 my $type = ref($carrier) || 'Scalar';
213 12 0       253 croak "Unsupported carrier format [$type]"
214             unless defined $context_formatter;
215            
216 36         959 return $context_formatter
217             }
218              
219              
220              
221             instance_method extract_context_from_array_reference(
222             ArrayRef $carrier,
223 9 0   9   82837 ) :ReturnMaybe(SpanContext) {};
  9 0       49  
  9 0       102  
  0 0       0  
  0         0  
  0         0  
  9         20734  
  9         20  
  12         264  
  12         37  
224              
225             instance_method extract_context_from_hash_reference(
226             HashRef $carrier,
227 9 0   9   34 ) :ReturnMaybe(SpanContext) {};
  0 0       0  
  0         0  
  0         0  
  0         0  
  9         11612  
  9         24  
  9         46  
  12         26  
228              
229             instance_method extract_context_from_http_headers(
230             Object $carrier,
231 0 0       0 ) :ReturnMaybe(SpanContext) {
  0 0       0  
  0         0  
  9         13513  
  9         32  
232 9         33 ( 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         12393  
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         12585  
249 9         89 ( InstanceOf['HTTP::Headers'] )->assert_valid( $carrier )
250 9     9   25 };
  9         41  
  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   9   60 ) :Return (Span) { };
  0 50       0  
  0 100       0  
  0 50       0  
  0 100       0  
  0 50       0  
  0         0  
  0         0  
  9         229348  
  9         28  
  9         56  
  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       10863 ) :Return (SpanContext) {
  9         23  
  9         121  
  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;