File Coverage

blib/lib/JIP/Debug.pm
Criterion Covered Total %
statement 71 71 100.0
branch 15 18 83.3
condition 10 11 90.9
subroutine 17 17 100.0
pod 2 7 28.5
total 115 124 92.7


line stmt bran cond sub pod time code
1             package JIP::Debug;
2              
3 1     1   3606 use base qw(Exporter);
  1         2  
  1         92  
4              
5 1     1   22 use 5.006;
  1         4  
6 1     1   6 use strict;
  1         4  
  1         28  
7 1     1   7 use warnings;
  1         11  
  1         51  
8 1     1   8 use Term::ANSIColor 3.00 ();
  1         23  
  1         25  
9 1     1   364 use Devel::StackTrace;
  1         3719  
  1         44  
10 1     1   8 use Carp qw(croak);
  1         2  
  1         64  
11 1     1   490 use Data::Dumper qw(Dumper);
  1         5585  
  1         56  
12 1     1   6 use Fcntl qw(LOCK_EX LOCK_UN);
  1         1  
  1         40  
13 1     1   5 use English qw(-no_match_vars);
  1         2  
  1         6  
14              
15             our $VERSION = '0.999_004';
16              
17             our @EXPORT_OK = qw(
18             to_debug
19             to_debug_raw
20             to_debug_empty
21             to_debug_count
22             to_debug_trace
23             );
24              
25             our $HANDLE = \*STDERR;
26              
27             our $MSG_FORMAT = qq{%s\n%s\n\n};
28             our $MSG_DELIMITER = q{-} x 80;
29             our $MSG_EMPTY_LINES = qq{\n} x 18;
30              
31             our $DUMPER_INDENT = 1;
32             our $DUMPER_DEEPCOPY = 1;
33             our $DUMPER_SORTKEYS = 1;
34              
35             our %TRACE_PARAMS = (
36             skip_frames => 1, # skip to_debug_trace
37             );
38             our %TRACE_AS_STRING_PARAMS;
39              
40             our $COLOR = 'bright_green';
41              
42             our $MAYBE_COLORED = sub {
43             my $text = shift;
44              
45             return defined $text && defined $COLOR
46             ? Term::ANSIColor::colored($text, $COLOR) : $text;
47             };
48              
49             our $MAKE_MSG_HEADER = sub {
50             # $MAKE_MSG_HEADER=0, to_debug=1
51             my ($package, undef, $line) = caller 1;
52              
53             # $MAKE_MSG_HEADER=0, to_debug=1, subroutine=2
54             my $subroutine = (caller 2)[3];
55              
56             $subroutine = resolve_subroutine_name($subroutine);
57              
58             my $text = join q{, }, (
59             sprintf('package=%s', $package),
60             (defined $subroutine ? sprintf('subroutine=%s', $subroutine) : ()),
61             sprintf('line=%d', $line, ),
62             );
63             $text = qq{[$text]:};
64              
65             {
66             my $msg_delimiter = defined $MSG_DELIMITER ? $MSG_DELIMITER : q{};
67             $text = sprintf qq{%s\n%s\n%s}, $msg_delimiter, $text, $msg_delimiter;
68             }
69              
70             return $MAYBE_COLORED->($text);
71             };
72              
73             our $NO_LABEL_KEY = '';
74             our %COUNT_OF_LABEL = ($NO_LABEL_KEY => 0);
75              
76             # Supported on Perl 5.22+
77             eval {
78             require Sub::Util;
79              
80             if (my $set_subname = Sub::Util->can('set_subname')) {
81             $set_subname->('MAYBE_COLORED', $MAYBE_COLORED);
82             $set_subname->('MAKE_MSG_HEADER', $MAKE_MSG_HEADER);
83             }
84             };
85              
86             sub to_debug {
87 1     1 0 4418 my $msg_body = do {
88 1         3 local $Data::Dumper::Indent = $DUMPER_INDENT;
89 1         2 local $Data::Dumper::Deepcopy = $DUMPER_DEEPCOPY;
90 1         2 local $Data::Dumper::Sortkeys = $DUMPER_SORTKEYS;
91              
92 1         5 Dumper(\@ARG);
93             };
94              
95 1         91 my $msg = sprintf $MSG_FORMAT, $MAKE_MSG_HEADER->(), $msg_body;
96              
97 1         9 return send_to_output($msg);
98             }
99              
100             sub to_debug_raw {
101 1     1 0 3900 my $msg_text = shift;
102              
103 1         3 my $msg = sprintf $MSG_FORMAT, $MAKE_MSG_HEADER->(), $msg_text;
104              
105 1         8 return send_to_output($msg);
106             }
107              
108             sub to_debug_empty {
109 1     1 0 4934 my $msg = sprintf $MSG_FORMAT, $MAKE_MSG_HEADER->(), $MSG_EMPTY_LINES;
110              
111 1         12 return send_to_output($msg);
112             }
113              
114             sub to_debug_count {
115 16     16 1 23530 my ($label, $cb);
116 16 100 66     99 if (@ARG == 2 && ref $ARG[1] eq 'CODE') {
    100 100        
    100          
117 2         4 ($label, $cb) = @ARG;
118             }
119             elsif (@ARG == 1 && ref $ARG[0] eq 'CODE') {
120 2         4 $cb = $ARG[0];
121             }
122             elsif (@ARG == 1) {
123 8         19 $label = $ARG[0];
124             }
125              
126 16 100 100     49 $label = defined $label && length $label ? $label : $NO_LABEL_KEY;
127              
128 16   100     50 my $count = $COUNT_OF_LABEL{$label} || 0;
129 16         28 $count++;
130 16         24 $COUNT_OF_LABEL{$label} = $count;
131              
132 16         59 my $msg_body = sprintf '%s: %d', $label, $count;
133              
134 16         36 my $msg = sprintf $MSG_FORMAT, $MAKE_MSG_HEADER->(), $msg_body;
135              
136 16 100       351 $cb->($label, $count) if defined $cb;
137              
138 16         52 return send_to_output($msg);
139             }
140              
141             sub to_debug_trace {
142 1     1 1 6889 my $cb = shift;
143              
144 1         12 my $trace = Devel::StackTrace->new(%TRACE_PARAMS);
145              
146 1         612 my $msg_body = $trace->as_string(%TRACE_AS_STRING_PARAMS);
147 1         1385 $msg_body =~ s{\n+$}{}x;
148              
149 1         20 my $msg = sprintf $MSG_FORMAT, $MAKE_MSG_HEADER->(), $msg_body;
150              
151 1 50       13 $cb->($trace) if defined $cb;
152              
153 1         6 return send_to_output($msg);
154             }
155              
156             sub send_to_output {
157 22     22 0 7263 my $msg = shift;
158              
159 22 50       55 return unless $HANDLE;
160              
161 22         155 flock $HANDLE, LOCK_EX;
162 22 50       82 $HANDLE->print($msg) or croak(sprintf q{Can't write to output: %s}, $OS_ERROR);
163 22         788 flock $HANDLE, LOCK_UN;
164              
165 22         141 return 1;
166             }
167              
168             sub resolve_subroutine_name {
169 14     14 0 13132 my $subroutine = shift;
170              
171 14 100       49 return unless defined $subroutine;
172              
173 12         72 my ($subroutine_name) = $subroutine =~ m{::(\w+)$}x;
174              
175 12         44 return $subroutine_name;
176             }
177              
178             1;
179              
180             __END__