File Coverage

blib/lib/Debuggit.pm
Criterion Covered Total %
statement 74 80 92.5
branch 32 34 94.1
condition 9 9 100.0
subroutine 18 21 85.7
pod 3 3 100.0
total 136 147 92.5


line stmt bran cond sub pod time code
1             package Debuggit;
2              
3 15     15   501994 use strict;
  15         26  
  15         524  
4 15     15   64 use warnings;
  15         22  
  15         2015  
5              
6             our $VERSION = '2.06';
7              
8              
9             #################### main pod documentation begin ###################
10             ####
11             ###
12             ##
13             #
14              
15             =head1 NAME
16              
17             Debuggit - A fairly simplistic debug statement handler
18              
19             =head1 SYNOPSIS
20              
21             use Debuggit DEBUG => 1;
22              
23             # say you have a global hashref for your site configuration
24             # (not to imply that global vars are good)
25             our $Config = get_global_config();
26              
27             # now we can set some config things based on whether we're in debug mode or not
28             $Config->{'DB'} = DEBUG ? 'dev' : 'prod';
29              
30             # maybe we need to pull our local Perl modules from our VC working copy
31             push @INC, $Config->{'vcdir/lib'} if DEBUG;
32              
33             # basic debugging output
34             debuggit("only print this if debugging is on");
35             debuggit(3 => "only print this if debugging is level 3 or higher");
36              
37             # show off our formatting
38             my $var1 = 6;
39             my $var2;
40             my $var3 = " leading and trailing spaces ";
41             # assuming debugging is enabled ...
42             debuggit("var1 is", $var1); # var1 is 6
43             debuggit("var2 is", $var2); # var2 is <>
44             debuggit("var3 is", $var3); # var3 is << leading and trailing spaces >>
45             # note that spaces between args, as well as final newlines, are provided automatically
46              
47             # use "functions" in the debugging args list
48             my $var4 = { complex => 'hash', with => 'lots', of => 'stuff' };
49             # this will call Data::Dumper::Dumper() for you
50             # (even if you've never loaded Data::Dumper)
51             debuggit("var4 is", DUMP => $var4);
52              
53             # or maybe you prefer Data::Printer instead?
54             use Debuggit DEBUG => 1, DataPrinter => 1;
55             debuggit("var4 is", DUMP => $var4);
56              
57             # make your own function
58             Debuggit::add_func(CONFIG => 1,
59             sub { my ($self, $var) = $_; return (lc($self), 'var', $var, 'is', $Config->{$var}) });
60             # and use it like so
61             debuggit(CONFIG => 'DB'); # config var DB is dev
62              
63              
64             =head1 DESCRIPTION
65              
66             You want debugging? No, you want sophisticated, full-featured, on-demand debugging, and you don't
67             want to take it out when you release the code because you might need it again later, but you also
68             don't want it to take up any space or cause any slowdown of your production application. Sound
69             impossible? Nah. Just use Debuggit.
70              
71              
72             =head2 Quick Start
73              
74             To start:
75              
76             use strict;
77             use warnings;
78              
79             use Debuggit;
80              
81              
82             my $var = 6;
83             debuggit(2 => "var is", $var); # this does not print
84             debuggit(4 => "var is", $var); # neither does this
85              
86             Later ...
87              
88             use strict;
89             use warnings;
90              
91             use Debuggit DEBUG => 2;
92              
93              
94             my $var = 6;
95             debuggit(2 => "var is", $var); # now this prints
96             debuggit(4 => "var is", $var); # but this still doesn't
97              
98             That's it. Really. Everything else is just gravy.
99              
100              
101             =head2 Documentation
102              
103             This POD explains just the basics of using C. For full details, see L.
104              
105             =cut
106              
107             #
108             ##
109             ###
110             ####
111             #################### main pod documentation end ###################
112              
113             my ($debuggit, $add_func);
114              
115              
116             #####################################################################
117             ##
118             #
119              
120             =head1 EXPORTS
121              
122             =head2 DEBUG
123              
124             DEBUG is a constant integer set to whatever value you choose:
125              
126             use Debuggit DEBUG => 2;
127              
128             or to 0 if you don't choose:
129              
130             use Debuggit;
131              
132             Actually, failure to specify a value only defaults to 0 the first time in a program this is seen.
133             Subsequent times (e.g. in modules included by the main script), DEBUG will be set to the first value
134             passed in. In this way, you can set DEBUG in the main script and have it "fall through" to all
135             included modules. See L for full details.
136              
137             =head2 Functions exported
138              
139             Only L is exported.
140              
141             =cut
142              
143             #
144             ##
145             #####################################################################
146              
147              
148             sub import
149             {
150 20     20   2737 my ($pkg, %opts) = @_;
151 20 100       151 my $caller_package = $opts{PolicyModule} ? caller(1) : caller;
152              
153 20         1037 my $master_debug = eval "Debuggit::DEBUG()";
154 20 100       82 my $debug_value = defined $opts{DEBUG} ? $opts{DEBUG} : defined $master_debug ? $master_debug : 0;
    100          
155 20 100       92 unless (defined $master_debug)
156             {
157             # Perl does not know whether the string eval below will modify
158             # $debug_value, so it assumes the worst. So make the constant
159             # out of a new lexical scalar outside the eval's visible scope.
160             # This quiets a new warning in 5.20. Thanks ANDK!
161 15         15 my $inner_val = $debug_value;
162 15     0   563 *Debuggit::DEBUG = sub () { $inner_val };
  0         0  
163 15         390 $master_debug = $debug_value;
164             }
165              
166 15     15   58 no strict 'refs';
  15         27  
  15         396  
167 15     15   45 no warnings 'redefine';
  15         19  
  15         2575  
168              
169 20         741 my $caller_value = eval "${caller_package}::DEBUG()";
170 20 100       59 if (defined $caller_value)
171             {
172 2 100       24 warn("Cannot redefine DEBUG; original value of $caller_value is used") if $debug_value ne $caller_value;
173             }
174             else
175             {
176             # Thanx to tye from perlmonks for this line of code, which solves the Pod::Coverage issue
177             # (see t/pod_coverage.t). http://www.perlmonks.org/?node_id=951831
178 18         20 my $inner_val = $debug_value; # See comment above about $inner_val.
179 18     0   83 *{ join('::', $caller_package, 'DEBUG') } = sub () { $inner_val };
  18         72  
  0         0  
180             }
181              
182 20 100       72 if ($debug_value)
183             {
184 16         47 _setup_funcs($master_debug, $debug_value, $caller_package, $opts{DataPrinter});
185             }
186             else
187             {
188 4     2   7 *{ join('::', $caller_package, 'debuggit') } = sub {};
  4         16  
  2         1532  
189 4 50   1   2503 *Debuggit::add_func = sub {} unless Debuggit->can('add_func');
  1         630  
190             }
191             }
192              
193              
194             sub _setup_funcs
195             {
196 16     16   33 my ($master_debug, $debug_value, $caller_package, $data_printer) = @_;
197              
198 15     15   57 no strict 'refs';
  15         665  
  15         377  
199 15     15   54 no warnings 'redefine';
  15         21  
  15         3173  
200              
201             # If our debug value is the same as the master debug value, we're just going to export our own
202             # debuggit() function out to the calling package. In this way, we avoid unnecessary code
203             # duplication by every package having its own copy of debuggit(). However, if the two values
204             # _don't_ match, it means that we're doing an override, and that in turns means that we _have_
205             # to give the calling package its own copy. This is because debuggit() is actually a closure,
206             # with the debug value stored in it. If we have two different debug values (one for the program
207             # as a whole, and a different one for this particular package), we have to have two different
208             # debuggit() calls as well.
209 16 100       28 if ($debug_value == $master_debug)
210             {
211 14 100 100 38   1085 *Debuggit::debuggit = eval $debuggit unless Debuggit->can('debuggit');
  38 100       65165  
  34 100       137  
212 14         45 *{ join('::', $caller_package, 'debuggit') } = \&debuggit;
  14         50  
213             }
214             else
215             {
216 2         224 *{ join('::', $caller_package, 'debuggit') } = eval $debuggit;
  2         10  
217             }
218              
219 16 100       4797 unless (Debuggit->can('add_func'))
220             {
221 11     15 1 522 eval $add_func;
  15         1120  
  15         37  
  15         9394  
222              
223             # create default function
224 11 50       34 if ($data_printer)
225             {
226             add_func(DUMP => 1, sub
227             {
228 0     0   0 require Data::Printer;
229 0         0 shift;
230 0         0 return &Data::Printer::p(shift, colored => 1, hash_separator => ' => ', print_escapes => 1);
231 0         0 });
232             }
233             else
234             {
235             add_func(DUMP => 1, sub
236             {
237 2     2   773 require Data::Dumper;
238 2         4772 shift;
239 2         3 local $Data::Dumper::Sortkeys = 1;
240 2         7 return Data::Dumper::Dumper(shift);
241 11         235 });
242             }
243             }
244             }
245              
246              
247             #####################################################################
248             ##
249             #
250              
251             =head1 FUNCTIONS
252              
253             =cut
254              
255             #####################################################################
256             ##
257             #
258              
259             =head2 debuggit
260              
261             Use this function to conditionally print debugging output. If the first argument is a positive
262             integer, the output is printed only if DEBUG is set to that number or higher. The remaining
263             arguments are concatenated with spaces, a newline is appended, and the results are printed to
264             STDERR. Some minor formatting is done to help distinguish C values and values with leading
265             or trailing spaces. To get further details, or to learn how to override any of those things, see
266             L.
267              
268             =head2 default_formatter
269              
270             This is what C is set to initially. You can call it directly if you want to "wrap"
271             C. For examples of this, see L.
272              
273             =cut
274              
275             #
276             ##
277             #####################################################################
278              
279             BEGIN
280             {
281             # This is an anonymous closure. It has to be both of those things.
282             # * It has to be anonymous because it may be put into different packages depending on the
283             # circumstances. See the comments in _setup_funcs() for further details on that.
284             # * It has to be a closure because we want the debug value (against which we have to check
285             # the first arg, if it's a positive integer), to be stored with the sub. We in turn want
286             # this for several reasons:
287             # - We have to reference the DEBUG value in the calling package.
288             # - If we determine that via reference, that works for most cases. But in the case of
289             # Moose classes, most of which are autocleaned, the DEBUG constant, which is just a
290             # function, may well be gone by the time debuggit() runs. If we were calling it
291             # directly, autocleaning wouldn't keep that from working. But calling by reference is
292             # a whole different story.
293             # - So our best bet is to use a closure. The $debug_value referred to below must exist
294             # in the scope in which this is eval'ed. Then that value gets wrapped in the closure
295             # and it doesn't matter a whit if the function is autocleaned.
296 15     15   1885 $debuggit = q{
297             sub
298             {
299             return unless @_ > 0 && ($_[0] =~ /^\d+$/ ? shift : 1) <= $debug_value;
300             $Debuggit::output->($Debuggit::formatter->(Debuggit::_process_funcs(@_)));
301             }
302             };
303             }
304              
305              
306             sub default_formatter
307             {
308 33 100 100 33 1 52 return join(' ', map { !defined $_ ? '<>' : /^ +/ || / +$/ ? "<<$_>>" : $_ } @_) . "\n";
  44 100       346  
309             }
310              
311             our $formatter = \&default_formatter;
312              
313             our $output = sub { print STDERR @_ };
314              
315              
316             #####################################################################
317             ###
318             ##
319             #
320              
321             =head2 add_func
322              
323             =head2 remove_func
324              
325             Add or remove debugging functions. Please see L.
326              
327             =cut
328              
329             #
330             ##
331             ###
332             #####################################################################
333              
334              
335             my %PROCS;
336              
337             BEGIN
338             {
339 15     15   1912 $add_func = q{
340             sub Debuggit::add_func
341             {
342             my ($name, $argc, $code) = @_;
343              
344             $Debuggit::PROCS{$name} = { argc => $argc, code => $code };
345              
346             return 1;
347             }
348             };
349             }
350              
351              
352             sub remove_func
353             {
354 2     2 1 949 delete $Debuggit::PROCS{shift()};
355 2         15 return 1;
356             }
357              
358              
359              
360             #####################################################################
361             # PRIVATE FUNCTIONS
362             #####################################################################
363              
364              
365             sub _process_funcs
366             {
367 34     34   142 my @parts;
368              
369 34         77 while (@_)
370             {
371 43         53 local $_ = shift;
372              
373 43 100 100     161 if ($_ and exists $Debuggit::PROCS{$_})
374             {
375 7         16 my @args = ($_);
376 7         35 push @args, shift foreach 1..$Debuggit::PROCS{$_}->{argc};
377 7         26 push @parts, $Debuggit::PROCS{$_}->{code}->(@args);
378             }
379             else
380             {
381 36         82 push @parts, $_;
382             }
383             }
384              
385 34         309 return @parts;
386             }
387              
388              
389             #################### remainder of pod begin ###################
390             ####
391             ###
392             ##
393             #
394              
395             =head1 DIAGNOSTICS
396              
397             =over 4
398              
399             =item * Cannot redefine DEBUG; original value of %s is used
400              
401             It means you did something like this:
402              
403             use Debuggit DEBUG => 2;
404             use Debuggit DEBUG => 3;
405              
406             only probably not nearly so obvious. Debuggit tries to be very tolerant of multiple imports into
407             the same package, but the C symbol is a constant function and can't be redefined without
408             engendering severe wonkiness, so Debuggit won't do it. As long as you pass the same value for
409             C, that's okay. But if the second (or more) value is different from the first, then you will
410             get the original value regardless. At least this way you'll be forewarned.
411              
412             =back
413              
414              
415              
416             =head1 PERFORMANCE
417              
418             Debuggit is designed to be left in your code, even when running in production environments.
419             Because of this, it needs to disappear entirely when debugging is turned off. It can achieve this
420             unlikely goal via the use of a compile-time constant. Please see
421             L for full details.
422              
423              
424              
425             =head1 BUGS and CAVEATS
426              
427             =over
428              
429             =item *
430              
431             Once you set C, you can't change it. Even if you try, you get the original value. See
432             L.
433              
434             =item *
435              
436             Doing:
437              
438             debuggit(0 => "in production mode");
439              
440             never prints anything, even when C is 0. That's because C is guaranteed to be an
441             empty function when debugging is turned off.
442              
443             =item *
444              
445             Doing:
446              
447             debuggit($var, "is the value");
448              
449             is inherently dangerous. If C<$var> is a positive integer, C would interpret it as a
450             debug level, and not print it. So, either do this:
451              
452             debuggit(1 => $var, "is the value");
453              
454             or this:
455              
456             debuggit("the value is", $var);
457              
458             Or, to look at it another way, you can pass a value as the first arg to print, or you can leave off
459             a debugging level altogether, but don't try to do both at once.
460              
461             =item *
462              
463             Doing:
464              
465             my $var1 = "DUMP";
466             my $var2 = "stuff";
467             debuggit(1 => "vars are", $var1, $var2);
468              
469             is equivalent to:
470              
471             debuggit(1 => "vars are", DUMP => $var2);
472              
473             which is probably not going to do what you want, assuming the default functions are still in place.
474             See L for full details.
475              
476             =item *
477              
478             Doing:
479              
480             debuggit(2 => "first thousand elements:", @array[0..999]);
481              
482             is likely going to have a performance impact even when debugging is off. Instead, do:
483              
484             debuggit("first thousand elements:", @array[0..999]) if DEBUG >= 2;
485              
486             See L for another example and details on the problem.
487              
488             =back
489              
490             That's all I know of. However, lacking omniscience, I welcome bug reports.
491              
492              
493              
494             =head1 SUPPORT
495              
496             Debuggit is on GitHub at barefootcoder/debuggit. Feel free to fork and submit patches. Please note
497             that I develop via TDD (Test-Driven Development), so a patch that includes a failing test is much
498             more likely to get accepted (or least likely to get accepted more quickly).
499              
500             If you just want to report a problem or request a feature, that's okay too. You can create an issue
501             on GitHub, or a bug in CPAN's RT (at http://rt.cpan.org). Or just send an email to
502             bug-Debuggit@rt.cpan.org.
503              
504              
505              
506             =head1 AUTHOR
507              
508             Buddy Burden
509             CPAN ID: BAREFOOT
510             Barefoot Software
511             barefootcoder@gmail.com
512              
513             =head1 COPYRIGHT
514              
515             This program is free software licensed under
516              
517             The Artistic License
518              
519             The full text of the license can be found in the LICENSE file included with this module.
520              
521              
522             This module is copyright (c) 2008-2015, Barefoot Software. It has many venerable ancestors (some
523             more direct than others), including but not limited to:
524              
525             =over
526              
527             =item *
528              
529             C, (c) 2000-2006 Barefoot Software, 2004-2006 ThinkGeek
530              
531             =item *
532              
533             C, (c) 2001-2006 Barefoot Software
534              
535             =item *
536              
537             C, (c) 2004 ThinkGeek
538              
539             =item *
540              
541             C, (c) 2004-2008 Barefoot Software, 2004 ThinkGeek
542              
543             =item *
544              
545             C, (c) 2006-2009 Barefoot Software
546              
547             =item *
548              
549             C, (c) 2008 Rent.com
550              
551             =back
552              
553              
554             =head1 SEE ALSO
555              
556             L, L, L, L, L.
557              
558             Comparison with most of these (and others) can be found in L.
559              
560             =cut
561              
562             #
563             ##
564             ###
565             ####
566             #################### remainder of pod end ###################
567              
568              
569             # Return a true value
570             1;