Codebase list liblog-report-perl / v1.06
distribution Log-Report-1.06.tar.gz Mark Overmeer authored 8 years ago Mark Overmeer committed 6 years ago
15 changed file(s) with 703 addition(s) and 29 deletion(s). Raw diff Collapse all Expand all
55
66 TODO:
77 . connect to Message::Passing framework
8
9 version 1.06: Mon Jun 15 17:30:33 CEST 2015
10
11 Fixes:
12 - t/60mojo.t will not run on old mojo's: requires 2.16 (2011)
13 [cpantesters]
14 - ::Dispatcher::File do not use %F/%T in strfime, which is not
15 supported by Windows.
16 - make ::Die understand multiline 'die()' messages.
17 rt.cpan.org#101389 [Ken Neighbors]
18
19 Improvements:
20 - add Dancer::Log::Report and examples/dancer/
21 - add Dancer2::*, contributed by [Andrew Beverly]
822
923 version 1.05: Tue Jun 24 09:38:15 CEST 2014
1024
11 MANIFEST
22 Makefile.PL
33 README
4 examples/dancer/dancer1.pl
5 lib/Dancer/Logger/LogReport.pm
6 lib/Dancer2/Logger/LogReport.pm
7 lib/Dancer2/Plugin/LogReport.pm
48 lib/Log/Report.pm
59 lib/Log/Report/Die.pm
610 lib/Log/Report/Dispatcher.pm
11
22 use 5.008;
33
4 my $version = '1.05';
4 my $version = '1.06';
55
66 my %prereq =
77 ( Test::More => '0.86'
4747 RAWDIR = ../public_html/log-report/raw
4848 DISTDIR = ../public_html/log-report/source
4949 LICENSE = artistic
50 SKIP_LINKS = XML::LibXML
50 SKIP_LINKS = Dancer2::Config
5151
5252 # for OODoc's oodist, POD
5353 FIRST_YEAR = 2007
0 #!/usr/bin/env perl
1 # Daemon at localhost:3000
2
3 use Dancer;
4 use Dancer::Logger::LogReport;
5 use Log::Report import => 'dispatcher';
6
7 dispatcher FILE => 'logfile' # open additional log destination
8 # , mode => 'DEBUG' # extended information
9 , to => '/tmp/dancer-demo.log';
10
11 dispatcher close => 'default'; # closes warn/die default dispatcher
12
13 set logger => 'log_report';
14 set log => 'debug';
15 set logger_format => 'LOG: %i%m';
16
17 get '/' => sub {
18 error "we reached the log"; # use Dancer's error() syntax!
19 notice "one more"; # additional levels, same syntax
20 return "Hello World!\n";
21 };
22
23 start;
0 package Dancer::Logger::LogReport;
1 use base 'Dancer::Logger::Abstract', 'Exporter';
2
3 use strict;
4 use warnings;
5
6 use Scalar::Util qw/blessed/;
7 use Log::Report 'logreport', import => 'report';
8 use Log::Report::Dispatcher ();
9
10 our $AUTHORITY = 'cpan:MARKOV';
11
12 our @EXPORT = qw/
13 trace
14 assert
15 notice
16 alert
17 panic
18 /;
19
20 my %level_dancer2lr =
21 ( core => 'TRACE'
22 , debug => 'TRACE'
23 );
24
25 =chapter NAME
26
27 Dancer::Logger::LogReport - reroute Dancer logs into Log::Report
28
29 =chapter SYNOPSIS
30
31 # When your main program is not a Dancer object
32 use My::Dancer::App;
33 use Log::Report;
34 ... start dispatcher ...
35 error "something is wrong"; # Log::Report::error()
36
37 # When your main program is a Dancer object
38 use Dancer;
39 use Dancer::Logger::LogReport;
40 use Log::Report import => 'dispatcher';
41 ... start dispatcher ...
42 error "something is wrong"; # Dancer::error()
43
44 # In any case, your main program needs to start log dispatcers
45 # Both Dancer and other Log::Report based modules will send
46 # their messages here:
47 dispatcher FILE => 'default', ...;
48
49 # In your config
50 logger: log_report
51 logger_format: %i%m # keep it simple
52 log: debug # filtered by dispatchers
53
54 =chapter DESCRIPTION
55
56 The M<Log::Report> exception/translation framework defines a large
57 number of logging back-ends. The same log messages can be sent to
58 multiple destinations at the same time via flexible dispatchers.
59 When you use this logger in your Dancer application, it will nicely
60 integrate with non-Dancer modules which need logging.
61
62 Many log back-ends, like syslog, have more levels of system messages.
63 Modules who explicitly load this module can use the missing C<assert>,
64 C<notice>, C<panic>, and C<alert> log levels. The C<trace> name is
65 provided as well: when you are debugging, you add a 'trace' to your
66 program... its just a better name than 'debug'.
67
68 You probably want to set a very simple C<logger_format>, because the
69 dispatchers do already add some of the fields that the default
70 C<simple> format adds. For instance, to get the filename/line-number
71 in messages depends on the dispatcher 'mode' (f.i. 'DEBUG').
72
73 You also want to set the log level to C<debug>, because level filtering
74 is controled per dispatcher (as well)
75
76 =cut
77
78 # Add some extra 'levels'
79 sub trace { goto &Dancer::Logger::debug }
80 sub assert { goto &Dancer::Logger::assert }
81 sub notice { goto &Dancer::Logger::notice }
82 sub panic { goto &Dancer::Logger::panic }
83 sub alert { goto &Dancer::Logger::alert }
84
85 { use Dancer::Logger;
86 package Dancer::Logger;
87 sub assert { my $l = logger(); $l && $l->_log(assert => _serialize(@_)) }
88 sub notice { my $l = logger(); $l && $l->_log(notice => _serialize(@_)) }
89 sub alert { my $l = logger(); $l && $l->_log(alert => _serialize(@_)) }
90 sub panic { my $l = logger(); $l && $l->_log(panic => _serialize(@_)) }
91 }
92
93 #sub init(@)
94 #{ my $self = shift;
95 # $self->SUPER::init(@_);
96 #}
97
98 sub _log {
99 my ($self, $level, $params) = @_;
100
101 # all dancer levels are the same as L::R levels, except:
102 my $msg;
103 if(blessed $params && $params->isa('Log::Report::Message'))
104 { $msg = $params;
105 }
106 else
107 { $msg = $self->format_message($level => $params);
108 $msg =~ s/\n+$//;
109 }
110
111 # The levels are nearly the same.
112 my $reason = $level_dancer2lr{$level} // uc $level;
113
114 # Gladly, report() does not get confused between Dancer's use of
115 # Try::Tiny and Log::Report's try() which starts a new dispatcher.
116 report {is_fatal => 0}, $reason => $msg;
117
118 undef;
119 }
120
121 1;
0 package Dancer2::Logger::LogReport;
1 # ABSTRACT: Dancer2 logger engine for Log::Report
2
3 use strict;
4 use warnings;
5
6 use Moo;
7 use Dancer2::Core::Types;
8 use Scalar::Util qw/blessed/;
9 use Log::Report 'logreport', syntax => 'REPORT', mode => 'DEBUG';
10
11 our $AUTHORITY = 'cpan:MARKOV';
12
13 my %level_dancer2lr =
14 ( core => 'TRACE'
15 , debug => 'TRACE'
16 );
17
18 with 'Dancer2::Core::Role::Logger';
19
20 # Set by calling function
21 has dispatchers =>
22 ( is => 'ro'
23 , isa => Maybe[HashRef]
24 , lazy => 1
25 );
26
27 sub BUILD
28 { my $self = shift;
29 my $dispatchers = $self->dispatchers;
30
31 foreach my $name (keys %$dispatchers)
32 { my %dispatcher = %{$dispatchers->{$name}};
33 my $type = delete $dispatcher{type};
34 dispatcher $type => $name, %dispatcher;
35 }
36 }
37
38 =chapter NAME
39
40 Dancer2::Logger::LogReport - reroute Dancer2 logs into Log::Report
41
42 =chapter SYNOPSIS
43
44 # This module is loaded when configured. It does not provide
45 # end-user functions or methods.
46
47 =chapter DESCRIPTION
48
49 This logger allows the use of the many logging backends available
50 in M<Log::Report>. It will process all of the Dancer2 log messages,
51 and also allow any other module to use the same logging facilities. The
52 same log messages can be sent to multiple destinations at the same time
53 via flexible dispatchers.
54
55 If using this logger, you may also want to use
56 M<Dancer2::Plugin::LogReport>
57
58 Many log back-ends, like syslog, have more levels of system messages.
59 Modules who explicitly load this module can use the missing C<assert>,
60 C<notice>, C<panic>, and C<alert> log levels. The C<trace> name is
61 provided as well: when you are debugging, you add a 'trace' to your
62 program... it's just a better name than 'debug'.
63
64 You probably want to set a very simple C<logger_format>, because the
65 dispatchers do already add some of the fields that the default C<simple>
66 format adds. For instance, to get the filename/line-number in messages
67 depends on the dispatcher 'mode' (f.i. 'DEBUG').
68
69 You also want to set the log level to C<debug>, because level filtering is
70 controlled per dispatcher (as well).
71
72 =chapter METHODS
73
74 =method log $level, $params
75
76 =cut
77
78 sub log($$$)
79 { my ($self, $level, $params) = @_;
80
81 # all dancer levels are the same as L::R levels, except:
82 my $msg;
83 if(blessed $params && $params->isa('Log::Report::Message'))
84 { $msg = $params;
85 }
86 else
87 { $msg = $self->format_message($level => $params);
88 $msg =~ s/\n+$//;
89 }
90
91 # The levels are nearly the same.
92 my $reason = $level_dancer2lr{$level} // uc $level;
93
94 report {is_fatal => 0}, $reason => $msg;
95
96 undef;
97 }
98
99 #--------------
100 =chapter DETAILS
101
102 =section Configuration
103
104 The setting B<logger> should be set to C<LogReport> in order to use
105 this logging engine in a Dancer application. See M<Dancer2::Config>
106 about ways to include these settings in your program.
107
108 There is only one optional configuration parameter: C<dispatchers>. This
109 defines the M<Log::Report> dispatchers to use. Any number of dispatchers
110 may be configured.
111
112 # instruct Dancer2 to load this module
113 logger: LogReport
114
115 # use default Log::Report dispatchers
116 engines:
117 logger:
118 LogReport:
119
120 # syslog and file dispatcher
121 engines:
122 logger:
123 LogReport:
124 logger_format: %i%m # keep it simple
125 dispatchers:
126 syslog: # Name
127 type: SYSLOG # Log::Report dispatcher type
128 identity: gads # Dispatcher options
129 facility: local0
130 flags: "pid ndelay nowait"
131 mode: DEBUG
132 default: # will replace default dispatcher
133 type: FILE
134 to: /var/log/mylog
135 charset: utf-8
136 accept: NOTICE- # Only accept NOTICE and above
137
138 =cut
139
140 1;
0 package Dancer2::Plugin::LogReport;
1
2 use warnings;
3 use strict;
4
5 use Dancer2::Plugin;
6 use Log::Report 'log-report', syntax => 'REPORT';
7
8 use Scalar::Util qw/blessed/;
9
10 my $_dsl; # XXX How to avoid the global?
11 my $_settings;
12
13 =chapter NAME
14
15 Dancer2::Plugin::LogReport - logging and exceptions via Log::Report
16
17 =chapter SYNOPSIS
18
19 # Load the plugin into Dancer2
20 # see Log::Report::import() for %options
21 use Dancer2::Plugin::LogReport %options;
22
23 # Stop execution, redirect, and display an error to the user
24 $name or error "Please enter a name";
25
26 # Add debug information to logger
27 trace "We're here";
28
29 # Handling user errors cleanly
30 if (process( sub {MyApp::Model->create_user} )) {
31 # Success, redirect user elsewhere
32 } else {
33 # Failed, continue as if submit hadn't been made.
34 # Error message will be in session for display later.
35 }
36
37 # Send errors to template for display
38 hook before_template => sub {
39 my $tokens = shift;
40 $tokens->{messages} = session 'messages';
41 session 'messages' => [];
42 }
43
44 =chapter DESCRIPTION
45
46 This module provides easy access to the extensive logging facilities
47 provided by M<Log::Report>. Along with M<Dancer2::Logger::LogReport>,
48 this brings together all the internal Dancer2 logging, handling for
49 expected and unexpected exceptions, translations and application logging.
50
51 Logging is extremely flexible using many of the available
52 L<dispatchers|Log::Report::Dispatcher/DETAILS>. Multiple dispatchers can be
53 used, each configured separately to display different messages in different
54 formats. By default, messages are logged to a session variable for display on
55 a webpage, and to STDERR.
56
57 =chapter METHODS
58
59 =cut
60
61 # "use" import
62 sub import
63 { my $class = shift;
64 Log::Report->import('+2', @_, syntax => 'LONG');
65 }
66
67 # Dancer2 import
68 on_plugin_import
69 { my $dsl = $_dsl = shift; # capture global singleton
70 my $settings = $_settings = plugin_setting;
71
72 # Need init_error for exceptions and other errors
73 $dsl->hook(init_error => sub {
74 my $error = shift;
75 # Catch other exceptions. This hook is called for all errors
76 # not just exceptions (including for example 404s), so check first.
77 # If it's an exception then panic it to get Log::Report
78 # to handle it nicely. If it's another error such as a 404
79 # then exception will not be set.
80 report 'PANIC' => $error->{exception}
81 if $error->{exception};
82 });
83
84 if ($settings->{handle_http_errors})
85 { # Need after_error for HTTP errors (eg 404) so as to
86 # be able to change the forwarding location
87 $dsl->hook(after_error => sub {
88 use Data::Dumper; say STDERR Dumper \@_;
89 my $error = shift;
90 my $msg = $error->status . ": "
91 . Dancer2::Core::HTTP->status_message($error->status);
92
93 # XXX How to write messages to the session? request() is not
94 # in the DSL at this point. At least log it.
95 report 'TRACE' => $msg;
96 _forward_home( $error, danger => $msg ); # $error is the request
97 });
98 }
99
100 # This is so that all messages go into the session, to be displayed
101 # on the web page (if required)
102 dispatcher CALLBACK => 'error_handler'
103 , callback => \&_error_handler
104 , mode => 'DEBUG';
105 }; # ";" required!
106
107 =method process
108
109 C<process()> is an eval, but one which expects and handles exceptions
110 generated by M<Log::Report>. Any messages will be logged as normal in
111 accordance with the dispatchers, but any fatal exceptions will be caught
112 and handled gracefully. This allows much simpler error handling, rather
113 than needing to test for lots of different scenarios.
114
115 In a module, it is enough to simply use the C<error> keyword in the event of a
116 fatal error.
117
118 The return value will be 1 for success or 0 if a fatal exception occurred.
119
120 See the L</DETAILS> for an example of how this is expected to be used.
121
122 Modules do not need to use this plugin, instead they can C<use Log::Report>.
123
124 =cut
125
126 sub process($$)
127 { my ($dsl, $coderef) = @_;
128 try { $coderef->() };
129
130 # Return true on success
131 if (my $exception = $@->wasFatal)
132 { $exception->throw(is_fatal => 0);
133 return 0;
134 }
135 $@->reportAll;
136 1;
137 }
138
139 register process => \&process;
140
141 sub _message_add($$)
142 { my ($type, $text) = @_;
143 $text && $type or return;
144 unless ($_dsl->app->request)
145 { # This happens for HTTP errors
146 # XXX the session is not available in the DSL
147 report 'ASSERT' => "Unable to write message to session: unable to write cookie";
148 return;
149 }
150 my $messages_variable = $_settings->{messages_key} || 'messages';
151 my $session = $_dsl->app->session;
152 my $msgs = $session->read($messages_variable);
153 push @$msgs, { text => $text, type => $type };
154 $session->write($messages_variable => $msgs);
155 }
156
157 #------
158 =section Handlers
159
160 All the standard M<Log::Report> functions are available to use. Please see the
161 L<Log::Report/"The Reason for the report"> for details
162 of when each one should be used.
163
164 =method trace
165 =method assert
166 =method info
167 =method notice
168 =method warning
169 =method mistake
170 =method error
171 =method fault
172 =method alert
173 =method failure
174 =method panic
175 =cut
176
177 sub _forward_home($$$)
178 { my $dsl = shift;
179 _message_add(shift, shift);
180 my $page = $_settings->{forward_url} || '/';
181 $dsl->redirect($page);
182 }
183
184 sub _error_handler($$$$)
185 { my ($disp, $options, $reason, $message) = @_;
186
187 my $fatal_handler = sub {
188 _forward_home( $_dsl, danger => $_[0] )
189 unless $_dsl->request->uri eq '/' && $_dsl->request->is_get;
190 };
191
192 my %handler =
193 ( # Default do nothing for the moment (TRACE|ASSERT|INFO)
194 default => sub {}
195
196 # Notice that something has happened. Not an error.
197 , NOTICE => sub {_message_add info => $_[0]}
198
199 # Non-fatal problem. Show warning.
200 , WARNING => sub {_message_add warning => $_[0]}
201
202 # Non-fatal problem. Show warning.
203 , MISTAKE => sub {_message_add warning => $_[0]}
204
205 # A user-created error condition that is not recoverable.
206 # This could have already been caught by the process
207 # subroutine, in which case we should continue running
208 # of the program. In all other cases, we should bail
209 # out. With the former, the exception will have been
210 # re-thrown as a non-fatal exception, so check that.
211 , ERROR => sub {
212 exists $options->{is_fatal} && !$options->{is_fatal}
213 ? _message_add( danger => $_[0] )
214 : _forward_home( $_dsl, danger => $_[0] );
215 }
216
217 # 'FAULT', 'ALERT', 'FAILURE', 'PANIC'
218 # All these are fatal errors. Display error to user, but
219 # forward home so that we can reload. However, don't if
220 # it's a GET request to the home, as it will cause a recursive
221 # loop. In this case, do nothing, and let dancer handle it.
222 , FAULT => $fatal_handler
223 , ALERT => $fatal_handler
224 , FAILURE => $fatal_handler
225 , PANIC => $fatal_handler
226 );
227
228 my $call = $handler{$reason} || $handler{default};
229 $call->("$message");
230 }
231
232 sub _report($@) {
233 my ($reason, $dsl) = (shift, shift);
234
235 my $msg = (blessed($_[0]) && $_[0]->isa('Log::Report::Message'))
236 ? $_[0] : Dancer2::Core::Role::Logger::_serialize(@_);
237
238 report uc($reason) => $msg;
239 }
240
241 register trace => sub { _report(TRACE => @_) };
242 register assert => sub { _report(ASSERT => @_) };
243 register notice => sub { _report(NOTICE => @_) };
244 register mistake => sub { _report(MISTAKE => @_) };
245 register panic => sub { _report(PANIC => @_) };
246 register alert => sub { _report(ALERT => @_) };
247
248 register_plugin for_versions => ['2'];
249
250 #----------
251 =chapter DETAILS
252
253 =section Larger example
254
255 In its simplest form, this module can be used for more flexible logging
256
257 get '/route' => sub {
258 # Stop execution, redirect, and display an error to the user
259 $name or error "Please enter a name";
260
261 # The same but translated
262 $name or error __"Please enter a name";
263
264 # The same but translated and with variables
265 $name or error __x"{name} is not valid", name => $name;
266
267 # Show the user a warning, but continue exection
268 mistake "Not sure that's what you wanted";
269
270 # Add debug information, can be caught in syslog by adding the syslog
271 # dispatcher
272 trace "Hello world"; };
273
274 The module can also be used in models to test for user input and act
275 accordingly, without needing to set up complicated error handling:
276
277 # In a module
278 package MyApp::MyModel sub create_user {
279 ...
280 $surname or error "Please enter a surname"; # Execution stops here
281 ...
282 $telephone or mistake "Tel not entered"; # Execution continues
283 ...
284 }
285
286 # In the main app
287 get '/user' => sub {
288 ...
289 if (param 'submit') {
290 if (process( sub { MyApp::Model->create_user() })) {
291 # Success, redirect user elsewhere
292 }
293 }
294 # Failed, continue as if submit hadn't been made. Error will have been
295 # logged in session to be displayed later.
296 };
297
298 This module will also catch any unexpected exceptions:
299
300 # This will be caught, the error will be logged (full stacktrace to STDOUT,
301 # short message to the session messages), and the user will be forwarded
302 # (default to /). This would also be sent to syslog with the appropriate
303 # dispatcher.
304 get 'route' => sub {
305 my $foo = 1;
306 my $bar = $foo->{x}; # whoops
307 }
308
309 Errors are all logged to the session. These need to be cleared once they have
310 been displayed.
311
312 hook before_template => sub {
313 my $tokens = shift;
314 # Pass messages to template and clear session
315 $tokens->{messages} = session 'messages';
316 session 'messages' => [];
317 }
318
319 In the template. This example prints them in Bootstrap colors:
320
321 [% FOR message IN messages %]
322 [% IF message.type %]
323 [% msgtype = message.type %]
324 [% ELSE %]
325 [% msgtype = "info" %]
326 [% END %]
327 <div class="alert alert-[% msgtype %]">
328 [% message.text | html_entity %]
329 </div>
330 [% END %]
331
332 =section Configuration
333
334 =subsection Dancer2 configuration
335
336 In your application's configuration file (values shown are defaults):
337
338 plugins: LogReport
339 # Set the forward URL on fatal error that isn't caught
340 forward_url: /
341
342 # Set to 1 if you want the module to also catch Dancer HTTP errors
343 # (such as 404s)
344 handle_http_errors: 0
345
346 # Configure session variable for messages
347 messages_key = messages
348
349 =subsection Log::Report configuration
350
351 Any L<Log::Report configuration options|Log::Report/Configuration> can also be
352 used with this plugin.
353
354 =subsection Dancer2::Logger::LogReport
355
356 You probably want to also use and configure M<Dancer2::Logger::LogReport>.
357 See its documentation for full details.
358
359 =cut
360
361 1;
362
1414
1515 =chapter DESCRIPTION
1616
17 =chapter OVERLOADING
17 This module is used internally, to translate output of 'die' and Carp
18 functions into M<Log::Report::Message> objects.
1819
1920 =chapter Functions
2021
6869 $text[0] =~ s/\s*[.:;]?\s*$err\s*$// # the $err is translation sensitive
6970 or delete $opt{errno};
7071
71 my $msg = shift @text;
72 length $msg or $msg = 'stopped';
72 my @msg = shift @text;
73 length $msg[0] or $msg[0] = 'stopped';
7374
7475 my @stack;
7576 foreach (@text)
76 { push @stack, [ $1, $2, $3 ]
77 if m/^\s*(.*?)\s+called at (.*?) line (\d+)\s*$/;
77 { if(m/^\s*(.*?)\s+called at (.*?) line (\d+)\s*$/)
78 { push @stack, [ $1, $2, $3 ] }
79 else { push @msg, $_ }
7880 }
7981 $opt{stack} = \@stack;
8082 $opt{classes} = [ 'perl', (@stack ? 'confess' : 'die') ];
8385 = @{$opt{stack}} ? ($opt{errno} ? 'ALERT' : 'PANIC')
8486 : ($opt{errno} ? 'FAULT' : 'ERROR');
8587
86 ($dietxt, \%opt, $reason, $msg);
88 ($dietxt, \%opt, $reason, join("\n",@msg));
8789 }
8890
8991 "to die or not to die, that's the question";
128128 : $format eq 'LONG'
129129 ? sub { my $msg = shift;
130130 my $domain = shift || '-';
131 my $stamp = strftime "%FT%T", gmtime;
131 my $stamp = strftime "%Y-%m-%dT%H:%M:%S", gmtime;
132132 "[$stamp $$] $domain $msg"
133133 }
134134 : error __x"unknown format parameter `{what}'"
1212 use File::Basename qw/basename/;
1313
1414 my %default_reasonToPrio =
15 ( TRACE => LOG_DEBUG
16 , ASSERT => LOG_DEBUG
17 , INFO => LOG_INFO
18 , NOTICE => LOG_NOTICE
19 , WARNING => LOG_WARNING
20 , MISTAKE => LOG_WARNING
21 , ERROR => LOG_ERR
22 , FAULT => LOG_ERR
23 , ALERT => LOG_ALERT
24 , FAILURE => LOG_EMERG
25 , PANIC => LOG_CRIT
26 );
15 ( TRACE => LOG_DEBUG
16 , ASSERT => LOG_DEBUG
17 , INFO => LOG_INFO
18 , NOTICE => LOG_NOTICE
19 , WARNING => LOG_WARNING
20 , MISTAKE => LOG_WARNING
21 , ERROR => LOG_ERR
22 , FAULT => LOG_ERR
23 , ALERT => LOG_ALERT
24 , FAILURE => LOG_EMERG
25 , PANIC => LOG_CRIT
26 );
2727
2828 @reasons==keys %default_reasonToPrio
2929 or panic __"not all reasons have a default translation";
148148 $self->SUPER::close;
149149 }
150150
151 #--------------
151152 =section Accessors
153 =cut
152154
155 #--------------
153156 =section Logging
154157 =cut
155158
3535 if($@->success) { # no errors # }
3636
3737 try { # something causes an error report, which is caught
38 report {to => 'stderr'}, FAILURE => 'no network';
38 failure 'no network';
3939 };
4040 $@->reportFatal(to => 'syslog'); # overrule destination
4141
343343 do { $sub = (caller $nest++)[3] }
344344 while(defined $sub && $sub ne 'Log::Report::report');
345345 defined $sub or $nest = 1; # not found
346
347 # skip syntax==SHORT routine entries
348 # $nest++ if defined $sub && $sub =~ m/^Log\:\:Report\:\:/;
349346
350347 # special trick by Perl for Carp::Heavy: adds @DB::args
351348 { package DB; # non-blank before package to avoid problem with OODoc
55 use Log::Report 'log-report';
66 use Log::Report::Util qw/is_fatal/;
77 use POSIX qw/locale_h/;
8 use Scalar::Util qw/blessed/;
89
910 =chapter NAME
1011 Log::Report::Exception - a collected report
100101 { my $self = shift;
101102 @_ or return $self->{message};
102103 my $msg = shift;
103 UNIVERSAL::isa($msg, 'Log::Report::Message')
104 or panic __x"message() of exception expects Log::Report::Message";
104 blessed $msg && $msg->isa('Log::Report::Message')
105 or panic "message() of exception expects Log::Report::Message";
105106 $self->{message} = $msg;
106107 }
107108
337337
338338 sub valueOf($) { $_[0]->{$_[1]} }
339339
340 #--------------
340341 =section Processing
341342
342343 =method inClass $class|Regexp
1010 use Data::Dumper;
1111
1212 BEGIN
13 { eval "require Mojo::Base";
14 plan skip_all => 'Mojo is not installed'
13 { eval "require Mojolicious";
14 plan skip_all => 'Mojolicious is not installed'
1515 if $@;
1616
17 plan skip_all => 'installed Mojolicious too old (requires 2.16)'
18 if $Mojolicious::VERSION < 2.16;
1719 plan tests => 7;
1820 }
1921