File Coverage

blib/lib/Eidolon/Debug.pm
Criterion Covered Total %
statement 26 47 55.3
branch 4 16 25.0
condition 1 3 33.3
subroutine 5 8 62.5
pod 5 5 100.0
total 41 79 51.9


line stmt bran cond sub pod time code
1             package Eidolon::Debug;
2             # ==============================================================================
3             #
4             # Eidolon
5             # Copyright (c) 2009, Atma 7
6             # ---
7             # Eidolon/Debug.pm - debugging facility
8             #
9             # ==============================================================================
10              
11 1     1   84871 use warnings;
  1         2  
  1         51  
12 1     1   6 use strict;
  1         2  
  1         99  
13              
14             our $VERSION = "0.02"; # 2009-05-12 05:50:18
15             my $console_started = 0;
16              
17             # ------------------------------------------------------------------------------
18             # BEGIN()
19             # package initialization
20             # ------------------------------------------------------------------------------
21             BEGIN
22             {
23 1     1   7 $SIG{"__WARN__"} = \&warn;
24 1         2097 $SIG{"__DIE__"} = \¨
25             }
26              
27             # ------------------------------------------------------------------------------
28             # start_console()
29             # start debug console
30             # ------------------------------------------------------------------------------
31             sub start_console
32             {
33 1     1 1 10 my $script;
34              
35             # print HTTP header
36 1         2729 print "Content-Type: text/html; charset=UTF-8\n\n";
37              
38             {
39 1         12 local $/;
  1         12  
40 1         79 $script = ;
41             }
42              
43 1         6924 print $script;
44 1         10 $console_started = 1;
45             }
46              
47             # ------------------------------------------------------------------------------
48             # \@ get_stack()
49             # get call stack
50             # ------------------------------------------------------------------------------
51             sub get_stack
52             {
53 0     0 1 0 my (@stack, $package, $file, $line, $sub, $level);
54              
55             # we don't need this function in stack
56 0         0 $level = 1;
57              
58             # walk stack
59 0         0 while (($package, $file, $line, $sub) = caller($level))
60             {
61 0         0 push @stack,
62             {
63             "package" => $package,
64             "file" => $file,
65             "line" => $line,
66             "sub" => $sub
67             };
68              
69 0         0 $level++;
70             }
71              
72 0         0 return \@stack;
73             }
74              
75             # ------------------------------------------------------------------------------
76             # print_stack(@$stack)
77             # print call stack
78             # ------------------------------------------------------------------------------
79             sub print_stack
80             {
81 0     0 1 0 my ($stack, $level, $sublen, $sub);
82              
83 0         0 $stack = shift;
84 0         0 $sublen = 0;
85            
86             # count fields width
87 0 0       0 $sublen = length($_->{"sub"}) > $sublen ? length($_->{"sub"}) : $sublen foreach (@$stack);
88              
89             # print stack
90 0         0 foreach (reverse @$stack)
91             {
92 0 0       0 printf
93             (
94             "{ line: '%05d', sub: '%-${sublen}s', file: '%s' },",
95             $_->{"line"},
96             $sub ? $sub : "main",
97             $_->{"file"}
98             );
99              
100 0         0 $sub = $_->{"sub"};
101             }
102             }
103              
104             # ------------------------------------------------------------------------------
105             # warn($message)
106             # warning handler
107             # ------------------------------------------------------------------------------
108             sub warn
109             {
110 0     0 1 0 my ($message, $stack, $phase);
111              
112 0         0 $message = shift;
113 0 0       0 $phase = defined $^S ? "Runtime" : "Compile";
114              
115 0 0       0 start_console unless $console_started;
116              
117 0         0 $message =~ s/[\r\n]//g;
118 0         0 $message =~ s/'/\\'/g;
119              
120 0         0 printf "";
121             }
122              
123             # ------------------------------------------------------------------------------
124             # die($message)
125             # die handler
126             # ------------------------------------------------------------------------------
127             sub die
128             {
129 1     1 1 4 my ($message, $stack, $phase);
130              
131 1         15 $message = shift;
132 1 50       11 $phase = defined $^S ? "Runtime" : "Compile";
133              
134             # call original die if called from eval block
135 1 50 33     10 CORE::die($message) if (defined $^S && $^S == 1);
136              
137 1 50       8 start_console unless $console_started;
138              
139 1         14 $message =~ s/[\r\n]//g;
140 1         10 $message =~ s/'/\\'/g;
141              
142 1         21 print "";
151              
152 1         80 exit;
153             }
154              
155             1;
156              
157             =pod
158              
159             =head1 NAME
160              
161             Eidolon::Debug - Eidolon debugging facility.
162              
163             =head1 SYNOPSIS
164              
165             In CGI/FCGI gateway of your application (C/C) write:
166              
167             use Eidolon::Debug;
168              
169             =head1 DESCRIPTION
170              
171             The I package provides an easy way to avoid a confusing
172             I web server message. It sends HTTP header before
173             displaying an error, so you don't need to dig web-server's log to find the cause
174             of the error anymore. Obviously, it will do nothing if error is in your
175             web-server configuration, so if I message still remains,
176             check your web-server configuration. Also, this package displays a stack trace
177             when application dies. It is very useful in application development, so
178             I is included in applications by default.
179              
180             This package doesn't depend on any other I package, so you can use it
181             outside I applications too.
182              
183             While used, I hooks global C and C subroutines, so be
184             careful using other packages, that modify or depend on C<$SIG{"__DIE__"}> and
185             C<$SIG{"__WARN__"}> handlers.
186              
187             =head1 METHODS
188              
189             =head2 start_console()
190              
191             Start a javascript debugging console. Prints a minimal HTTP header and javascript
192             code, so further error and warning messages could be displayed in nice-looking
193             form.
194              
195             =head2 get_stack()
196              
197             Get subroutine call stack. Returns reference to array of hashrefs, each hashref
198             stands for one level of the call stack. This hashref contains the following
199             data:
200              
201             =over 4
202              
203             =item * package
204              
205             Package name, where error has been occured.
206              
207             =item * file
208              
209             File name, where error has been occured.
210              
211             =item * line
212              
213             Line number, which caused program to die.
214              
215             =item * sub
216              
217             Subroutine name, where error has been occured.
218              
219             =back
220              
221             =head2 print_stack($stack)
222              
223             Prints the call stack in nice preformatted table. C<$stack> - reference to
224             array of call stack hashrefs (result, returned by C subroutine).
225              
226             =head2 warn($message)
227              
228             Custom warning handler. C<$message> - warning message to be displayed.
229              
230             =head2 die($message)
231              
232             Custom error handler. C<$message> - error message to be displayed.
233              
234             =head1 SEE ALSO
235              
236             L, L
237              
238             =head1 LICENSE
239              
240             This library is free software; you can redistribute it and/or modify
241             it under the same terms as Perl itself.
242              
243             =head1 AUTHOR
244              
245             Anton Belousov, Eabel@cpan.orgE
246              
247             =head1 COPYRIGHT
248              
249             Copyright (c) 2009, Atma 7, L
250              
251             =cut
252              
253             __DATA__