1Dancer2::Plugin::LogRepUosretr(3C)ontributed Perl DocumeDnatnacteiro2n::Plugin::LogReport(3)
2
3
4

NAME

6       Dancer2::Plugin::LogReport - logging and exceptions via Log::Report
7

INHERITANCE

9        Dancer2::Plugin::LogReport
10          is a Dancer2::Plugin
11

SYNOPSIS

13         # Load the plugin into Dancer2
14         # see Log::Report::import() for %options
15         use Dancer2::Plugin::LogReport %options;
16
17         # Stop execution, redirect, and display an error to the user
18         $name or error "Please enter a name";
19
20         # Add debug information to logger
21         trace "We're here";
22
23         # Handling user errors cleanly
24         if (process( sub {MyApp::Model->create_user} )) {
25             # Success, redirect user elsewhere
26         } else {
27             # Failed, continue as if submit hadn't been made.
28             # Error message will be in session for display later.
29         }
30
31         # Send errors to template for display
32         hook before_template => sub {
33             my $tokens = shift;
34             $tokens->{messages} = session 'messages';
35             session 'messages' => [];
36         }
37

DESCRIPTION

39       [The Dancer2 plugin was contributed by Andrew Beverley]
40
41       This module provides easy access to the extensive logging facilities
42       provided by Log::Report. Along with Dancer2::Logger::LogReport, this
43       brings together all the internal Dancer2 logging, handling for expected
44       and unexpected exceptions, translations and application logging.
45
46       Logging is extremely flexible using many of the available dispatchers.
47       Multiple dispatchers can be used, each configured separately to display
48       different messages in different formats.  By default, messages are
49       logged to a session variable for display on a webpage, and to STDERR.
50
51       Messages within this plugin use the extended
52       Dancer2::Logger::LogReport::Message class rather than the standard
53       Log::Report::Message class.
54
55       Note that it is currently recommended to use the plugin in all apps
56       within a Dancer2 program, not only some. Therefore, wherever you "use
57       Dancer2" you should also "use Dancer2::Plugin::LogReport". This does
58       not apply if using the same app name ("use Dancer2 appname,
59       'Already::Exists'"). In all other modules, you can just "use
60       Log::Report".
61
62       Read the "DETAILS" in below in this manual-page.
63

METHODS

65       $obj->fatal_handler()
66           "fatal_handler()" allows alternative handlers to be defined in
67           place of (or in addition to) the default redirect handler that is
68           called on a fatal error.
69
70           Calls should be made with 1 parameter: the subroutine to call in
71           the case of a fatal error. The subroutine is passed 3 parameters:
72           the DSL, the message in question, and the reason. The subroutine
73           should return true or false depending on whether it handled the
74           error. If it returns false, the next fatal handler is called, and
75           if there are no others then the default redirect fatal handler is
76           called.
77
78           example: Error handler based on URL (e.g. API)
79
80             fatal_handler sub {
81               my ($dsl, $msg, $reason) = @_;
82               return if $dsl->app->request->uri !~ m!^/api/!;
83               status $reason eq 'PANIC' ? 'Internal Server Error' : 'Bad Request';
84               $dsl->send_as(JSON => {
85                   error             => 1,
86                   error_description => $msg->toString,
87               }, {
88                   content_type => 'application/json; charset=UTF-8',
89               });
90             };
91
92           example: Return JSON responses for requests with content-type of
93           application/json
94
95           fatal_handler sub {
96               my ($dsl, $msg, $reason, $default) = @_;
97
98               (my $ctype = $dsl->request->header('content-type')) =~ s/;.*//;
99               return if $ctype ne 'application/json';
100               status $reason eq 'PANIC' ? 'Internal Server Error' : 'Bad Request';
101               $dsl->send_as(JSON => {
102                   error       => 1,
103                   description => $msg->toString,
104               }, {
105                   content_type => 'application/json; charset=UTF-8',
106               });
107             };
108
109       $obj->process()
110           "process()" is an eval, but one which expects and understands
111           exceptions generated by Log::Report. Any messages will be logged as
112           normal in accordance with the dispatchers, but any fatal exceptions
113           will be caught and handled gracefully.  This allows much simpler
114           error handling, rather than needing to test for lots of different
115           scenarios.
116
117           In a module, it is enough to simply use the "error" keyword in the
118           event of a fatal error.
119
120           The return value will be 1 for success or 0 if a fatal exception
121           occurred.
122
123           See the "DETAILS" for an example of how this is expected to be
124           used.
125
126           This module is configured only once in your application. The other
127           modules which make your website do not need to require this plugin,
128           instead they can "use Log::Report" to get useful functions like
129           error and fault.
130
131   Handlers
132       All the standard Log::Report functions are available to use. Please see
133       the "The Reason for the report" in Log::Report for details of when each
134       one should be used.
135
136       Log::Report class functionality to class messages (which can then be
137       tested later):
138
139         notice __x"Class me up", _class => 'label';
140         ...
141         if ($msg->inClass('label')) ...
142
143       Dancer2::Plugin::LogReport has a special message class, "no_session",
144       which prevents the message from being saved to the messages session
145       variable. This is useful, for example, if you are writing messages
146       within the session hooks, in which case recursive loops can be
147       experienced.
148
149       $obj->alert()
150       $obj->assert()
151       $obj->error()
152       $obj->failure()
153       $obj->fault()
154       $obj->info()
155       $obj->mistake()
156       $obj->notice()
157       $obj->panic()
158       $obj->success()
159           This is a special additional type, equivalent to "notice".  The
160           difference is that messages using this keyword will have the class
161           "success" added, which can be used to color the messages
162           differently to the end user. For example,
163           Dancer2::Plugin::LogReport::Message#bootstrap_color uses this to
164           display the message in green.
165
166       $obj->trace()
167       $obj->warning()
168

DETAILS

170       This chapter will guide you through the myriad of ways that you can use
171       Log::Report in your Dancer2 application.
172
173       We will set up our application to do the following:
174
175       Messages to the user
176           We'll look at an easy way to output messages to the user's web
177           page, whether they be informational messages, warnings or errors.
178
179       Debug information
180           We'll look at an easy way to log debug information, at different
181           levels.
182
183       Manage unexpected exceptions
184           We'll handle unexpected exceptions cleanly, in the unfortunate
185           event that they happen in your production application.
186
187       Email alerts of significant errors
188           If we do get unexpected errors then we want to be notified them.
189
190       Log DBIC information and errors
191           We'll specifically look at nice ways to log SQL queries and errors
192           when using DBIx::Class.
193
194   Larger example
195       In its simplest form, this module can be used for more flexible logging
196
197         get '/route' => sub {
198             # Stop execution, redirect, and display an error to the user
199             $name or error "Please enter a name";
200
201             # The same but translated
202             $name or error __"Please enter a name";
203
204             # The same but translated and with variables
205             $name or error __x"{name} is not valid", name => $name;
206
207             # Show the user a warning, but continue execution
208             mistake "Not sure that's what you wanted";
209
210             # Add debug information, can be caught in syslog by adding
211             # the (for instance) syslog dispatcher
212             trace "Hello world";
213          };
214
215   Setup and Configuration
216       To make full use of Log::Report, you'll need to use both
217       Dancer2::Logger::LogReport and Dancer2::Plugin::LogReport.
218
219       Dancer2::Logger::LogReport
220
221       Set up Dancer2::Logger::LogReport by adding it to your Dancer2
222       application configuration (see Dancer2::Config). By default, all
223       messages will go to STDERR.
224
225       To get all message out "the Perl way" (using print, warn and die) just
226       use
227
228         logger: "LogReport"
229
230       At start, these are handled by a Log::Report::Dispatcher::Perl object,
231       named 'default'.  If you open a new dispatcher with the name 'default',
232       the output via the perl mechanisms will be stopped.
233
234       To also send messages to your syslog:
235
236         logger: "LogReport"
237
238         engines:
239           logger:
240             LogReport:
241               log_format: %a%i%m      # See Dancer2::Logger::LogReport
242               app_name: MyApp
243               dispatchers:
244                 default:              # Name
245                   type: SYSLOG        # Log::Reporter::dispatcher() options
246                   identity: myapp
247                   facility: local0
248                   flags: "pid ndelay nowait"
249                   mode: DEBUG
250
251       To send messages to a file:
252
253         logger: "LogReport"
254
255         engines:
256           logger:
257             LogReport:
258               log_format: %a%i%m      # See Dancer2::Logger::LogReport
259               app_name: MyApp
260               dispatchers:
261                 logfile:              # "default" dispatcher stays open as well
262                   type: FILE
263                   to: /var/log/myapp.log
264                   charset: utf-8
265                   mode: DEBUG
266
267       See Log::Report::Dispatcher for full details of options.
268
269       Finally: a Dancer2 script may run many applications.  Each application
270       can have its own logger configuration.  However, Log::Report
271       dispatchers are global, so will be shared between Dancer2 applications.
272       Any attempt to create a new Log::Report dispatcher by the same name (as
273       will happen when a new Dancer2 application is started with the same
274       configuration) will be ignored.
275
276       Dancer2::Plugin::LogReport
277
278       To use the plugin, you simply use it in your application:
279
280         package MyApp;
281         use Log::Report ();  # use early and minimal once
282         use Dancer2;
283         use Dancer2::Plugin::LogReport %config;
284
285       Dancer2::Plugin::LogReport takes the same %config options as
286       Log::Report itself (see Log::Report::import()).
287
288       If you want to send messages from your modules/models, there is no need
289       to use this specific plugin. Instead, you should simply "use
290       Log::Report" to negate the need of loading all the Dancer2 specific
291       code.
292
293   In use
294       Logging debug information
295
296       In its simplest form, you can now use all the Log::Report logging
297       functions to send messages to your dispatchers (as configured in the
298       Logger configuration):
299
300         trace "I'm here";
301
302         warning "Something dodgy happened";
303
304         panic "I'm bailing out";
305
306         # Additional, special Dancer2 keyword
307         success "Settings saved successfully";
308
309       Exceptions
310
311       Log::Report is a combination of a logger and an exception system.
312       Messages to be logged are thrown to all listening dispatchers to be
313       handled.
314
315       This module will also catch any unexpected exceptions:
316
317         # This will be caught, the error will be logged (full stacktrace to STDOUT,
318         # short message to the session messages), and the user will be forwarded
319         # (default to /). This would also be sent to syslog with the appropriate
320         # dispatcher.
321         get 'route' => sub {
322             my $foo = 1;
323             my $bar = $foo->{x}; # whoops
324         }
325
326       For a production application ("show_errors: 1"), the message saved in
327       the session will be the generic text "An unexpected error has
328       occurred". This can be customised in the configuration file, and will
329       be translated.
330
331       Sending messages to the user
332
333       To make it easier to send messages to your users, messages at the
334       following levels are also stored in the user's session: "notice",
335       "warning", "mistake", "error", "fault", "alert", "failure" and "panic".
336
337       You can pass these to your template and display them at each page
338       render:
339
340         hook before_template => sub {
341           my $tokens = shift;
342           $tokens->{messages} = session 'messages';
343           session 'messages' => []; # Clear the message queue
344         }
345
346       Then in your template (for example the main layout):
347
348         [% FOR message IN messages %]
349           <div class="alert alert-[% message.bootstrap_color %]">
350             [% message.toString | html_entity %]
351           </div>
352         [% END %]
353
354       The "bootstrap_color" of the message is compatible with Bootstrap
355       contextual colors: "success", "info", "warning" or "danger".
356
357       Now, anywhere in your application that you have used Log::Report, you
358       can
359
360         warning "Hey user, you should now about this";
361
362       and the message will be sent to the next page the user sees.
363
364       Handling user errors
365
366       Sometimes we write a function in a model, and it would be nice to have
367       a nice easy way to return from the function with an error message. One
368       way of doing this is with a separate error message variable, but that
369       can be messy code. An alternative is to use exceptions, but these can
370       be a pain to deal with in terms of catching them.  Here's how to do it
371       with Log::Report.
372
373       In this example, we do use exceptions, but in a neat, easier to use
374       manner.
375
376       First, your module/model:
377
378         package MyApp::CD;
379
380         sub update {
381           my ($self, %values) = @_;
382           $values{title} or error "Please enter a title";
383           $values{description} or warning "No description entered";
384         }
385
386       Then, in your controller:
387
388         package MyApp;
389         use Dancer2;
390
391         post '/cd' => sub {
392           my %values = (
393             title       => param('title');
394             description => param('description');
395           );
396           if (process sub { MyApp::CD->update(%values) } ) {
397             success "CD updated successfully";
398             redirect '/cd';
399           }
400
401           template 'cd' => { values => \%values };
402         }
403
404       Now, when update() is called, any exceptions are caught. However, there
405       is no need to worry about any error messages. Both the error and
406       warning messages in the above code will have been stored in the
407       messages session variable, where they can be displayed using the code
408       in the previous section.  The "error" will have caused the code to stop
409       running, and process() will have returned false. "warning" will have
410       simply logged the warning and not caused the function to stop running.
411
412       Logging DBIC database queries and errors
413
414       If you use DBIx::Class in your application, you can easily integrate
415       its logging and exceptions. To log SQL queries:
416
417         # Log all queries and execution time
418         $schema->storage->debugobj(new Log::Report::DBIC::Profiler);
419         $schema->storage->debug(1);
420
421       By default, exceptions from DBIC are classified at the level "error".
422       This is normally a user level error, and thus may be filtered as normal
423       program operation. If you do not expect to receive any DBIC exceptions,
424       then it is better to class them at the level "panic":
425
426         # panic() DBIC errors
427         $schema->exception_action(sub { panic @_ });
428         # Optionally get a stracktrace too
429         $schema->stacktrace(1);
430
431       If you are occasionally running queries where you expect to naturally
432       get exceptions (such as not inserting multiple values on a unique
433       constraint), then you can catch these separately:
434
435         try { $self->schema->resultset('Unique')->create() };
436         # Log any messages from try block, but only as trace
437         $@->reportAll(reason => 'TRACE');
438
439       Email alerts of exceptions
440
441       If you have an unexpected exception in your production application,
442       then you probably want to be notified about it. One way to do so is
443       configure rsyslog to send emails of messages at the panic level. Use
444       the following configuration to do so:
445
446         # Normal logging from LOCAL0
447         local0.*                        -/var/log/myapp.log
448
449         # Load the mail module
450         $ModLoad ommail
451         # Configure sender, receiver and mail server
452         $ActionMailSMTPServer localhost
453         $ActionMailFrom root
454         $ActionMailTo root
455         # Set up an email template
456         $template mailSubject,"Critical error on %hostname%"
457         $template mailBody,"RSYSLOG Alert\r\nmsg='%msg%'\r\nseverity='%syslogseverity-text%'"
458         $ActionMailSubject mailSubject
459         # Send an email no more frequently than every minute
460         $ActionExecOnlyOnceEveryInterval 60
461         # Configure the level of message to notify via email
462         if $syslogfacility-text == 'local0' and $syslogseverity < 3 then :ommail:;mailBody
463         $ActionExecOnlyOnceEveryInterval 0
464
465       With the above configuration, you will only be emailed of severe
466       errors, but can view the full log information in /var/log/myapp.log
467

CONFIGURATION

469       All configuration is optional. The example configuration file below
470       shows the configuration options and defaults.
471
472           plugins:
473             LogReport:
474               # Whether to handle Dancer HTTP errors such as 404s. Currently has
475               # no effect due to unresolved issues saving messages to the session
476               # and accessing the DSL at that time.
477               handle_http_errors: 1
478               # Where to forward users in the event of an uncaught fatal
479               # error within a GET request
480               forward_url: /
481               # Or you can specify a template instead [1.13]
482               forward_template: error_template_file   # Defaults to empty
483               # For a production server (show_errors: 0), this is the text that
484               # will be displayed instead of unexpected exception errors
485               fatal_error_message: An unexpected error has occurred
486               # The levels of messages that will be saved to the session, and
487               # thus displayed to the end user
488               session_messages: [ NOTICE, WARNING, MISTAKE, ERROR, FAULT, ALERT, FAILURE, PANIC ]
489

SEE ALSO

491       This module is part of Log-Report distribution version 1.29, built on
492       November 08, 2019. Website: http://perl.overmeer.net/CPAN/
493

LICENSE

495       Copyrights 2007-2019 by [Mark Overmeer <markov@cpan.org>]. For other
496       contributors see ChangeLog.
497
498       This program is free software; you can redistribute it and/or modify it
499       under the same terms as Perl itself.  See http://dev.perl.org/licenses/
500
501
502
503perl v5.30.1                      2019-11-08     Dancer2::Plugin::LogReport(3)
Impressum