File Coverage

blib/lib/OpenTelemetry/SDK.pm
Criterion Covered Total %
statement 103 105 98.1
branch 32 34 94.1
condition 7 10 70.0
subroutine 17 17 100.0
pod 2 2 100.0
total 161 168 95.8


line stmt bran cond sub pod time code
1             package OpenTelemetry::SDK;
2             # ABSTRACT: An implementation of the OpenTelemetry SDK for Perl
3              
4             our $VERSION = '0.028';
5              
6 3     3   27 use strict;
  3         7  
  3         138  
7 3     3   17 use warnings;
  3         5  
  3         182  
8 3     3   18 use experimental 'signatures';
  3         5  
  3         21  
9 3     3   436 use feature 'state';
  3         4  
  3         93  
10              
11 3     3   512 use Feature::Compat::Try;
  3         372  
  3         28  
12 3     3   736 use Module::Runtime;
  3         2310  
  3         45  
13 3     3   136 use OpenTelemetry::Common 'config';
  3         6  
  3         201  
14 3     3   1654 use OpenTelemetry::Propagator::Composite;
  3         24423  
  3         198  
15 3     3   530 use OpenTelemetry::SDK::Trace::TracerProvider;
  3         9  
  3         198  
16 3     3   17 use OpenTelemetry::X;
  3         7  
  3         108  
17 3     3   16 use OpenTelemetry;
  3         7  
  3         35  
18 3     3   1064 use Ref::Util 'is_coderef';
  3         6  
  3         202  
19 3     3   16 use Scalar::Util 'blessed';
  3         7  
  3         138  
20              
21 3     3   14 use isa 'OpenTelemetry::X';
  3         6  
  3         22  
22              
23 12     12 1 110088 sub configure_propagators ($, @args) {
  12         34  
  12         19  
24 12         59 my $logger = OpenTelemetry::Common::internal_logger;
25              
26 12         65 state %map = (
27             b3 => 'B3',
28             b3multi => 'B3::Multi',
29             baggage => 'Baggage',
30             jaeger => 'Jaeger',
31             none => 'None',
32             ottrace => 'OTTrace',
33             tracecontext => 'TraceContext',
34             xray => 'XRay',
35             );
36              
37 12 100 100     62 push @args, split ',',
38             ( config('PROPAGATORS') // 'tracecontext,baggage' ) =~ s/\s//gr
39             unless @args;
40              
41 11         329 my ( %seen, @propagators );
42 11         96 for my $candidate ( grep !!$_, @args ) {
43 13 100       87 if ( blessed $candidate ) {
44 3 100       32 if ( $candidate->DOES('OpenTelemetry::Propagator') ) {
45 2         5 push @propagators, $candidate;
46             }
47             else {
48 1         7 $logger->warnf("Attempted to configure a '%s' propagator, but it does not do the OpenTelemetry::Propagator role", ref $candidate );
49             }
50 3         126 next;
51             }
52              
53 10         43 my $suffix = $map{$candidate};
54 10 100       30 unless ($suffix) {
55 2         18 $logger->warn("Unknown propagator '$candidate' cannot be configured");
56 2         183 next;
57             }
58              
59 8 50       39 next if $seen{$suffix}++;
60              
61 8         21 my $class = 'OpenTelemetry::Propagator::' . $suffix;
62              
63 8         22 try {
64 8         46 Module::Runtime::require_module $class;
65 7         25905 push @propagators, $class->new;
66             }
67             catch ($e) {
68 1         29 die OpenTelemetry::X->create(
69             Invalid => "Error configuring '$candidate' propagator: $e",
70             );
71             }
72             }
73              
74             # If we have no good ones, keep the default
75 10 100       138 return OpenTelemetry->propagator unless @propagators;
76              
77             # If we have only one good one, set that one as the global one
78 7 100       56 return OpenTelemetry->propagator = shift @propagators if @propagators == 1;
79              
80             # If we have multiple good ones, wrap them in a composite
81 2         31 OpenTelemetry->propagator
82             = OpenTelemetry::Propagator::Composite->new(@propagators),
83             }
84              
85 6     6 1 100357 sub configure_tracer_provider ($, $provider = undef, @) {
  6         23  
  6         13  
86 6         56 my $logger = OpenTelemetry::Common::internal_logger;
87              
88 6         38 state %map = (
89             jaeger => '::Jaeger',
90             otlp => '::OTLP::Traces',
91             zipkin => '::Zipkin',
92             console => 'OpenTelemetry::SDK::Exporter::Console',
93             );
94              
95 6   100     61 my @names = split ',',
96             ( config('TRACES_EXPORTER') // 'otlp' ) =~ s/\s//gr;
97              
98 6 100       396 if ($provider) {
99 3 100 33     90 if ( ! blessed $provider ) {
    100          
100 1         10 $logger->warnf('Attempted to configure a tracer provider that was not a blessed reference: %s', $provider );
101 1         120 undef $provider;
102             }
103             elsif (
104             !$provider->can('tracer')
105             || !$provider->can('add_span_processor')
106             || !$provider->can('shutdown')
107             || !$provider->can('force_flush')
108             ) {
109 1         62 $logger->warnf("Attempted to configure a '%s' tracer provider, but it does not implement the OpenTelemetry::SDK::Trace::TracerProvider interface", ref $provider );
110 1         163 undef $provider;
111             }
112             }
113              
114 6   66     144 $provider //= OpenTelemetry::SDK::Trace::TracerProvider->new;
115              
116 6         5872 my %seen;
117 6         24 for my $name ( @names ) {
118 6 100       30 next if $name eq 'none';
119              
120 5 100       26 unless ( $map{$name} ) {
121 1         9 $logger->warnf("Unknown exporter '%s' cannot be configured", $name);
122 1         126 next;
123             }
124              
125 4 50       28 next if $seen{ $map{$name} }++;
126              
127             my $exporter = $map{$name} =~ /^::/
128             ? ( 'OpenTelemetry::Exporter' . $map{$name} )
129 4 100       30 : $map{$name};
130              
131 4 100       29 my $processor = 'OpenTelemetry::SDK::Trace::Span::Processor::'
132             . ( $name eq 'console' ? 'Simple' : 'Batch' );
133              
134 4         16 try {
135 4         77 Module::Runtime::require_module $exporter;
136 4         213951 Module::Runtime::require_module $processor;
137              
138 4         177 $provider->add_span_processor(
139             $processor->new( exporter => $exporter->new )
140             );
141             }
142             catch ($e) {
143 0         0 die OpenTelemetry::X->create(
144             Invalid => "Error configuring '$name' span processor: $e",
145             );
146             }
147             }
148              
149 6         12215 OpenTelemetry->tracer_provider = $provider;
150             }
151              
152 3     3   606678 sub import ( $class ) {
  3         9  
  3         5  
153 3 100       13 return if config('SDK_DISABLED');
154              
155 2         97 try {
156             # TODO: logger
157             # TODO: error_handler
158              
159 2         10 configure_propagators(1);
160 0         0 configure_tracer_provider(1);
161             }
162             catch ($e) {
163 2 100       704 die $e if isa_OpenTelemetry_X $e;
164 1         17 die OpenTelemetry::X->create(
165             Invalid => "Unexpected error initialising OpenTelemetry::SDK: $e",
166             );
167             }
168             }
169              
170             1;