File Coverage

blib/lib/DBG.pm
Criterion Covered Total %
statement 236 247 95.5
branch 68 114 59.6
condition 15 31 48.3
subroutine 44 44 100.0
pod 15 15 100.0
total 378 451 83.8


line stmt bran cond sub pod time code
1             package DBG;
2             # ABSTRACT: A collection of debugging functions
3 1     1   25324 use version;
  1         1819  
  1         5  
4             our $VERSION = 'v0.4.1'; # VERSION
5              
6 1     1   90 use v5.10;
  1         6  
7 1     1   5 use strict;
  1         2  
  1         18  
8 1     1   4 use warnings;
  1         2  
  1         26  
9              
10 1     1   5 use parent 'Exporter';
  1         1  
  1         5  
11 1     1   500 use FileHandle;
  1         2310  
  1         5  
12 1     1   834 use Data::Dumper;
  1         6997  
  1         58  
13 1     1   906 use Perl::Tidy;
  1         243696  
  1         472  
14 1     1   913 use DateTime;
  1         519025  
  1         52  
15 1     1   9 use File::Spec;
  1         2  
  1         30  
16 1     1   6 use Scalar::Util qw(refaddr reftype blessed);
  1         2  
  1         74  
17 1     1   7 use List::MoreUtils qw(natatime);
  1         3  
  1         10  
18 1     1   712 use B qw(svref_2object);
  1         2  
  1         52  
19 1     1   7 use B::Deparse;
  1         2  
  1         27  
20 1     1   641 use Devel::Size qw(total_size);
  1         663  
  1         58  
21 1     1   556 use Class::MOP;
  1         104261  
  1         163  
22              
23             our @EXPORT = qw(dmp png trc dbg ts rt cyc prp cnm pkg sz mtd inh dpr flt);
24              
25             our $ON = $ENV{DBG_ON} // 1;
26             our $HEADER = $ENV{DBG_HEADER} // 1;
27              
28             our ( $fh, $fn, $stamped );
29              
30             BEGIN {
31             $fn =
32             defined $ENV{DBG_LOG}
33             ? $ENV{DBG_LOG} eq '0'
34             ? ''
35             : $ENV{DBG_LOG} . ''
36 1 50   1   318 : File::Spec->catfile( $ENV{HOME}, 'DBG.log' );
    50          
37             }
38              
39             sub _tee($) {
40 41 100   41   126 return unless $ON;
41 40         74 my $data = shift;
42 40 50       82 return unless defined $data;
43 40 100 66     159 if ( $HEADER && !$stamped ) {
44 1         10 my @msg = (
45             '>> DEBUGGING SESSION START: ',
46             DateTime->now, ' ; PID: ', $$, ' <<', "\n\n"
47             );
48 1 50       534 print $fh @msg if $fh;
49 1         120 print STDERR @msg;
50 1         64 $stamped = 1;
51             }
52 40         191 $data =~ s/\s++$//;
53 40         70 $data .= "\n";
54 40 50       714 print $fh $data if $fh;
55 40         912 print STDERR $data;
56             }
57              
58             BEGIN {
59 1 50   1   7 if ( length $fn ) {
60 1 50       16 $fh = FileHandle->new(">> $fn") or die $!;
61 1         149 binmode $fh, ':utf8';
62 1         3 binmode *STDERR, ':utf8';
63 1         6 $fh->autoflush(1);
64             }
65             }
66              
67             END {
68 1 50 33 1   917 if ( $HEADER && $stamped ) {
69 1         13 my $msg = join '', "\n", '** DEBUGGING SESSION END: ', DateTime->now,
70             ' ; PID: ', $$, ' **';
71 1         469 _tee($msg);
72             }
73 1 50       9 $fh->close if $fh;
74             }
75              
76             { # DateTime with optional label payload
77              
78             package DBG::ts;
79             $DBG::ts::VERSION = '0.004';
80 1     1   199 use parent 'DateTime';
  1         2  
  1         9  
81 1     1   79 use Scalar::Util qw(refaddr);
  1         3  
  1         2678  
82              
83             our %messages;
84              
85             sub text {
86 6     6   332 my ( $self, $text ) = @_;
87 6         17 my $addr = refaddr $self;
88 6         12 my $old = $messages{$addr};
89 6 100       15 $messages{$addr} = $text if defined $text;
90 6         12 return $old;
91             }
92              
93             sub DESTROY {
94 3     3   2277 my $self = shift;
95 3         15 delete $messages{ refaddr $self };
96 3 50       186 $self->SUPER::DESTROY if $self->can("SUPER::DESTROY");
97             }
98             }
99              
100              
101             sub ts(;$) {
102 3     3 1 2907 my $ts = DBG::ts->now;
103 3         1074 $ts->text(shift);
104 3         13 return $ts;
105             }
106              
107              
108             sub rt($$) {
109 2 50   2 1 5 return unless $ON;
110 2         6 for (@_) {
111 4 50 33     32 die 'DBG::ts expected'
112             unless blessed($_) && $_->isa('DBG::ts');
113             }
114 2         4 my ( $t1, $t2 ) = @_;
115 2         10 my $i = natatime 2, ( $t2 - $t1 )->deltas;
116 2         887 my $reported;
117 2         6 my $text = $t1->text;
118 2         5 my $prefix = '';
119 2 100       6 if ( defined $text ) {
120 1         5 _tee("timestamp $text");
121 1         5 $prefix = "\t";
122             }
123 2         24 while ( my ( $unit, $amt ) = $i->() ) {
124 10 50       33 next unless $amt;
125 0         0 $reported = 1;
126 0 0       0 $unit =~ s/s$// if $amt == 1;
127 0         0 _tee("$prefix$amt $unit");
128             }
129 2 50       11 _tee("${prefix}negligible time elapsed") unless $reported;
130 2         24 return $t2;
131             }
132              
133              
134             sub trc() {
135 1 50   1 1 1988 return unless $ON;
136 1         5 _tee 'TRACE';
137 1         4 my $i = 0;
138 1         37 my @stack;
139 1         14 while ( my @frame = caller($i) ) {
140 6         39 push @stack, [ $i++, $frame[3], $frame[1], $frame[2] ];
141             }
142 1         5 my $fmt = '%' . length( $stack[-1][0] ) . 'd) %s (%s:%d)';
143 1         5 for $i ( 1 .. $#stack ) {
144 5         11 _tee sprintf $fmt, ( @{ $stack[$i] } )[ 0 .. 1 ],
145 5         10 ( @{ $stack[ $i - 1 ] } )[ 2 .. 3 ];
  5         26  
146             }
147 1         5 _tee 'END TRACE';
148             }
149              
150              
151             sub dmp($) {
152 3 50   3 1 1425 return unless $ON;
153 3         6 my $ref = shift;
154 3         9 local $Data::Dumper::Indent = 1;
155 3         7 local $Data::Dumper::Sortkeys = 1;
156 3         7 local $Data::Dumper::Quotekeys = 0;
157 3         5 local $Data::Dumper::Terse = 1;
158 3         16 my $code = Dumper $ref;
159 3         245 _dmp($code);
160             }
161              
162             sub _dmp {
163 4     4   11 my $code = shift;
164 4         8 my ( $ds, $stderr_string );
165 4         10 local @ARGV; # prevents Perl::Tidy craziness
166 4         19 my $error = Perl::Tidy::perltidy(
167             source => \$code,
168             destination => \$ds,
169             stderr => \$stderr_string
170             );
171 4 50       183102 if ($error) {
172 0         0 _tee "TIDY ERROR: $stderr_string";
173 0         0 _tee $code;
174             }
175             else {
176 4         19 _tee $ds;
177             }
178             }
179              
180              
181             sub dbg($) {
182 1 50   1 1 1294 return unless $ON;
183 1         2 my $data = shift;
184 1         4 _tee $data;
185             }
186              
187              
188             sub png(;$) {
189 3 50   3 1 4875 return unless $ON;
190 3         5 my $msg = shift;
191 3         22 my @frame = caller(1);
192 3         6 my $data;
193 3 100 66     18 if ( @frame && $msg ) {
194 2         20 ( $data = $frame[3] ) =~ s/.*::(.*)/in code $1/;
195             }
196             else {
197 1 50       7 $data = @frame ? sprintf( 'PING %4$s (%2$s:%3$d)', @frame ) : 'PING';
198             }
199 3 100 66     19 $data .= " -- $msg" if $msg && ( ref $msg || $msg ne '1' );
      100        
200 3         8 _tee $data;
201             }
202              
203              
204             sub cyc($) {
205 1 50   1 1 1496 return unless $ON;
206 1         6 _tee '===== OBJECT GRAPH =====';
207 1         8 _cycles( shift, {}, 0, 'base' );
208             }
209              
210             sub _cycles {
211 3     3   9 my ( $ref, $hash, $indent, $parent ) = @_;
212 3         13 my $type = reftype $ref;
213 3 50       10 return unless $type;
214             ## Please see file perltidy.ERR
215 3         9 my $addr = refaddr $ref;
216 3   33     14 my $name = blessed $ref // $type;
217 3         11 my $left = ' ' x ( $indent * 3 );
218 3 100       12 if ( $hash->{$addr}++ ) {
219             _tee sprintf '%s%s (%s <- %s) -- ref count: %d', $left, $name, $addr,
220             $parent,
221 1         8 $hash->{$addr};
222             }
223             else {
224 2         14 _tee sprintf '%s%s (%s <- %s)', $left, $name, $addr, $parent;
225 2 50       11 if ( $type eq 'HASH' ) {
    0          
226 2         19 _cycles( $_, $hash, $indent + 1, $addr ) for values %$ref;
227             }
228             elsif ( $type eq 'ARRAY' ) {
229 0         0 _cycles( $_, $hash, $indent + 1, $addr ) for @$ref;
230             }
231             }
232             }
233              
234              
235             sub prp($$) {
236 2     2 1 2808 my ( $msg, $var ) = @_;
237 2         17 $msg =~ s/\??\s*$/? /;
238 2 100       13 _tee( $msg . ( $var ? 'yes' : 'no' ) );
239             }
240              
241              
242             sub cnm($;$) {
243 1     1 1 1739 my ( $code, $quiet ) = @_;
244 1 50       5 return unless ref $code;
245 1         20 my $gv = _code_name($code);
246 1         2 my $name = '';
247 1 50       13 if ( my $st = $gv->STASH ) {
248 1         8 $name = $st->NAME . '::';
249             }
250 1         4 my $n = $gv->NAME;
251 1 50       5 if ($n) {
252 1         3 $name .= $n;
253 1 50       4 if ( $n eq '__ANON__' ) {
254 1         10 $name .= ' defined at ' . $gv->FILE . ':' . $gv->LINE;
255             }
256             }
257 1 50       9 _tee($name) unless $quiet;
258 1         8 return $name;
259             }
260              
261             sub _code_name {
262 9     9   58 my $code = shift;
263 9 50       50 return unless my $cv = svref_2object($code);
264             return
265 9 50 33     89 unless $cv->isa('B::CV')
266             and my $gv = $cv->GV;
267 9         20 return $gv;
268             }
269              
270              
271             sub pkg($$;$) {
272 2     2 1 2919 my ( $obj, $method, $file ) = @_;
273 2 50       12 return _tee('first parameter must be an object') unless blessed $obj;
274 2 50       6 return _tee('method not defined') unless defined $method;
275 2         13 my $m = $obj->can($method);
276 2 50       6 return _tee( "did not find method $method in " . ref $obj ) unless $m;
277 2         5 my $gv = _code_name($m);
278 2 50       6 return _tee("could not find $method") unless $gv;
279 2 100       7 if ( !$file ) {
280 1         14 _tee( sprintf 'package: %s; file: %s; line: %s',
281             $gv->STASH->NAME, $gv->FILE, $gv->LINE );
282             }
283             else {
284 1         9 _tee( $gv->STASH->NAME );
285             }
286             }
287              
288              
289             sub sz($;$) {
290 2     2 1 2817 state $ts = eval { require Devel::Size };
  1         9  
291 2 50       6 if ($ts) {
292 2         58 my $msg = Devel::Size::total_size( pop @_ );
293 2 100       9 $msg = pop(@_) . ' ' . $msg if @_;
294 2         6 _tee($msg);
295             }
296             else {
297 0         0 _tee('sz requires Devel::Size');
298             }
299             }
300              
301              
302             sub mtd($;$) {
303 2     2 1 3257 my ( $obj, $verbose ) = @_;
304 2 50       9 if ( my $class = ref $obj ) {
305 2         24 my $meta = Class::MOP::Class->initialize($class);
306 2         203 _tee("Class: $class");
307 2 100       12 if ($verbose) {
308 1         5 my $longest = 0;
309 1         8 for ( $meta->get_all_methods ) {
310 6         118 my $l = length $_->name;
311 6 100       13 $longest = $l if $l > $longest;
312             }
313 1         8 my $format = '%-' . $longest . 's : %s %s';
314 1         5 for my $method ( sort { $a->name cmp $b->name }
  8         102  
315             $meta->get_all_methods )
316             {
317 6         39 my $code = $obj->can( $method->name );
318 6         15 my $gv = _code_name($code);
319 6 100       18 if ( $gv->LINE ) {
320 3         24 _tee( sprintf $format, $method->name, $gv->FILE,
321             $gv->LINE );
322             }
323             else {
324 3         13 _tee( $method->fully_qualified_name );
325             }
326             }
327             }
328             else {
329             dmp(
330             [
331 1         8 sort map { $_->fully_qualified_name }
  6         707  
332             $meta->get_all_methods
333             ]
334             );
335             }
336             }
337             else {
338 0         0 _tee "NOT AN OBJECT: $obj";
339             }
340             }
341              
342              
343             sub inh($) {
344 1     1 1 1507 my $class = shift;
345 1 50 0     8 _tee('inh needs a class') && return unless length( $class // '' );
      50        
346 1   33     6 $class = ref($class) || $class;
347 1         3 my $hash = { $class => 1 };
348 1         4 _fetch_classes( $class, $hash );
349 1         6 my @classes = sort keys %$hash;
350 1         6 _tee("Classes in the inheritance hierarchy of $class:");
351 1         8 _tee(" $_") for @classes;
352             }
353              
354             sub _fetch_classes {
355 2     2   6 my ( $class, $hash ) = @_;
356 2         96 my @ar = eval '@' . $class . '::ISA';
357 2         8 my @new = grep { !$hash->{$_} } @ar;
  1         4  
358 2         6 $hash->{$_} = 1 for @ar;
359 2         9 _fetch_classes( $_, $hash ) for @new;
360             }
361              
362              
363             sub dpr {
364 1     1 1 1442 my $ref = shift;
365 1 50       6 die 'code reference expected' unless ref $ref eq 'CODE';
366 1         48 my $d = B::Deparse->new(@_);
367 1         1421 _dmp( $d->coderef2text($ref) );
368             }
369              
370              
371             sub flt($;$) {
372 1     1 1 2131 my $v = _flt(shift);
373 1 50       6 dmp($v) unless shift;
374 1         7 return $v;
375             }
376              
377             sub _flt {
378 2     2   5 my $i = shift;
379 2 100       37 return "$i" if blessed $i;
380 1         4 for ( ref $i ) {
381 1 50       4 if ($_ eq 'HASH') {
    0          
382 1         5 my %h = %$i;
383 1         15 $_ = _flt($_) for values %h;
384 1         8 return \%h;
385             }
386             elsif ($_ eq 'ARRAY') {
387 0           return [ map { _flt($_) } @$i ];
  0            
388             }
389             }
390 0           return $i;
391             }
392              
393             1;
394              
395             __END__
396              
397             =pod
398              
399             =encoding UTF-8
400              
401             =head1 NAME
402              
403             DBG - A collection of debugging functions
404              
405             =head1 VERSION
406              
407             version v0.4.1
408              
409             =head1 SYNOPSIS
410              
411             package Foo::Bar::Baz;
412             use DBG;
413              
414             ...
415             dbg "log this $message";
416             ...
417             png; # do I ever get here?
418             ...
419             trc; # how did I get here?
420             ...
421             dmp $obj; # what is this?
422             ...
423             cyc $obj; # does this have reference cycles?
424             ...
425             my $ts = ts; # get me the current time
426             ...
427             rt $ts, ts; # how long did that take?
428             ...
429             prp "is it so", $val; # prints message plus "yes" or "no"
430             ...
431             pkg $obj, 'doit'; # prints package providing obj's doit method
432             ...
433              
434             =head1 DESCRIPTION
435              
436             This is just a collection of functions useful for debugging. Instead of adding
437              
438             use Data::Dumper;
439             use B::Deparse;
440             use Devel::Size qw(total_size);
441              
442             and so forth you can just type
443              
444             use DBG;
445              
446             at the top of the script. If you're using git, or another version control system
447             with similar functionality, you can write a simple pre-commit hook to prevent
448             yourself from committing debugging lines to the repository. Once you've deleted
449             the C<use DBG;> line you can find all the other stuff you may have left in by
450             trying to compile the code and looking at the errors.
451              
452             All functions have short names to make debugging quick(er).
453              
454             All debugging messages are printed both to the screen and to a log. The log will
455             be C<~/DBG.log> unless otherwise specified. See C<$ENV{DBG_LOG}>. This facilitates
456             examining debugging output at one's leisure without having to visually cull away
457             any other output produced by the program.
458              
459             All debugging functions are exported by default.
460              
461             A timestamp will be printed before any debugging output to facilitate
462             distinguising one debugging session from another.
463              
464             =head1 FUNCTIONS
465              
466             =head2 ts(;$) -- "get timestamp"
467              
468             Returns a L<DateTime>-based timestamp. The optional argument is a label for the
469             timestamp. The label will be accessible via the timestamp's C<text> method.
470              
471             my $t = ts 'foo';
472             say $t->text; # foo
473             say $t; # 2014-05-31T22:31:52
474              
475             =head2 rt($$) -- "report timestamp"
476              
477             Report time difference. This function expects two objects generated by the
478             C<ts> function, the earlier first. It returns the second timestamp to facilitate
479             the
480              
481             my $ts = ts;
482             # some code
483             $ts = rt $ts, ts
484              
485             pattern.
486              
487             The report will vary according to whether the first timestamp holds a label.
488              
489             my $t1 = ts 'foo';
490             my $t2 = rt $t1, ts 'bar';
491             sleep 1;
492             my $t3 = rt $t2, ts;
493             sleep 61;
494             rt $t3, ts;
495              
496             # timestamp foo
497             # negligible time elapsed
498             # timestamp bar
499             # 1 second
500             # 1 minute
501             # 1 second
502              
503             =head2 trc() -- "trace"
504              
505             Prints a stack trace, skipping its own frame. Each line of the trace is
506             formatted as
507              
508             frame number) code name (file:line)
509              
510             This involves munging the frames as returned by C<caller> so instead of saying
511             "you got here when called from here" it says simply "you are here". The next
512             line says how you got here. That is, the code name is the name of the code
513             you're in, not the code that just called you. I simply find this easier to
514             follow.
515              
516             sub foo { bar() }
517             sub bar { baz() }
518             sub baz { plugh() }
519             sub plugh { trc }
520             foo();
521              
522             # TRACE
523             # 1) main::plugh (test.pl:11)
524             # 2) main::baz (test.pl:10)
525             # 3) main::bar (test.pl:9)
526             # 4) main::foo (test.pl:8)
527             # END TRACE
528              
529             =head2 dmp($) -- "dump"
530              
531             Prints a pretty data dump. This uses a combination of L<Perl::Tidy> and
532             L<Data::Dumper>.
533              
534             my $r = { a => [qw(1 2 3)], c => { d => undef, egg => [ {}, {} ] } };
535             dmp $r;
536              
537             # {
538             # a => [ '1', '2', '3' ],
539             # c => {
540             # d => undef,
541             # egg => [ {}, {} ]
542             # }
543             # }
544              
545             =head2 dbg($) -- "debug"
546              
547             Prints a message to the debugging log.
548              
549             dbg 'foo'; # foo
550              
551             =head2 png(;$) -- "ping"
552              
553             Prints a ping message to the debugging log. If optional argument is true, just
554             prints "in code <code name> -- <optional arg>", where C<code name> is the name
555             of the function or method minus the package. If the optional argument is just
556             "1", it is not suffixed to the ping message.
557              
558             sub foo { png }
559             sub bar { png 1 }
560             sub baz { png 'la la la la la' }
561             foo();
562             bar();
563             baz();
564              
565             # PING main::foo (test.pl:11)
566             # in code bar
567             # in code baz -- la la la la la
568              
569             =head2 cyc($) -- "cycles"
570              
571             Checks for cycles in a reference, teeing out the entire object graph.
572             This is like a condensed dump concerning itself only with references.
573              
574             my $a = {};
575             my $b = { b => $a };
576             my $c = { c => $b };
577             $a->{a} = $c;
578             cyc $a;
579              
580             # HASH (140416464744656 <- base)
581             # HASH (140416464745304 <- 140416464744656)
582             # HASH (140416464744992 <- 140416464745304)
583             # HASH (140416464744656 <- 140416464744992) -- ref count: 2
584              
585             =head2 prp($$) -- "property"
586              
587             Takes a message and a scalar to be evaluated as a boolean and submits this to
588             C<dbg> as C<"$message? yes/no">.
589              
590             prp 'true', 1;
591             prp 'true', 0;
592              
593             # true? yes
594             # true? no
595              
596             =head2 cnm($;$) -- "code name"
597              
598             cnm $ua->can('request'); # LWP::UserAgent::request
599              
600             Converts a code reference to the place in the source code it comes from. This
601             uses B::svref_2object to do its magic. Sometimes it will provide the file and
602             line number, sometimes not.
603              
604             If the optional second parameter is provided, the information is only returned,
605             not teed out.
606              
607             =head2 pkg($$;$) -- "package"
608              
609             Determines the package providing a method to an object. The first parameter is
610             the object and the second the method name. Unless the optional third parameter
611             is true, the file and line are also provided.
612              
613             my $d = DateTime->now;
614             pkg $d, 'ymd';
615              
616             # package: DateTime; file: /Users/houghton/perl5/lib/perl5/darwin-thread-multi-2level/DateTime.pm; line: 820
617              
618             pkg $d, 'ymd', 1;
619              
620             # DateTime
621              
622             =head2 sz($;$) -- "size"
623              
624             Tees out the size of a scalar. If two arguments are given, the first is taken
625             as a label and the second the scalar.
626              
627             sz {}; # 128
628             sz 'foo', {}; # foo 128
629              
630             This delegates to the C<total_size> function in L<Devel::Size>. If you do not
631             have L<Devel::Size>, the C<sz> will only emit a warning that it requires
632             L<Devel::Size>.
633              
634             =head2 mtd($;$) -- "method"
635              
636             Dumps out a sorted list of the object's method names, fully qualified. If the
637             optional parameter is provided, it also lists where the code for each method
638             can be found.
639              
640             my $d = DateTime->now;
641             mtd $d;
642              
643             # Class: DateTime
644             # [
645             # 'DateTime::DefaultLanguage',
646             # 'DateTime::DefaultLocale',
647             # 'DateTime::INFINITY',
648             # 'DateTime::MAX_NANOSECONDS',
649             # ... # many lines omitted
650             # ]
651              
652             mtd $d, 1;
653              
654             # Class: DateTime
655             # UNIVERSAL::DOES
656             # DefaultLanguage : /Users/houghton/perl5/lib/perl5/darwin-thread-multi-2level/DateTime.pm 106
657             # DefaultLocale : /Users/houghton/perl5/lib/perl5/darwin-thread-multi-2level/DateTime.pm 106
658             # INFINITY : /Users/houghton/perl5/lib/perl5/constant.pm 30
659             # MAX_NANOSECONDS : /Users/houghton/perl5/lib/perl5/darwin-thread-multi-2level/Class/MOP/Mixin/HasMethods.pm 131
660             # ...
661              
662             =head2 inh($) -- "inheritance"
663              
664             Takes an object or class and prints out a sorted list of all the classes in
665             that object or class's inheritance tree.
666              
667             package Plugh;
668             package Foo;
669             our @ISA = qw(Plugh);
670             package Bar;
671             package Baz;
672             our @ISA = qw(Foo Bar);
673             package main;
674              
675             inh 'Baz';
676              
677             # Classes in the inheritance hierarchy of Baz:
678             # Bar
679             # Baz
680             # Foo
681             # Plugh
682              
683             =head2 dpr -- "deparse"
684              
685             Takes a code reference and any optional parameters to pass to L<B::Deparse>.
686             Tees out the result of deparsing this reference.
687              
688             my $foo = sub { print "foo\n" };
689             ...
690             dpr $foo; # what is this mystery code ref?
691              
692             # {
693             # use warnings;
694             # use strict 'refs';
695             # print "foo\n";
696             # }
697              
698             =head2 flt($;$) -- "flatten"
699              
700             Takes a parameter and flattens it. For an ordinary scalar this just
701             means it returns it. For containers -- hash or array references -- it returns
702             copies with flattened values. Anything blessed it stringifies.
703              
704             flt { bar => 1, baz => DateTime->now };
705              
706             # {
707             # 'bar' => 1,
708             # 'baz' => '2014-05-31T21:04:07'
709             # };
710              
711             This is useful for dumping hashes containing huge objects whose innards you
712             don't need to see.
713              
714             If the optional second parameter is provided, the information is only returned,
715             not also dumped out via C<dmp>.
716              
717             =head1 VARIABLES
718              
719             =head3 $ENV{DBG_LOG}
720              
721             If the C<DBG_LOG> environment variable is set and is not equal to 0, this will
722             be understood as the file into which debugging output should be dumped. If it
723             is set to 0, the debugging output will only be sent to STDERR. If it is
724             undefined, the log will be C<~/DBG.log>.
725              
726             =head3 $ENV{DBG_ON}
727              
728             If the C<DBG_ON> environment variable is set, its boolean value will be used to
729             determine the value of C<$DBG::ON>.
730              
731             =head3 $ENV{DBG_HEADER}
732              
733             If the C<DBG_HEADER> environment variable is set, its boolean value will be used to
734             determine the value of C<$DBG::HEADER>.
735              
736             =head3 $DBG::ON
737              
738             If C<$DBG::ON> is true, which it is by default, all debugging code is executed.
739             If it is false, debugging code is ignored (aside from the initial timestamp).
740             The state of C<$ON> can be manipulated programmatically or set by the
741             C<$ENV{DBG_ON}> environment variable. This can be used to constrain debugging
742             output to a particular section of a program. For instance, one may set debugging
743             to off and then locally set it to one within a particular method.
744              
745             sub foo {
746             local $DBG::ON = 1;
747             my self = shift;
748             ...
749             }
750              
751             =head3 $DBG::HEADER
752              
753             Unless C<$DBG::HEADER> is false, a timestamp and process ID will be logged for
754             a debugging process. The header is not printed until the first debugging line
755             is logged, so this need not be set in a BEGIN block.
756              
757             =head1 PRE-COMMIT HOOK
758              
759             You probably don't want debugging code, at least not that associated with
760             DBG, getting into your repository. Here's a sample git pre-commit hook script
761             for screening it out:
762              
763             my $rx = qr/
764             ( (?&line){0,3} (?&dbg) (?&line){0,3} )
765             (?(DEFINE)
766             (?<line> ^.*?(?:\R|\z) )
767             (?<dbg> ^\+\s*use\s+DBG\b.*?(?:\R|\z) )
768             )
769             /mx;
770             my $text = `git diff --staged`;
771             if ( my @matches = $text =~ /$rx/g ) {
772             @matches = grep defined, @matches;
773             exit 0 unless @matches;
774             print STDERR "DBG lines: \n\n" . join "\n", @matches;
775             print STDERR "\nRun with --no-verify if you want to skip the DBG check.\n";
776             print STDERR "Aborting commit.\n";
777             exit 1;
778             }
779             exit 0;
780              
781             =head1 AUTHOR
782              
783             Grant Street Group <developers@grantstreet.com>
784              
785             =head1 COPYRIGHT AND LICENSE
786              
787             This software is Copyright (c) 2014 - 2020 by Grant Street Group.
788              
789             This is free software, licensed under:
790              
791             The Artistic License 2.0 (GPL Compatible)
792              
793             =cut