File Coverage

blib/lib/OpenTracing/Integration/DBI.pm
Criterion Covered Total %
statement 51 59 86.4
branch 2 4 50.0
condition 4 11 36.3
subroutine 13 14 92.8
pod 0 2 0.0
total 70 90 77.7


line stmt bran cond sub pod time code
1             package OpenTracing::Integration::DBI;
2             # ABSTRACT: OpenTracing APM support for DBI-based database interaction
3              
4 1     1   195168 use strict;
  1         13  
  1         32  
5 1     1   5 use warnings;
  1         3  
  1         52  
6              
7             our $VERSION = '0.001';
8             our $AUTHORITY = 'cpan:TEAM'; # AUTHORITY
9              
10 1     1   5 no indirect;
  1         4  
  1         7  
11 1     1   49 use utf8;
  1         2  
  1         7  
12              
13             =encoding utf8
14              
15             =head1 NAME
16              
17             OpenTracing::Integration::DBI - support L tracing
18              
19             =head1 SYNOPSIS
20              
21             use OpenTracing::Integration qw(DBI);
22             my $dbh = DBI->connect(...);
23             $dbh->selectall_arrayref(qw{select * from information_schema.tables});
24              
25             =head1 DESCRIPTION
26              
27             See L for more details.
28              
29             =cut
30              
31 1     1   47 use Syntax::Keyword::Try;
  1         2  
  1         8  
32 1     1   530 use Role::Tiny::With;
  1         293  
  1         58  
33 1     1   514 use Class::Method::Modifiers qw(install_modifier);
  1         1732  
  1         75  
34              
35 1     1   447 use OpenTracing::DSL qw(:v1);
  1         936  
  1         1690  
36              
37             with qw(OpenTracing::Integration);
38              
39             my $loaded;
40              
41             sub type_from_sql {
42 4     4 0 11 my ($class, $sql) = @_;
43 4         25 my ($type) = $sql =~ /\b(insert|select|update|delete|truncate\s+[a-z]+|copy\s+[a-z]+|show|vacuum|alter\s+[a-z]+|create\s+[a-z]+|drop\s+[a-z]+)\b/i;
44 4         12 return $type;
45             }
46              
47             sub load {
48 1     1 0 16 my ($class, $load_deps) = @_;
49 1 50 33     8 return unless $load_deps or DBI->can('connect');
50              
51 1 50       5 unless($loaded++) {
52 1         18 require DBI;
53             install_modifier q{DBI::db}, around => prepare => sub {
54 1     1   38 my ($code, $dbh, $sql, @rest) = @_;
55 1         5 my $type = $class->type_from_sql($sql);
56             return trace {
57 1         313330048 my ($span) = @_;
58             try {
59             $span->tag(
60             'component' => 'DBI',
61             'span.kind' => 'client',
62             'db.operation' => 'prepare',
63             'db.statement' => $sql,
64             'db.type' => 'sql',
65             (defined $dbh->{Name} ? ('db.instance' => $dbh->{Name}) : ()),
66             (defined $dbh->{Username} ? ('db.user' => $dbh->{Username}) : ()),
67             );
68             return $dbh->$code($sql, @rest);
69 1         4 } catch {
70             my $err = $@;
71             $span->tag(
72             error => 1,
73             );
74             die $@;
75             }
76 1   50     13 } operation_name => 'sql prepare: ' . ($type // 'unknown');
77 1         10 };
78             install_modifier q{DBI::st}, around => execute => sub {
79 0     0   0 my ($code, $sth, @bind) = @_;
80 0         0 my $sql = $sth->{Statement};
81 0         0 my $type = $class->type_from_sql($sql);
82             return trace {
83 0         0 my ($span) = @_;
84 0         0 my $cursor = $sth->{CursorName};
85 0         0 my $dbh = $sth->{Database};
86             try {
87             $span->tag(
88             'component' => 'DBI',
89             'span.kind' => 'client',
90             'db.operation' => 'execute',
91             'db.statement' => $sql,
92             'db.type' => 'sql',
93             (defined $cursor ? ('db.cursor' => $cursor) : ()),
94             (defined $dbh->{Name} ? ('db.instance' => $dbh->{Name}) : ()),
95             (defined $dbh->{Username} ? ('db.user' => $dbh->{Username}) : ()),
96             );
97             return $sth->$code(@bind);
98 0         0 } catch {
99             my $err = $@;
100             $span->tag(
101             error => 1,
102             );
103             die $@;
104             }
105 0   0     0 } operation_name => 'sql execute: ' . ($type // 'unknown');
106 1         334 };
107             install_modifier q{DBI::db}, around => do => sub {
108 2     2   3001 my ($code, $dbh, $sql, @rest) = @_;
109 2         27 my $type = $class->type_from_sql($sql);
110             return trace {
111 2         161 my ($span) = @_;
112             try {
113             $span->tag(
114             'component' => 'DBI',
115             'span.kind' => 'client',
116             'db.operation' => 'do',
117             'db.statement' => $sql,
118             'db.type' => 'sql',
119             (defined $dbh->{Name} ? ('db.instance' => $dbh->{Name}) : ()),
120             (defined $dbh->{Username} ? ('db.user' => $dbh->{Username}) : ()),
121             );
122             return $dbh->$code($sql, @rest);
123 2         4 } catch {
124             my $err = $@;
125             $span->tag(
126             error => 1,
127             );
128             die $@;
129             }
130 2   50     31 } operation_name => 'sql do: ' . ($type // 'unknown');
131 1         286 };
132 1         281 for my $op (qw(
133             selectall_arrayref
134             selectall_hashref
135             selectall_array
136             )) {
137             install_modifier q{DBI::db}, around => $op => sub {
138 1     1   195 my ($code, $dbh, $sql, @rest) = @_;
139 1         4 my $type = $class->type_from_sql($sql);
140             return trace {
141 1         48 my ($span) = @_;
142             try {
143             $span->tag(
144             'component' => 'DBI',
145             'span.kind' => 'client',
146             'db.operation' => 'selectall',
147             'db.statement' => $sql,
148             'db.type' => 'sql',
149             (defined $dbh->{Name} ? ('db.instance' => $dbh->{Name}) : ()),
150             (defined $dbh->{Username} ? ('db.user' => $dbh->{Username}) : ()),
151             );
152             return $dbh->$code($sql, @rest);
153 1         3 } catch {
154             my $err = $@;
155             $span->tag(
156             error => 1,
157             );
158             die $@;
159             }
160 1   50     13 } operation_name => 'sql selectall: ' . ($type // 'unknown');
161 3         596 };
162             }
163             }
164             }
165              
166             1;
167              
168             __END__