File Coverage

blib/lib/OpenTelemetry.pm
Criterion Covered Total %
statement 83 85 97.6
branch n/a
condition n/a
subroutine 44 46 95.6
pod 5 6 83.3
total 132 137 96.3


line stmt bran cond sub pod time code
1             package OpenTelemetry;
2             # ABSTRACT: A Perl implementation of the OpenTelemetry standard
3              
4 9     9   431436 use strict;
  9         22  
  9         384  
5 9     9   58 use warnings;
  9         16  
  9         506  
6 9     9   618 use experimental qw( signatures );
  9         4889  
  9         78  
7              
8             our $VERSION = '0.033';
9              
10 9     9   7282 use Mutex;
  9         4603  
  9         378  
11 9     9   2475 use OpenTelemetry::Common;
  9         30  
  9         600  
12 9     9   2177 use OpenTelemetry::Context;
  9         26  
  9         450  
13 9     9   5157 use OpenTelemetry::Propagator::None;
  9         48  
  9         488  
14 9     9   4173 use OpenTelemetry::Trace::TracerProvider;
  9         39  
  9         556  
15 9     9   4859 use OpenTelemetry::Logs::LoggerProvider;
  9         30  
  9         476  
16 9     9   71 use OpenTelemetry::X;
  9         22  
  9         315  
17 9     9   57 use Scalar::Util 'refaddr';
  9         20  
  9         718  
18 9     9   82 use Ref::Util 'is_coderef';
  9         21  
  9         515  
19 9     9   58 use Sentinel;
  9         19  
  9         615  
20              
21 9         80 use isa qw(
22             OpenTelemetry::Logs::LoggerProvider
23             OpenTelemetry::Trace::TracerProvider
24 9     9   61 );
  9         19  
25              
26 9     9   2720 use Log::Any;
  9         22  
  9         88  
27              
28 9         94 use Exporter::Shiny qw(
29             otel_config
30             otel_context_with_span
31             otel_current_context
32             otel_error_handler
33             otel_handle_error
34             otel_logger
35             otel_logger_provider
36             otel_propagator
37             otel_span_from_context
38             otel_tracer_provider
39             otel_untraced_context
40 9     9   829 );
  9         20  
41              
42             my $logger = OpenTelemetry::Common::internal_logger;
43 2     2 0 397589 sub logger { $logger }
44 2     2   169 sub _generate_otel_logger { \&logger }
45              
46             {
47             my $lock = Mutex->new;
48             my $instance = OpenTelemetry::Trace::TracerProvider->new;
49              
50             my $set = sub ( $new ) {
51             die OpenTelemetry::X->create(
52             Invalid => 'Global tracer provider must be a subclass of OpenTelemetry::Trace::TracerProvider, got instead ' . ( ref $new || 'a plain scalar' ),
53             ) unless isa_OpenTelemetry_Trace_TracerProvider $new;
54              
55             $lock->enter( sub { $instance = $new });
56             };
57              
58             sub _generate_otel_tracer_provider {
59 5     5   16 my $x = sub :lvalue { sentinel get => sub { $instance }, set => $set };
  4     2   1391  
  2         236  
60             }
61              
62 9     9 1 25 sub tracer_provider :lvalue { sentinel get => sub { $instance }, set => $set }
  6     6   4521  
63             }
64              
65             # FIXME: The functions in this block mean that in all likelihood
66             # OpenTelemetry->logger will have to go away. It no longer fits,
67             # since we gain the concept of a logger, which is different from
68             # the logger we used to return (which is just a Log::Any logger).
69             # This is not such a big problem: it just means that users who
70             # want to use the same logger as the rest of the OpenTelemetry
71             # implementation need to do
72             #
73             # my $log = Log::Any->get_logger( category => 'OpenTelemetry' );
74             #
75             # but you can argue that that's not so onerous, and if it is, that
76             # logging on that given category rather than the default one is
77             # pointless.
78             {
79             my $lock = Mutex->new;
80             my $instance = OpenTelemetry::Logs::LoggerProvider->new;
81              
82             my $set = sub ( $new ) {
83             die OpenTelemetry::X->create(
84             Invalid => 'Global logger provider must be a subclass of OpenTelemetry::Logs::LoggerProvider, got instead ' . ( ref $new || 'a plain scalar' ),
85             ) unless isa_OpenTelemetry_Logs_LoggerProvider $new;
86              
87             $lock->enter( sub { $instance = $new });
88             };
89              
90             sub _generate_otel_logger_provider {
91 48     48   382 my $x = sub :lvalue { sentinel get => sub { $instance }, set => $set };
  94     3   558  
  3         297  
92             }
93              
94 0     0 1 0 sub logger_provider :lvalue { sentinel get => sub { $instance }, set => $set }
  0     0   0  
95             }
96              
97             {
98             my $lock = Mutex->new;
99             my $instance = OpenTelemetry::Propagator::None->new;
100              
101             my $set = sub ( $new ) {
102             die OpenTelemetry::X->create(
103             Invalid => 'Global propagator must implement the OpenTelemetry::Propagator role, got instead ' . ( ref $new || 'a plain scalar' ),
104             ) unless $new && $new->DOES('OpenTelemetry::Propagator');
105              
106             $lock->enter( sub { $instance = $new });
107             };
108              
109             sub _generate_otel_propagator {
110 3     3   89 my $x = sub :lvalue { sentinel get => sub { $instance }, set => $set };
  5     2   17  
  2         180  
111             }
112              
113 34     34 1 179 sub propagator :lvalue { sentinel get => sub { $instance }, set => $set }
  18     18   2140  
114             }
115              
116             sub _generate_otel_untraced_context {
117 1     1   1560 my $sub = sub :lvalue { OpenTelemetry::Trace->untraced_context };
  2     2   175  
118             }
119              
120             sub _generate_otel_current_context {
121 5     5   1723 my $sub = sub :lvalue { OpenTelemetry::Context->current };
  2     2   185  
122             }
123              
124             sub _generate_otel_context_with_span {
125 1     1   2259 sub { OpenTelemetry::Trace->context_with_span(@_) };
  2     2   281  
126             }
127              
128             sub _generate_otel_span_from_context {
129 3     3   629 sub { OpenTelemetry::Trace->span_from_context(@_) };
  3     3   325  
130             }
131              
132             sub _generate_otel_config {
133 3     3   2064 \&OpenTelemetry::Common::config;
134             }
135              
136             {
137             my $lock = Mutex->new;
138             my $instance = sub (%args) {
139             my $error = join ' - ', grep defined,
140             @args{qw( message exception )};
141              
142             $logger->error( "OpenTelemetry error: $error", $args{details} );
143             };
144              
145             my $set = sub ( $new ) {
146             die OpenTelemetry::X->create(
147             Invalid => 'Global error handler must be a code reference, got instead ' . ( ref $new || 'a plain scalar' ),
148             ) unless is_coderef $new;
149              
150             $lock->enter( sub { $instance = $new });
151             };
152              
153             sub _generate_otel_error_handler {
154 4     4   1140 my $x = sub :lvalue { sentinel get => sub { $instance }, set => $set };
  3     2   100  
  2         177  
155             }
156              
157 2     2 1 10 sub error_handler :lvalue { sentinel get => sub { $instance }, set => $set }
  3     3   2776  
158              
159 5     5   34 sub _generate_otel_handle_error { sub { $instance->(@_); return } }
  5     2   9384  
  2         180  
160 5     5 1 32 sub handle_error { shift; $instance->(@_); return }
  5         19  
  5         308  
161             }
162              
163             1;