Standardize the Moo import block, move quote_sub/qsub into ::_Util
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / Statistics.pm
1 package DBIx::Class::Storage::Statistics;
2
3 use strict;
4 use warnings;
5
6 # DO NOT edit away without talking to riba first, he will just put it back
7 # BEGIN pre-Moo2 import block
8 BEGIN {
9   my $initial_fatal_bits = (${^WARNING_BITS}||'') & $warnings::DeadBits{all};
10   local $ENV{PERL_STRICTURES_EXTRA} = 0;
11   require Moo; Moo->import;
12   ${^WARNING_BITS} &= ( $initial_fatal_bits | ~ $warnings::DeadBits{all} );
13 }
14 # END pre-Moo2 import block
15
16 extends 'DBIx::Class';
17 use DBIx::Class::_Util qw(sigwarn_silencer qsub);
18 use namespace::clean;
19
20 =head1 NAME
21
22 DBIx::Class::Storage::Statistics - SQL Statistics
23
24 =head1 SYNOPSIS
25
26 =head1 DESCRIPTION
27
28 This class is called by DBIx::Class::Storage::DBI as a means of collecting
29 statistics on its actions.  Using this class alone merely prints the SQL
30 executed, the fact that it completes and begin/end notification for
31 transactions.
32
33 To really use this class you should subclass it and create your own method
34 for collecting the statistics as discussed in L<DBIx::Class::Manual::Cookbook>.
35
36 =head1 METHODS
37
38 =head2 new
39
40 Returns a new L<DBIx::Class::Storage::Statistics> object.
41
42 =head2 debugfh
43
44 Sets or retrieves the filehandle used for trace/debug output.  This should
45 be an IO::Handle compatible object (only the C<print> method is used). Initially
46 should be set to STDERR - although see information on the
47 L<DBIC_TRACE> environment variable.
48
49 As getter it will lazily open a filehandle for you if one is not already set.
50
51 =cut
52
53 # FIXME - there ought to be a way to fold this into _debugfh itself
54 # having the undef re-trigger the builder (or better yet a default
55 # which can be folded in as a qsub)
56 sub debugfh {
57   my $self = shift;
58
59   return $self->_debugfh(@_) if @_;
60   $self->_debugfh || $self->_build_debugfh;
61 }
62
63 has _debugfh => (
64   is => 'rw',
65   lazy => 1,
66   trigger => qsub '$_[0]->_defaulted_to_stderr(undef)',
67   builder => '_build_debugfh',
68 );
69
70 sub _build_debugfh {
71   my $fh;
72
73   my $debug_env = $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG} || $ENV{DBIC_TRACE};
74
75   if (defined($debug_env) and ($debug_env =~ /=(.+)$/)) {
76     open ($fh, '>>', $1)
77       or die("Cannot open trace file $1: $!\n");
78   }
79   else {
80     open ($fh, '>&STDERR')
81       or die("Duplication of STDERR for debug output failed (perhaps your STDERR is closed?): $!\n");
82     $_[0]->_defaulted_to_stderr(1);
83   }
84
85   $fh;
86 }
87
88 has [qw(_defaulted_to_stderr silence callback)] => (
89   is => 'rw',
90 );
91
92 =head2 print
93
94 Prints the specified string to our debugging filehandle.  Provided to save our
95 methods the worry of how to display the message.
96
97 =cut
98 sub print {
99   my ($self, $msg) = @_;
100
101   return if $self->silence;
102
103   my $fh = $self->debugfh;
104
105   # not using 'no warnings' here because all of this can change at runtime
106   local $SIG{__WARN__} = sigwarn_silencer(qr/^Wide character in print/)
107     if $self->_defaulted_to_stderr;
108
109   $fh->printflush($msg);
110 }
111
112 =head2 silence
113
114 Turn off all output if set to true.
115
116 =head2 txn_begin
117
118 Called when a transaction begins.
119
120 =cut
121 sub txn_begin {
122   my $self = shift;
123
124   return if $self->callback;
125
126   $self->print("BEGIN WORK\n");
127 }
128
129 =head2 txn_rollback
130
131 Called when a transaction is rolled back.
132
133 =cut
134 sub txn_rollback {
135   my $self = shift;
136
137   return if $self->callback;
138
139   $self->print("ROLLBACK\n");
140 }
141
142 =head2 txn_commit
143
144 Called when a transaction is committed.
145
146 =cut
147 sub txn_commit {
148   my $self = shift;
149
150   return if $self->callback;
151
152   $self->print("COMMIT\n");
153 }
154
155 =head2 svp_begin
156
157 Called when a savepoint is created.
158
159 =cut
160 sub svp_begin {
161   my ($self, $name) = @_;
162
163   return if $self->callback;
164
165   $self->print("SAVEPOINT $name\n");
166 }
167
168 =head2 svp_release
169
170 Called when a savepoint is released.
171
172 =cut
173 sub svp_release {
174   my ($self, $name) = @_;
175
176   return if $self->callback;
177
178   $self->print("RELEASE SAVEPOINT $name\n");
179 }
180
181 =head2 svp_rollback
182
183 Called when rolling back to a savepoint.
184
185 =cut
186 sub svp_rollback {
187   my ($self, $name) = @_;
188
189   return if $self->callback;
190
191   $self->print("ROLLBACK TO SAVEPOINT $name\n");
192 }
193
194 =head2 query_start
195
196 Called before a query is executed.  The first argument is the SQL string being
197 executed and subsequent arguments are the parameters used for the query.
198
199 =cut
200 sub query_start {
201   my ($self, $string, @bind) = @_;
202
203   my $message = "$string: ".join(', ', @bind)."\n";
204
205   if(defined($self->callback)) {
206     $string =~ m/^(\w+)/;
207     $self->callback->($1, $message);
208     return;
209   }
210
211   $self->print($message);
212 }
213
214 =head2 query_end
215
216 Called when a query finishes executing.  Has the same arguments as query_start.
217
218 =cut
219 sub query_end {
220   my ($self, $string) = @_;
221 }
222
223 1;
224
225 =head1 AUTHOR AND CONTRIBUTORS
226
227 See L<AUTHOR|DBIx::Class/AUTHOR> and L<CONTRIBUTORS|DBIx::Class/CONTRIBUTORS> in DBIx::Class
228
229 =head1 LICENSE
230
231 You may distribute this code under the same terms as Perl itself.
232
233 =cut