• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jjatria / perl-opentelemetry / 5978321176

25 Aug 2023 04:39PM UTC coverage: 91.902% (-0.3%) from 92.179%
5978321176

push

github

jjatria
Avoid setting undefined attributes from DBI integration

5 of 5 new or added lines in 1 file covered. (100.0%)

715 of 778 relevant lines covered (91.9%)

6.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.25
/lib/OpenTelemetry/Integration/DBI.pm
1
package OpenTelemetry::Integration::DBI;
2
# ABSTRACT: OpenTelemetry integration for DBI
3

4
our $VERSION = '0.001';
5

6
use strict;
2✔
7
use warnings;
2✔
8
use experimental 'signatures';
2✔
9
use feature 'state';
2✔
10

11
use Class::Inspector;
2✔
12
use Class::Method::Modifiers 'install_modifier';
2✔
13
use Feature::Compat::Try;
2✔
14
use OpenTelemetry::Constants qw( SPAN_KIND_CLIENT SPAN_STATUS_ERROR SPAN_STATUS_OK );
2✔
15
use OpenTelemetry::Context;
2✔
16
use OpenTelemetry::Trace;
2✔
17
use OpenTelemetry;
2✔
18
use Syntax::Keyword::Dynamically;
2✔
19

20
use parent 'OpenTelemetry::Integration';
2✔
21

22
sub dependencies { 'DBI' }
1✔
23

24
my ( $EXECUTE, $DO, $loaded );
25
sub uninstall ( $class ) {
1✔
26
    return unless $loaded;
1✔
27
    no strict 'refs';
2✔
28
    no warnings 'redefine';
2✔
29
    delete $Class::Method::Modifiers::MODIFIER_CACHE{'DBI::st'}{execute};
×
30
    *{'DBI::st::execute'} = $EXECUTE;
×
31
    *{'DBI::db::do'}      = $DO;
×
32
    undef $loaded;
×
33
    return;
×
34
}
35

36
sub install ( $class, %options ) {
3✔
37
    return if $loaded;
3✔
38
    return unless Class::Inspector->loaded('DBI');
2✔
39

40
    my $wrapper = sub ( $dbh, $statement, $orig, $handle, @args ) {
5✔
41
        state %meta;
5✔
42

43
        my $name = $dbh->{Name};
5✔
44

45
        my $info = $meta{$name} //= do {
5✔
46
            my %meta = (
47
                'db.system' => lc $dbh->{Driver}{Name},
48
            );
1✔
49

50
            $meta{'db.user'}        = $dbh->{Username} if $dbh->{Username};
1✔
51
            $meta{'server.address'} = $1               if $name =~ /host=([^;]+)/;
1✔
52
            $meta{'server.port'}    = $1               if $name =~ /port=([0-9]+)/;
1✔
53

54
            # Driver-specific metadata available before call
55
            if ( $meta{'db.system'} eq 'mysql' ) {
1✔
56
                $meta{'network.transport'} = 'IP.TCP';
×
57
            }
58

59
            \%meta;
1✔
60
        };
61

62
        $statement = $statement =~ s/^\s+|\s+$//gr =~ s/\s+/ /gr;
5✔
63

64
        my $span = OpenTelemetry->tracer_provider->tracer->create_span(
5✔
65
            name       => substr($statement, 0, 100) =~ s/\s+$//r,
66
            kind       => SPAN_KIND_CLIENT,
67
            attributes => {
68
                'db.connection_string' => $name,
69
                'db.statement'         => $statement,
70
                %$info,
71
            },
72
        );
73

74
        dynamically OpenTelemetry::Context->current
5✔
75
            = OpenTelemetry::Trace->context_with_span($span);
76

77
        try {
5✔
78
            return $handle->$orig(@args);
5✔
79
        }
80
        catch ( $error ) {
81
            $span->record_exception($error);
×
82
            $span->set_status( SPAN_STATUS_ERROR, $error );
×
83
            die $error;
×
84
        }
85
        finally {
86
            if ( $handle->err ) {
5✔
87
                $span->set_status( SPAN_STATUS_ERROR, $handle->errstr );
2✔
88
            }
89
            else {
90
                $span->set_status( SPAN_STATUS_OK );
3✔
91
            }
92

93
            $span->end;
5✔
94
        }
95
    };
1✔
96

97
    $EXECUTE = \&DBI::st::execute;
1✔
98
    install_modifier 'DBI::st' => around => execute => sub {
99
        my ( undef, $sth ) = @_;
3✔
100
        unshift @_, $sth->{Database}, $sth->{Statement};
3✔
101
        goto $wrapper;
3✔
102
    };
1✔
103

104
    $DO = \&DBI::st::execute;
1✔
105
    install_modifier 'DBI::db' => around => do => sub {
106
        my ( undef, $dbh, $sql ) = @_;
2✔
107
        unshift @_, $dbh, $sql;
2✔
108
        goto $wrapper;
2✔
109
    };
1✔
110

111
    return $loaded = 1;
1✔
112
}
113

114
1;
115

116
__END__
117

118
=encoding utf8
119

120
=head1 NAME
121

122
OpenTelemetry::Integration::DBI - OpenTelemetry integration for DBI
123

124
=head1 SYNOPSIS
125

126
    use OpenTelemetry::Integration 'DBI';
127
    my $dbh = DBI->connect(...);
128
    my $result = $dbh->selectall_hashref($statement);
129

130
=head1 DESCRIPTION
131

132
See L<OpenTelemetry::Integration> for more details.
133

134
Since this is a core module, it's included in the L<OpenTelemetry> core
135
distribution as well.
136

137
=head1 COPYRIGHT
138

139
...
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc