Import upstream version 1.33
Debian Janitor
2 years ago
5 | 5 | |
6 | 6 | TODO: |
7 | 7 | . connect to Message::Passing framework |
8 | ||
9 | version 1.33: Sat Jul 17 10:56:52 CEST 2021 | |
10 | ||
11 | Changes: | |
12 | - the $@->died with always return the original die causing object or | |
13 | string. In most cases, you want to use $@->wasFatal, which is the | |
14 | translated (hence compatible) ::Exception object. [Andy Beverley] | |
8 | 15 | |
9 | 16 | version 1.32: Tue 26 Jan 09:13:31 CET 2021 |
10 | 17 |
0 | 0 | ChangeLog |
1 | 1 | MANIFEST |
2 | 2 | Makefile.PL |
3 | README | |
4 | 3 | README.md |
5 | 4 | examples/dancer/dancer1.pl |
6 | 5 | lib/Dancer/Logger/LogReport.pm |
7 | lib/Dancer/Logger/LogReport.pod | |
8 | 6 | lib/Dancer2/Logger/LogReport.pm |
9 | lib/Dancer2/Logger/LogReport.pod | |
10 | 7 | lib/Dancer2/Plugin/LogReport.pm |
11 | lib/Dancer2/Plugin/LogReport.pod | |
12 | 8 | lib/Dancer2/Plugin/LogReport/Message.pm |
13 | lib/Dancer2/Plugin/LogReport/Message.pod | |
14 | 9 | lib/Log/Report.pm |
15 | lib/Log/Report.pod | |
16 | 10 | lib/Log/Report/DBIC/Profiler.pm |
17 | lib/Log/Report/DBIC/Profiler.pod | |
18 | 11 | lib/Log/Report/Die.pm |
19 | lib/Log/Report/Die.pod | |
20 | 12 | lib/Log/Report/Dispatcher.pm |
21 | lib/Log/Report/Dispatcher.pod | |
22 | 13 | lib/Log/Report/Dispatcher/Callback.pm |
23 | lib/Log/Report/Dispatcher/Callback.pod | |
24 | 14 | lib/Log/Report/Dispatcher/File.pm |
25 | lib/Log/Report/Dispatcher/File.pod | |
26 | 15 | lib/Log/Report/Dispatcher/Log4perl.pm |
27 | lib/Log/Report/Dispatcher/Log4perl.pod | |
28 | 16 | lib/Log/Report/Dispatcher/LogDispatch.pm |
29 | lib/Log/Report/Dispatcher/LogDispatch.pod | |
30 | 17 | lib/Log/Report/Dispatcher/Perl.pm |
31 | lib/Log/Report/Dispatcher/Perl.pod | |
32 | 18 | lib/Log/Report/Dispatcher/Syslog.pm |
33 | lib/Log/Report/Dispatcher/Syslog.pod | |
34 | 19 | lib/Log/Report/Dispatcher/Try.pm |
35 | lib/Log/Report/Dispatcher/Try.pod | |
36 | 20 | lib/Log/Report/Domain.pm |
37 | lib/Log/Report/Domain.pod | |
38 | 21 | lib/Log/Report/Exception.pm |
39 | lib/Log/Report/Exception.pod | |
40 | 22 | lib/Log/Report/Message.pm |
41 | lib/Log/Report/Message.pod | |
42 | 23 | lib/Log/Report/Translator.pm |
43 | lib/Log/Report/Translator.pod | |
44 | 24 | lib/Log/Report/messages/first-domain.utf-8.po |
45 | 25 | lib/Log/Report/messages/log-report.utf-8.po |
46 | 26 | lib/Log/Report/messages/log-report/nl_NL.po |
47 | 27 | lib/MojoX/Log/Report.pm |
48 | lib/MojoX/Log/Report.pod | |
49 | 28 | t/00use.t |
50 | 29 | t/09message.t |
51 | 30 | t/10interp.t |
3 | 3 | "Mark Overmeer <markov@cpan.org>" |
4 | 4 | ], |
5 | 5 | "dynamic_config" : 1, |
6 | "generated_by" : "ExtUtils::MakeMaker version 7.3, CPAN::Meta::Converter version 2.150010", | |
6 | "generated_by" : "ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010", | |
7 | 7 | "license" : [ |
8 | 8 | "perl_5" |
9 | 9 | ], |
53 | 53 | "web" : "https://github.com/markov2/perl5-Log-Report" |
54 | 54 | } |
55 | 55 | }, |
56 | "version" : "1.32", | |
57 | "x_serialization_backend" : "JSON::PP version 2.94" | |
56 | "version" : "1.33", | |
57 | "x_serialization_backend" : "JSON::PP version 4.04" | |
58 | 58 | } |
6 | 6 | configure_requires: |
7 | 7 | ExtUtils::MakeMaker: '0' |
8 | 8 | dynamic_config: 1 |
9 | generated_by: 'ExtUtils::MakeMaker version 7.3, CPAN::Meta::Converter version 2.150010' | |
9 | generated_by: 'ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010' | |
10 | 10 | license: perl |
11 | 11 | meta-spec: |
12 | 12 | url: http://module-build.sourceforge.net/META-spec-v1.4.html |
28 | 28 | homepage: http://perl.overmeer.net/CPAN/ |
29 | 29 | license: http://dev.perl.org/licenses/ |
30 | 30 | repository: https://github.com/markov2/perl5-Log-Report.git |
31 | version: '1.32' | |
32 | x_serialization_backend: 'CPAN::Meta::YAML version 0.011' | |
31 | version: '1.33' | |
32 | x_serialization_backend: 'CPAN::Meta::YAML version 0.018' |
1 | 1 | |
2 | 2 | use 5.010; |
3 | 3 | |
4 | my $version = '1.32'; | |
4 | my $version = '1.33'; | |
5 | 5 | |
6 | 6 | my %prereq = |
7 | 7 | ( Test::More => '0.86' |
0 | === README for Log-Report version 1.30 | |
1 | = Generated on Fri Jan 15 12:45:38 2021 by OODoc 2.02 | |
2 | ||
3 | There are various ways to install this module: | |
4 | ||
5 | (1) if you have a command-line, you can do: | |
6 | perl -MCPAN -e 'install <any package from this distribution>' | |
7 | ||
8 | (2) if you use Windows, have a look at http://ppm.activestate.com/ | |
9 | ||
10 | (3) if you have downloaded this module manually (as root/administrator) | |
11 | gzip -d Log-Report-1.30.tar.gz | |
12 | tar -xf Log-Report-1.30.tar | |
13 | cd Log-Report-1.30 | |
14 | perl Makefile.PL | |
15 | make # optional | |
16 | make test # optional | |
17 | make install | |
18 | ||
19 | For usage, see the included manual-pages or | |
20 | http://search.cpan.org/dist/Log-Report-1.30/ | |
21 | ||
22 | Please report problems to | |
23 | http://rt.cpan.org/Dist/Display.html?Queue=Log-Report | |
24 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Dancer::Logger::LogReport; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Dancer::Logger::Abstract', 'Exporter'; |
13 | 6 | |
14 | 7 | use strict; |
33 | 26 | , debug => 'TRACE' |
34 | 27 | ); |
35 | 28 | |
29 | =chapter NAME | |
30 | ||
31 | Dancer::Logger::LogReport - reroute Dancer logs into Log::Report | |
32 | ||
33 | =chapter SYNOPSIS | |
34 | ||
35 | # When your main program is not a Dancer object | |
36 | use My::Dancer::App; | |
37 | use Log::Report; | |
38 | ... start dispatcher ... | |
39 | error "something is wrong"; # Log::Report::error() | |
40 | ||
41 | # When your main program is a Dancer object | |
42 | use Dancer; | |
43 | use Dancer::Logger::LogReport; | |
44 | use Log::Report import => 'dispatcher'; | |
45 | ... start dispatcher ... | |
46 | error "something is wrong"; # Dancer::error() | |
47 | ||
48 | # In any case, your main program needs to start log dispatcers | |
49 | # Both Dancer and other Log::Report based modules will send | |
50 | # their messages here: | |
51 | dispatcher FILE => 'default', ...; | |
52 | ||
53 | # In your config | |
54 | logger: log_report | |
55 | logger_format: %i%m # keep it simple | |
56 | log: debug # filtered by dispatchers | |
57 | ||
58 | =chapter DESCRIPTION | |
59 | ||
60 | The M<Log::Report> exception/translation framework defines a large | |
61 | number of logging back-ends. The same log messages can be sent to | |
62 | multiple destinations at the same time via flexible dispatchers. | |
63 | When you use this logger in your Dancer application, it will nicely | |
64 | integrate with non-Dancer modules which need logging. | |
65 | ||
66 | Many log back-ends, like syslog, have more levels of system messages. | |
67 | Modules who explicitly load this module can use the missing C<assert>, | |
68 | C<notice>, C<panic>, and C<alert> log levels. The C<trace> name is | |
69 | provided as well: when you are debugging, you add a 'trace' to your | |
70 | program... its just a better name than 'debug'. | |
71 | ||
72 | You probably want to set a very simple C<logger_format>, because the | |
73 | dispatchers do already add some of the fields that the default | |
74 | C<simple> format adds. For instance, to get the filename/line-number | |
75 | in messages depends on the dispatcher 'mode' (f.i. 'DEBUG'). | |
76 | ||
77 | You also want to set the log level to C<debug>, because level filtering | |
78 | is controlled per dispatcher (as well) | |
79 | ||
80 | =cut | |
36 | 81 | |
37 | 82 | # Add some extra 'levels' |
38 | 83 | sub trace { goto &Dancer::Logger::debug } |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Dancer::Logger::LogReport - reroute Dancer logs into Log::Report | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Dancer::Logger::LogReport | |
9 | is a Dancer::Logger::Abstract | |
10 | ||
11 | Dancer::Logger::LogReport | |
12 | is a Exporter | |
13 | ||
14 | =head1 SYNOPSIS | |
15 | ||
16 | # When your main program is not a Dancer object | |
17 | use My::Dancer::App; | |
18 | use Log::Report; | |
19 | ... start dispatcher ... | |
20 | error "something is wrong"; # Log::Report::error() | |
21 | ||
22 | # When your main program is a Dancer object | |
23 | use Dancer; | |
24 | use Dancer::Logger::LogReport; | |
25 | use Log::Report import => 'dispatcher'; | |
26 | ... start dispatcher ... | |
27 | error "something is wrong"; # Dancer::error() | |
28 | ||
29 | # In any case, your main program needs to start log dispatcers | |
30 | # Both Dancer and other Log::Report based modules will send | |
31 | # their messages here: | |
32 | dispatcher FILE => 'default', ...; | |
33 | ||
34 | # In your config | |
35 | logger: log_report | |
36 | logger_format: %i%m # keep it simple | |
37 | log: debug # filtered by dispatchers | |
38 | ||
39 | =head1 DESCRIPTION | |
40 | ||
41 | The L<Log::Report|Log::Report> exception/translation framework defines a large | |
42 | number of logging back-ends. The same log messages can be sent to | |
43 | multiple destinations at the same time via flexible dispatchers. | |
44 | When you use this logger in your Dancer application, it will nicely | |
45 | integrate with non-Dancer modules which need logging. | |
46 | ||
47 | Many log back-ends, like syslog, have more levels of system messages. | |
48 | Modules who explicitly load this module can use the missing C<assert>, | |
49 | C<notice>, C<panic>, and C<alert> log levels. The C<trace> name is | |
50 | provided as well: when you are debugging, you add a 'trace' to your | |
51 | program... its just a better name than 'debug'. | |
52 | ||
53 | You probably want to set a very simple C<logger_format>, because the | |
54 | dispatchers do already add some of the fields that the default | |
55 | C<simple> format adds. For instance, to get the filename/line-number | |
56 | in messages depends on the dispatcher 'mode' (f.i. 'DEBUG'). | |
57 | ||
58 | You also want to set the log level to C<debug>, because level filtering | |
59 | is controlled per dispatcher (as well) | |
60 | ||
61 | =head1 SEE ALSO | |
62 | ||
63 | This module is part of Log-Report distribution version 1.32, | |
64 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
65 | ||
66 | =head1 LICENSE | |
67 | ||
68 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
69 | ||
70 | This program is free software; you can redistribute it and/or modify it | |
71 | under the same terms as Perl itself. | |
72 | See F<http://dev.perl.org/licenses/> | |
73 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Dancer2::Logger::LogReport; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | # ABSTRACT: Dancer2 logger engine for Log::Report |
13 | 6 | |
14 | 7 | use strict; |
37 | 30 | sub BUILD |
38 | 31 | { my $self = shift; |
39 | 32 | my $configs = $self->dispatchers || {default => undef}; |
40 | $self->{use} = [keys %$configs]; | |
33 | $self->{use} = [ keys %$configs ]; | |
41 | 34 | |
42 | 35 | dispatcher 'do-not-reopen'; |
43 | 36 | |
65 | 58 | $self->log(error => @_); |
66 | 59 | }; |
67 | 60 | |
61 | =chapter NAME | |
62 | ||
63 | Dancer2::Logger::LogReport - reroute Dancer2 logs into Log::Report | |
64 | ||
65 | =chapter SYNOPSIS | |
66 | ||
67 | # This module is loaded when configured. It does not provide | |
68 | # end-user functions or methods. | |
69 | ||
70 | # See L<Dancer2::Plugin::LogReport/"DETAILS"> | |
71 | ||
72 | =chapter DESCRIPTION | |
73 | ||
74 | [The Dancer2 plugin was contributed by Andrew Beverley] | |
75 | ||
76 | This logger allows the use of the many logging backends available | |
77 | in M<Log::Report>. It will process all of the Dancer2 log messages, | |
78 | and also allow any other module to use the same logging facilities. The | |
79 | same log messages can be sent to multiple destinations at the same time | |
80 | via flexible dispatchers. | |
81 | ||
82 | If using this logger, you may also want to use | |
83 | M<Dancer2::Plugin::LogReport> | |
84 | ||
85 | Many log back-ends, like syslog, have more levels of system messages. | |
86 | Modules who explicitly load this module can use the missing C<assert>, | |
87 | C<notice>, C<panic>, and C<alert> log levels. The C<trace> name is | |
88 | provided as well: when you are debugging, you add a 'trace' to your | |
89 | program... it's just a better name than 'debug'. You will need to load | |
90 | Log::Report in order to use the additional levels; if doing so directly within | |
91 | a Dancer2 application (not a sub-module), then you will either need to load | |
92 | Log::Report with C<syntax, 'LONG'> or use M<Dancer2::Plugin::LogReport> to | |
93 | prevent namespace clashes. | |
94 | ||
95 | =head2 Log Format | |
96 | ||
97 | If using this module on its own (such as a drop-in replacement for | |
98 | M<Dancer2::Logger::Syslog>), then the logging format is configured as with any | |
99 | other Dancer logger. If using this module with M<Dancer2::Plugin::LogReport>, | |
100 | then log_format is ignored and messages are not formatted, in order to keep the | |
101 | message format consistent regardless of where the message was generated (be it | |
102 | another module using Log::Report, the plugin, or Dancer itself). In this case, | |
103 | the log format should be configured using the applicable dispatcher (such as | |
104 | M<Log::Report::Dispatcher::Syslog::new(format)>). | |
105 | ||
106 | If also using with the L<Log::Report> logging functions, then you probably want | |
107 | to set a very simple C<logger_format>, because the dispatchers do already add | |
108 | some of the fields that the default C<simple> format adds. For instance, to | |
109 | get the filename/line-number in messages depends on the dispatcher 'mode' (f.i. | |
110 | 'DEBUG'). | |
111 | ||
112 | You also want to set the Dancer2 log level to C<debug>, because level filtering | |
113 | is controlled per dispatcher (as well). | |
114 | ||
115 | See L<Dancer2::Plugin::LogReport/"DETAILS"> for examples. | |
116 | ||
117 | =chapter METHODS | |
118 | ||
119 | =method log $level, $params | |
120 | ||
121 | =cut | |
68 | 122 | |
69 | 123 | sub log # no protoypes in Dancer2 |
70 | 124 | { my ($self, $level, $msg) = @_; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Dancer2::Logger::LogReport - reroute Dancer2 logs into Log::Report | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Dancer2::Logger::LogReport | |
9 | is a Moo::Object | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | # This module is loaded when configured. It does not provide | |
14 | # end-user functions or methods. | |
15 | ||
16 | # See DETAILS | |
17 | ||
18 | =head1 DESCRIPTION | |
19 | ||
20 | [The Dancer2 plugin was contributed by Andrew Beverley] | |
21 | ||
22 | This logger allows the use of the many logging backends available | |
23 | in L<Log::Report|Log::Report>. It will process all of the Dancer2 log messages, | |
24 | and also allow any other module to use the same logging facilities. The | |
25 | same log messages can be sent to multiple destinations at the same time | |
26 | via flexible dispatchers. | |
27 | ||
28 | If using this logger, you may also want to use | |
29 | L<Dancer2::Plugin::LogReport|Dancer2::Plugin::LogReport> | |
30 | ||
31 | Many log back-ends, like syslog, have more levels of system messages. | |
32 | Modules who explicitly load this module can use the missing C<assert>, | |
33 | C<notice>, C<panic>, and C<alert> log levels. The C<trace> name is | |
34 | provided as well: when you are debugging, you add a 'trace' to your | |
35 | program... it's just a better name than 'debug'. You will need to load | |
36 | Log::Report in order to use the additional levels; if doing so directly within | |
37 | a Dancer2 application (not a sub-module), then you will either need to load | |
38 | Log::Report with C<syntax, 'LONG'> or use L<Dancer2::Plugin::LogReport|Dancer2::Plugin::LogReport> to | |
39 | prevent namespace clashes. | |
40 | ||
41 | =head2 Log Format | |
42 | ||
43 | If using this module on its own (such as a drop-in replacement for | |
44 | Dancer2::Logger::Syslog), then the logging format is configured as with any | |
45 | other Dancer logger. If using this module with L<Dancer2::Plugin::LogReport|Dancer2::Plugin::LogReport>, | |
46 | then log_format is ignored and messages are not formatted, in order to keep the | |
47 | message format consistent regardless of where the message was generated (be it | |
48 | another module using Log::Report, the plugin, or Dancer itself). In this case, | |
49 | the log format should be configured using the applicable dispatcher (such as | |
50 | L<Log::Report::Dispatcher::Syslog::new(format)|Log::Report::Dispatcher::Syslog/"Constructors">). | |
51 | ||
52 | If also using with the L<Log::Report> logging functions, then you probably want | |
53 | to set a very simple C<logger_format>, because the dispatchers do already add | |
54 | some of the fields that the default C<simple> format adds. For instance, to | |
55 | get the filename/line-number in messages depends on the dispatcher 'mode' (f.i. | |
56 | 'DEBUG'). | |
57 | ||
58 | You also want to set the Dancer2 log level to C<debug>, because level filtering | |
59 | is controlled per dispatcher (as well). | |
60 | ||
61 | See L<Dancer2::Plugin::LogReport/"DETAILS"> for examples. | |
62 | ||
63 | =head1 METHODS | |
64 | ||
65 | =over 4 | |
66 | ||
67 | =item $obj-E<gt>B<log>($level, $params) | |
68 | ||
69 | =back | |
70 | ||
71 | =head1 SEE ALSO | |
72 | ||
73 | This module is part of Log-Report distribution version 1.32, | |
74 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
75 | ||
76 | =head1 LICENSE | |
77 | ||
78 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
79 | ||
80 | This program is free software; you can redistribute it and/or modify it | |
81 | under the same terms as Perl itself. | |
82 | See F<http://dev.perl.org/licenses/> | |
83 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Dancer2::Plugin::LogReport::Message; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use parent 'Log::Report::Message'; |
13 | 6 | |
14 | 7 | use strict; |
15 | 8 | use warnings; |
16 | 9 | |
10 | =chapter NAME | |
11 | ||
12 | Dancer2::Plugin::LogReport::Message - extended Log::Report message class | |
13 | ||
14 | =chapter SYNOPSIS | |
15 | ||
16 | In your template: | |
17 | ||
18 | [% FOR message IN messages %] | |
19 | <div class="alert alert-[% message.bootstrap_color %]"> | |
20 | [% message.toString | html_entity %] | |
21 | </div> | |
22 | [% END %] | |
23 | ||
24 | =chapter DESCRIPTION | |
25 | ||
26 | [The Dancer2 plugin was contributed by Andrew Beverley] | |
27 | ||
28 | This class is an extension of L<Log::Report::Message>, with functions | |
29 | specifically designed for Dancer applications. Minimal functions are | |
30 | provided (currently only aimed at Bootstrap), but ideas for new ones are | |
31 | welcome. | |
32 | ||
33 | =chapter METHODS | |
34 | =cut | |
17 | 35 | |
18 | 36 | sub init($) |
19 | 37 | { my ($self, $args) = @_; |
21 | 39 | $self; |
22 | 40 | } |
23 | 41 | |
42 | =method reason | |
43 | ||
44 | Get or set the reason of a message | |
45 | =cut | |
24 | 46 | |
25 | 47 | sub reason |
26 | 48 | { my $self = shift; |
37 | 59 | , MISTAKE => 'warning' |
38 | 60 | ); |
39 | 61 | |
62 | =method bootstrap_color | |
63 | ||
64 | Get a suitable bootstrap context color for the message. This can be | |
65 | used as per the SYNOPSIS. | |
66 | ||
67 | C<success> is used for M<Dancer2::Plugin::LogReport::success()> messages, | |
68 | C<info> colors are used for messages C<notice> and below, C<warning> is used | |
69 | for C<warning> and C<mistake>, C<danger> is used for all other messages | |
70 | =cut | |
40 | 71 | |
41 | 72 | sub bootstrap_color |
42 | 73 | { my $self = shift; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Dancer2::Plugin::LogReport::Message - extended Log::Report message class | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Dancer2::Plugin::LogReport::Message | |
9 | is a Log::Report::Message | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | In your template: | |
14 | ||
15 | [% FOR message IN messages %] | |
16 | <div class="alert alert-[% message.bootstrap_color %]"> | |
17 | [% message.toString | html_entity %] | |
18 | </div> | |
19 | [% END %] | |
20 | ||
21 | =head1 DESCRIPTION | |
22 | ||
23 | [The Dancer2 plugin was contributed by Andrew Beverley] | |
24 | ||
25 | This class is an extension of L<Log::Report::Message>, with functions | |
26 | specifically designed for Dancer applications. Minimal functions are | |
27 | provided (currently only aimed at Bootstrap), but ideas for new ones are | |
28 | welcome. | |
29 | ||
30 | Extends L<"DESCRIPTION" in Log::Report::Message|Log::Report::Message/"DESCRIPTION">. | |
31 | ||
32 | =head1 METHODS | |
33 | ||
34 | Extends L<"METHODS" in Log::Report::Message|Log::Report::Message/"METHODS">. | |
35 | ||
36 | =over 4 | |
37 | ||
38 | =item $obj-E<gt>B<bootstrap_color>() | |
39 | ||
40 | Get a suitable bootstrap context color for the message. This can be | |
41 | used as per the SYNOPSIS. | |
42 | ||
43 | C<success> is used for L<Dancer2::Plugin::LogReport::success()|Dancer2::Plugin::LogReport/"Handlers"> messages, | |
44 | C<info> colors are used for messages C<notice> and below, C<warning> is used | |
45 | for C<warning> and C<mistake>, C<danger> is used for all other messages | |
46 | ||
47 | =item $obj-E<gt>B<reason>() | |
48 | ||
49 | Get or set the reason of a message | |
50 | ||
51 | =back | |
52 | ||
53 | =head1 DETAILS | |
54 | ||
55 | Extends L<"DETAILS" in Log::Report::Message|Log::Report::Message/"DETAILS">. | |
56 | ||
57 | =head1 OVERLOADING | |
58 | ||
59 | Extends L<"OVERLOADING" in Log::Report::Message|Log::Report::Message/"OVERLOADING">. | |
60 | ||
61 | =over 4 | |
62 | ||
63 | =item overload: B<as $function> | |
64 | ||
65 | Inherited, see L<Log::Report::Message/"OVERLOADING"> | |
66 | ||
67 | =item overload: B<concatenation> | |
68 | ||
69 | Inherited, see L<Log::Report::Message/"OVERLOADING"> | |
70 | ||
71 | =item overload: B<stringification> | |
72 | ||
73 | Inherited, see L<Log::Report::Message/"OVERLOADING"> | |
74 | ||
75 | =back | |
76 | ||
77 | =head1 SEE ALSO | |
78 | ||
79 | This module is part of Log-Report distribution version 1.32, | |
80 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
81 | ||
82 | =head1 LICENSE | |
83 | ||
84 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
85 | ||
86 | This program is free software; you can redistribute it and/or modify it | |
87 | under the same terms as Perl itself. | |
88 | See F<http://dev.perl.org/licenses/> | |
89 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Dancer2::Plugin::LogReport; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | |
13 | 6 | use warnings; |
14 | 7 | use strict; |
25 | 18 | my %_all_dsls; # The DSLs for each app within the Dancer application |
26 | 19 | my $_settings; |
27 | 20 | |
21 | =chapter NAME | |
22 | ||
23 | Dancer2::Plugin::LogReport - logging and exceptions via Log::Report | |
24 | ||
25 | =chapter SYNOPSIS | |
26 | ||
27 | # Load the plugin into Dancer2 | |
28 | # see Log::Report::import() for %options | |
29 | use Dancer2::Plugin::LogReport %options; | |
30 | ||
31 | # Stop execution, redirect, and display an error to the user | |
32 | $name or error "Please enter a name"; | |
33 | ||
34 | # Add debug information to logger | |
35 | trace "We're here"; | |
36 | ||
37 | # Handling user errors cleanly | |
38 | if (process( sub {MyApp::Model->create_user} )) { | |
39 | # Success, redirect user elsewhere | |
40 | } else { | |
41 | # Failed, continue as if submit hadn't been made. | |
42 | # Error message will be in session for display later. | |
43 | } | |
44 | ||
45 | # Send errors to template for display | |
46 | hook before_template => sub { | |
47 | my $tokens = shift; | |
48 | $tokens->{messages} = session 'messages'; | |
49 | session 'messages' => []; | |
50 | } | |
51 | ||
52 | =chapter DESCRIPTION | |
53 | ||
54 | [The Dancer2 plugin was contributed by Andrew Beverley] | |
55 | ||
56 | This module provides easy access to the extensive logging facilities | |
57 | provided by M<Log::Report>. Along with M<Dancer2::Logger::LogReport>, | |
58 | this brings together all the internal Dancer2 logging, handling for | |
59 | expected and unexpected exceptions, translations and application logging. | |
60 | ||
61 | Logging is extremely flexible using many of the available | |
62 | L<dispatchers|Log::Report::Dispatcher/DETAILS>. Multiple dispatchers can be | |
63 | used, each configured separately to display different messages in different | |
64 | formats. By default, messages are logged to a session variable for display on | |
65 | a webpage, and to STDERR. | |
66 | ||
67 | Messages within this plugin use the extended | |
68 | L<Dancer2::Logger::LogReport::Message> class rather than the standard | |
69 | L<Log::Report::Message> class. | |
70 | ||
71 | Note that it is currently recommended to use the plugin in all apps within | |
72 | a Dancer2 program, not only some. Therefore, wherever you C<use Dancer2> | |
73 | you should also C<use Dancer2::Plugin::LogReport>. This does not apply if | |
74 | using the same app name (C<use Dancer2 appname, 'Already::Exists'>). In | |
75 | all other modules, you can just C<use Log::Report>. | |
76 | ||
77 | Read the L</DETAILS> in below in this manual-page. | |
78 | ||
79 | =chapter METHODS | |
80 | ||
81 | =cut | |
28 | 82 | |
29 | 83 | # "use" import |
30 | 84 | sub import |
137 | 191 | |
138 | 192 | }; # ";" required! |
139 | 193 | |
194 | =method process | |
195 | ||
196 | C<process()> is an eval, but one which expects and understands exceptions | |
197 | generated by M<Log::Report>. Any messages will be logged as normal in | |
198 | accordance with the dispatchers, but any fatal exceptions will be caught | |
199 | and handled gracefully. This allows much simpler error handling, rather | |
200 | than needing to test for lots of different scenarios. | |
201 | ||
202 | In a module, it is enough to simply use the C<error> keyword in the event | |
203 | of a fatal error. | |
204 | ||
205 | The return value will be 1 for success or 0 if a fatal exception occurred. | |
206 | ||
207 | See the L</DETAILS> for an example of how this is expected to be used. | |
208 | ||
209 | This module is configured only once in your application. The other modules | |
210 | which make your website do not need to require this plugin, instead they | |
211 | can C<use Log::Report> to get useful functions like error and fault. | |
212 | ||
213 | =cut | |
140 | 214 | |
141 | 215 | sub process($$) |
142 | 216 | { my ($dsl, $coderef) = @_; |
149 | 223 | register process => \&process; |
150 | 224 | |
151 | 225 | |
226 | =method fatal_handler | |
227 | ||
228 | C<fatal_handler()> allows alternative handlers to be defined in place of (or in | |
229 | addition to) the default redirect handler that is called on a fatal error. | |
230 | ||
231 | Calls should be made with 1 parameter: the subroutine to call in the case of a | |
232 | fatal error. The subroutine is passed 3 parameters: the DSL, the message in | |
233 | question, and the reason. The subroutine should return true or false depending | |
234 | on whether it handled the error. If it returns false, the next fatal handler is | |
235 | called, and if there are no others then the default redirect fatal handler is | |
236 | called. | |
237 | ||
238 | =example Error handler based on URL (e.g. API) | |
239 | ||
240 | fatal_handler sub { | |
241 | my ($dsl, $msg, $reason) = @_; | |
242 | return if $dsl->app->request->uri !~ m!^/api/!; | |
243 | status $reason eq 'PANIC' ? 'Internal Server Error' : 'Bad Request'; | |
244 | $dsl->send_as(JSON => { | |
245 | error => 1, | |
246 | error_description => $msg->toString, | |
247 | }, { | |
248 | content_type => 'application/json; charset=UTF-8', | |
249 | }); | |
250 | }; | |
251 | ||
252 | =example Return JSON responses for requests with content-type of application/json | |
253 | ||
254 | fatal_handler sub { | |
255 | my ($dsl, $msg, $reason, $default) = @_; | |
256 | ||
257 | (my $ctype = $dsl->request->header('content-type')) =~ s/;.*//; | |
258 | return if $ctype ne 'application/json'; | |
259 | status $reason eq 'PANIC' ? 'Internal Server Error' : 'Bad Request'; | |
260 | $dsl->send_as(JSON => { | |
261 | error => 1, | |
262 | description => $msg->toString, | |
263 | }, { | |
264 | content_type => 'application/json; charset=UTF-8', | |
265 | }); | |
266 | }; | |
267 | ||
268 | ||
269 | =cut | |
152 | 270 | |
153 | 271 | my @user_fatal_handlers; |
154 | 272 | |
232 | 350 | } |
233 | 351 | |
234 | 352 | #------ |
353 | =section Handlers | |
354 | ||
355 | All the standard M<Log::Report> functions are available to use. Please see the | |
356 | L<Log::Report/"The Reason for the report"> for details | |
357 | of when each one should be used. | |
358 | ||
359 | L<Log::Report class functionality|Log::Report::Message.pod#class-STRING-ARRAY> | |
360 | to class messages (which can then be tested later): | |
361 | ||
362 | notice __x"Class me up", _class => 'label'; | |
363 | ... | |
364 | if ($msg->inClass('label')) ... | |
365 | ||
366 | M<Dancer2::Plugin::LogReport> has a special message class, C<no_session>, | |
367 | which prevents the message from being saved to the messages session | |
368 | variable. This is useful, for example, if you are writing messages within | |
369 | the session hooks, in which case recursive loops can be experienced. | |
370 | ||
371 | =method trace | |
372 | =method assert | |
373 | =method info | |
374 | =method notice | |
375 | =method warning | |
376 | =method mistake | |
377 | =method error | |
378 | =method fault | |
379 | =method alert | |
380 | =method failure | |
381 | =method panic | |
382 | =cut | |
235 | 383 | |
236 | 384 | sub _forward_home($) |
237 | 385 | { my ($dsl, $msg) = _message_add(shift); |
326 | 474 | register fault => sub { _report(FAULT => @_) }; |
327 | 475 | register failure => sub { _report(FAILURE => @_) }; |
328 | 476 | |
477 | =method success | |
478 | This is a special additional type, equivalent to C<notice>. The difference is | |
479 | that messages using this keyword will have the class C<success> added, which | |
480 | can be used to color the messages differently to the end user. For example, | |
481 | L<Dancer2::Plugin::LogReport::Message#bootstrap_color> uses this to display the | |
482 | message in green. | |
483 | =cut | |
329 | 484 | register success => sub { _report(SUCCESS => @_) }; |
330 | 485 | |
331 | 486 | register_plugin for_versions => ['2']; |
332 | 487 | |
333 | 488 | #---------- |
334 | 489 | |
490 | =chapter CONFIGURATION | |
491 | ||
492 | All configuration is optional. The example configuration file below shows the | |
493 | configuration options and defaults. | |
494 | ||
495 | plugins: | |
496 | LogReport: | |
497 | # Whether to handle Dancer HTTP errors such as 404s. Currently has | |
498 | # no effect due to unresolved issues saving messages to the session | |
499 | # and accessing the DSL at that time. | |
500 | handle_http_errors: 1 | |
501 | # Where to forward users in the event of an uncaught fatal | |
502 | # error within a GET request | |
503 | forward_url: / | |
504 | # Or you can specify a template instead [1.13] | |
505 | forward_template: error_template_file # Defaults to empty | |
506 | # For a production server (show_errors: 0), this is the text that | |
507 | # will be displayed instead of unexpected exception errors | |
508 | fatal_error_message: An unexpected error has occurred | |
509 | # The levels of messages that will be saved to the session, and | |
510 | # thus displayed to the end user | |
511 | session_messages: [ NOTICE, WARNING, MISTAKE, ERROR, FAULT, ALERT, FAILURE, PANIC ] | |
512 | ||
513 | ||
514 | =chapter DETAILS | |
515 | ||
516 | This chapter will guide you through the myriad of ways that you can use | |
517 | M<Log::Report> in your Dancer2 application. | |
518 | ||
519 | We will set up our application to do the following: | |
520 | ||
521 | =over 4 | |
522 | ||
523 | =item Messages to the user | |
524 | We'll look at an easy way to output messages to the user's web page, whether | |
525 | they be informational messages, warnings or errors. | |
526 | ||
527 | =item Debug information | |
528 | We'll look at an easy way to log debug information, at different levels. | |
529 | ||
530 | =item Manage unexpected exceptions | |
531 | We'll handle unexpected exceptions cleanly, in the unfortunate event that | |
532 | they happen in your production application. | |
533 | ||
534 | =item Email alerts of significant errors | |
535 | If we do get unexpected errors then we want to be notified them. | |
536 | ||
537 | =item Log DBIC information and errors | |
538 | We'll specifically look at nice ways to log SQL queries and errors when | |
539 | using DBIx::Class. | |
540 | ||
541 | =back | |
542 | ||
543 | =section Larger example | |
544 | ||
545 | In its simplest form, this module can be used for more flexible logging | |
546 | ||
547 | get '/route' => sub { | |
548 | # Stop execution, redirect, and display an error to the user | |
549 | $name or error "Please enter a name"; | |
550 | ||
551 | # The same but translated | |
552 | $name or error __"Please enter a name"; | |
553 | ||
554 | # The same but translated and with variables | |
555 | $name or error __x"{name} is not valid", name => $name; | |
556 | ||
557 | # Show the user a warning, but continue execution | |
558 | mistake "Not sure that's what you wanted"; | |
559 | ||
560 | # Add debug information, can be caught in syslog by adding | |
561 | # the (for instance) syslog dispatcher | |
562 | trace "Hello world"; | |
563 | }; | |
564 | ||
565 | =section Setup and Configuration | |
566 | ||
567 | To make full use of L<Log::Report>, you'll need to use both | |
568 | L<Dancer2::Logger::LogReport> and L<Dancer2::Plugin::LogReport>. | |
569 | ||
570 | =subsection Dancer2::Logger::LogReport | |
571 | ||
572 | Set up L<Dancer2::Logger::LogReport> by adding it to your Dancer2 | |
573 | application configuration (see L<Dancer2::Config>). By default, | |
574 | all messages will go to STDERR. | |
575 | ||
576 | To get all message out "the Perl way" (using print, warn and die) just use | |
577 | ||
578 | logger: "LogReport" | |
579 | ||
580 | At start, these are handled by a M<Log::Report::Dispatcher::Perl> object, | |
581 | named 'default'. If you open a new dispatcher with the name 'default', | |
582 | the output via the perl mechanisms will be stopped. | |
583 | ||
584 | To also send messages to your syslog: | |
585 | ||
586 | logger: "LogReport" | |
587 | ||
588 | engines: | |
589 | logger: | |
590 | LogReport: | |
591 | log_format: %a%i%m # See Dancer2::Logger::LogReport | |
592 | app_name: MyApp | |
593 | dispatchers: | |
594 | default: # Name | |
595 | type: SYSLOG # Log::Reporter::dispatcher() options | |
596 | identity: myapp | |
597 | facility: local0 | |
598 | flags: "pid ndelay nowait" | |
599 | mode: DEBUG | |
600 | ||
601 | To send messages to a file: | |
602 | ||
603 | logger: "LogReport" | |
604 | ||
605 | engines: | |
606 | logger: | |
607 | LogReport: | |
608 | log_format: %a%i%m # See Dancer2::Logger::LogReport | |
609 | app_name: MyApp | |
610 | dispatchers: | |
611 | logfile: # "default" dispatcher stays open as well | |
612 | type: FILE | |
613 | to: /var/log/myapp.log | |
614 | charset: utf-8 | |
615 | mode: DEBUG | |
616 | ||
617 | See L<Log::Report::Dispatcher> for full details of options. | |
618 | ||
619 | Finally: a Dancer2 script may run many applications. Each application | |
620 | can have its own logger configuration. However, Log::Report dispatchers | |
621 | are global, so will be shared between Dancer2 applications. Any attempt | |
622 | to create a new Log::Report dispatcher by the same name (as will happen | |
623 | when a new Dancer2 application is started with the same configuration) | |
624 | will be ignored. | |
625 | ||
626 | =subsection Dancer2::Plugin::LogReport | |
627 | ||
628 | To use the plugin, you simply use it in your application: | |
629 | ||
630 | package MyApp; | |
631 | use Log::Report (); # use early and minimal once | |
632 | use Dancer2; | |
633 | use Dancer2::Plugin::LogReport %config; | |
634 | ||
635 | Dancer2::Plugin::LogReport takes the same C<%config> options as | |
636 | L<Log::Report> itself (see M<Log::Report::import()>). | |
637 | ||
638 | If you want to send messages from your modules/models, there is | |
639 | no need to use this specific plugin. Instead, you should simply | |
640 | C<use Log::Report> to negate the need of loading all the Dancer2 | |
641 | specific code. | |
642 | ||
643 | =section In use | |
644 | ||
645 | =subsection Logging debug information | |
646 | ||
647 | In its simplest form, you can now use all the | |
648 | L<Log::Report logging functions|Log::Report#The-Reason-for-the-report> | |
649 | to send messages to your dispatchers (as configured in the Logger | |
650 | configuration): | |
651 | ||
652 | trace "I'm here"; | |
653 | ||
654 | warning "Something dodgy happened"; | |
655 | ||
656 | panic "I'm bailing out"; | |
657 | ||
658 | # Additional, special Dancer2 keyword | |
659 | success "Settings saved successfully"; | |
660 | ||
661 | =subsection Exceptions | |
662 | ||
663 | Log::Report is a combination of a logger and an exception system. Messages | |
664 | to be logged are I<thrown> to all listening dispatchers to be handled. | |
665 | ||
666 | This module will also catch any unexpected exceptions: | |
667 | ||
668 | # This will be caught, the error will be logged (full stacktrace to STDOUT, | |
669 | # short message to the session messages), and the user will be forwarded | |
670 | # (default to /). This would also be sent to syslog with the appropriate | |
671 | # dispatcher. | |
672 | get 'route' => sub { | |
673 | my $foo = 1; | |
674 | my $bar = $foo->{x}; # whoops | |
675 | } | |
676 | ||
677 | For a production application (C<show_errors: 1>), the message saved in the | |
678 | session will be the generic text "An unexpected error has occurred". This | |
679 | can be customised in the configuration file, and will be translated. | |
680 | ||
681 | =subsection Sending messages to the user | |
682 | ||
683 | To make it easier to send messages to your users, messages at the following | |
684 | levels are also stored in the user's session: C<notice>, C<warning>, C<mistake>, | |
685 | C<error>, C<fault>, C<alert>, C<failure> and C<panic>. | |
686 | ||
687 | You can pass these to your template and display them at each page render: | |
688 | ||
689 | hook before_template => sub { | |
690 | my $tokens = shift; | |
691 | $tokens->{messages} = session 'messages'; | |
692 | session 'messages' => []; # Clear the message queue | |
693 | } | |
694 | ||
695 | Then in your template (for example the main layout): | |
696 | ||
697 | [% FOR message IN messages %] | |
698 | <div class="alert alert-[% message.bootstrap_color %]"> | |
699 | [% message.toString | html_entity %] | |
700 | </div> | |
701 | [% END %] | |
702 | ||
703 | The C<bootstrap_color> of the message is compatible with Bootstrap contextual | |
704 | colors: C<success>, C<info>, C<warning> or C<danger>. | |
705 | ||
706 | Now, anywhere in your application that you have used Log::Report, you can | |
707 | ||
708 | warning "Hey user, you should now about this"; | |
709 | ||
710 | and the message will be sent to the next page the user sees. | |
711 | ||
712 | =subsection Handling user errors | |
713 | ||
714 | Sometimes we write a function in a model, and it would be nice to have a | |
715 | nice easy way to return from the function with an error message. One | |
716 | way of doing this is with a separate error message variable, but that | |
717 | can be messy code. An alternative is to use exceptions, but these | |
718 | can be a pain to deal with in terms of catching them. | |
719 | Here's how to do it with Log::Report. | |
720 | ||
721 | In this example, we do use exceptions, but in a neat, easier to use manner. | |
722 | ||
723 | First, your module/model: | |
724 | ||
725 | package MyApp::CD; | |
726 | ||
727 | sub update { | |
728 | my ($self, %values) = @_; | |
729 | $values{title} or error "Please enter a title"; | |
730 | $values{description} or warning "No description entered"; | |
731 | } | |
732 | ||
733 | Then, in your controller: | |
734 | ||
735 | package MyApp; | |
736 | use Dancer2; | |
737 | ||
738 | post '/cd' => sub { | |
739 | my %values = ( | |
740 | title => param('title'); | |
741 | description => param('description'); | |
742 | ); | |
743 | if (process sub { MyApp::CD->update(%values) } ) { | |
744 | success "CD updated successfully"; | |
745 | redirect '/cd'; | |
746 | } | |
747 | ||
748 | template 'cd' => { values => \%values }; | |
749 | } | |
750 | ||
751 | Now, when update() is called, any exceptions are caught. However, there is | |
752 | no need to worry about any error messages. Both the error and warning | |
753 | messages in the above code will have been stored in the messages session | |
754 | variable, where they can be displayed using the code in the previous section. | |
755 | The C<error> will have caused the code to stop running, and process() | |
756 | will have returned false. C<warning> will have simply logged the warning | |
757 | and not caused the function to stop running. | |
758 | ||
759 | =subsection Logging DBIC database queries and errors | |
760 | ||
761 | If you use L<DBIx::Class> in your application, you can easily integrate | |
762 | its logging and exceptions. To log SQL queries: | |
763 | ||
764 | # Log all queries and execution time | |
765 | $schema->storage->debugobj(new Log::Report::DBIC::Profiler); | |
766 | $schema->storage->debug(1); | |
767 | ||
768 | By default, exceptions from DBIC are classified at the level "error". This | |
769 | is normally a user level error, and thus may be filtered as normal program | |
770 | operation. If you do not expect to receive any DBIC exceptions, then it | |
771 | is better to class them at the level "panic": | |
772 | ||
773 | # panic() DBIC errors | |
774 | $schema->exception_action(sub { panic @_ }); | |
775 | # Optionally get a stracktrace too | |
776 | $schema->stacktrace(1); | |
777 | ||
778 | If you are occasionally running queries where you expect to naturally | |
779 | get exceptions (such as not inserting multiple values on a unique constraint), | |
780 | then you can catch these separately: | |
781 | ||
782 | try { $self->schema->resultset('Unique')->create() }; | |
783 | # Log any messages from try block, but only as trace | |
784 | $@->reportAll(reason => 'TRACE'); | |
785 | ||
786 | =subsection Email alerts of exceptions | |
787 | ||
788 | If you have an unexpected exception in your production application, | |
789 | then you probably want to be notified about it. One way to do so is | |
790 | configure rsyslog to send emails of messages at the panic level. Use | |
791 | the following configuration to do so: | |
792 | ||
793 | # Normal logging from LOCAL0 | |
794 | local0.* -/var/log/myapp.log | |
795 | ||
796 | # Load the mail module | |
797 | $ModLoad ommail | |
798 | # Configure sender, receiver and mail server | |
799 | $ActionMailSMTPServer localhost | |
800 | $ActionMailFrom root | |
801 | $ActionMailTo root | |
802 | # Set up an email template | |
803 | $template mailSubject,"Critical error on %hostname%" | |
804 | $template mailBody,"RSYSLOG Alert\r\nmsg='%msg%'\r\nseverity='%syslogseverity-text%'" | |
805 | $ActionMailSubject mailSubject | |
806 | # Send an email no more frequently than every minute | |
807 | $ActionExecOnlyOnceEveryInterval 60 | |
808 | # Configure the level of message to notify via email | |
809 | if $syslogfacility-text == 'local0' and $syslogseverity < 3 then :ommail:;mailBody | |
810 | $ActionExecOnlyOnceEveryInterval 0 | |
811 | ||
812 | With the above configuration, you will only be emailed of severe errors, but can | |
813 | view the full log information in /var/log/myapp.log | |
814 | ||
815 | ||
816 | =cut | |
335 | 817 | |
336 | 818 | 1; |
337 | 819 |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Dancer2::Plugin::LogReport - logging and exceptions via Log::Report | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Dancer2::Plugin::LogReport | |
9 | is a Dancer2::Plugin | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
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 | ||
38 | =head1 DESCRIPTION | |
39 | ||
40 | [The Dancer2 plugin was contributed by Andrew Beverley] | |
41 | ||
42 | This module provides easy access to the extensive logging facilities | |
43 | provided by L<Log::Report|Log::Report>. Along with L<Dancer2::Logger::LogReport|Dancer2::Logger::LogReport>, | |
44 | this brings together all the internal Dancer2 logging, handling for | |
45 | expected and unexpected exceptions, translations and application logging. | |
46 | ||
47 | Logging is extremely flexible using many of the available | |
48 | L<dispatchers|Log::Report::Dispatcher/DETAILS>. Multiple dispatchers can be | |
49 | used, each configured separately to display different messages in different | |
50 | formats. By default, messages are logged to a session variable for display on | |
51 | a webpage, and to STDERR. | |
52 | ||
53 | Messages within this plugin use the extended | |
54 | L<Dancer2::Logger::LogReport::Message> class rather than the standard | |
55 | L<Log::Report::Message> class. | |
56 | ||
57 | Note that it is currently recommended to use the plugin in all apps within | |
58 | a Dancer2 program, not only some. Therefore, wherever you C<use Dancer2> | |
59 | you should also C<use Dancer2::Plugin::LogReport>. This does not apply if | |
60 | using the same app name (C<use Dancer2 appname, 'Already::Exists'>). In | |
61 | all other modules, you can just C<use Log::Report>. | |
62 | ||
63 | Read the L</DETAILS> in below in this manual-page. | |
64 | ||
65 | =head1 METHODS | |
66 | ||
67 | =over 4 | |
68 | ||
69 | =item $obj-E<gt>B<fatal_handler>() | |
70 | ||
71 | C<fatal_handler()> allows alternative handlers to be defined in place of (or in | |
72 | addition to) the default redirect handler that is called on a fatal error. | |
73 | ||
74 | Calls should be made with 1 parameter: the subroutine to call in the case of a | |
75 | fatal error. The subroutine is passed 3 parameters: the DSL, the message in | |
76 | question, and the reason. The subroutine should return true or false depending | |
77 | on whether it handled the error. If it returns false, the next fatal handler is | |
78 | called, and if there are no others then the default redirect fatal handler is | |
79 | called. | |
80 | ||
81 | example: Error handler based on URL (e.g. API) | |
82 | ||
83 | fatal_handler sub { | |
84 | my ($dsl, $msg, $reason) = @_; | |
85 | return if $dsl->app->request->uri !~ m!^/api/!; | |
86 | status $reason eq 'PANIC' ? 'Internal Server Error' : 'Bad Request'; | |
87 | $dsl->send_as(JSON => { | |
88 | error => 1, | |
89 | error_description => $msg->toString, | |
90 | }, { | |
91 | content_type => 'application/json; charset=UTF-8', | |
92 | }); | |
93 | }; | |
94 | ||
95 | example: Return JSON responses for requests with content-type of application/json | |
96 | ||
97 | fatal_handler sub { | |
98 | my ($dsl, $msg, $reason, $default) = @_; | |
99 | ||
100 | (my $ctype = $dsl->request->header('content-type')) =~ s/;.*//; | |
101 | return if $ctype ne 'application/json'; | |
102 | status $reason eq 'PANIC' ? 'Internal Server Error' : 'Bad Request'; | |
103 | $dsl->send_as(JSON => { | |
104 | error => 1, | |
105 | description => $msg->toString, | |
106 | }, { | |
107 | content_type => 'application/json; charset=UTF-8', | |
108 | }); | |
109 | }; | |
110 | ||
111 | =item $obj-E<gt>B<process>() | |
112 | ||
113 | C<process()> is an eval, but one which expects and understands exceptions | |
114 | generated by L<Log::Report|Log::Report>. Any messages will be logged as normal in | |
115 | accordance with the dispatchers, but any fatal exceptions will be caught | |
116 | and handled gracefully. This allows much simpler error handling, rather | |
117 | than needing to test for lots of different scenarios. | |
118 | ||
119 | In a module, it is enough to simply use the C<error> keyword in the event | |
120 | of a fatal error. | |
121 | ||
122 | The return value will be 1 for success or 0 if a fatal exception occurred. | |
123 | ||
124 | See the L</DETAILS> for an example of how this is expected to be used. | |
125 | ||
126 | This module is configured only once in your application. The other modules | |
127 | which make your website do not need to require this plugin, instead they | |
128 | can C<use Log::Report> to get useful functions like error and fault. | |
129 | ||
130 | =back | |
131 | ||
132 | =head2 Handlers | |
133 | ||
134 | All the standard L<Log::Report|Log::Report> functions are available to use. Please see the | |
135 | L<Log::Report/"The Reason for the report"> for details | |
136 | of when each one should be used. | |
137 | ||
138 | L<Log::Report class functionality|Log::Report::Message.pod#class-STRING-ARRAY> | |
139 | to class messages (which can then be tested later): | |
140 | ||
141 | notice __x"Class me up", _class => 'label'; | |
142 | ... | |
143 | if ($msg->inClass('label')) ... | |
144 | ||
145 | L<Dancer2::Plugin::LogReport|Dancer2::Plugin::LogReport> has a special message class, C<no_session>, | |
146 | which prevents the message from being saved to the messages session | |
147 | variable. This is useful, for example, if you are writing messages within | |
148 | the session hooks, in which case recursive loops can be experienced. | |
149 | ||
150 | =over 4 | |
151 | ||
152 | =item $obj-E<gt>B<alert>() | |
153 | ||
154 | =item $obj-E<gt>B<assert>() | |
155 | ||
156 | =item $obj-E<gt>B<error>() | |
157 | ||
158 | =item $obj-E<gt>B<failure>() | |
159 | ||
160 | =item $obj-E<gt>B<fault>() | |
161 | ||
162 | =item $obj-E<gt>B<info>() | |
163 | ||
164 | =item $obj-E<gt>B<mistake>() | |
165 | ||
166 | =item $obj-E<gt>B<notice>() | |
167 | ||
168 | =item $obj-E<gt>B<panic>() | |
169 | ||
170 | =item $obj-E<gt>B<success>() | |
171 | ||
172 | This is a special additional type, equivalent to C<notice>. The difference is | |
173 | that messages using this keyword will have the class C<success> added, which | |
174 | can be used to color the messages differently to the end user. For example, | |
175 | L<Dancer2::Plugin::LogReport::Message#bootstrap_color> uses this to display the | |
176 | message in green. | |
177 | ||
178 | =item $obj-E<gt>B<trace>() | |
179 | ||
180 | =item $obj-E<gt>B<warning>() | |
181 | ||
182 | =back | |
183 | ||
184 | =head1 DETAILS | |
185 | ||
186 | This chapter will guide you through the myriad of ways that you can use | |
187 | L<Log::Report|Log::Report> in your Dancer2 application. | |
188 | ||
189 | We will set up our application to do the following: | |
190 | ||
191 | =over 4 | |
192 | ||
193 | =item Messages to the user | |
194 | ||
195 | We'll look at an easy way to output messages to the user's web page, whether | |
196 | they be informational messages, warnings or errors. | |
197 | ||
198 | =item Debug information | |
199 | ||
200 | We'll look at an easy way to log debug information, at different levels. | |
201 | ||
202 | =item Manage unexpected exceptions | |
203 | ||
204 | We'll handle unexpected exceptions cleanly, in the unfortunate event that | |
205 | they happen in your production application. | |
206 | ||
207 | =item Email alerts of significant errors | |
208 | ||
209 | If we do get unexpected errors then we want to be notified them. | |
210 | ||
211 | =item Log DBIC information and errors | |
212 | ||
213 | We'll specifically look at nice ways to log SQL queries and errors when | |
214 | using DBIx::Class. | |
215 | ||
216 | =back | |
217 | ||
218 | =head2 Larger example | |
219 | ||
220 | In its simplest form, this module can be used for more flexible logging | |
221 | ||
222 | get '/route' => sub { | |
223 | # Stop execution, redirect, and display an error to the user | |
224 | $name or error "Please enter a name"; | |
225 | ||
226 | # The same but translated | |
227 | $name or error __"Please enter a name"; | |
228 | ||
229 | # The same but translated and with variables | |
230 | $name or error __x"{name} is not valid", name => $name; | |
231 | ||
232 | # Show the user a warning, but continue execution | |
233 | mistake "Not sure that's what you wanted"; | |
234 | ||
235 | # Add debug information, can be caught in syslog by adding | |
236 | # the (for instance) syslog dispatcher | |
237 | trace "Hello world"; | |
238 | }; | |
239 | ||
240 | =head2 Setup and Configuration | |
241 | ||
242 | To make full use of L<Log::Report>, you'll need to use both | |
243 | L<Dancer2::Logger::LogReport> and L<Dancer2::Plugin::LogReport>. | |
244 | ||
245 | =head3 Dancer2::Logger::LogReport | |
246 | ||
247 | Set up L<Dancer2::Logger::LogReport> by adding it to your Dancer2 | |
248 | application configuration (see L<Dancer2::Config>). By default, | |
249 | all messages will go to STDERR. | |
250 | ||
251 | To get all message out "the Perl way" (using print, warn and die) just use | |
252 | ||
253 | logger: "LogReport" | |
254 | ||
255 | At start, these are handled by a L<Log::Report::Dispatcher::Perl|Log::Report::Dispatcher::Perl> object, | |
256 | named 'default'. If you open a new dispatcher with the name 'default', | |
257 | the output via the perl mechanisms will be stopped. | |
258 | ||
259 | To also send messages to your syslog: | |
260 | ||
261 | logger: "LogReport" | |
262 | ||
263 | engines: | |
264 | logger: | |
265 | LogReport: | |
266 | log_format: %a%i%m # See Dancer2::Logger::LogReport | |
267 | app_name: MyApp | |
268 | dispatchers: | |
269 | default: # Name | |
270 | type: SYSLOG # Log::Reporter::dispatcher() options | |
271 | identity: myapp | |
272 | facility: local0 | |
273 | flags: "pid ndelay nowait" | |
274 | mode: DEBUG | |
275 | ||
276 | To send messages to a file: | |
277 | ||
278 | logger: "LogReport" | |
279 | ||
280 | engines: | |
281 | logger: | |
282 | LogReport: | |
283 | log_format: %a%i%m # See Dancer2::Logger::LogReport | |
284 | app_name: MyApp | |
285 | dispatchers: | |
286 | logfile: # "default" dispatcher stays open as well | |
287 | type: FILE | |
288 | to: /var/log/myapp.log | |
289 | charset: utf-8 | |
290 | mode: DEBUG | |
291 | ||
292 | See L<Log::Report::Dispatcher> for full details of options. | |
293 | ||
294 | Finally: a Dancer2 script may run many applications. Each application | |
295 | can have its own logger configuration. However, Log::Report dispatchers | |
296 | are global, so will be shared between Dancer2 applications. Any attempt | |
297 | to create a new Log::Report dispatcher by the same name (as will happen | |
298 | when a new Dancer2 application is started with the same configuration) | |
299 | will be ignored. | |
300 | ||
301 | =head3 Dancer2::Plugin::LogReport | |
302 | ||
303 | To use the plugin, you simply use it in your application: | |
304 | ||
305 | package MyApp; | |
306 | use Log::Report (); # use early and minimal once | |
307 | use Dancer2; | |
308 | use Dancer2::Plugin::LogReport %config; | |
309 | ||
310 | Dancer2::Plugin::LogReport takes the same C<%config> options as | |
311 | L<Log::Report> itself (see L<Log::Report::import()|Log::Report/"Configuration">). | |
312 | ||
313 | If you want to send messages from your modules/models, there is | |
314 | no need to use this specific plugin. Instead, you should simply | |
315 | C<use Log::Report> to negate the need of loading all the Dancer2 | |
316 | specific code. | |
317 | ||
318 | =head2 In use | |
319 | ||
320 | =head3 Logging debug information | |
321 | ||
322 | In its simplest form, you can now use all the | |
323 | L<Log::Report logging functions|Log::Report#The-Reason-for-the-report> | |
324 | to send messages to your dispatchers (as configured in the Logger | |
325 | configuration): | |
326 | ||
327 | trace "I'm here"; | |
328 | ||
329 | warning "Something dodgy happened"; | |
330 | ||
331 | panic "I'm bailing out"; | |
332 | ||
333 | # Additional, special Dancer2 keyword | |
334 | success "Settings saved successfully"; | |
335 | ||
336 | =head3 Exceptions | |
337 | ||
338 | Log::Report is a combination of a logger and an exception system. Messages | |
339 | to be logged are I<thrown> to all listening dispatchers to be handled. | |
340 | ||
341 | This module will also catch any unexpected exceptions: | |
342 | ||
343 | # This will be caught, the error will be logged (full stacktrace to STDOUT, | |
344 | # short message to the session messages), and the user will be forwarded | |
345 | # (default to /). This would also be sent to syslog with the appropriate | |
346 | # dispatcher. | |
347 | get 'route' => sub { | |
348 | my $foo = 1; | |
349 | my $bar = $foo->{x}; # whoops | |
350 | } | |
351 | ||
352 | For a production application (C<show_errors: 1>), the message saved in the | |
353 | session will be the generic text "An unexpected error has occurred". This | |
354 | can be customised in the configuration file, and will be translated. | |
355 | ||
356 | =head3 Sending messages to the user | |
357 | ||
358 | To make it easier to send messages to your users, messages at the following | |
359 | levels are also stored in the user's session: C<notice>, C<warning>, C<mistake>, | |
360 | C<error>, C<fault>, C<alert>, C<failure> and C<panic>. | |
361 | ||
362 | You can pass these to your template and display them at each page render: | |
363 | ||
364 | hook before_template => sub { | |
365 | my $tokens = shift; | |
366 | $tokens->{messages} = session 'messages'; | |
367 | session 'messages' => []; # Clear the message queue | |
368 | } | |
369 | ||
370 | Then in your template (for example the main layout): | |
371 | ||
372 | [% FOR message IN messages %] | |
373 | <div class="alert alert-[% message.bootstrap_color %]"> | |
374 | [% message.toString | html_entity %] | |
375 | </div> | |
376 | [% END %] | |
377 | ||
378 | The C<bootstrap_color> of the message is compatible with Bootstrap contextual | |
379 | colors: C<success>, C<info>, C<warning> or C<danger>. | |
380 | ||
381 | Now, anywhere in your application that you have used Log::Report, you can | |
382 | ||
383 | warning "Hey user, you should now about this"; | |
384 | ||
385 | and the message will be sent to the next page the user sees. | |
386 | ||
387 | =head3 Handling user errors | |
388 | ||
389 | Sometimes we write a function in a model, and it would be nice to have a | |
390 | nice easy way to return from the function with an error message. One | |
391 | way of doing this is with a separate error message variable, but that | |
392 | can be messy code. An alternative is to use exceptions, but these | |
393 | can be a pain to deal with in terms of catching them. | |
394 | Here's how to do it with Log::Report. | |
395 | ||
396 | In this example, we do use exceptions, but in a neat, easier to use manner. | |
397 | ||
398 | First, your module/model: | |
399 | ||
400 | package MyApp::CD; | |
401 | ||
402 | sub update { | |
403 | my ($self, %values) = @_; | |
404 | $values{title} or error "Please enter a title"; | |
405 | $values{description} or warning "No description entered"; | |
406 | } | |
407 | ||
408 | Then, in your controller: | |
409 | ||
410 | package MyApp; | |
411 | use Dancer2; | |
412 | ||
413 | post '/cd' => sub { | |
414 | my %values = ( | |
415 | title => param('title'); | |
416 | description => param('description'); | |
417 | ); | |
418 | if (process sub { MyApp::CD->update(%values) } ) { | |
419 | success "CD updated successfully"; | |
420 | redirect '/cd'; | |
421 | } | |
422 | ||
423 | template 'cd' => { values => \%values }; | |
424 | } | |
425 | ||
426 | Now, when update() is called, any exceptions are caught. However, there is | |
427 | no need to worry about any error messages. Both the error and warning | |
428 | messages in the above code will have been stored in the messages session | |
429 | variable, where they can be displayed using the code in the previous section. | |
430 | The C<error> will have caused the code to stop running, and process() | |
431 | will have returned false. C<warning> will have simply logged the warning | |
432 | and not caused the function to stop running. | |
433 | ||
434 | =head3 Logging DBIC database queries and errors | |
435 | ||
436 | If you use L<DBIx::Class> in your application, you can easily integrate | |
437 | its logging and exceptions. To log SQL queries: | |
438 | ||
439 | # Log all queries and execution time | |
440 | $schema->storage->debugobj(new Log::Report::DBIC::Profiler); | |
441 | $schema->storage->debug(1); | |
442 | ||
443 | By default, exceptions from DBIC are classified at the level "error". This | |
444 | is normally a user level error, and thus may be filtered as normal program | |
445 | operation. If you do not expect to receive any DBIC exceptions, then it | |
446 | is better to class them at the level "panic": | |
447 | ||
448 | # panic() DBIC errors | |
449 | $schema->exception_action(sub { panic @_ }); | |
450 | # Optionally get a stracktrace too | |
451 | $schema->stacktrace(1); | |
452 | ||
453 | If you are occasionally running queries where you expect to naturally | |
454 | get exceptions (such as not inserting multiple values on a unique constraint), | |
455 | then you can catch these separately: | |
456 | ||
457 | try { $self->schema->resultset('Unique')->create() }; | |
458 | # Log any messages from try block, but only as trace | |
459 | $@->reportAll(reason => 'TRACE'); | |
460 | ||
461 | =head3 Email alerts of exceptions | |
462 | ||
463 | If you have an unexpected exception in your production application, | |
464 | then you probably want to be notified about it. One way to do so is | |
465 | configure rsyslog to send emails of messages at the panic level. Use | |
466 | the following configuration to do so: | |
467 | ||
468 | # Normal logging from LOCAL0 | |
469 | local0.* -/var/log/myapp.log | |
470 | ||
471 | # Load the mail module | |
472 | $ModLoad ommail | |
473 | # Configure sender, receiver and mail server | |
474 | $ActionMailSMTPServer localhost | |
475 | $ActionMailFrom root | |
476 | $ActionMailTo root | |
477 | # Set up an email template | |
478 | $template mailSubject,"Critical error on %hostname%" | |
479 | $template mailBody,"RSYSLOG Alert\r\nmsg='%msg%'\r\nseverity='%syslogseverity-text%'" | |
480 | $ActionMailSubject mailSubject | |
481 | # Send an email no more frequently than every minute | |
482 | $ActionExecOnlyOnceEveryInterval 60 | |
483 | # Configure the level of message to notify via email | |
484 | if $syslogfacility-text == 'local0' and $syslogseverity < 3 then :ommail:;mailBody | |
485 | $ActionExecOnlyOnceEveryInterval 0 | |
486 | ||
487 | With the above configuration, you will only be emailed of severe errors, but can | |
488 | view the full log information in /var/log/myapp.log | |
489 | ||
490 | =head1 CONFIGURATION | |
491 | ||
492 | All configuration is optional. The example configuration file below shows the | |
493 | configuration options and defaults. | |
494 | ||
495 | plugins: | |
496 | LogReport: | |
497 | # Whether to handle Dancer HTTP errors such as 404s. Currently has | |
498 | # no effect due to unresolved issues saving messages to the session | |
499 | # and accessing the DSL at that time. | |
500 | handle_http_errors: 1 | |
501 | # Where to forward users in the event of an uncaught fatal | |
502 | # error within a GET request | |
503 | forward_url: / | |
504 | # Or you can specify a template instead [1.13] | |
505 | forward_template: error_template_file # Defaults to empty | |
506 | # For a production server (show_errors: 0), this is the text that | |
507 | # will be displayed instead of unexpected exception errors | |
508 | fatal_error_message: An unexpected error has occurred | |
509 | # The levels of messages that will be saved to the session, and | |
510 | # thus displayed to the end user | |
511 | session_messages: [ NOTICE, WARNING, MISTAKE, ERROR, FAULT, ALERT, FAILURE, PANIC ] | |
512 | ||
513 | =head1 SEE ALSO | |
514 | ||
515 | This module is part of Log-Report distribution version 1.32, | |
516 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
517 | ||
518 | =head1 LICENSE | |
519 | ||
520 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
521 | ||
522 | This program is free software; you can redistribute it and/or modify it | |
523 | under the same terms as Perl itself. | |
524 | See F<http://dev.perl.org/licenses/> | |
525 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::DBIC::Profiler; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'DBIx::Class::Storage::Statistics'; |
13 | 6 | |
14 | 7 | use strict; |
17 | 10 | use Log::Report 'log-report', import => 'trace'; |
18 | 11 | use Time::HiRes qw(time); |
19 | 12 | |
13 | =chapter NAME | |
14 | ||
15 | Log::Report::DBIC::Profiler - query profiler for DBIx::Class | |
16 | ||
17 | =chapter SYNOPSIS | |
18 | ||
19 | use Log::Report::DBIC::Profiler; | |
20 | $schema->storage->debugobj(Log::Report::DBIC::Profiler->new); | |
21 | $schema->storage->debug(1); | |
22 | ||
23 | # And maybe (if no exceptions expected from DBIC) | |
24 | $schema->exception_action(sub { panic @_ }); | |
25 | ||
26 | # Log to syslog | |
27 | use Log::Report; | |
28 | dispatcher SYSLOG => 'myapp' | |
29 | , identity => 'myapp' | |
30 | , facility => 'local0' | |
31 | , flags => "pid ndelay nowait" | |
32 | , mode => 'DEBUG'; | |
33 | ||
34 | =chapter DESCRIPTION | |
35 | ||
36 | This profile will log M<DBIx::Class> queries via M<Log::Report> to a | |
37 | selected back-end (via a dispatcher, see M<Log::Report::Dispatcher>) | |
38 | ||
39 | =cut | |
20 | 40 | |
21 | 41 | my $start; |
22 | 42 |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::DBIC::Profiler - query profiler for DBIx::Class | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::DBIC::Profiler | |
9 | is a DBIx::Class::Storage::Statistics | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | use Log::Report::DBIC::Profiler; | |
14 | $schema->storage->debugobj(Log::Report::DBIC::Profiler->new); | |
15 | $schema->storage->debug(1); | |
16 | ||
17 | # And maybe (if no exceptions expected from DBIC) | |
18 | $schema->exception_action(sub { panic @_ }); | |
19 | ||
20 | # Log to syslog | |
21 | use Log::Report; | |
22 | dispatcher SYSLOG => 'myapp' | |
23 | , identity => 'myapp' | |
24 | , facility => 'local0' | |
25 | , flags => "pid ndelay nowait" | |
26 | , mode => 'DEBUG'; | |
27 | ||
28 | =head1 DESCRIPTION | |
29 | ||
30 | This profile will log DBIx::Class queries via L<Log::Report|Log::Report> to a | |
31 | selected back-end (via a dispatcher, see L<Log::Report::Dispatcher|Log::Report::Dispatcher>) | |
32 | ||
33 | =head1 SEE ALSO | |
34 | ||
35 | This module is part of Log-Report distribution version 1.32, | |
36 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
37 | ||
38 | =head1 LICENSE | |
39 | ||
40 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
41 | ||
42 | This program is free software; you can redistribute it and/or modify it | |
43 | under the same terms as Perl itself. | |
44 | See F<http://dev.perl.org/licenses/> | |
45 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Die; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Exporter'; |
13 | 6 | |
14 | 7 | use warnings; |
18 | 11 | |
19 | 12 | use POSIX qw/locale_h/; |
20 | 13 | |
14 | =chapter NAME | |
15 | Log::Report::Die - compatibility routines with Perl's die/croak/confess | |
16 | ||
17 | =chapter SYNOPSIS | |
18 | # use internally only | |
19 | ||
20 | =chapter DESCRIPTION | |
21 | ||
22 | This module is used internally, to translate output of 'die' and Carp | |
23 | functions into M<Log::Report::Message> objects. Also, it tries to | |
24 | convert other kinds of exception frameworks into our message object. | |
25 | ||
26 | =chapter FUNCTIONS | |
27 | ||
28 | =function die_decode STRING, %options | |
29 | The STRING is the content of C<$@> after an eval() caught a die(). | |
30 | croak(), or confess(). This routine tries to convert this into | |
31 | parameters for M<Log::Report::report()>. This is done in a very | |
32 | smart way, even trying to find the stringifications of C<$!>. | |
33 | ||
34 | Returned are four elements: the error string or object which triggered | |
35 | the death originally (the original $@), and the opts, reason, and plain | |
36 | text message. The opts is a HASH which, amongst other things, may contain | |
37 | a stack trace and location extracted from the death text or object. | |
38 | ||
39 | Translated components will have exception classes C<perl>, and C<die> or | |
40 | C<confess>. On the moment, the C<croak> cannot be distiguished from the | |
41 | C<confess> (when used in package main) or C<die> (otherwise). | |
42 | ||
43 | The returned reason depends on whether the translation of the current | |
44 | C<$!> is found in the STRING, and the presence of a stack trace. The | |
45 | following table is used: | |
46 | ||
47 | errstr stack => reason | |
48 | no no ERROR (die) application internal problem | |
49 | yes no FAULT (die) external problem, think open() | |
50 | no yes PANIC (confess) implementation error | |
51 | yes yes ALERT (confess) external problem, caught | |
52 | ||
53 | =option on_die REASON | |
54 | =default on_die 'ERROR' | |
55 | =cut | |
21 | 56 | |
22 | 57 | sub die_decode($%) |
23 | 58 | { my ($text, %args) = @_; |
30 | 65 | my %opt = (errno => $! + 0); |
31 | 66 | my $err = "$!"; |
32 | 67 | |
33 | my $dietxt = $text[0]; | |
34 | 68 | if($text[0] =~ s/ at (.+) line (\d+)\.?$// ) |
35 | 69 | { $opt{location} = [undef, $1, $2, undef]; |
36 | 70 | } |
60 | 94 | : @stack ? 'PANIC' |
61 | 95 | : $args{on_die} || 'ERROR'; |
62 | 96 | |
63 | ($dietxt, \%opt, $reason, join("\n", @msg)); | |
97 | (\%opt, $reason, join("\n", @msg)); | |
64 | 98 | } |
65 | 99 | |
100 | =function exception_decode $exception, %options | |
101 | [1.23] This function attempts to translate object of other exception frameworks | |
102 | into information to create a M<Log::Report::Exception>. It returns the | |
103 | same list of parameters as M<die_decode()> does. | |
104 | ||
105 | Currently supported: | |
106 | =over 4 | |
107 | =item * DBIx::Class::Exception | |
108 | =item * XML::LibXML::Error | |
109 | =back | |
110 | =cut | |
66 | 111 | |
67 | 112 | sub _exception_dbix($$) |
68 | 113 | { my ($exception, $args) = @_; |
93 | 138 | : @stack ? 'PANIC' |
94 | 139 | : $on_die || 'ERROR'; |
95 | 140 | |
96 | ('caught '.ref $exception, \%opts, $reason, $message); | |
141 | (\%opts, $reason, $message); | |
97 | 142 | } |
98 | 143 | |
99 | 144 | my %_libxml_errno2reason = (1 => 'WARNING', 2 => 'MISTAKE', 3 => 'ERROR'); |
111 | 156 | . ' (' . $exc->domain . ' error ' . $exc->code . ')'; |
112 | 157 | |
113 | 158 | my $reason = $_libxml_errno2reason{$exc->level} || 'PANIC'; |
114 | ('caught '.ref $exc, \%opts, $reason, $msg); | |
159 | (\%opts, $reason, $msg); | |
115 | 160 | } |
116 | 161 | |
117 | 162 | sub exception_decode($%) |
126 | 171 | |
127 | 172 | # Unsupported exception system, sane guesses |
128 | 173 | my %opt = |
129 | ( classes => [ 'unknown exception', 'die', ref $exception ] | |
130 | , errno => $errno | |
131 | ); | |
174 | ( classes => [ 'unknown exception', 'die', ref $exception ] | |
175 | , errno => $errno | |
176 | ); | |
132 | 177 | |
133 | 178 | my $reason = $errno ? 'FAULT' : $args{on_die} || 'ERROR'; |
134 | 179 | |
135 | 180 | # hopefully stringification is overloaded |
136 | ( "caught ".ref $exception, \%opt, $reason, "$exception"); | |
181 | (\%opt, $reason, "$exception"); | |
137 | 182 | } |
138 | 183 | |
139 | 184 | "to die or not to die, that's the question"; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Die - compatibility routines with Perl's die/croak/confess | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Die | |
9 | is a Exporter | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | # use internally only | |
14 | ||
15 | =head1 DESCRIPTION | |
16 | ||
17 | This module is used internally, to translate output of 'die' and Carp | |
18 | functions into L<Log::Report::Message|Log::Report::Message> objects. Also, it tries to | |
19 | convert other kinds of exception frameworks into our message object. | |
20 | ||
21 | =head1 FUNCTIONS | |
22 | ||
23 | =over 4 | |
24 | ||
25 | =item B<die_decode>(STRING, %options) | |
26 | ||
27 | The STRING is the content of C<$@> after an eval() caught a die(). | |
28 | croak(), or confess(). This routine tries to convert this into | |
29 | parameters for L<Log::Report::report()|Log::Report/"Report Production and Configuration">. This is done in a very | |
30 | smart way, even trying to find the stringifications of C<$!>. | |
31 | ||
32 | Return are four elements: the error string which is used to trigger | |
33 | a C<Log::Report> compatible C<die()>, and the options, reason, and | |
34 | text message. The options is a HASH which, amongst other things, | |
35 | may contain a stack trace and location. | |
36 | ||
37 | Translated components will have exception classes C<perl>, and C<die> or | |
38 | C<confess>. On the moment, the C<croak> cannot be distiguished from the | |
39 | C<confess> (when used in package main) or C<die> (otherwise). | |
40 | ||
41 | The returned reason depends on whether the translation of the current | |
42 | C<$!> is found in the STRING, and the presence of a stack trace. The | |
43 | following table is used: | |
44 | ||
45 | errstr stack => reason | |
46 | no no ERROR (die) application internal problem | |
47 | yes no FAULT (die) external problem, think open() | |
48 | no yes PANIC (confess) implementation error | |
49 | yes yes ALERT (confess) external problem, caught | |
50 | ||
51 | -Option--Default | |
52 | on_die 'ERROR' | |
53 | ||
54 | =over 2 | |
55 | ||
56 | =item on_die => REASON | |
57 | ||
58 | =back | |
59 | ||
60 | =item B<exception_decode>($exception, %options) | |
61 | ||
62 | [1.23] This function attempts to translate object of other exception frameworks | |
63 | into information to create a L<Log::Report::Exception|Log::Report::Exception>. It returns the | |
64 | same list of parameters as L<die_decode()|Log::Report::Die/"FUNCTIONS"> does. | |
65 | ||
66 | Currently supported: | |
67 | ||
68 | =over 4 | |
69 | ||
70 | =item * DBIx::Class::Exception | |
71 | ||
72 | =item * XML::LibXML::Error | |
73 | ||
74 | =back | |
75 | ||
76 | =back | |
77 | ||
78 | =head1 SEE ALSO | |
79 | ||
80 | This module is part of Log-Report distribution version 1.32, | |
81 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
82 | ||
83 | =head1 LICENSE | |
84 | ||
85 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
86 | ||
87 | This program is free software; you can redistribute it and/or modify it | |
88 | under the same terms as Perl itself. | |
89 | See F<http://dev.perl.org/licenses/> | |
90 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Dispatcher::Callback; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Log::Report::Dispatcher'; |
13 | 6 | |
14 | 7 | use warnings; |
16 | 9 | |
17 | 10 | use Log::Report 'log-report'; |
18 | 11 | |
12 | =chapter NAME | |
13 | Log::Report::Dispatcher::Callback - call a code-ref for each log-line | |
14 | ||
15 | =chapter SYNOPSIS | |
16 | sub cb($$$) | |
17 | { my ($disp, $options, $reason, $message) = @_; | |
18 | ... | |
19 | } | |
20 | ||
21 | dispatcher Log::Report::Dispatcher::Callback => 'cb' | |
22 | , callback => \&cb; | |
23 | ||
24 | dispatcher CALLBACK => 'cb' # same | |
25 | , callback => \&cb; | |
26 | ||
27 | =chapter DESCRIPTION | |
28 | This basic file logger accepts a callback, which is called for each | |
29 | message which is to be logged. When you need complex things, you | |
30 | may best make your own extension to M<Log::Report::Dispatcher>, but | |
31 | for simple things this will do. | |
32 | ||
33 | =example | |
34 | sub send_mail($$$) | |
35 | { my ($disp, $options, $reason, $message) = @_; | |
36 | my $msg = Mail::Send->new(Subject => $reason | |
37 | , To => 'admin@localhost'); | |
38 | my $fh = $msg->open('sendmail'); | |
39 | print $fh $disp->translate($reason, $message); | |
40 | close $fh; | |
41 | } | |
42 | ||
43 | dispatcher CALLBACK => 'mail', callback => \&send_mail; | |
44 | ||
45 | =chapter METHODS | |
46 | ||
47 | =section Constructors | |
48 | ||
49 | =c_method new $type, $name, %options | |
50 | ||
51 | =requires callback CODE | |
52 | Your C<callback> is called with five parameters: this dispatcher object, | |
53 | the options, a reason and a message. The C<options> are the first | |
54 | parameter of M<Log::Report::report()> (read over there). The C<reason> | |
55 | is a capitized string like C<ERROR>. Then, the C<message> (is a | |
56 | M<Log::Report::Message>). Finally the text-domain of the message. | |
57 | ||
58 | =cut | |
19 | 59 | |
20 | 60 | sub init($) |
21 | 61 | { my ($self, $args) = @_; |
27 | 67 | $self; |
28 | 68 | } |
29 | 69 | |
70 | =section Accessors | |
71 | ||
72 | =method callback | |
73 | Returns the code reference which will handle each logged message. | |
74 | =cut | |
30 | 75 | |
31 | 76 | sub callback() {shift->{callback}} |
32 | 77 | |
78 | =section Logging | |
79 | =cut | |
33 | 80 | |
34 | 81 | sub log($$$$) |
35 | 82 | { my $self = shift; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Dispatcher::Callback - call a code-ref for each log-line | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Dispatcher::Callback | |
9 | is a Log::Report::Dispatcher | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | sub cb($$$) | |
14 | { my ($disp, $options, $reason, $message) = @_; | |
15 | ... | |
16 | } | |
17 | ||
18 | dispatcher Log::Report::Dispatcher::Callback => 'cb' | |
19 | , callback => \&cb; | |
20 | ||
21 | dispatcher CALLBACK => 'cb' # same | |
22 | , callback => \&cb; | |
23 | ||
24 | =head1 DESCRIPTION | |
25 | ||
26 | This basic file logger accepts a callback, which is called for each | |
27 | message which is to be logged. When you need complex things, you | |
28 | may best make your own extension to L<Log::Report::Dispatcher|Log::Report::Dispatcher>, but | |
29 | for simple things this will do. | |
30 | ||
31 | Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">. | |
32 | ||
33 | B<. Example> | |
34 | ||
35 | sub send_mail($$$) | |
36 | { my ($disp, $options, $reason, $message) = @_; | |
37 | my $msg = Mail::Send->new(Subject => $reason | |
38 | , To => 'admin@localhost'); | |
39 | my $fh = $msg->open('sendmail'); | |
40 | print $fh $disp->translate($reason, $message); | |
41 | close $fh; | |
42 | } | |
43 | ||
44 | dispatcher CALLBACK => 'mail', callback => \&send_mail; | |
45 | ||
46 | =head1 METHODS | |
47 | ||
48 | Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">. | |
49 | ||
50 | =head2 Constructors | |
51 | ||
52 | Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">. | |
53 | ||
54 | =over 4 | |
55 | ||
56 | =item $obj-E<gt>B<close>() | |
57 | ||
58 | Inherited, see L<Log::Report::Dispatcher/"Constructors"> | |
59 | ||
60 | =item Log::Report::Dispatcher::Callback-E<gt>B<new>($type, $name, %options) | |
61 | ||
62 | -Option --Defined in --Default | |
63 | accept Log::Report::Dispatcher depend on mode | |
64 | callback <required> | |
65 | charset Log::Report::Dispatcher <undef> | |
66 | format_reason Log::Report::Dispatcher 'LOWERCASE' | |
67 | locale Log::Report::Dispatcher <system locale> | |
68 | mode Log::Report::Dispatcher 'NORMAL' | |
69 | ||
70 | =over 2 | |
71 | ||
72 | =item accept => REASONS | |
73 | ||
74 | =item callback => CODE | |
75 | ||
76 | Your C<callback> is called with five parameters: this dispatcher object, | |
77 | the options, a reason and a message. The C<options> are the first | |
78 | parameter of L<Log::Report::report()|Log::Report/"Report Production and Configuration"> (read over there). The C<reason> | |
79 | is a capitized string like C<ERROR>. Then, the C<message> (is a | |
80 | L<Log::Report::Message|Log::Report::Message>). Finally the text-domain of the message. | |
81 | ||
82 | =item charset => CHARSET | |
83 | ||
84 | =item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE | |
85 | ||
86 | =item locale => LOCALE | |
87 | ||
88 | =item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3 | |
89 | ||
90 | =back | |
91 | ||
92 | =back | |
93 | ||
94 | =head2 Accessors | |
95 | ||
96 | Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">. | |
97 | ||
98 | =over 4 | |
99 | ||
100 | =item $obj-E<gt>B<callback>() | |
101 | ||
102 | Returns the code reference which will handle each logged message. | |
103 | ||
104 | =item $obj-E<gt>B<isDisabled>() | |
105 | ||
106 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
107 | ||
108 | =item $obj-E<gt>B<mode>() | |
109 | ||
110 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
111 | ||
112 | =item $obj-E<gt>B<name>() | |
113 | ||
114 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
115 | ||
116 | =item $obj-E<gt>B<needs>( [$reason] ) | |
117 | ||
118 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
119 | ||
120 | =item $obj-E<gt>B<type>() | |
121 | ||
122 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
123 | ||
124 | =back | |
125 | ||
126 | =head2 Logging | |
127 | ||
128 | Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">. | |
129 | ||
130 | =over 4 | |
131 | ||
132 | =item $obj-E<gt>B<addSkipStack>(@CODE) | |
133 | ||
134 | =item Log::Report::Dispatcher::Callback-E<gt>B<addSkipStack>(@CODE) | |
135 | ||
136 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
137 | ||
138 | =item $obj-E<gt>B<collectLocation>() | |
139 | ||
140 | =item Log::Report::Dispatcher::Callback-E<gt>B<collectLocation>() | |
141 | ||
142 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
143 | ||
144 | =item $obj-E<gt>B<collectStack>( [$maxdepth] ) | |
145 | ||
146 | =item Log::Report::Dispatcher::Callback-E<gt>B<collectStack>( [$maxdepth] ) | |
147 | ||
148 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
149 | ||
150 | =item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain) | |
151 | ||
152 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
153 | ||
154 | =item $obj-E<gt>B<skipStack>() | |
155 | ||
156 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
157 | ||
158 | =item $obj-E<gt>B<stackTraceLine>(%options) | |
159 | ||
160 | =item Log::Report::Dispatcher::Callback-E<gt>B<stackTraceLine>(%options) | |
161 | ||
162 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
163 | ||
164 | =item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message) | |
165 | ||
166 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
167 | ||
168 | =back | |
169 | ||
170 | =head1 DETAILS | |
171 | ||
172 | Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">. | |
173 | ||
174 | =head1 SEE ALSO | |
175 | ||
176 | This module is part of Log-Report distribution version 1.32, | |
177 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
178 | ||
179 | =head1 LICENSE | |
180 | ||
181 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
182 | ||
183 | This program is free software; you can redistribute it and/or modify it | |
184 | under the same terms as Perl itself. | |
185 | See F<http://dev.perl.org/licenses/> | |
186 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Dispatcher::File; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Log::Report::Dispatcher'; |
13 | 6 | |
14 | 7 | use warnings; |
21 | 14 | use Encode qw/find_encoding/; |
22 | 15 | use Fcntl qw/:flock/; |
23 | 16 | |
17 | =chapter NAME | |
18 | Log::Report::Dispatcher::File - send messages to a file or file-handle | |
19 | ||
20 | =chapter SYNOPSIS | |
21 | dispatcher Log::Report::Dispatcher::File => 'stderr' | |
22 | , to => \*STDERR, accept => 'NOTICE-'; | |
23 | ||
24 | # close a dispatcher | |
25 | dispatcher close => 'stderr'; | |
26 | ||
27 | # let dispatcher open and close the file | |
28 | dispatcher FILE => 'mylog', to => '/var/log/mylog' | |
29 | , charset => 'utf-8'; | |
30 | ... | |
31 | dispatcher close => 'mylog'; # will close file | |
32 | ||
33 | # open yourself, then also close yourself | |
34 | open OUT, ">:encoding('iso-8859-1')", '/var/log/mylog' | |
35 | or fault "..."; | |
36 | dispatcher FILE => 'mylog', to => \*OUT; | |
37 | ... | |
38 | dispatcher close => 'mylog'; | |
39 | close OUT; | |
40 | ||
41 | # dispatch into a scalar | |
42 | my $output = ''; | |
43 | open $outfile, '>', \$output; | |
44 | dispatcher FILE => 'into-scalar', to => \$outfile; | |
45 | ... | |
46 | dispatcher close => 'into-scalar'; | |
47 | print $output; | |
48 | ||
49 | =chapter DESCRIPTION | |
50 | This basic file logger accepts an file-handle or filename as destination. | |
51 | ||
52 | [1.00] writing to the file protected by a lock, so multiple processes | |
53 | can write to the same file. | |
54 | ||
55 | =chapter METHODS | |
56 | ||
57 | =section Constructors | |
58 | ||
59 | =c_method new $type, $name, %options | |
60 | ||
61 | =requires to FILENAME|FILEHANDLE|OBJECT|CODE | |
62 | You can either specify a FILENAME, which is opened in append mode with | |
63 | autoflush on. Or pass any kind of FILE-HANDLE or some OBJECT which | |
64 | implements a C<print()> method. You probably want to have autoflush | |
65 | enabled on your FILE-HANDLES. | |
66 | ||
67 | When cleaning-up the dispatcher, the file will only be closed in case | |
68 | of a FILENAME. | |
69 | ||
70 | [1.10] When you pass a CODE, then for each log message the function is | |
71 | called with two arguments: this dispatcher object and the message object. | |
72 | In some way (maybe via the message context) you have to determine the | |
73 | log filename. This means that probably many log-files are open at the | |
74 | same time. | |
75 | ||
76 | # configuration time | |
77 | dispatcher FILE => 'logfile', to => | |
78 | sub { my ($disp, $msg) = @_; $msg->context->{logfile} }; | |
79 | ||
80 | # whenever you want to change the logfile | |
81 | textdomain->updateContext(logfile => '/var/log/app'); | |
82 | (textdomain 'mydomain')->setContext(logfile => '/var/log/app'); | |
83 | ||
84 | # or | |
85 | error __x"help", _context => {logfile => '/dev/tty'}; | |
86 | error __x"help", _context => "logfile=/dev/tty"; | |
87 | ||
88 | =option replace BOOLEAN | |
89 | =default replace C<false> | |
90 | Only used in combination with a FILENAME: throw away the old file | |
91 | if it exists. Probably you wish to append to existing information. | |
92 | ||
93 | =default charset LOCALE | |
94 | Use the LOCALE setting by default, which is LC_CTYPE or LC_ALL or LANG | |
95 | (in that order). If these contain a character-set which Perl understands, | |
96 | then that is used, otherwise silently ignored. | |
97 | ||
98 | =option format CODE|'LONG' | |
99 | =default format <adds timestamp> | |
100 | [1.00] process each printed line. By default, this adds a timestamp, | |
101 | but you may want to add hostname, process number, or more. | |
102 | ||
103 | format => sub { '['.localtime().'] '.$_[0] } | |
104 | format => sub { shift } # no timestamp | |
105 | format => 'LONG' | |
106 | ||
107 | The first parameter to format is the string to print; it is already | |
108 | translated and trailed by a newline. The second parameter is the | |
109 | text-domain (if known). | |
110 | ||
111 | [1.10] As third parameter, you get the $msg raw object as well (maybe | |
112 | you want to use the message context?) | |
113 | [1.19] After the three positional parameters, there may be a list | |
114 | of pairs providing additional facts about the exception. It may | |
115 | contain C<location> information. | |
116 | ||
117 | The "LONG" format is equivalent to: | |
118 | ||
119 | my $t = strftime "%FT%T", gmtime; | |
120 | "[$t $$] $_[1] $_[0]" | |
121 | ||
122 | Use of context: | |
123 | ||
124 | format => sub { my ($msgstr, $domain, $msg, %more) = @_; | |
125 | my $host = $msg->context->{host}; | |
126 | "$host $msgstr"; | |
127 | } | |
128 | ||
129 | =cut | |
24 | 130 | |
25 | 131 | sub init($) |
26 | 132 | { my ($self, $args) = @_; |
54 | 160 | } |
55 | 161 | |
56 | 162 | |
163 | =method close | |
164 | Only when initiated with a FILENAME, the file will be closed. In any | |
165 | other case, nothing will be done. | |
166 | =cut | |
57 | 167 | |
58 | 168 | sub close() |
59 | 169 | { my $self = shift; |
71 | 181 | } |
72 | 182 | |
73 | 183 | #----------- |
184 | =section Accessors | |
185 | ||
186 | =method filename | |
187 | Returns the name of the opened file, or C<undef> in case this dispatcher | |
188 | was started from a file-handle or file-object. | |
189 | ||
190 | =method format | |
191 | =cut | |
74 | 192 | |
75 | 193 | sub filename() {shift->{LRDF_filename}} |
76 | 194 | sub format() {shift->{LRDF_format}} |
77 | 195 | |
196 | =method output $msg | |
197 | Returns the file-handle to write the log lines to. [1.10] This may | |
198 | depend on the $msg (especially message context) | |
199 | =cut | |
78 | 200 | |
79 | 201 | sub output($) |
80 | 202 | { # fast simple case |
119 | 241 | |
120 | 242 | |
121 | 243 | #----------- |
244 | =section File maintenance | |
245 | ||
246 | =method rotate $filename|CODE | |
247 | [1.00] Move the current file to $filename, and start a new file. | |
248 | =cut | |
122 | 249 | |
123 | 250 | sub rotate($) |
124 | 251 | { my ($self, $old) = @_; |
149 | 276 | } |
150 | 277 | |
151 | 278 | #----------- |
279 | =section Logging | |
280 | =cut | |
152 | 281 | |
153 | 282 | sub log($$$$) |
154 | 283 | { my ($self, $opts, $reason, $msg, $domain) = @_; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Dispatcher::File - send messages to a file or file-handle | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Dispatcher::File | |
9 | is a Log::Report::Dispatcher | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | dispatcher Log::Report::Dispatcher::File => 'stderr' | |
14 | , to => \*STDERR, accept => 'NOTICE-'; | |
15 | ||
16 | # close a dispatcher | |
17 | dispatcher close => 'stderr'; | |
18 | ||
19 | # let dispatcher open and close the file | |
20 | dispatcher FILE => 'mylog', to => '/var/log/mylog' | |
21 | , charset => 'utf-8'; | |
22 | ... | |
23 | dispatcher close => 'mylog'; # will close file | |
24 | ||
25 | # open yourself, then also close yourself | |
26 | open OUT, ">:encoding('iso-8859-1')", '/var/log/mylog' | |
27 | or fault "..."; | |
28 | dispatcher FILE => 'mylog', to => \*OUT; | |
29 | ... | |
30 | dispatcher close => 'mylog'; | |
31 | close OUT; | |
32 | ||
33 | # dispatch into a scalar | |
34 | my $output = ''; | |
35 | open $outfile, '>', \$output; | |
36 | dispatcher FILE => 'into-scalar', to => \$outfile; | |
37 | ... | |
38 | dispatcher close => 'into-scalar'; | |
39 | print $output; | |
40 | ||
41 | =head1 DESCRIPTION | |
42 | ||
43 | This basic file logger accepts an file-handle or filename as destination. | |
44 | ||
45 | [1.00] writing to the file protected by a lock, so multiple processes | |
46 | can write to the same file. | |
47 | ||
48 | Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">. | |
49 | ||
50 | =head1 METHODS | |
51 | ||
52 | Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">. | |
53 | ||
54 | =head2 Constructors | |
55 | ||
56 | Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">. | |
57 | ||
58 | =over 4 | |
59 | ||
60 | =item $obj-E<gt>B<close>() | |
61 | ||
62 | Only when initiated with a FILENAME, the file will be closed. In any | |
63 | other case, nothing will be done. | |
64 | ||
65 | =item Log::Report::Dispatcher::File-E<gt>B<new>($type, $name, %options) | |
66 | ||
67 | -Option --Defined in --Default | |
68 | accept Log::Report::Dispatcher depend on mode | |
69 | charset Log::Report::Dispatcher LOCALE | |
70 | format <adds timestamp> | |
71 | format_reason Log::Report::Dispatcher 'LOWERCASE' | |
72 | locale Log::Report::Dispatcher <system locale> | |
73 | mode Log::Report::Dispatcher 'NORMAL' | |
74 | replace false | |
75 | to <required> | |
76 | ||
77 | =over 2 | |
78 | ||
79 | =item accept => REASONS | |
80 | ||
81 | =item charset => CHARSET | |
82 | ||
83 | =item format => CODE|'LONG' | |
84 | ||
85 | [1.00] process each printed line. By default, this adds a timestamp, | |
86 | but you may want to add hostname, process number, or more. | |
87 | ||
88 | format => sub { '['.localtime().'] '.$_[0] } | |
89 | format => sub { shift } # no timestamp | |
90 | format => 'LONG' | |
91 | ||
92 | The first parameter to format is the string to print; it is already | |
93 | translated and trailed by a newline. The second parameter is the | |
94 | text-domain (if known). | |
95 | ||
96 | [1.10] As third parameter, you get the $msg raw object as well (maybe | |
97 | you want to use the message context?) | |
98 | [1.19] After the three positional parameters, there may be a list | |
99 | of pairs providing additional facts about the exception. It may | |
100 | contain C<location> information. | |
101 | ||
102 | The "LONG" format is equivalent to: | |
103 | ||
104 | my $t = strftime "%FT%T", gmtime; | |
105 | "[$t $$] $_[1] $_[0]" | |
106 | ||
107 | Use of context: | |
108 | ||
109 | format => sub { my ($msgstr, $domain, $msg, %more) = @_; | |
110 | my $host = $msg->context->{host}; | |
111 | "$host $msgstr"; | |
112 | } | |
113 | ||
114 | =item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE | |
115 | ||
116 | =item locale => LOCALE | |
117 | ||
118 | =item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3 | |
119 | ||
120 | =item replace => BOOLEAN | |
121 | ||
122 | Only used in combination with a FILENAME: throw away the old file | |
123 | if it exists. Probably you wish to append to existing information. | |
124 | ||
125 | Use the LOCALE setting by default, which is LC_CTYPE or LC_ALL or LANG | |
126 | (in that order). If these contain a character-set which Perl understands, | |
127 | then that is used, otherwise silently ignored. | |
128 | ||
129 | =item to => FILENAME|FILEHANDLE|OBJECT|CODE | |
130 | ||
131 | You can either specify a FILENAME, which is opened in append mode with | |
132 | autoflush on. Or pass any kind of FILE-HANDLE or some OBJECT which | |
133 | implements a C<print()> method. You probably want to have autoflush | |
134 | enabled on your FILE-HANDLES. | |
135 | ||
136 | When cleaning-up the dispatcher, the file will only be closed in case | |
137 | of a FILENAME. | |
138 | ||
139 | [1.10] When you pass a CODE, then for each log message the function is | |
140 | called with two arguments: this dispatcher object and the message object. | |
141 | In some way (maybe via the message context) you have to determine the | |
142 | log filename. This means that probably many log-files are open at the | |
143 | same time. | |
144 | ||
145 | # configuration time | |
146 | dispatcher FILE => 'logfile', to => | |
147 | sub { my ($disp, $msg) = @_; $msg->context->{logfile} }; | |
148 | ||
149 | # whenever you want to change the logfile | |
150 | textdomain->updateContext(logfile => '/var/log/app'); | |
151 | (textdomain 'mydomain')->setContext(logfile => '/var/log/app'); | |
152 | ||
153 | # or | |
154 | error __x"help", _context => {logfile => '/dev/tty'}; | |
155 | error __x"help", _context => "logfile=/dev/tty"; | |
156 | ||
157 | =back | |
158 | ||
159 | =back | |
160 | ||
161 | =head2 Accessors | |
162 | ||
163 | Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">. | |
164 | ||
165 | =over 4 | |
166 | ||
167 | =item $obj-E<gt>B<filename>() | |
168 | ||
169 | Returns the name of the opened file, or C<undef> in case this dispatcher | |
170 | was started from a file-handle or file-object. | |
171 | ||
172 | =item $obj-E<gt>B<format>() | |
173 | ||
174 | =item $obj-E<gt>B<isDisabled>() | |
175 | ||
176 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
177 | ||
178 | =item $obj-E<gt>B<mode>() | |
179 | ||
180 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
181 | ||
182 | =item $obj-E<gt>B<name>() | |
183 | ||
184 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
185 | ||
186 | =item $obj-E<gt>B<needs>( [$reason] ) | |
187 | ||
188 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
189 | ||
190 | =item $obj-E<gt>B<output>($msg) | |
191 | ||
192 | Returns the file-handle to write the log lines to. [1.10] This may | |
193 | depend on the $msg (especially message context) | |
194 | ||
195 | =item $obj-E<gt>B<type>() | |
196 | ||
197 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
198 | ||
199 | =back | |
200 | ||
201 | =head2 File maintenance | |
202 | ||
203 | =over 4 | |
204 | ||
205 | =item $obj-E<gt>B<rotate>($filename|CODE) | |
206 | ||
207 | [1.00] Move the current file to $filename, and start a new file. | |
208 | ||
209 | =back | |
210 | ||
211 | =head2 Logging | |
212 | ||
213 | Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">. | |
214 | ||
215 | =over 4 | |
216 | ||
217 | =item $obj-E<gt>B<addSkipStack>(@CODE) | |
218 | ||
219 | =item Log::Report::Dispatcher::File-E<gt>B<addSkipStack>(@CODE) | |
220 | ||
221 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
222 | ||
223 | =item $obj-E<gt>B<collectLocation>() | |
224 | ||
225 | =item Log::Report::Dispatcher::File-E<gt>B<collectLocation>() | |
226 | ||
227 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
228 | ||
229 | =item $obj-E<gt>B<collectStack>( [$maxdepth] ) | |
230 | ||
231 | =item Log::Report::Dispatcher::File-E<gt>B<collectStack>( [$maxdepth] ) | |
232 | ||
233 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
234 | ||
235 | =item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain) | |
236 | ||
237 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
238 | ||
239 | =item $obj-E<gt>B<skipStack>() | |
240 | ||
241 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
242 | ||
243 | =item $obj-E<gt>B<stackTraceLine>(%options) | |
244 | ||
245 | =item Log::Report::Dispatcher::File-E<gt>B<stackTraceLine>(%options) | |
246 | ||
247 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
248 | ||
249 | =item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message) | |
250 | ||
251 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
252 | ||
253 | =back | |
254 | ||
255 | =head1 DETAILS | |
256 | ||
257 | Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">. | |
258 | ||
259 | =head1 SEE ALSO | |
260 | ||
261 | This module is part of Log-Report distribution version 1.32, | |
262 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
263 | ||
264 | =head1 LICENSE | |
265 | ||
266 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
267 | ||
268 | This program is free software; you can redistribute it and/or modify it | |
269 | under the same terms as Perl itself. | |
270 | See F<http://dev.perl.org/licenses/> | |
271 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Dispatcher::Log4perl; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Log::Report::Dispatcher'; |
13 | 6 | |
14 | 7 | use warnings; |
43 | 36 | Log::Report::Dispatcher::Try |
44 | 37 | /; |
45 | 38 | |
39 | =chapter NAME | |
40 | Log::Report::Dispatcher::Log4perl - send messages to Log::Log4perl back-end | |
41 | ||
42 | =chapter SYNOPSIS | |
43 | ||
44 | # start using log4perl via a config file | |
45 | # The name of the dispatcher is the name of the default category. | |
46 | dispatcher LOG4PERL => 'logger' | |
47 | , accept => 'NOTICE-' | |
48 | , config => "$ENV{HOME}/.log.conf"; | |
49 | ||
50 | # disable default dispatcher | |
51 | dispatcher close => 'logger'; | |
52 | ||
53 | # configuration inline, not in file: adapted from the Log4perl manpage | |
54 | my $name = 'logger'; | |
55 | my $outfile = '/tmp/a.log'; | |
56 | my $config = <<__CONFIG; | |
57 | log4perl.category.$name = INFO, Logfile | |
58 | log4perl.logger.Logfile = Log::Log4perl::Appender::File | |
59 | log4perl.logger.Logfile.filename = $outfn | |
60 | log4perl.logger.Logfile.layout = Log::Log4perl::Layout::PatternLayout | |
61 | log4perl.logger.Logfile.layout.ConversionPattern = %d %F{1} %L> %m | |
62 | __CONFIG | |
63 | ||
64 | dispatcher LOG4PERL => $name, config => \$config; | |
65 | ||
66 | =chapter DESCRIPTION | |
67 | This dispatchers produces output tot syslog, based on the C<Sys::Log4perl> | |
68 | module (which will not be automatically installed for you). | |
69 | ||
70 | =section Reasons <--> Levels | |
71 | ||
72 | The REASONs for a message in M<Log::Report> are names quite similar to | |
73 | the log levels used by M<Log::Log4perl>. The default mapping is list | |
74 | below. You can change the mapping using M<new(to_level)>. | |
75 | ||
76 | TRACE => $DEBUG ERROR => $ERROR | |
77 | ASSERT => $DEBUG FAULT => $ERROR | |
78 | INFO => $INFO ALERT => $FATAL | |
79 | NOTICE => $INFO FAILURE => $FATAL | |
80 | WARNING => $WARN PANIC => $FATAL | |
81 | MISTAKE => $WARN | |
82 | ||
83 | =section Categories | |
84 | ||
85 | C<Log::Report> uses text-domains for translation tables. These are | |
86 | also used as categories for the Log4perl infrastructure. So, typically | |
87 | every module start with: | |
88 | ||
89 | use Log::Report 'my-text-domain', %more_options; | |
90 | ||
91 | Now, if there is a logger inside the log4perl configuration which is | |
92 | named 'my-text-domain', that will be used. Otherwise, the name of the | |
93 | dispatcher is used to select the logger. | |
94 | ||
95 | =subsection Limitiations | |
96 | ||
97 | The global C<$caller_depth> concept of M<Log::Log4perl> is broken. | |
98 | That variable is used to find the filename and line number of the logged | |
99 | messages. But these messages may have been caught, rerouted, eval'ed, and | |
100 | otherwise followed a unpredictable multi-leveled path before it reached | |
101 | the Log::Log4perl dispatcher. This means that layout patterns C<%F> | |
102 | and C<%L> are not useful in the generic case, maybe in your specific case. | |
103 | ||
104 | =chapter METHODS | |
105 | ||
106 | =section Constructors | |
107 | ||
108 | =c_method new $type, $name, %options | |
109 | The M<Log::Log4perl> infrastructure has all settings in a configuration | |
110 | file. In that file, you should find a category with the $name. | |
111 | ||
112 | =option to_level ARRAY-of-PAIRS | |
113 | =default to_level [] | |
114 | See M<reasonToLevel()>. | |
115 | ||
116 | =option config FILENAME|SCALAR | |
117 | =default config <undef> | |
118 | When a SCALAR reference is passed in, that must refer to a string which | |
119 | contains the configuration text. Otherwise, specify an existing FILENAME. | |
120 | ||
121 | By default, it is expected that M<Log::Log4perl> has been initialized | |
122 | externally. That module uses global variables to communicate, which | |
123 | should be present before any logging is attempted. | |
124 | ||
125 | =default accept 'ALL' | |
126 | ||
127 | =cut | |
46 | 128 | |
47 | 129 | sub init($) |
48 | 130 | { my ($self, $args) = @_; |
79 | 161 | # $self; |
80 | 162 | #} |
81 | 163 | |
164 | =section Accessors | |
165 | ||
166 | =method logger [$domain] | |
167 | Returns the M<Log::Log4perl::Logger> object which is used for logging. | |
168 | When there is no specific logger for this $domain (logger with the exact | |
169 | name of the $domain) the default logger is being used, with the name of | |
170 | this dispatcher. | |
171 | =cut | |
82 | 172 | |
83 | 173 | sub logger(;$) |
84 | 174 | { my ($self, $domain) = @_; |
91 | 181 | ||= Log::Log4perl->get_logger($self->name); |
92 | 182 | } |
93 | 183 | |
184 | =section Logging | |
185 | =cut | |
94 | 186 | |
95 | 187 | sub log($$$$) |
96 | 188 | { my ($self, $opts, $reason, $msg, $domain) = @_; |
104 | 196 | $self; |
105 | 197 | } |
106 | 198 | |
199 | =method reasonToLevel $reason | |
200 | Returns a level which is understood by Log::Dispatch, based on | |
201 | a translation table. This can be changed with M<new(to_level)>. | |
202 | ||
203 | =example | |
204 | ||
205 | use Log::Log4perl qw/:levels/; | |
206 | ||
207 | # by default, ALERTs are output as $FATAL | |
208 | dispatcher Log::Log4perl => 'logger' | |
209 | , to_level => [ ALERT => $ERROR, ] | |
210 | , ...; | |
211 | ||
212 | =cut | |
107 | 213 | |
108 | 214 | sub reasonToLevel($) { $_[0]->{LRDL_levels}{$_[1]} } |
109 | 215 |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Dispatcher::Log4perl - send messages to Log::Log4perl back-end | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Dispatcher::Log4perl | |
9 | is a Log::Report::Dispatcher | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | # start using log4perl via a config file | |
14 | # The name of the dispatcher is the name of the default category. | |
15 | dispatcher LOG4PERL => 'logger' | |
16 | , accept => 'NOTICE-' | |
17 | , config => "$ENV{HOME}/.log.conf"; | |
18 | ||
19 | # disable default dispatcher | |
20 | dispatcher close => 'logger'; | |
21 | ||
22 | # configuration inline, not in file: adapted from the Log4perl manpage | |
23 | my $name = 'logger'; | |
24 | my $outfile = '/tmp/a.log'; | |
25 | my $config = <<__CONFIG; | |
26 | log4perl.category.$name = INFO, Logfile | |
27 | log4perl.logger.Logfile = Log::Log4perl::Appender::File | |
28 | log4perl.logger.Logfile.filename = $outfn | |
29 | log4perl.logger.Logfile.layout = Log::Log4perl::Layout::PatternLayout | |
30 | log4perl.logger.Logfile.layout.ConversionPattern = %d %F{1} %L> %m | |
31 | __CONFIG | |
32 | ||
33 | dispatcher LOG4PERL => $name, config => \$config; | |
34 | ||
35 | =head1 DESCRIPTION | |
36 | ||
37 | This dispatchers produces output tot syslog, based on the C<Sys::Log4perl> | |
38 | module (which will not be automatically installed for you). | |
39 | ||
40 | Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">. | |
41 | ||
42 | =head2 Reasons <--> Levels | |
43 | ||
44 | The REASONs for a message in L<Log::Report|Log::Report> are names quite similar to | |
45 | the log levels used by Log::Log4perl. The default mapping is list | |
46 | below. You can change the mapping using L<new(to_level)|Log::Report::Dispatcher::Log4perl/"Constructors">. | |
47 | ||
48 | TRACE => $DEBUG ERROR => $ERROR | |
49 | ASSERT => $DEBUG FAULT => $ERROR | |
50 | INFO => $INFO ALERT => $FATAL | |
51 | NOTICE => $INFO FAILURE => $FATAL | |
52 | WARNING => $WARN PANIC => $FATAL | |
53 | MISTAKE => $WARN | |
54 | ||
55 | =head2 Categories | |
56 | ||
57 | C<Log::Report> uses text-domains for translation tables. These are | |
58 | also used as categories for the Log4perl infrastructure. So, typically | |
59 | every module start with: | |
60 | ||
61 | use Log::Report 'my-text-domain', %more_options; | |
62 | ||
63 | Now, if there is a logger inside the log4perl configuration which is | |
64 | named 'my-text-domain', that will be used. Otherwise, the name of the | |
65 | dispatcher is used to select the logger. | |
66 | ||
67 | =head3 Limitiations | |
68 | ||
69 | The global C<$caller_depth> concept of Log::Log4perl is broken. | |
70 | That variable is used to find the filename and line number of the logged | |
71 | messages. But these messages may have been caught, rerouted, eval'ed, and | |
72 | otherwise followed a unpredictable multi-leveled path before it reached | |
73 | the Log::Log4perl dispatcher. This means that layout patterns C<%F> | |
74 | and C<%L> are not useful in the generic case, maybe in your specific case. | |
75 | ||
76 | =head1 METHODS | |
77 | ||
78 | Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">. | |
79 | ||
80 | =head2 Constructors | |
81 | ||
82 | Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">. | |
83 | ||
84 | =over 4 | |
85 | ||
86 | =item $obj-E<gt>B<close>() | |
87 | ||
88 | Inherited, see L<Log::Report::Dispatcher/"Constructors"> | |
89 | ||
90 | =item Log::Report::Dispatcher::Log4perl-E<gt>B<new>($type, $name, %options) | |
91 | ||
92 | The Log::Log4perl infrastructure has all settings in a configuration | |
93 | file. In that file, you should find a category with the $name. | |
94 | ||
95 | -Option --Defined in --Default | |
96 | accept Log::Report::Dispatcher 'ALL' | |
97 | charset Log::Report::Dispatcher <undef> | |
98 | config <undef> | |
99 | format_reason Log::Report::Dispatcher 'LOWERCASE' | |
100 | locale Log::Report::Dispatcher <system locale> | |
101 | mode Log::Report::Dispatcher 'NORMAL' | |
102 | to_level [] | |
103 | ||
104 | =over 2 | |
105 | ||
106 | =item accept => REASONS | |
107 | ||
108 | =item charset => CHARSET | |
109 | ||
110 | =item config => FILENAME|SCALAR | |
111 | ||
112 | When a SCALAR reference is passed in, that must refer to a string which | |
113 | contains the configuration text. Otherwise, specify an existing FILENAME. | |
114 | ||
115 | By default, it is expected that Log::Log4perl has been initialized | |
116 | externally. That module uses global variables to communicate, which | |
117 | should be present before any logging is attempted. | |
118 | ||
119 | =item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE | |
120 | ||
121 | =item locale => LOCALE | |
122 | ||
123 | =item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3 | |
124 | ||
125 | =item to_level => ARRAY-of-PAIRS | |
126 | ||
127 | See L<reasonToLevel()|Log::Report::Dispatcher::Log4perl/"Logging">. | |
128 | ||
129 | =back | |
130 | ||
131 | =back | |
132 | ||
133 | =head2 Accessors | |
134 | ||
135 | Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">. | |
136 | ||
137 | =over 4 | |
138 | ||
139 | =item $obj-E<gt>B<isDisabled>() | |
140 | ||
141 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
142 | ||
143 | =item $obj-E<gt>B<logger>( [$domain] ) | |
144 | ||
145 | Returns the Log::Log4perl::Logger object which is used for logging. | |
146 | When there is no specific logger for this $domain (logger with the exact | |
147 | name of the $domain) the default logger is being used, with the name of | |
148 | this dispatcher. | |
149 | ||
150 | =item $obj-E<gt>B<mode>() | |
151 | ||
152 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
153 | ||
154 | =item $obj-E<gt>B<name>() | |
155 | ||
156 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
157 | ||
158 | =item $obj-E<gt>B<needs>( [$reason] ) | |
159 | ||
160 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
161 | ||
162 | =item $obj-E<gt>B<type>() | |
163 | ||
164 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
165 | ||
166 | =back | |
167 | ||
168 | =head2 Logging | |
169 | ||
170 | Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">. | |
171 | ||
172 | =over 4 | |
173 | ||
174 | =item $obj-E<gt>B<addSkipStack>(@CODE) | |
175 | ||
176 | =item Log::Report::Dispatcher::Log4perl-E<gt>B<addSkipStack>(@CODE) | |
177 | ||
178 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
179 | ||
180 | =item $obj-E<gt>B<collectLocation>() | |
181 | ||
182 | =item Log::Report::Dispatcher::Log4perl-E<gt>B<collectLocation>() | |
183 | ||
184 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
185 | ||
186 | =item $obj-E<gt>B<collectStack>( [$maxdepth] ) | |
187 | ||
188 | =item Log::Report::Dispatcher::Log4perl-E<gt>B<collectStack>( [$maxdepth] ) | |
189 | ||
190 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
191 | ||
192 | =item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain) | |
193 | ||
194 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
195 | ||
196 | =item $obj-E<gt>B<reasonToLevel>($reason) | |
197 | ||
198 | Returns a level which is understood by Log::Dispatch, based on | |
199 | a translation table. This can be changed with L<new(to_level)|Log::Report::Dispatcher::Log4perl/"Constructors">. | |
200 | ||
201 | example: | |
202 | ||
203 | use Log::Log4perl qw/:levels/; | |
204 | ||
205 | # by default, ALERTs are output as $FATAL | |
206 | dispatcher Log::Log4perl => 'logger' | |
207 | , to_level => [ ALERT => $ERROR, ] | |
208 | , ...; | |
209 | ||
210 | =item $obj-E<gt>B<skipStack>() | |
211 | ||
212 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
213 | ||
214 | =item $obj-E<gt>B<stackTraceLine>(%options) | |
215 | ||
216 | =item Log::Report::Dispatcher::Log4perl-E<gt>B<stackTraceLine>(%options) | |
217 | ||
218 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
219 | ||
220 | =item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message) | |
221 | ||
222 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
223 | ||
224 | =back | |
225 | ||
226 | =head1 DETAILS | |
227 | ||
228 | Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">. | |
229 | ||
230 | =head1 SEE ALSO | |
231 | ||
232 | This module is part of Log-Report distribution version 1.32, | |
233 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
234 | ||
235 | =head1 LICENSE | |
236 | ||
237 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
238 | ||
239 | This program is free software; you can redistribute it and/or modify it | |
240 | under the same terms as Perl itself. | |
241 | See F<http://dev.perl.org/licenses/> | |
242 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Dispatcher::LogDispatch; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Log::Report::Dispatcher'; |
13 | 6 | |
14 | 7 | use warnings; |
36 | 29 | @reasons != keys %default_reasonToLevel |
37 | 30 | and panic __"Not all reasons have a default translation"; |
38 | 31 | |
32 | =chapter NAME | |
33 | Log::Report::Dispatcher::LogDispatch - send messages to Log::Dispatch back-end | |
34 | ||
35 | =chapter SYNOPSIS | |
36 | use Log::Dispatch::File; | |
37 | dispatcher Log::Dispatch::File => 'logger', accept => 'NOTICE-' | |
38 | , filename => 'logfile', to_level => [ 'ALERT-' => 'err' ]; | |
39 | ||
40 | # disable default dispatcher | |
41 | dispatcher close => 'logger'; | |
42 | ||
43 | =chapter DESCRIPTION | |
44 | This dispatchers produces output to and C<Log::Dispatch> back-end. | |
45 | (which will NOT be automatically installed for you). | |
46 | ||
47 | The REASON for a message often uses names which are quite similar to the | |
48 | log-levels used by M<Log::Dispatch>. However: they have a different | |
49 | approach. The REASON of Log::Report limits the responsibility of the | |
50 | programmer to indicate the cause of the message: whether it was able to | |
51 | handle a certain situation. The Log::Dispatch levels are there for the | |
52 | user's of the program. However: the programmer does not known anything | |
53 | about the application (in the general case). This is cause of much of | |
54 | the trickery in Perl programs. | |
55 | ||
56 | The default translation table is list below. You can change the mapping | |
57 | using M<new(to_level)>. See example in SYNOPSIS. | |
58 | ||
59 | =chapter METHODS | |
60 | ||
61 | =section Constructors | |
62 | ||
63 | =c_method new $type, $name, %options | |
64 | The Log::Dispatch infrastructure has quite a large number of output | |
65 | TYPEs, each extending the M<Log::Dispatch::Output> base-class. You | |
66 | do not create these objects yourself: Log::Report is doing it for you. | |
67 | ||
68 | The Log::Dispatch back-ends are very careful with validating their | |
69 | parameters, so you will need to restrict the options to what is supported | |
70 | for the specific back-end. See their respective manual-pages. The errors | |
71 | produced by the back-ends quite horrible and untranslated, sorry. | |
72 | ||
73 | =option to_level ARRAY-of-PAIRS | |
74 | =default to_level [] | |
75 | See M<reasonToLevel()>. | |
76 | ||
77 | =option min_level LEVEL | |
78 | =default min_level C<debug> | |
79 | Restrict the messages which are passed through based on the LEVEL, | |
80 | so after the reason got translated into a Log::Dispatch compatible | |
81 | LEVEL. The default will use Log::Report restrictions only. | |
82 | ||
83 | =option max_level LEVEL | |
84 | =default max_level C<undef> | |
85 | Like C<min_level>. | |
86 | ||
87 | =option callbacks CODE|ARRAY-of-CODE | |
88 | =default callbacks [] | |
89 | See M<Log::Dispatch::Output>. | |
90 | ||
91 | =cut | |
39 | 92 | |
40 | 93 | sub init($) |
41 | 94 | { my ($self, $args) = @_; |
70 | 123 | $self; |
71 | 124 | } |
72 | 125 | |
126 | =section Accessors | |
127 | ||
128 | =method backend | |
129 | Returns the M<Log::Dispatch::Output> object which is used for logging. | |
130 | =cut | |
73 | 131 | |
74 | 132 | sub backend() {shift->{backend}} |
75 | 133 | |
134 | =section Logging | |
135 | =cut | |
76 | 136 | |
77 | 137 | sub log($$$$$) |
78 | 138 | { my $self = shift; |
83 | 143 | $self; |
84 | 144 | } |
85 | 145 | |
146 | =method reasonToLevel $reason | |
147 | Returns a level which is understood by Log::Dispatch, based on | |
148 | a translation table. This can be changed with M<new(to_level)>. | |
149 | =cut | |
86 | 150 | |
87 | 151 | sub reasonToLevel($) { $_[0]->{level}{$_[1]} } |
88 | 152 |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Dispatcher::LogDispatch - send messages to Log::Dispatch back-end | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Dispatcher::LogDispatch | |
9 | is a Log::Report::Dispatcher | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | use Log::Dispatch::File; | |
14 | dispatcher Log::Dispatch::File => 'logger', accept => 'NOTICE-' | |
15 | , filename => 'logfile', to_level => [ 'ALERT-' => 'err' ]; | |
16 | ||
17 | # disable default dispatcher | |
18 | dispatcher close => 'logger'; | |
19 | ||
20 | =head1 DESCRIPTION | |
21 | ||
22 | This dispatchers produces output to and C<Log::Dispatch> back-end. | |
23 | (which will NOT be automatically installed for you). | |
24 | ||
25 | The REASON for a message often uses names which are quite similar to the | |
26 | log-levels used by Log::Dispatch. However: they have a different | |
27 | approach. The REASON of Log::Report limits the responsibility of the | |
28 | programmer to indicate the cause of the message: whether it was able to | |
29 | handle a certain situation. The Log::Dispatch levels are there for the | |
30 | user's of the program. However: the programmer does not known anything | |
31 | about the application (in the general case). This is cause of much of | |
32 | the trickery in Perl programs. | |
33 | ||
34 | The default translation table is list below. You can change the mapping | |
35 | using L<new(to_level)|Log::Report::Dispatcher::LogDispatch/"Constructors">. See example in SYNOPSIS. | |
36 | ||
37 | Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">. | |
38 | ||
39 | =head1 METHODS | |
40 | ||
41 | Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">. | |
42 | ||
43 | =head2 Constructors | |
44 | ||
45 | Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">. | |
46 | ||
47 | =over 4 | |
48 | ||
49 | =item $obj-E<gt>B<close>() | |
50 | ||
51 | Inherited, see L<Log::Report::Dispatcher/"Constructors"> | |
52 | ||
53 | =item Log::Report::Dispatcher::LogDispatch-E<gt>B<new>($type, $name, %options) | |
54 | ||
55 | The Log::Dispatch infrastructure has quite a large number of output | |
56 | TYPEs, each extending the Log::Dispatch::Output base-class. You | |
57 | do not create these objects yourself: Log::Report is doing it for you. | |
58 | ||
59 | The Log::Dispatch back-ends are very careful with validating their | |
60 | parameters, so you will need to restrict the options to what is supported | |
61 | for the specific back-end. See their respective manual-pages. The errors | |
62 | produced by the back-ends quite horrible and untranslated, sorry. | |
63 | ||
64 | -Option --Defined in --Default | |
65 | accept Log::Report::Dispatcher depend on mode | |
66 | callbacks [] | |
67 | charset Log::Report::Dispatcher <undef> | |
68 | format_reason Log::Report::Dispatcher 'LOWERCASE' | |
69 | locale Log::Report::Dispatcher <system locale> | |
70 | max_level undef | |
71 | min_level debug | |
72 | mode Log::Report::Dispatcher 'NORMAL' | |
73 | to_level [] | |
74 | ||
75 | =over 2 | |
76 | ||
77 | =item accept => REASONS | |
78 | ||
79 | =item callbacks => CODE|ARRAY-of-CODE | |
80 | ||
81 | See Log::Dispatch::Output. | |
82 | ||
83 | =item charset => CHARSET | |
84 | ||
85 | =item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE | |
86 | ||
87 | =item locale => LOCALE | |
88 | ||
89 | =item max_level => LEVEL | |
90 | ||
91 | Like C<min_level>. | |
92 | ||
93 | =item min_level => LEVEL | |
94 | ||
95 | Restrict the messages which are passed through based on the LEVEL, | |
96 | so after the reason got translated into a Log::Dispatch compatible | |
97 | LEVEL. The default will use Log::Report restrictions only. | |
98 | ||
99 | =item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3 | |
100 | ||
101 | =item to_level => ARRAY-of-PAIRS | |
102 | ||
103 | See L<reasonToLevel()|Log::Report::Dispatcher::LogDispatch/"Logging">. | |
104 | ||
105 | =back | |
106 | ||
107 | =back | |
108 | ||
109 | =head2 Accessors | |
110 | ||
111 | Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">. | |
112 | ||
113 | =over 4 | |
114 | ||
115 | =item $obj-E<gt>B<backend>() | |
116 | ||
117 | Returns the Log::Dispatch::Output object which is used for logging. | |
118 | ||
119 | =item $obj-E<gt>B<isDisabled>() | |
120 | ||
121 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
122 | ||
123 | =item $obj-E<gt>B<mode>() | |
124 | ||
125 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
126 | ||
127 | =item $obj-E<gt>B<name>() | |
128 | ||
129 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
130 | ||
131 | =item $obj-E<gt>B<needs>( [$reason] ) | |
132 | ||
133 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
134 | ||
135 | =item $obj-E<gt>B<type>() | |
136 | ||
137 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
138 | ||
139 | =back | |
140 | ||
141 | =head2 Logging | |
142 | ||
143 | Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">. | |
144 | ||
145 | =over 4 | |
146 | ||
147 | =item $obj-E<gt>B<addSkipStack>(@CODE) | |
148 | ||
149 | =item Log::Report::Dispatcher::LogDispatch-E<gt>B<addSkipStack>(@CODE) | |
150 | ||
151 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
152 | ||
153 | =item $obj-E<gt>B<collectLocation>() | |
154 | ||
155 | =item Log::Report::Dispatcher::LogDispatch-E<gt>B<collectLocation>() | |
156 | ||
157 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
158 | ||
159 | =item $obj-E<gt>B<collectStack>( [$maxdepth] ) | |
160 | ||
161 | =item Log::Report::Dispatcher::LogDispatch-E<gt>B<collectStack>( [$maxdepth] ) | |
162 | ||
163 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
164 | ||
165 | =item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain) | |
166 | ||
167 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
168 | ||
169 | =item $obj-E<gt>B<reasonToLevel>($reason) | |
170 | ||
171 | Returns a level which is understood by Log::Dispatch, based on | |
172 | a translation table. This can be changed with L<new(to_level)|Log::Report::Dispatcher::LogDispatch/"Constructors">. | |
173 | ||
174 | =item $obj-E<gt>B<skipStack>() | |
175 | ||
176 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
177 | ||
178 | =item $obj-E<gt>B<stackTraceLine>(%options) | |
179 | ||
180 | =item Log::Report::Dispatcher::LogDispatch-E<gt>B<stackTraceLine>(%options) | |
181 | ||
182 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
183 | ||
184 | =item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message) | |
185 | ||
186 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
187 | ||
188 | =back | |
189 | ||
190 | =head1 DETAILS | |
191 | ||
192 | Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">. | |
193 | ||
194 | =head1 SEE ALSO | |
195 | ||
196 | This module is part of Log-Report distribution version 1.32, | |
197 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
198 | ||
199 | =head1 LICENSE | |
200 | ||
201 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
202 | ||
203 | This program is free software; you can redistribute it and/or modify it | |
204 | under the same terms as Perl itself. | |
205 | See F<http://dev.perl.org/licenses/> | |
206 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Dispatcher::Perl; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Log::Report::Dispatcher'; |
13 | 6 | |
14 | 7 | use warnings; |
19 | 12 | |
20 | 13 | my $singleton = 0; # can be only one (per thread) |
21 | 14 | |
15 | =chapter NAME | |
16 | Log::Report::Dispatcher::Perl - send messages to die and warn | |
17 | ||
18 | =chapter SYNOPSIS | |
19 | dispatcher Log::Report::Dispatcher::Perl => 'default' | |
20 | , accept => 'NOTICE-'; | |
21 | ||
22 | # close the default dispatcher | |
23 | dispatcher close => 'default'; | |
24 | ||
25 | =chapter DESCRIPTION | |
26 | Ventilate the problem reports via the standard Perl error mechanisms: | |
27 | C<die()>, C<warn()>, and C<print()>. There can be only one such dispatcher | |
28 | (per thread), because once C<die()> is called, we are not able to return. | |
29 | Therefore, this dispatcher will always be called last. | |
30 | ||
31 | In the early releases of Log::Report, it tried to simulate the behavior | |
32 | of warn and die using STDERR and exit; however: that is not possible. | |
33 | ||
34 | =chapter METHODS | |
35 | ||
36 | =section Constructors | |
37 | ||
38 | =section Accessors | |
39 | ||
40 | =section Logging | |
41 | =cut | |
22 | 42 | |
23 | 43 | sub log($$$$) |
24 | 44 | { my ($self, $opts, $reason, $message, $domain) = @_; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Dispatcher::Perl - send messages to die and warn | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Dispatcher::Perl | |
9 | is a Log::Report::Dispatcher | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | dispatcher Log::Report::Dispatcher::Perl => 'default' | |
14 | , accept => 'NOTICE-'; | |
15 | ||
16 | # close the default dispatcher | |
17 | dispatcher close => 'default'; | |
18 | ||
19 | =head1 DESCRIPTION | |
20 | ||
21 | Ventilate the problem reports via the standard Perl error mechanisms: | |
22 | C<die()>, C<warn()>, and C<print()>. There can be only one such dispatcher | |
23 | (per thread), because once C<die()> is called, we are not able to return. | |
24 | Therefore, this dispatcher will always be called last. | |
25 | ||
26 | In the early releases of Log::Report, it tried to simulate the behavior | |
27 | of warn and die using STDERR and exit; however: that is not possible. | |
28 | ||
29 | Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">. | |
30 | ||
31 | =head1 METHODS | |
32 | ||
33 | Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">. | |
34 | ||
35 | =head1 DETAILS | |
36 | ||
37 | Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">. | |
38 | ||
39 | =head1 SEE ALSO | |
40 | ||
41 | This module is part of Log-Report distribution version 1.32, | |
42 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
43 | ||
44 | =head1 LICENSE | |
45 | ||
46 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
47 | ||
48 | This program is free software; you can redistribute it and/or modify it | |
49 | under the same terms as Perl itself. | |
50 | See F<http://dev.perl.org/licenses/> | |
51 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Dispatcher::Syslog; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Log::Report::Dispatcher'; |
13 | 6 | |
14 | 7 | use warnings; |
39 | 32 | @reasons==keys %default_reasonToPrio |
40 | 33 | or panic __"not all reasons have a default translation"; |
41 | 34 | |
35 | =chapter NAME | |
36 | Log::Report::Dispatcher::Syslog - send messages to syslog | |
37 | ||
38 | =chapter SYNOPSIS | |
39 | # add syslog dispatcher | |
40 | dispatcher SYSLOG => 'syslog', accept => 'NOTICE-' | |
41 | , format_reason => 'IGNORE' | |
42 | , to_prio => [ 'ALERT-' => 'err' ]; | |
43 | ||
44 | # disable default dispatcher, when daemon | |
45 | dispatcher close => 'default'; | |
46 | ||
47 | =chapter DESCRIPTION | |
48 | This dispatchers produces output to syslog, based on the M<Sys::Syslog> | |
49 | module (which will NOT be automatically installed for you, because some | |
50 | systems have a problem with this dependency). | |
51 | ||
52 | The REASON for a message often uses names which are quite similar to | |
53 | the log-levels used by syslog. However: they have a different purpose. | |
54 | The REASON is used by the programmer to indicate the cause of the message: | |
55 | whether it was able to handle a certain situation. The syslog levels | |
56 | are there for the user's of the program (with syslog usually the | |
57 | system administrators). It is not unusual to see a "normal" error | |
58 | or mistake as a very serious situation in a production environment. So, | |
59 | you may wish to translate any message above reason MISTAKE into a LOG_CRIT. | |
60 | ||
61 | The default translation table is list below. You can change the mapping | |
62 | using M<new(to_prio)>. See example in SYNOPSIS. | |
63 | ||
64 | TRACE => LOG_DEBUG ERROR => LOG_ERR | |
65 | ASSERT => LOG_DEBUG FAULT => LOG_ERR | |
66 | INFO => LOG_INFO ALERT => LOG_ALERT | |
67 | NOTICE => LOG_NOTICE FAILURE => LOG_EMERG | |
68 | WARNING => LOG_WARNING PANIC => LOG_CRIT | |
69 | MISTAKE => LOG_WARNING | |
70 | ||
71 | =chapter METHODS | |
72 | ||
73 | =section Constructors | |
74 | ||
75 | =c_method new $type, $name, %options | |
76 | With syslog, people tend not to include the REASON of the message | |
77 | in the logs, because that is already used to determine the destination | |
78 | of the message. | |
79 | ||
80 | =default format_reason 'IGNORE' | |
81 | ||
82 | =option identity STRING | |
83 | =default identity <basename $0> | |
84 | ||
85 | =option flags STRING | |
86 | =default flags 'pid,nowait' | |
87 | Any combination of flags as defined by M<Sys::Syslog>, for instance | |
88 | C<pid>, C<ndelay>, and C<nowait>. | |
89 | ||
90 | =option facility STRING | |
91 | =default facility 'user' | |
92 | The possible values for this depend (a little) on the system. POSIX | |
93 | only defines C<user>, and C<local0> up to C<local7>. | |
94 | ||
95 | =option to_prio ARRAY-of-PAIRS | |
96 | =default to_prio [] | |
97 | See M<reasonToPrio()>. | |
98 | ||
99 | =option logsocket 'unix'|'inet'|'stream'|HASH | |
100 | =default logsocket C<undef> | |
101 | If specified, the log socket type will be initialized to this before | |
102 | C<openlog()> is called. If not specified, the system default is used. | |
103 | ||
104 | =option include_domain BOOLEAN | |
105 | =default include_domain <false> | |
106 | [1.00] Include the text-domain of the message in each logged message. | |
107 | ||
108 | =option charset CHARSET | |
109 | =default charset 'utf8' | |
110 | Translate the text-strings into the specified charset, otherwise the | |
111 | sysadmin may get unreadable text. | |
112 | ||
113 | =option format CODE | |
114 | =default format <unchanged> | |
115 | [1.10] With a CODE reference you get your hands on the text before | |
116 | it gets sent to syslog. The three parameters are: the (translated) text, | |
117 | the related text domain object, and the message object. You may want to | |
118 | use context information from the latter. | |
119 | ||
120 | [1.19] After the three positional parameters, there may be a list of | |
121 | pairs (named parameters) with additional info. This may contain a | |
122 | C<location> with an ARRAY of information produced by caller() about the | |
123 | origin of the exception. | |
124 | =cut | |
42 | 125 | |
43 | 126 | my $active; |
44 | 127 | |
92 | 175 | } |
93 | 176 | |
94 | 177 | #-------------- |
178 | =section Accessors | |
179 | ||
180 | =method format [CODE] | |
181 | Returns the CODE ref which formats the syslog line. | |
182 | =cut | |
95 | 183 | |
96 | 184 | sub format(;$) |
97 | 185 | { my $self = shift; |
99 | 187 | } |
100 | 188 | |
101 | 189 | #-------------- |
190 | =section Logging | |
191 | =cut | |
102 | 192 | |
103 | 193 | sub log($$$$$) |
104 | 194 | { my ($self, $opts, $reason, $msg, $domain) = @_; |
121 | 211 | for @text; |
122 | 212 | } |
123 | 213 | |
214 | =method reasonToPrio $reason | |
215 | Returns a level which is understood by syslog(3), based on a translation | |
216 | table. This can be changed with M<new(to_prio)>. | |
217 | =cut | |
124 | 218 | |
125 | 219 | sub reasonToPrio($) { $_[0]->{prio}{$_[1]} } |
126 | 220 |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Dispatcher::Syslog - send messages to syslog | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Dispatcher::Syslog | |
9 | is a Log::Report::Dispatcher | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | # add syslog dispatcher | |
14 | dispatcher SYSLOG => 'syslog', accept => 'NOTICE-' | |
15 | , format_reason => 'IGNORE' | |
16 | , to_prio => [ 'ALERT-' => 'err' ]; | |
17 | ||
18 | # disable default dispatcher, when daemon | |
19 | dispatcher close => 'default'; | |
20 | ||
21 | =head1 DESCRIPTION | |
22 | ||
23 | This dispatchers produces output to syslog, based on the Sys::Syslog | |
24 | module (which will NOT be automatically installed for you, because some | |
25 | systems have a problem with this dependency). | |
26 | ||
27 | The REASON for a message often uses names which are quite similar to | |
28 | the log-levels used by syslog. However: they have a different purpose. | |
29 | The REASON is used by the programmer to indicate the cause of the message: | |
30 | whether it was able to handle a certain situation. The syslog levels | |
31 | are there for the user's of the program (with syslog usually the | |
32 | system administrators). It is not unusual to see a "normal" error | |
33 | or mistake as a very serious situation in a production environment. So, | |
34 | you may wish to translate any message above reason MISTAKE into a LOG_CRIT. | |
35 | ||
36 | The default translation table is list below. You can change the mapping | |
37 | using L<new(to_prio)|Log::Report::Dispatcher::Syslog/"Constructors">. See example in SYNOPSIS. | |
38 | ||
39 | TRACE => LOG_DEBUG ERROR => LOG_ERR | |
40 | ASSERT => LOG_DEBUG FAULT => LOG_ERR | |
41 | INFO => LOG_INFO ALERT => LOG_ALERT | |
42 | NOTICE => LOG_NOTICE FAILURE => LOG_EMERG | |
43 | WARNING => LOG_WARNING PANIC => LOG_CRIT | |
44 | MISTAKE => LOG_WARNING | |
45 | ||
46 | Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">. | |
47 | ||
48 | =head1 METHODS | |
49 | ||
50 | Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">. | |
51 | ||
52 | =head2 Constructors | |
53 | ||
54 | Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">. | |
55 | ||
56 | =over 4 | |
57 | ||
58 | =item $obj-E<gt>B<close>() | |
59 | ||
60 | Inherited, see L<Log::Report::Dispatcher/"Constructors"> | |
61 | ||
62 | =item Log::Report::Dispatcher::Syslog-E<gt>B<new>($type, $name, %options) | |
63 | ||
64 | With syslog, people tend not to include the REASON of the message | |
65 | in the logs, because that is already used to determine the destination | |
66 | of the message. | |
67 | ||
68 | -Option --Defined in --Default | |
69 | accept Log::Report::Dispatcher depend on mode | |
70 | charset 'utf8' | |
71 | facility 'user' | |
72 | flags 'pid,nowait' | |
73 | format <unchanged> | |
74 | format_reason Log::Report::Dispatcher 'IGNORE' | |
75 | identity <basename $0> | |
76 | include_domain <false> | |
77 | locale Log::Report::Dispatcher <system locale> | |
78 | logsocket undef | |
79 | mode Log::Report::Dispatcher 'NORMAL' | |
80 | to_prio [] | |
81 | ||
82 | =over 2 | |
83 | ||
84 | =item accept => REASONS | |
85 | ||
86 | =item charset => CHARSET | |
87 | ||
88 | Translate the text-strings into the specified charset, otherwise the | |
89 | sysadmin may get unreadable text. | |
90 | ||
91 | =item facility => STRING | |
92 | ||
93 | The possible values for this depend (a little) on the system. POSIX | |
94 | only defines C<user>, and C<local0> up to C<local7>. | |
95 | ||
96 | =item flags => STRING | |
97 | ||
98 | Any combination of flags as defined by Sys::Syslog, for instance | |
99 | C<pid>, C<ndelay>, and C<nowait>. | |
100 | ||
101 | =item format => CODE | |
102 | ||
103 | [1.10] With a CODE reference you get your hands on the text before | |
104 | it gets sent to syslog. The three parameters are: the (translated) text, | |
105 | the related text domain object, and the message object. You may want to | |
106 | use context information from the latter. | |
107 | ||
108 | [1.19] After the three positional parameters, there may be a list of | |
109 | pairs (named parameters) with additional info. This may contain a | |
110 | C<location> with an ARRAY of information produced by caller() about the | |
111 | origin of the exception. | |
112 | ||
113 | =item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE | |
114 | ||
115 | =item identity => STRING | |
116 | ||
117 | =item include_domain => BOOLEAN | |
118 | ||
119 | [1.00] Include the text-domain of the message in each logged message. | |
120 | ||
121 | =item locale => LOCALE | |
122 | ||
123 | =item logsocket => 'unix'|'inet'|'stream'|HASH | |
124 | ||
125 | If specified, the log socket type will be initialized to this before | |
126 | C<openlog()> is called. If not specified, the system default is used. | |
127 | ||
128 | =item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3 | |
129 | ||
130 | =item to_prio => ARRAY-of-PAIRS | |
131 | ||
132 | See L<reasonToPrio()|Log::Report::Dispatcher::Syslog/"Logging">. | |
133 | ||
134 | =back | |
135 | ||
136 | =back | |
137 | ||
138 | =head2 Accessors | |
139 | ||
140 | Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">. | |
141 | ||
142 | =over 4 | |
143 | ||
144 | =item $obj-E<gt>B<format>( [CODE] ) | |
145 | ||
146 | Returns the CODE ref which formats the syslog line. | |
147 | ||
148 | =item $obj-E<gt>B<isDisabled>() | |
149 | ||
150 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
151 | ||
152 | =item $obj-E<gt>B<mode>() | |
153 | ||
154 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
155 | ||
156 | =item $obj-E<gt>B<name>() | |
157 | ||
158 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
159 | ||
160 | =item $obj-E<gt>B<needs>( [$reason] ) | |
161 | ||
162 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
163 | ||
164 | =item $obj-E<gt>B<type>() | |
165 | ||
166 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
167 | ||
168 | =back | |
169 | ||
170 | =head2 Logging | |
171 | ||
172 | Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">. | |
173 | ||
174 | =over 4 | |
175 | ||
176 | =item $obj-E<gt>B<addSkipStack>(@CODE) | |
177 | ||
178 | =item Log::Report::Dispatcher::Syslog-E<gt>B<addSkipStack>(@CODE) | |
179 | ||
180 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
181 | ||
182 | =item $obj-E<gt>B<collectLocation>() | |
183 | ||
184 | =item Log::Report::Dispatcher::Syslog-E<gt>B<collectLocation>() | |
185 | ||
186 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
187 | ||
188 | =item $obj-E<gt>B<collectStack>( [$maxdepth] ) | |
189 | ||
190 | =item Log::Report::Dispatcher::Syslog-E<gt>B<collectStack>( [$maxdepth] ) | |
191 | ||
192 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
193 | ||
194 | =item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain) | |
195 | ||
196 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
197 | ||
198 | =item $obj-E<gt>B<reasonToPrio>($reason) | |
199 | ||
200 | Returns a level which is understood by syslog(3), based on a translation | |
201 | table. This can be changed with L<new(to_prio)|Log::Report::Dispatcher::Syslog/"Constructors">. | |
202 | ||
203 | =item $obj-E<gt>B<skipStack>() | |
204 | ||
205 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
206 | ||
207 | =item $obj-E<gt>B<stackTraceLine>(%options) | |
208 | ||
209 | =item Log::Report::Dispatcher::Syslog-E<gt>B<stackTraceLine>(%options) | |
210 | ||
211 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
212 | ||
213 | =item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message) | |
214 | ||
215 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
216 | ||
217 | =back | |
218 | ||
219 | =head1 DETAILS | |
220 | ||
221 | Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">. | |
222 | ||
223 | =head1 SEE ALSO | |
224 | ||
225 | This module is part of Log-Report distribution version 1.32, | |
226 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
227 | ||
228 | =head1 LICENSE | |
229 | ||
230 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
231 | ||
232 | This program is free software; you can redistribute it and/or modify it | |
233 | under the same terms as Perl itself. | |
234 | See F<http://dev.perl.org/licenses/> | |
235 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Dispatcher::Try; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Log::Report::Dispatcher'; |
13 | 6 | |
14 | 7 | use warnings; |
19 | 12 | use Log::Report::Util qw/%reason_code expand_reasons/; |
20 | 13 | use List::Util qw/first/; |
21 | 14 | |
15 | =chapter NAME | |
16 | Log::Report::Dispatcher::Try - capture all reports as exceptions | |
17 | ||
18 | =chapter SYNOPSIS | |
19 | try { ... }; # mind the ';' !! | |
20 | if($@) { # signals something went wrong | |
21 | ||
22 | if(try {...}) { # block ended normally | |
23 | ||
24 | my $x = try { read_temperature() }; | |
25 | my @x = try { read_lines_from_file() }; | |
26 | ||
27 | try { ... } # no comma!! | |
28 | mode => 'DEBUG', accept => 'ERROR-'; | |
29 | ||
30 | try sub { ... }, # with comma | |
31 | mode => 'DEBUG', accept => 'ALL'; | |
32 | ||
33 | try \&myhandler, accept => 'ERROR-'; | |
34 | try { ... } hide => 'TRACE'; | |
35 | ||
36 | print ref $@; # Log::Report::Dispatcher::Try | |
37 | ||
38 | $@->reportFatal; # re-dispatch result of try block | |
39 | $@->reportAll; # ... also warnings etc | |
40 | if($@) {...} # if errors | |
41 | if($@->failed) { # same # } | |
42 | if($@->success) { # no errors # } | |
43 | ||
44 | try { # something causes an error report, which is caught | |
45 | failure 'no network'; | |
46 | }; | |
47 | $@->reportFatal(to => 'syslog'); # overrule destination | |
48 | ||
49 | print $@->exceptions; # no re-cast, just print | |
50 | ||
51 | =chapter DESCRIPTION | |
52 | The B<try> works like Perl's build-in C<eval()>, but implements | |
53 | real exception handling which Perl core lacks. | |
54 | ||
55 | The M<Log::Report::try()> function creates this C<::Try> dispatcher | |
56 | object with name 'try'. After the C<try()> is over, you can find | |
57 | the object in C<$@>. The C<$@> as C<::Try> object behaves exactly | |
58 | as the C<$@> produced by C<eval>, but has many added features. | |
59 | ||
60 | The C<try()> function catches fatal errors happening inside the BLOCK | |
61 | (CODE reference which is just following the function name) into the | |
62 | C<::Try> object C<$@>. The errors are not automatically progressed to | |
63 | active dispatchers. However, non-fatal exceptions (like info or notice) | |
64 | are also collected (unless not accepted, see M<new(accept)>, but also | |
65 | immediately passed to the active dispatchers (unless the reason is hidden, | |
66 | see M<new(hide)>) | |
67 | ||
68 | After the C<try()> has run, you can introspect the collected exceptions. | |
69 | Typically, you use M<wasFatal()> to get the exception which terminated | |
70 | the run of the BLOCK. | |
71 | ||
72 | =chapter OVERLOADING | |
73 | ||
74 | =overload boolean | |
75 | Returns true if the previous try block did produce a terminal | |
76 | error. This "try" object is assigned to C<$@>, and the usual | |
77 | perl syntax is C<if($@) {...error-handler...}>. | |
78 | ||
79 | =overload stringify | |
80 | When C<$@> is used the traditional way, it is checked to have | |
81 | a string content. In this case, stringify into the fatal error | |
82 | or nothing. | |
83 | =cut | |
22 | 84 | |
23 | 85 | use overload |
24 | 86 | bool => 'failed' |
26 | 88 | , fallback => 1; |
27 | 89 | |
28 | 90 | #----------------- |
91 | =chapter METHODS | |
92 | ||
93 | =section Constructors | |
94 | ||
95 | =c_method new $type, $name, %options | |
96 | =option exceptions ARRAY | |
97 | =default exceptions [] | |
98 | ARRAY of M<Log::Report::Exception> objects. | |
99 | ||
100 | =option died STRING | |
101 | =default died C<undef> | |
102 | The exit string or object ($@) of the eval'ed block, in its unprocessed state. | |
103 | ||
104 | =option hide REASONS|ARRAY|'ALL'|'NONE' | |
105 | =default hide 'NONE' | |
106 | [1.09] see M<hide()> | |
107 | ||
108 | =option on_die 'ERROR'|'PANIC' | |
109 | =default on_die 'ERROR' | |
110 | When code which runs in this block exits with a die(), it will get | |
111 | translated into a M<Log::Report::Exception> using | |
112 | M<Log::Report::Die::die_decode()>. How serious are we about these | |
113 | errors? | |
114 | ||
115 | =cut | |
29 | 116 | |
30 | 117 | sub init($) |
31 | 118 | { my ($self, $args) = @_; |
38 | 125 | } |
39 | 126 | |
40 | 127 | #----------------- |
128 | =section Accessors | |
129 | ||
130 | =method died [STRING] | |
131 | The exit string or object ($@) of the eval'ed block, in its unprocessed state. | |
132 | They will always return true when they where deadly, and it always stringifies | |
133 | into something useful. | |
134 | =cut | |
41 | 135 | |
42 | 136 | sub died(;$) |
43 | 137 | { my $self = shift; |
44 | 138 | @_ ? ($self->{died} = shift) : $self->{died}; |
45 | 139 | } |
46 | 140 | |
141 | =method exceptions | |
142 | Returns all collected C<Log::Report::Exceptions>. The last of | |
143 | them may be a fatal one. The other are non-fatal. | |
144 | =cut | |
47 | 145 | |
48 | 146 | sub exceptions() { @{shift->{exceptions}} } |
49 | 147 | |
148 | =method hides $reason | |
149 | Check whether the try stops message which were produced for C<$reason>. | |
150 | =cut | |
50 | 151 | |
51 | 152 | sub hides($) { $_[0]->{LRDT_hides}{$_[1]} } |
52 | 153 | |
154 | =method hide @reasons | |
155 | [1.09] By default, the try will only catch messages which stop the | |
156 | execution of the block (errors etc, internally a 'die'). Other messages | |
157 | are passed to the parent dispatchers. | |
158 | ||
159 | This option gives the opportunity to stop, for instance, trace messages. | |
160 | Those messages are still collected inside the try object (unless excluded | |
161 | by M<new(accept)>), so may get passed-on later via M<reportAll()> if | |
162 | you like. | |
163 | ||
164 | Be warned: Using this method will reset the whole 'hide' configuration: | |
165 | it's a I<set> not an I<add>. | |
166 | ||
167 | =example change the setting of the running block | |
168 | my $parent_try = dispatcher 'active-try'; | |
169 | $parent_try->hide('ALL'); | |
170 | =cut | |
53 | 171 | |
54 | 172 | sub hide(@) |
55 | 173 | { my $self = shift; |
57 | 175 | $self->{LRDT_hides} = +{ map +($_ => 1), @reasons }; |
58 | 176 | } |
59 | 177 | |
178 | =method die2reason | |
179 | Returns the value of M<new(on_die)>. | |
180 | =cut | |
60 | 181 | |
61 | 182 | sub die2reason() { shift->{on_die} } |
62 | 183 | |
63 | 184 | #----------------- |
185 | =section Logging | |
186 | ||
187 | =method log $opts, $reason, $message | |
188 | Other dispatchers translate the message here, and make it leave the | |
189 | program. However, messages in a "try" block are only captured in | |
190 | an intermediate layer: they may never be presented to an end-users. | |
191 | And for sure, we do not know the language yet. | |
192 | ||
193 | The $message is either a STRING or a M<Log::Report::Message>. | |
194 | =cut | |
64 | 195 | |
65 | 196 | sub log($$$$) |
66 | 197 | { my ($self, $opts, $reason, $message, $domain) = @_; |
89 | 220 | $self; |
90 | 221 | } |
91 | 222 | |
223 | =method reportAll %options | |
224 | Re-cast the messages in all collect exceptions into the defined | |
225 | dispatchers, which were disabled during the try block. The %options | |
226 | will end-up as HASH of %options to M<Log::Report::report()>; see | |
227 | M<Log::Report::Exception::throw()> which does the job. | |
228 | ||
229 | =method reportFatal | |
230 | Re-cast only the fatal message to the defined dispatchers. If the | |
231 | block was left without problems, then nothing will be done. The %options | |
232 | will end-up as HASH of %options to M<Log::Report::report()>; see | |
233 | M<Log::Report::Exception::throw()> which does the job. | |
234 | =cut | |
92 | 235 | |
93 | 236 | sub reportFatal(@) { $_->throw(@_) for shift->wasFatal } |
94 | 237 | sub reportAll(@) { $_->throw(@_) for shift->exceptions } |
95 | 238 | |
96 | 239 | #----------------- |
240 | =section Status | |
241 | ||
242 | =method failed | |
243 | Returns true if the block was left with an fatal message. | |
244 | ||
245 | =method success | |
246 | Returns true if the block exited normally. | |
247 | =cut | |
97 | 248 | |
98 | 249 | sub failed() { defined shift->{died}} |
99 | 250 | sub success() { ! defined shift->{died}} |
100 | 251 | |
252 | =method wasFatal %options | |
253 | Returns the M<Log::Report::Exception> which caused the "try" block to | |
254 | die, otherwise an empty LIST (undef). | |
255 | ||
256 | =option class CLASS|REGEX | |
257 | =default class C<undef> | |
258 | Only return the exception if it was fatal, and in the same time in | |
259 | the specified CLASS (as string) or matches the REGEX. | |
260 | See M<Log::Report::Message::inClass()> | |
261 | =cut | |
101 | 262 | |
102 | 263 | sub wasFatal(@) |
103 | 264 | { my ($self, %args) = @_; |
110 | 271 | (!$args{class} || $ex->inClass($args{class})) ? $ex : (); |
111 | 272 | } |
112 | 273 | |
274 | =method showStatus | |
275 | If this object is kept in C<$@>, and someone uses this as string, we | |
276 | want to show the fatal error message. | |
277 | ||
278 | The message is not very informative for the good cause: we do not want | |
279 | people to simply print the C<$@>, but wish for a re-cast of the message | |
280 | using M<reportAll()> or M<reportFatal()>. | |
281 | =cut | |
113 | 282 | |
114 | 283 | sub showStatus() |
115 | 284 | { my $self = shift; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Dispatcher::Try - capture all reports as exceptions | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Dispatcher::Try | |
9 | is a Log::Report::Dispatcher | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | try { ... }; # mind the ';' !! | |
14 | if($@) { # signals something went wrong | |
15 | ||
16 | if(try {...}) { # block ended normally | |
17 | ||
18 | my $x = try { read_temperature() }; | |
19 | my @x = try { read_lines_from_file() }; | |
20 | ||
21 | try { ... } # no comma!! | |
22 | mode => 'DEBUG', accept => 'ERROR-'; | |
23 | ||
24 | try sub { ... }, # with comma | |
25 | mode => 'DEBUG', accept => 'ALL'; | |
26 | ||
27 | try \&myhandler, accept => 'ERROR-'; | |
28 | try { ... } hide => 'TRACE'; | |
29 | ||
30 | print ref $@; # Log::Report::Dispatcher::Try | |
31 | ||
32 | $@->reportFatal; # re-dispatch result of try block | |
33 | $@->reportAll; # ... also warnings etc | |
34 | if($@) {...} # if errors | |
35 | if($@->failed) { # same # } | |
36 | if($@->success) { # no errors # } | |
37 | ||
38 | try { # something causes an error report, which is caught | |
39 | failure 'no network'; | |
40 | }; | |
41 | $@->reportFatal(to => 'syslog'); # overrule destination | |
42 | ||
43 | print $@->exceptions; # no re-cast, just print | |
44 | ||
45 | =head1 DESCRIPTION | |
46 | ||
47 | The B<try> works like Perl's build-in C<eval()>, but implements | |
48 | real exception handling which Perl core lacks. | |
49 | ||
50 | The L<Log::Report::try()|Log::Report/"Report Production and Configuration"> function creates this C<::Try> dispatcher | |
51 | object with name 'try'. After the C<try()> is over, you can find | |
52 | the object in C<$@>. The C<$@> as C<::Try> object behaves exactly | |
53 | as the C<$@> produced by C<eval>, but has many added features. | |
54 | ||
55 | The C<try()> function catches fatal errors happening inside the BLOCK | |
56 | (CODE reference which is just following the function name) into the | |
57 | C<::Try> object C<$@>. The errors are not automatically progressed to | |
58 | active dispatchers. However, non-fatal exceptions (like info or notice) | |
59 | are also collected (unless not accepted, see L<new(accept)|Log::Report::Dispatcher/"Constructors">, but also | |
60 | immediately passed to the active dispatchers (unless the reason is hidden, | |
61 | see L<new(hide)|Log::Report::Dispatcher::Try/"Constructors">) | |
62 | ||
63 | After the C<try()> has run, you can introspect the collected exceptions. | |
64 | Typically, you use L<wasFatal()|Log::Report::Dispatcher::Try/"Status"> to get the exception which terminated | |
65 | the run of the BLOCK. | |
66 | ||
67 | Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">. | |
68 | ||
69 | =head1 METHODS | |
70 | ||
71 | Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">. | |
72 | ||
73 | =head2 Constructors | |
74 | ||
75 | Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">. | |
76 | ||
77 | =over 4 | |
78 | ||
79 | =item $obj-E<gt>B<close>() | |
80 | ||
81 | Inherited, see L<Log::Report::Dispatcher/"Constructors"> | |
82 | ||
83 | =item Log::Report::Dispatcher::Try-E<gt>B<new>($type, $name, %options) | |
84 | ||
85 | -Option --Defined in --Default | |
86 | accept Log::Report::Dispatcher depend on mode | |
87 | charset Log::Report::Dispatcher <undef> | |
88 | died undef | |
89 | exceptions [] | |
90 | format_reason Log::Report::Dispatcher 'LOWERCASE' | |
91 | hide 'NONE' | |
92 | locale Log::Report::Dispatcher <system locale> | |
93 | mode Log::Report::Dispatcher 'NORMAL' | |
94 | on_die 'ERROR' | |
95 | ||
96 | =over 2 | |
97 | ||
98 | =item accept => REASONS | |
99 | ||
100 | =item charset => CHARSET | |
101 | ||
102 | =item died => STRING | |
103 | ||
104 | The exit string ($@) of the eval'ed block. | |
105 | ||
106 | =item exceptions => ARRAY | |
107 | ||
108 | ARRAY of L<Log::Report::Exception|Log::Report::Exception> objects. | |
109 | ||
110 | =item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE | |
111 | ||
112 | =item hide => REASONS|ARRAY|'ALL'|'NONE' | |
113 | ||
114 | [1.09] see L<hide()|Log::Report::Dispatcher::Try/"Accessors"> | |
115 | ||
116 | =item locale => LOCALE | |
117 | ||
118 | =item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3 | |
119 | ||
120 | =item on_die => 'ERROR'|'PANIC' | |
121 | ||
122 | When code which runs in this block exits with a die(), it will get | |
123 | translated into a L<Log::Report::Exception|Log::Report::Exception> using | |
124 | L<Log::Report::Die::die_decode()|Log::Report::Die/"FUNCTIONS">. How serious are we about these | |
125 | errors? | |
126 | ||
127 | =back | |
128 | ||
129 | =back | |
130 | ||
131 | =head2 Accessors | |
132 | ||
133 | Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">. | |
134 | ||
135 | =over 4 | |
136 | ||
137 | =item $obj-E<gt>B<die2reason>() | |
138 | ||
139 | Returns the value of L<new(on_die)|Log::Report::Dispatcher::Try/"Constructors">. | |
140 | ||
141 | =item $obj-E<gt>B<died>( [STRING] ) | |
142 | ||
143 | The message which was reported by C<eval>, which is used internally | |
144 | to catch problems in the try block. | |
145 | ||
146 | =item $obj-E<gt>B<exceptions>() | |
147 | ||
148 | Returns all collected C<Log::Report::Exceptions>. The last of | |
149 | them may be a fatal one. The other are non-fatal. | |
150 | ||
151 | =item $obj-E<gt>B<hide>(@reasons) | |
152 | ||
153 | [1.09] By default, the try will only catch messages which stop the | |
154 | execution of the block (errors etc, internally a 'die'). Other messages | |
155 | are passed to the parent dispatchers. | |
156 | ||
157 | This option gives the opportunity to stop, for instance, trace messages. | |
158 | Those messages are still collected inside the try object (unless excluded | |
159 | by L<new(accept)|Log::Report::Dispatcher/"Constructors">), so may get passed-on later via L<reportAll()|Log::Report::Dispatcher::Try/"Logging"> if | |
160 | you like. | |
161 | ||
162 | Be warned: Using this method will reset the whole 'hide' configuration: | |
163 | it's a I<set> not an I<add>. | |
164 | ||
165 | example: change the setting of the running block | |
166 | ||
167 | my $parent_try = dispatcher 'active-try'; | |
168 | $parent_try->hide('ALL'); | |
169 | ||
170 | =item $obj-E<gt>B<hides>($reason) | |
171 | ||
172 | Check whether the try stops message which were produced for C<$reason>. | |
173 | ||
174 | =item $obj-E<gt>B<isDisabled>() | |
175 | ||
176 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
177 | ||
178 | =item $obj-E<gt>B<mode>() | |
179 | ||
180 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
181 | ||
182 | =item $obj-E<gt>B<name>() | |
183 | ||
184 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
185 | ||
186 | =item $obj-E<gt>B<needs>( [$reason] ) | |
187 | ||
188 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
189 | ||
190 | =item $obj-E<gt>B<type>() | |
191 | ||
192 | Inherited, see L<Log::Report::Dispatcher/"Accessors"> | |
193 | ||
194 | =back | |
195 | ||
196 | =head2 Logging | |
197 | ||
198 | Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">. | |
199 | ||
200 | =over 4 | |
201 | ||
202 | =item $obj-E<gt>B<addSkipStack>(@CODE) | |
203 | ||
204 | =item Log::Report::Dispatcher::Try-E<gt>B<addSkipStack>(@CODE) | |
205 | ||
206 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
207 | ||
208 | =item $obj-E<gt>B<collectLocation>() | |
209 | ||
210 | =item Log::Report::Dispatcher::Try-E<gt>B<collectLocation>() | |
211 | ||
212 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
213 | ||
214 | =item $obj-E<gt>B<collectStack>( [$maxdepth] ) | |
215 | ||
216 | =item Log::Report::Dispatcher::Try-E<gt>B<collectStack>( [$maxdepth] ) | |
217 | ||
218 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
219 | ||
220 | =item $obj-E<gt>B<log>($opts, $reason, $message) | |
221 | ||
222 | Other dispatchers translate the message here, and make it leave the | |
223 | program. However, messages in a "try" block are only captured in | |
224 | an intermediate layer: they may never be presented to an end-users. | |
225 | And for sure, we do not know the language yet. | |
226 | ||
227 | The $message is either a STRING or a L<Log::Report::Message|Log::Report::Message>. | |
228 | ||
229 | =item $obj-E<gt>B<reportAll>(%options) | |
230 | ||
231 | Re-cast the messages in all collect exceptions into the defined | |
232 | dispatchers, which were disabled during the try block. The %options | |
233 | will end-up as HASH of %options to L<Log::Report::report()|Log::Report/"Report Production and Configuration">; see | |
234 | L<Log::Report::Exception::throw()|Log::Report::Exception/"Processing"> which does the job. | |
235 | ||
236 | =item $obj-E<gt>B<reportFatal>() | |
237 | ||
238 | Re-cast only the fatal message to the defined dispatchers. If the | |
239 | block was left without problems, then nothing will be done. The %options | |
240 | will end-up as HASH of %options to L<Log::Report::report()|Log::Report/"Report Production and Configuration">; see | |
241 | L<Log::Report::Exception::throw()|Log::Report::Exception/"Processing"> which does the job. | |
242 | ||
243 | =item $obj-E<gt>B<skipStack>() | |
244 | ||
245 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
246 | ||
247 | =item $obj-E<gt>B<stackTraceLine>(%options) | |
248 | ||
249 | =item Log::Report::Dispatcher::Try-E<gt>B<stackTraceLine>(%options) | |
250 | ||
251 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
252 | ||
253 | =item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message) | |
254 | ||
255 | Inherited, see L<Log::Report::Dispatcher/"Logging"> | |
256 | ||
257 | =back | |
258 | ||
259 | =head2 Status | |
260 | ||
261 | =over 4 | |
262 | ||
263 | =item $obj-E<gt>B<failed>() | |
264 | ||
265 | Returns true if the block was left with an fatal message. | |
266 | ||
267 | =item $obj-E<gt>B<showStatus>() | |
268 | ||
269 | If this object is kept in C<$@>, and someone uses this as string, we | |
270 | want to show the fatal error message. | |
271 | ||
272 | The message is not very informative for the good cause: we do not want | |
273 | people to simply print the C<$@>, but wish for a re-cast of the message | |
274 | using L<reportAll()|Log::Report::Dispatcher::Try/"Logging"> or L<reportFatal()|Log::Report::Dispatcher::Try/"Logging">. | |
275 | ||
276 | =item $obj-E<gt>B<success>() | |
277 | ||
278 | Returns true if the block exited normally. | |
279 | ||
280 | =item $obj-E<gt>B<wasFatal>(%options) | |
281 | ||
282 | Returns the L<Log::Report::Exception|Log::Report::Exception> which caused the "try" block to | |
283 | die, otherwise an empty LIST (undef). | |
284 | ||
285 | -Option--Default | |
286 | class undef | |
287 | ||
288 | =over 2 | |
289 | ||
290 | =item class => CLASS|REGEX | |
291 | ||
292 | Only return the exception if it was fatal, and in the same time in | |
293 | the specified CLASS (as string) or matches the REGEX. | |
294 | See L<Log::Report::Message::inClass()|Log::Report::Message/"Processing"> | |
295 | ||
296 | =back | |
297 | ||
298 | =back | |
299 | ||
300 | =head1 DETAILS | |
301 | ||
302 | Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">. | |
303 | ||
304 | =head1 OVERLOADING | |
305 | ||
306 | =over 4 | |
307 | ||
308 | =item overload: B<boolean> | |
309 | ||
310 | Returns true if the previous try block did produce a terminal | |
311 | error. This "try" object is assigned to C<$@>, and the usual | |
312 | perl syntax is C<if($@) {...error-handler...}>. | |
313 | ||
314 | =item overload: B<stringify> | |
315 | ||
316 | When C<$@> is used the traditional way, it is checked to have | |
317 | a string content. In this case, stringify into the fatal error | |
318 | or nothing. | |
319 | ||
320 | =back | |
321 | ||
322 | =head1 SEE ALSO | |
323 | ||
324 | This module is part of Log-Report distribution version 1.32, | |
325 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
326 | ||
327 | =head1 LICENSE | |
328 | ||
329 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
330 | ||
331 | This program is free software; you can redistribute it and/or modify it | |
332 | under the same terms as Perl itself. | |
333 | See F<http://dev.perl.org/licenses/> | |
334 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Dispatcher; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | |
13 | 6 | use warnings; |
14 | 7 | use strict; |
38 | 31 | |
39 | 32 | my @skip_stack = sub { $_[0][0] =~ m/^Log\:\:Report(?:\:\:|$)/ }; |
40 | 33 | |
34 | =chapter NAME | |
35 | Log::Report::Dispatcher - manage message dispatching, display or logging | |
36 | ||
37 | =chapter SYNOPSIS | |
38 | use Log::Report; | |
39 | ||
40 | # The following will be created for you automatically | |
41 | dispatcher 'PERL', 'default', accept => 'NOTICE-'; | |
42 | dispatcher close => 'default'; # after deamonize | |
43 | ||
44 | dispatcher 'FILE', 'log' | |
45 | , mode => 'DEBUG', to => '/var/log/mydir/myfile'; | |
46 | ||
47 | # Full package name is used, same as 'FILE' | |
48 | dispatcher Log::Report::Dispatch::File => 'stderr' | |
49 | , to => \*STDERR, accept => 'NOTICE-'; | |
50 | ||
51 | =chapter DESCRIPTION | |
52 | In M<Log::Report>, dispatchers are used to handle (exception) messages | |
53 | which are created somewhere else. Those message were produced (thrown) | |
54 | by M<Log::Report::error()> and friends. | |
55 | ||
56 | This base-class handles the creation of dispatchers, plus the common | |
57 | filtering rules. See the L</DETAILS> section, below. | |
58 | ||
59 | =chapter METHODS | |
60 | ||
61 | =section Constructors | |
62 | ||
63 | =c_method new $type, $name, %options | |
64 | Create a dispatcher. The $type of back-end to start is required, and listed | |
65 | in the L</DESCRIPTION> part of this manual-page. For various external | |
66 | back-ends, special wrappers are created. | |
67 | ||
68 | The $name must be uniquely identifying this dispatcher. When a second | |
69 | dispatcher is created (via M<Log::Report::dispatcher()>) with the name | |
70 | of an existing dispatcher, the existing one will get replaced. | |
71 | ||
72 | All %options which are not consumed by this base constructor are passed | |
73 | to the wrapped back-end. Some of them will check whether all %options | |
74 | are understood, other ignore unknown %options. | |
75 | ||
76 | =option accept REASONS | |
77 | =default accept C<depend on mode> | |
78 | See M<Log::Report::Util::expand_reasons()> for possible values. If | |
79 | the initial mode for this dispatcher does not need verbose or debug | |
80 | information, then those levels will not be accepted. | |
81 | ||
82 | When the mode equals "NORMAL" (the default) then C<accept>'s default | |
83 | is C<NOTICE->. In case of "VERBOSE" it will be C<INFO->, C<ASSERT> | |
84 | results in C<ASSERT->, and "DEBUG" in C<ALL>. | |
85 | ||
86 | =option locale LOCALE | |
87 | =default locale <system locale> | |
88 | Overrules the global setting. Can be overruled by | |
89 | M<Log::Report::report(locale)>. | |
90 | ||
91 | =option mode 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3 | |
92 | =default mode 'NORMAL' | |
93 | Possible values are C<NORMAL> (or C<0> or C<undef>), which will not show | |
94 | C<INFO> or debug messages, C<VERBOSE> (C<1>; shows C<INFO> not debug), | |
95 | C<ASSERT> (C<2>; only ignores C<TRACE> messages), or C<DEBUG> (C<3>) | |
96 | which shows everything. See section L<Log::Report/Run modes>. | |
97 | ||
98 | You are advised to use the symbolic mode names when the mode is | |
99 | changed within your program: the numerical values are available | |
100 | for smooth M<Getopt::Long> integration. | |
101 | ||
102 | =option format_reason 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE | |
103 | =default format_reason 'LOWERCASE' | |
104 | How to show the reason text which is printed before the message. When | |
105 | a CODE is specified, it will be called with a translated text and the | |
106 | returned text is used. | |
107 | ||
108 | =option charset CHARSET | |
109 | =default charset <undef> | |
110 | Convert the messages in the specified character-set (codeset). By | |
111 | default, no conversion will take place, because the right choice cannot | |
112 | be determined automatically. | |
113 | ||
114 | =cut | |
41 | 115 | |
42 | 116 | sub new(@) |
43 | 117 | { my ($class, $type, $name, %args) = @_; |
89 | 163 | $self; |
90 | 164 | } |
91 | 165 | |
166 | =method close | |
167 | Terminate the dispatcher activities. The dispatcher gets disabled, | |
168 | to avoid the case that it is accidentally used. Returns C<undef> (false) | |
169 | if the dispatcher was already closed. | |
170 | =cut | |
92 | 171 | |
93 | 172 | sub close() |
94 | 173 | { my $self = shift; |
101 | 180 | |
102 | 181 | #---------------------------- |
103 | 182 | |
183 | =section Accessors | |
184 | ||
185 | =method name | |
186 | Returns the unique name of this dispatcher. | |
187 | =cut | |
104 | 188 | |
105 | 189 | sub name {shift->{name}} |
106 | 190 | |
191 | =method type | |
192 | The dispatcher $type, which is usually the same as the class of this | |
193 | object, but not in case of wrappers like for Log::Dispatch. | |
194 | =cut | |
107 | 195 | |
108 | 196 | sub type() {shift->{type}} |
109 | 197 | |
198 | =method mode | |
199 | Returns the mode in use for the dispatcher as number. See M<new(mode)> | |
200 | and L<Log::Report/Run modes>. | |
201 | =cut | |
110 | 202 | |
111 | 203 | sub mode() {shift->{mode}} |
112 | 204 | |
136 | 228 | @_ ? ($self->{disabled} = shift) : $self->{disabled}; |
137 | 229 | } |
138 | 230 | |
231 | =method isDisabled | |
232 | =cut | |
139 | 233 | |
140 | 234 | sub isDisabled() {shift->{disabled}} |
141 | 235 | |
236 | =method needs [$reason] | |
237 | Returns the list with all REASONS which are needed to fulfill this | |
238 | dispatcher's needs. When disabled, the list is empty, but not forgotten. | |
239 | ||
240 | [0.999] when only one $reason is specified, it is returned if in the | |
241 | list. | |
242 | =cut | |
142 | 243 | |
143 | 244 | sub needs(;$) |
144 | 245 | { my $self = shift; |
152 | 253 | } |
153 | 254 | |
154 | 255 | #----------- |
256 | =section Logging | |
257 | ||
258 | =method log HASH-$of-%options, $reason, $message, $domain | |
259 | This method is called by M<Log::Report::report()> and should not be called | |
260 | directly. Internally, it will call M<translate()>, which does most $of | |
261 | the work. | |
262 | =cut | |
155 | 263 | |
156 | 264 | sub log($$$$) |
157 | 265 | { panic "method log() must be extended per back-end"; |
158 | 266 | } |
159 | 267 | |
268 | =method translate HASH-$of-%options, $reason, $message | |
269 | See L</Processing the message>, which describes the actions taken by | |
270 | this method. A string is returned, which ends on a new-line, and | |
271 | may be multi-line (in case a stack trace is produced). | |
272 | =cut | |
160 | 273 | |
161 | 274 | sub translate($$$) |
162 | 275 | { my ($self, $opts, $reason, $msg) = @_; |
227 | 340 | $self->{charset_enc}->($text); |
228 | 341 | } |
229 | 342 | |
343 | =ci_method collectStack [$maxdepth] | |
344 | Returns an ARRAY of ARRAYs with text, filename, line-number. | |
345 | =cut | |
230 | 346 | |
231 | 347 | sub collectStack($) |
232 | 348 | { my ($thing, $max) = @_; |
248 | 364 | } |
249 | 365 | } |
250 | 366 | |
367 | =ci_method addSkipStack @CODE | |
368 | [1.13] Add one or more CODE blocks of caller lines which should not be | |
369 | collected for stack-traces or location display. A CODE gets | |
370 | called with an ARRAY of caller information, and returns true | |
371 | when that line should get skipped. | |
372 | ||
373 | B<Warning:> this logic is applied globally: on all dispatchers. | |
374 | ||
375 | =example | |
376 | By default, all lines in the Log::Report packages are skipped from | |
377 | display, with a simple CODE as this: | |
378 | ||
379 | sub in_lr { $_[0][0] =~ m/^Log\:\:Report(?:\:\:|$)/ } | |
380 | Log::Report::Dispatcher->addSkipStack(\&in_lr); | |
381 | ||
382 | The only parameter to in_lr is the return of caller(). The first | |
383 | element of that ARRAY is the package name of a stack line. | |
384 | =cut | |
251 | 385 | |
252 | 386 | sub addSkipStack(@) |
253 | 387 | { my $thing = shift; |
255 | 389 | $thing; |
256 | 390 | } |
257 | 391 | |
392 | =method skipStack | |
393 | [1.13] Returns the number of nestings in the stack which should be skipped | |
394 | to get outside the Log::Report (and related) modules. The end-user | |
395 | does not want to see those internals in stack-traces. | |
396 | =cut | |
258 | 397 | |
259 | 398 | sub skipStack() |
260 | 399 | { my $thing = shift; |
268 | 407 | @$args ? $nest-1 : 1; |
269 | 408 | } |
270 | 409 | |
410 | =ci_method collectLocation | |
411 | Collect the information to be displayed as line where the error occurred. | |
412 | =cut | |
271 | 413 | |
272 | 414 | sub collectLocation() { [caller shift->skipStack] } |
273 | 415 | |
416 | =ci_method stackTraceLine %options | |
417 | =requires package CLASS | |
418 | =requires filename STRING | |
419 | =requires linenr INTEGER | |
420 | =requires call STRING | |
421 | =requires params ARRAY | |
422 | ||
423 | =option max_line INTEGER | |
424 | =default max_line C<undef> | |
425 | ||
426 | =option max_params INTEGER | |
427 | =default max_params 8 | |
428 | ||
429 | =option abstract INTEGER | |
430 | =default abstract 1 | |
431 | The higher the abstraction value, the less details are given | |
432 | about the caller. The minimum abstraction is specified, and | |
433 | then increased internally to make the line fit within the C<max_line> | |
434 | margin. | |
435 | =cut | |
274 | 436 | |
275 | 437 | sub stackTraceLine(@) |
276 | 438 | { my ($thing, %args) = @_; |
356 | 518 | } |
357 | 519 | |
358 | 520 | #------------ |
521 | =chapter DETAILS | |
522 | ||
523 | =section Available back-ends | |
524 | ||
525 | When a dispatcher is created (via M<new()> or M<Log::Report::dispatcher()>), | |
526 | you must specify the TYPE of the dispatcher. This can either be a class | |
527 | name, which extends a M<Log::Report::Dispatcher>, or a pre-defined | |
528 | abbreviation of a class name. Implemented are: | |
529 | ||
530 | =over 4 | |
531 | =item M<Log::Report::Dispatcher::Perl> (abbreviation 'PERL') | |
532 | Use Perl's own C<print()>, C<warn()> and C<die()> to ventilate | |
533 | reports. This is the default dispatcher. | |
534 | ||
535 | =item M<Log::Report::Dispatcher::File> (abbreviation 'FILE') | |
536 | Logs the message into a file, which can either be opened by the | |
537 | class or be opened before the dispatcher is created. | |
538 | ||
539 | =item M<Log::Report::Dispatcher::Syslog> (abbreviation 'SYSLOG') | |
540 | Send messages into the system's syslog infrastructure, using | |
541 | M<Sys::Syslog>. | |
542 | ||
543 | =item M<Log::Report::Dispatcher::Callback> (abbreviation 'CALLBACK') | |
544 | Calls any CODE reference on receipt of each selected message, for | |
545 | instance to send important message as email or SMS. | |
546 | ||
547 | =item C<Log::Dispatch::*> | |
548 | All of the M<Log::Dispatch::Output> extensions can be used directly. | |
549 | The M<Log::Report::Dispatcher::LogDispatch> will wrap around that | |
550 | back-end. | |
551 | ||
552 | =item C<Log::Log4perl> | |
553 | Use the M<Log::Log4perl> main object to write to dispatchers. This | |
554 | infrastructure uses a configuration file. | |
555 | ||
556 | =item M<Log::Report::Dispatcher::Try> (abbreviation 'TRY') | |
557 | Used by function M<Log::Report::try()>. It collects the exceptions | |
558 | and can produce them on request. | |
559 | ||
560 | =back | |
561 | ||
562 | =section Processing the message | |
563 | ||
564 | =subsection Addition information | |
565 | ||
566 | The modules which use C<Log::Report> will only specify the base of | |
567 | the message string. The base dispatcher and the back-ends will extend | |
568 | this message with additional information: | |
569 | ||
570 | =over 4 | |
571 | =item . the reason | |
572 | =item . the filename/line-number where the problem appeared | |
573 | =item . the filename/line-number where it problem was reported | |
574 | =item . the error text in C<$!> | |
575 | =item . a stack-trace | |
576 | =item . a trailing new-line | |
577 | =back | |
578 | ||
579 | When the message is a translatable object (M<Log::Report::Message>, for | |
580 | instance created with M<Log::Report::__()>), then the added components | |
581 | will get translated as well. Otherwise, all will be in English. | |
582 | ||
583 | Exactly what will be added depends on the actual mode of the dispatcher | |
584 | (change it with M<mode()>, initiate it with M<new(mode)>). | |
585 | ||
586 | mode mode mode mode | |
587 | REASON SOURCE TE! NORM VERB ASSE DEBUG | |
588 | trace program ... S | |
589 | assert program ... SL SL | |
590 | info program T.. S S S | |
591 | notice program T.. S S S S | |
592 | mistake user T.. S S S SL | |
593 | warning program T.. S S SL SL | |
594 | error user TE. S S SL SC | |
595 | fault system TE! S S SL SC | |
596 | alert system T.! SL SL SC SC | |
597 | failure system TE! SL SL SC SC | |
598 | panic program .E. SC SC SC SC | |
599 | ||
600 | T - usually translated | |
601 | E - exception (execution interrupted) | |
602 | ! - will include $! text at display | |
603 | L - include filename and linenumber | |
604 | S - show/print when accepted | |
605 | C - stack trace (like Carp::confess()) | |
606 | ||
607 | =subsection Filters | |
608 | ||
609 | With a filter, you can block or modify specific messages before | |
610 | translation. There may be a wish to change the REASON of a report | |
611 | or its content. It is not possible to avoid the exit which is | |
612 | related to the original message, because a module's flow depends | |
613 | on it to happen. | |
614 | ||
615 | When there are filters defined, they will be called in order of | |
616 | definition. For each of the dispatchers which are called for a | |
617 | certain REASON (which C<accept> that REASON), it is checked whether | |
618 | its name is listed for the filter (when no names where specified, | |
619 | then the filter is applied to all dispatchers). | |
620 | ||
621 | When selected, the filter's CODE reference is called with four arguments: | |
622 | the dispatcher object (a M<Log::Report::Dispatcher>), the HASH-of-OPTIONS | |
623 | passed as optional first argument to M<Log::Report::report()>, the | |
624 | REASON, and the MESSAGE. Returned is the new REASON and MESSAGE. | |
625 | When the returned REASON is C<undef>, then the message will be ignored | |
626 | for that dispatcher. | |
627 | ||
628 | Be warned about processing the MESSAGE: it is a M<Log::Report::Message> | |
629 | object which may have a C<prepend> string and C<append> string or | |
630 | object. When the call to M<Log::Report::report()> contained multiple | |
631 | comma-separated components, these will already have been joined together | |
632 | using concatenation (see M<Log::Report::Message::concat()>. | |
633 | ||
634 | =example a filter on syslog | |
635 | dispatcher filter => \&myfilter, 'syslog'; | |
636 | ||
637 | # ignore all translatable and non-translatable messages containing | |
638 | # the word "skip" | |
639 | sub myfilter($$$$) | |
640 | { my ($disp, $opts, $reason, $message) = @_; | |
641 | return () if $message->untranslated =~ m/\bskip\b/; | |
642 | ($reason, $message); | |
643 | } | |
644 | ||
645 | =example take all mistakes and warnings serious | |
646 | dispatch filter => \&take_warns_seriously; | |
647 | sub take_warns_seriously($$$$) | |
648 | { my ($disp, $opts, $reason, $message) = @_; | |
649 | $reason eq 'MISTAKE' ? (ERROR => $message) | |
650 | : $reason eq 'WARNING' ? (FAULT => $message) | |
651 | : ($reason => $message); | |
652 | } | |
653 | ||
654 | =cut | |
359 | 655 | |
360 | 656 | 1; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Dispatcher - manage message dispatching, display or logging | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Dispatcher is extended by | |
9 | Log::Report::Dispatcher::Callback | |
10 | Log::Report::Dispatcher::File | |
11 | Log::Report::Dispatcher::Log4perl | |
12 | Log::Report::Dispatcher::LogDispatch | |
13 | Log::Report::Dispatcher::Perl | |
14 | Log::Report::Dispatcher::Syslog | |
15 | Log::Report::Dispatcher::Try | |
16 | ||
17 | =head1 SYNOPSIS | |
18 | ||
19 | use Log::Report; | |
20 | ||
21 | # The following will be created for you automatically | |
22 | dispatcher 'PERL', 'default', accept => 'NOTICE-'; | |
23 | dispatcher close => 'default'; # after deamonize | |
24 | ||
25 | dispatcher 'FILE', 'log' | |
26 | , mode => 'DEBUG', to => '/var/log/mydir/myfile'; | |
27 | ||
28 | # Full package name is used, same as 'FILE' | |
29 | dispatcher Log::Report::Dispatch::File => 'stderr' | |
30 | , to => \*STDERR, accept => 'NOTICE-'; | |
31 | ||
32 | =head1 DESCRIPTION | |
33 | ||
34 | In L<Log::Report|Log::Report>, dispatchers are used to handle (exception) messages | |
35 | which are created somewhere else. Those message were produced (thrown) | |
36 | by L<Log::Report::error()|Log::Report/"Abbreviations for report()"> and friends. | |
37 | ||
38 | This base-class handles the creation of dispatchers, plus the common | |
39 | filtering rules. See the L</DETAILS> section, below. | |
40 | ||
41 | =head1 METHODS | |
42 | ||
43 | =head2 Constructors | |
44 | ||
45 | =over 4 | |
46 | ||
47 | =item $obj-E<gt>B<close>() | |
48 | ||
49 | Terminate the dispatcher activities. The dispatcher gets disabled, | |
50 | to avoid the case that it is accidentally used. Returns C<undef> (false) | |
51 | if the dispatcher was already closed. | |
52 | ||
53 | =item Log::Report::Dispatcher-E<gt>B<new>($type, $name, %options) | |
54 | ||
55 | Create a dispatcher. The $type of back-end to start is required, and listed | |
56 | in the L</DESCRIPTION> part of this manual-page. For various external | |
57 | back-ends, special wrappers are created. | |
58 | ||
59 | The $name must be uniquely identifying this dispatcher. When a second | |
60 | dispatcher is created (via L<Log::Report::dispatcher()|Log::Report/"Report Production and Configuration">) with the name | |
61 | of an existing dispatcher, the existing one will get replaced. | |
62 | ||
63 | All %options which are not consumed by this base constructor are passed | |
64 | to the wrapped back-end. Some of them will check whether all %options | |
65 | are understood, other ignore unknown %options. | |
66 | ||
67 | -Option --Default | |
68 | accept depend on mode | |
69 | charset <undef> | |
70 | format_reason 'LOWERCASE' | |
71 | locale <system locale> | |
72 | mode 'NORMAL' | |
73 | ||
74 | =over 2 | |
75 | ||
76 | =item accept => REASONS | |
77 | ||
78 | See L<Log::Report::Util::expand_reasons()|Log::Report::Util/"Reasons"> for possible values. If | |
79 | the initial mode for this dispatcher does not need verbose or debug | |
80 | information, then those levels will not be accepted. | |
81 | ||
82 | When the mode equals "NORMAL" (the default) then C<accept>'s default | |
83 | is C<NOTICE->. In case of "VERBOSE" it will be C<INFO->, C<ASSERT> | |
84 | results in C<ASSERT->, and "DEBUG" in C<ALL>. | |
85 | ||
86 | =item charset => CHARSET | |
87 | ||
88 | Convert the messages in the specified character-set (codeset). By | |
89 | default, no conversion will take place, because the right choice cannot | |
90 | be determined automatically. | |
91 | ||
92 | =item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE | |
93 | ||
94 | How to show the reason text which is printed before the message. When | |
95 | a CODE is specified, it will be called with a translated text and the | |
96 | returned text is used. | |
97 | ||
98 | =item locale => LOCALE | |
99 | ||
100 | Overrules the global setting. Can be overruled by | |
101 | L<Log::Report::report(locale)|Log::Report/"Report Production and Configuration">. | |
102 | ||
103 | =item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3 | |
104 | ||
105 | Possible values are C<NORMAL> (or C<0> or C<undef>), which will not show | |
106 | C<INFO> or debug messages, C<VERBOSE> (C<1>; shows C<INFO> not debug), | |
107 | C<ASSERT> (C<2>; only ignores C<TRACE> messages), or C<DEBUG> (C<3>) | |
108 | which shows everything. See section L<Log::Report/Run modes>. | |
109 | ||
110 | You are advised to use the symbolic mode names when the mode is | |
111 | changed within your program: the numerical values are available | |
112 | for smooth Getopt::Long integration. | |
113 | ||
114 | =back | |
115 | ||
116 | =back | |
117 | ||
118 | =head2 Accessors | |
119 | ||
120 | =over 4 | |
121 | ||
122 | =item $obj-E<gt>B<isDisabled>() | |
123 | ||
124 | =item $obj-E<gt>B<mode>() | |
125 | ||
126 | Returns the mode in use for the dispatcher as number. See L<new(mode)|Log::Report::Dispatcher/"Constructors"> | |
127 | and L<Log::Report/Run modes>. | |
128 | ||
129 | =item $obj-E<gt>B<name>() | |
130 | ||
131 | Returns the unique name of this dispatcher. | |
132 | ||
133 | =item $obj-E<gt>B<needs>( [$reason] ) | |
134 | ||
135 | Returns the list with all REASONS which are needed to fulfill this | |
136 | dispatcher's needs. When disabled, the list is empty, but not forgotten. | |
137 | ||
138 | [0.999] when only one $reason is specified, it is returned if in the | |
139 | list. | |
140 | ||
141 | =item $obj-E<gt>B<type>() | |
142 | ||
143 | The dispatcher $type, which is usually the same as the class of this | |
144 | object, but not in case of wrappers like for Log::Dispatch. | |
145 | ||
146 | =back | |
147 | ||
148 | =head2 Logging | |
149 | ||
150 | =over 4 | |
151 | ||
152 | =item $obj-E<gt>B<addSkipStack>(@CODE) | |
153 | ||
154 | =item Log::Report::Dispatcher-E<gt>B<addSkipStack>(@CODE) | |
155 | ||
156 | [1.13] Add one or more CODE blocks of caller lines which should not be | |
157 | collected for stack-traces or location display. A CODE gets | |
158 | called with an ARRAY of caller information, and returns true | |
159 | when that line should get skipped. | |
160 | ||
161 | B<Warning:> this logic is applied globally: on all dispatchers. | |
162 | ||
163 | example: | |
164 | ||
165 | By default, all lines in the Log::Report packages are skipped from | |
166 | display, with a simple CODE as this: | |
167 | ||
168 | sub in_lr { $_[0][0] =~ m/^Log\:\:Report(?:\:\:|$)/ } | |
169 | Log::Report::Dispatcher->addSkipStack(\&in_lr); | |
170 | ||
171 | The only parameter to in_lr is the return of caller(). The first | |
172 | element of that ARRAY is the package name of a stack line. | |
173 | ||
174 | =item $obj-E<gt>B<collectLocation>() | |
175 | ||
176 | =item Log::Report::Dispatcher-E<gt>B<collectLocation>() | |
177 | ||
178 | Collect the information to be displayed as line where the error occurred. | |
179 | ||
180 | =item $obj-E<gt>B<collectStack>( [$maxdepth] ) | |
181 | ||
182 | =item Log::Report::Dispatcher-E<gt>B<collectStack>( [$maxdepth] ) | |
183 | ||
184 | Returns an ARRAY of ARRAYs with text, filename, line-number. | |
185 | ||
186 | =item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain) | |
187 | ||
188 | This method is called by L<Log::Report::report()|Log::Report/"Report Production and Configuration"> and should not be called | |
189 | directly. Internally, it will call L<translate()|Log::Report::Dispatcher/"Logging">, which does most $of | |
190 | the work. | |
191 | ||
192 | =item $obj-E<gt>B<skipStack>() | |
193 | ||
194 | [1.13] Returns the number of nestings in the stack which should be skipped | |
195 | to get outside the Log::Report (and related) modules. The end-user | |
196 | does not want to see those internals in stack-traces. | |
197 | ||
198 | =item $obj-E<gt>B<stackTraceLine>(%options) | |
199 | ||
200 | =item Log::Report::Dispatcher-E<gt>B<stackTraceLine>(%options) | |
201 | ||
202 | -Option --Default | |
203 | abstract 1 | |
204 | call <required> | |
205 | filename <required> | |
206 | linenr <required> | |
207 | max_line undef | |
208 | max_params 8 | |
209 | package <required> | |
210 | params <required> | |
211 | ||
212 | =over 2 | |
213 | ||
214 | =item abstract => INTEGER | |
215 | ||
216 | The higher the abstraction value, the less details are given | |
217 | about the caller. The minimum abstraction is specified, and | |
218 | then increased internally to make the line fit within the C<max_line> | |
219 | margin. | |
220 | ||
221 | =item call => STRING | |
222 | ||
223 | =item filename => STRING | |
224 | ||
225 | =item linenr => INTEGER | |
226 | ||
227 | =item max_line => INTEGER | |
228 | ||
229 | =item max_params => INTEGER | |
230 | ||
231 | =item package => CLASS | |
232 | ||
233 | =item params => ARRAY | |
234 | ||
235 | =back | |
236 | ||
237 | =item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message) | |
238 | ||
239 | See L</Processing the message>, which describes the actions taken by | |
240 | this method. A string is returned, which ends on a new-line, and | |
241 | may be multi-line (in case a stack trace is produced). | |
242 | ||
243 | =back | |
244 | ||
245 | =head1 DETAILS | |
246 | ||
247 | =head2 Available back-ends | |
248 | ||
249 | When a dispatcher is created (via L<new()|Log::Report::Dispatcher/"Constructors"> or L<Log::Report::dispatcher()|Log::Report/"Report Production and Configuration">), | |
250 | you must specify the TYPE of the dispatcher. This can either be a class | |
251 | name, which extends a L<Log::Report::Dispatcher|Log::Report::Dispatcher>, or a pre-defined | |
252 | abbreviation of a class name. Implemented are: | |
253 | ||
254 | =over 4 | |
255 | ||
256 | =item L<Log::Report::Dispatcher::Perl|Log::Report::Dispatcher::Perl> (abbreviation 'PERL') | |
257 | ||
258 | Use Perl's own C<print()>, C<warn()> and C<die()> to ventilate | |
259 | reports. This is the default dispatcher. | |
260 | ||
261 | =item L<Log::Report::Dispatcher::File|Log::Report::Dispatcher::File> (abbreviation 'FILE') | |
262 | ||
263 | Logs the message into a file, which can either be opened by the | |
264 | class or be opened before the dispatcher is created. | |
265 | ||
266 | =item L<Log::Report::Dispatcher::Syslog|Log::Report::Dispatcher::Syslog> (abbreviation 'SYSLOG') | |
267 | ||
268 | Send messages into the system's syslog infrastructure, using | |
269 | Sys::Syslog. | |
270 | ||
271 | =item L<Log::Report::Dispatcher::Callback|Log::Report::Dispatcher::Callback> (abbreviation 'CALLBACK') | |
272 | ||
273 | Calls any CODE reference on receipt of each selected message, for | |
274 | instance to send important message as email or SMS. | |
275 | ||
276 | =item C<Log::Dispatch::*> | |
277 | ||
278 | All of the Log::Dispatch::Output extensions can be used directly. | |
279 | The L<Log::Report::Dispatcher::LogDispatch|Log::Report::Dispatcher::LogDispatch> will wrap around that | |
280 | back-end. | |
281 | ||
282 | =item C<Log::Log4perl> | |
283 | ||
284 | Use the Log::Log4perl main object to write to dispatchers. This | |
285 | infrastructure uses a configuration file. | |
286 | ||
287 | =item L<Log::Report::Dispatcher::Try|Log::Report::Dispatcher::Try> (abbreviation 'TRY') | |
288 | ||
289 | Used by function L<Log::Report::try()|Log::Report/"Report Production and Configuration">. It collects the exceptions | |
290 | and can produce them on request. | |
291 | ||
292 | =back | |
293 | ||
294 | =head2 Processing the message | |
295 | ||
296 | =head3 Addition information | |
297 | ||
298 | The modules which use C<Log::Report> will only specify the base of | |
299 | the message string. The base dispatcher and the back-ends will extend | |
300 | this message with additional information: | |
301 | ||
302 | =over 4 | |
303 | ||
304 | =item . the reason | |
305 | ||
306 | =item . the filename/line-number where the problem appeared | |
307 | ||
308 | =item . the filename/line-number where it problem was reported | |
309 | ||
310 | =item . the error text in C<$!> | |
311 | ||
312 | =item . a stack-trace | |
313 | ||
314 | =item . a trailing new-line | |
315 | ||
316 | =back | |
317 | ||
318 | When the message is a translatable object (L<Log::Report::Message|Log::Report::Message>, for | |
319 | instance created with L<Log::Report::__()|Log::Report/"Messages (optionally translatable)">), then the added components | |
320 | will get translated as well. Otherwise, all will be in English. | |
321 | ||
322 | Exactly what will be added depends on the actual mode of the dispatcher | |
323 | (change it with L<mode()|Log::Report::Dispatcher/"Accessors">, initiate it with L<new(mode)|Log::Report::Dispatcher/"Constructors">). | |
324 | ||
325 | mode mode mode mode | |
326 | REASON SOURCE TE! NORM VERB ASSE DEBUG | |
327 | trace program ... S | |
328 | assert program ... SL SL | |
329 | info program T.. S S S | |
330 | notice program T.. S S S S | |
331 | mistake user T.. S S S SL | |
332 | warning program T.. S S SL SL | |
333 | error user TE. S S SL SC | |
334 | fault system TE! S S SL SC | |
335 | alert system T.! SL SL SC SC | |
336 | failure system TE! SL SL SC SC | |
337 | panic program .E. SC SC SC SC | |
338 | ||
339 | T - usually translated | |
340 | E - exception (execution interrupted) | |
341 | ! - will include $! text at display | |
342 | L - include filename and linenumber | |
343 | S - show/print when accepted | |
344 | C - stack trace (like Carp::confess()) | |
345 | ||
346 | =head3 Filters | |
347 | ||
348 | With a filter, you can block or modify specific messages before | |
349 | translation. There may be a wish to change the REASON of a report | |
350 | or its content. It is not possible to avoid the exit which is | |
351 | related to the original message, because a module's flow depends | |
352 | on it to happen. | |
353 | ||
354 | When there are filters defined, they will be called in order of | |
355 | definition. For each of the dispatchers which are called for a | |
356 | certain REASON (which C<accept> that REASON), it is checked whether | |
357 | its name is listed for the filter (when no names where specified, | |
358 | then the filter is applied to all dispatchers). | |
359 | ||
360 | When selected, the filter's CODE reference is called with four arguments: | |
361 | the dispatcher object (a L<Log::Report::Dispatcher|Log::Report::Dispatcher>), the HASH-of-OPTIONS | |
362 | passed as optional first argument to L<Log::Report::report()|Log::Report/"Report Production and Configuration">, the | |
363 | REASON, and the MESSAGE. Returned is the new REASON and MESSAGE. | |
364 | When the returned REASON is C<undef>, then the message will be ignored | |
365 | for that dispatcher. | |
366 | ||
367 | Be warned about processing the MESSAGE: it is a L<Log::Report::Message|Log::Report::Message> | |
368 | object which may have a C<prepend> string and C<append> string or | |
369 | object. When the call to L<Log::Report::report()|Log::Report/"Report Production and Configuration"> contained multiple | |
370 | comma-separated components, these will already have been joined together | |
371 | using concatenation (see L<Log::Report::Message::concat()|Log::Report::Message/"Processing">. | |
372 | ||
373 | B<. Example: a filter on syslog> | |
374 | ||
375 | dispatcher filter => \&myfilter, 'syslog'; | |
376 | ||
377 | # ignore all translatable and non-translatable messages containing | |
378 | # the word "skip" | |
379 | sub myfilter($$$$) | |
380 | { my ($disp, $opts, $reason, $message) = @_; | |
381 | return () if $message->untranslated =~ m/\bskip\b/; | |
382 | ($reason, $message); | |
383 | } | |
384 | ||
385 | B<. Example: take all mistakes and warnings serious> | |
386 | ||
387 | dispatch filter => \&take_warns_seriously; | |
388 | sub take_warns_seriously($$$$) | |
389 | { my ($disp, $opts, $reason, $message) = @_; | |
390 | $reason eq 'MISTAKE' ? (ERROR => $message) | |
391 | : $reason eq 'WARNING' ? (FAULT => $message) | |
392 | : ($reason => $message); | |
393 | } | |
394 | ||
395 | =head1 SEE ALSO | |
396 | ||
397 | This module is part of Log-Report distribution version 1.32, | |
398 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
399 | ||
400 | =head1 LICENSE | |
401 | ||
402 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
403 | ||
404 | This program is free software; you can redistribute it and/or modify it | |
405 | under the same terms as Perl itself. | |
406 | See F<http://dev.perl.org/licenses/> | |
407 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Domain; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Log::Report::Minimal::Domain'; |
13 | 6 | |
14 | 7 | use warnings; |
20 | 13 | |
21 | 14 | use Log::Report::Translator; |
22 | 15 | |
16 | =chapter NAME | |
17 | Log::Report::Domain - administer one text-domain | |
18 | ||
19 | =chapter SYNOPSIS | |
20 | ||
21 | # internal usage | |
22 | use Log::Report::Domain; | |
23 | my $domain = Log::Report::Domain->new(name => $name); | |
24 | ||
25 | # find a ::Domain object | |
26 | use Log::Report 'my-domain'; | |
27 | my $domain = textdomain 'my-domain'; # find domain config | |
28 | my $domain = textdomain; # config of this package | |
29 | ||
30 | # explicit domain configuration | |
31 | package My::Package; | |
32 | use Log::Report 'my-domain'; # set textdomain for package | |
33 | ||
34 | textdomain $name, %configure; # set config, once per program | |
35 | (textdomain $name)->configure(%configure); # same | |
36 | textdomain->configure(%configure); # same if current package in $name | |
37 | ||
38 | # implicit domain configuration | |
39 | package My::Package; | |
40 | use Log::Report 'my-domain', %configure; | |
41 | ||
42 | # external file for configuration (perl or json format) | |
43 | use Log::Report 'my-domain', config => $filename; | |
44 | ||
45 | use Log::Report 'my-domain'; | |
46 | textdomain->configure(config => $filename); | |
47 | ||
48 | =chapter DESCRIPTION | |
49 | ||
50 | L<Log::Report> can handle multiple sets of packages at the same | |
51 | time: in the usual case a program consists of more than one software | |
52 | distribution, each containing a number of packages. Each module | |
53 | in an application belongs to one of these sets, by default the domain set | |
54 | 'default'. | |
55 | ||
56 | For C<Log::Report>, those packags sets are differentiated via the | |
57 | text-domain value in the C<use> statement: | |
58 | ||
59 | use Log::Report 'my-domain'; | |
60 | ||
61 | There are many things you can configure per (text)domain. This is not | |
62 | only related to translations, but also -for instance- for text formatting | |
63 | configuration. The administration for the configuration is managed in | |
64 | this package. | |
65 | ||
66 | =chapter METHODS | |
67 | ||
68 | =section Constructors | |
69 | ||
70 | =c_method new %options | |
71 | Create a new Domain object. | |
72 | =cut | |
23 | 73 | |
24 | 74 | sub init($) |
25 | 75 | { my ($self, $args) = @_; |
29 | 79 | } |
30 | 80 | |
31 | 81 | #---------------- |
82 | =section Attributes | |
83 | =method nativeLanguage | |
84 | =method translator | |
85 | =method contextRules | |
86 | =cut | |
32 | 87 | |
33 | 88 | sub nativeLanguage() {shift->{LRD_native}} |
34 | 89 | sub translator() {shift->{LRD_transl}} |
35 | 90 | sub contextRules() {shift->{LRD_ctxt_rules}} |
36 | 91 | |
37 | 92 | #---------------- |
93 | =method configure %options | |
94 | The import is automatically called when the package is compiled. For all | |
95 | but one packages in your distribution, it will only contain the name of | |
96 | the DOMAIN. For one package, it will contain configuration information. | |
97 | These %options are used for all packages which use the same DOMAIN. | |
98 | See chapter L</Configuring> below. | |
99 | ||
100 | =option formatter CODE|HASH|'PRINTI' | |
101 | =default formatter C<PRINTI> | |
102 | Selects the formatter used for the errors messages. The default is C<PRINTI>, | |
103 | which will use M<String::Print::printi()>: interpolation with curly | |
104 | braces around the variable names. | |
105 | ||
106 | =option translator M<Log::Report::Translator>|HASH | |
107 | =default translator C<created internally> | |
108 | Set the object which will do the translations for this domain. | |
109 | ||
110 | =option native_language CODESET | |
111 | =default native_language 'en_US' | |
112 | This is the language which you have used to write the translatable and | |
113 | the non-translatable messages in. In case no translation is needed, | |
114 | you still wish the system error messages to be in the same language | |
115 | as the report. Of course, each textdomain can define its own. | |
116 | ||
117 | =option context_rules HASH|OBJECT | |
118 | =default context_rules C<undef> | |
119 | When rules are provided, the translator will use the C<msgctxt> fields | |
120 | as provided by PO-files (gettext). This parameter is used to initialize | |
121 | a M<Log::Report::Translator::Context> helper object. | |
122 | ||
123 | =option config FILENAME | |
124 | =default config C<undef> | |
125 | Read the settings from the file. The parameters found in the file are | |
126 | used as default for the parameters above. This parameter is especially | |
127 | useful for the C<context_rules>, which need to be shared between the | |
128 | running application and F<xgettext-perl>. See M<readConfig()> | |
129 | ||
130 | =cut | |
38 | 131 | |
39 | 132 | sub configure(%) |
40 | 133 | { my ($self, %args) = @_; |
98 | 191 | undef; |
99 | 192 | } |
100 | 193 | |
194 | =method setContext STRING|HASH|ARRAY|PAIRS | |
195 | Temporary set the default translation context for messages. This is used | |
196 | when the message is created without a C<_context> parameter. The context | |
197 | can be retrieved with M<defaultContext()>. | |
198 | ||
199 | Contexts are totally ignored then there are no C<context_rules>. When | |
200 | you do not wish to change settings, you may simply provide a HASH. | |
201 | ||
202 | =example | |
203 | use Log::Report 'my-domain', context_rules => {}; | |
204 | =cut | |
101 | 205 | |
102 | 206 | sub setContext(@) |
103 | 207 | { my $self = shift; |
107 | 211 | $self->{LRD_ctxt_def} = $cr->needDecode(set => @_); |
108 | 212 | } |
109 | 213 | |
214 | =method updateContext STRING|HASH|ARRAY|PAIRS | |
215 | [1.10] Make changes and additions to the active context (see M<setContext()>). | |
216 | =cut | |
110 | 217 | |
111 | 218 | sub updateContext(@) |
112 | 219 | { my $self = shift; |
119 | 226 | $r; |
120 | 227 | } |
121 | 228 | |
229 | =method defaultContext | |
230 | Returns the current default translation context settings as HASH. You should | |
231 | not modify the content of that HASH: change it by called M<setContext()> or | |
232 | M<updateContext()>. | |
233 | =cut | |
122 | 234 | |
123 | 235 | sub defaultContext() { shift->{LRD_ctxt_def} } |
124 | 236 | |
237 | =ci_method readConfig $filename | |
238 | Helper method, which simply parses the content $filename into a HASH to be | |
239 | used as parameters to M<configure()>. The filename must end on '.pl', | |
240 | to indicate that it uses perl syntax (can be processed with Perl's C<do> | |
241 | command) or end on '.json'. See also chapter L</Configuring> below. | |
242 | ||
243 | Currently, this file can be in Perl native format (when ending on C<.pl>) | |
244 | or JSON (when it ends with C<.json>). Various modules may explain parts | |
245 | of what can be found in these files, for instance | |
246 | M<Log::Report::Translator::Context>. | |
247 | =cut | |
125 | 248 | |
126 | 249 | sub readConfig($) |
127 | 250 | { my ($self, $fn) = @_; |
146 | 269 | } |
147 | 270 | |
148 | 271 | #------------------- |
272 | =section Action | |
273 | ||
274 | =method translate $message, $language | |
275 | Translate the $message into the $language. | |
276 | =cut | |
149 | 277 | |
150 | 278 | sub translate($$) |
151 | 279 | { my ($self, $msg, $lang) = @_; |
179 | 307 | 1; |
180 | 308 | |
181 | 309 | __END__ |
310 | =chapter DETAILS | |
311 | ||
312 | =section Configuring | |
313 | ||
314 | Configuration of a domain can happen in many ways: either explicitly or | |
315 | implicitly. The explicit form: | |
316 | ||
317 | package My::Package; | |
318 | use Log::Report 'my-domain'; | |
319 | ||
320 | textdomain 'my-domain', %configuration; | |
321 | textdomain->configure(%configuration); | |
322 | textdomain->configure(\%configuration); | |
323 | ||
324 | textdomain->configure(conf => $filename); | |
325 | ||
326 | The implicit form is (no variables possible, only constants!) | |
327 | ||
328 | package My::Package; | |
329 | use Log::Report 'my-domain', %configuration; | |
330 | use Log::Report 'my-domain', conf => '/filename'; | |
331 | ||
332 | You can only configure your domain in one place in your program. The | |
333 | textdomain setup is then used for all packages in the same domain. | |
334 | ||
335 | This also works for M<Log::Report::Optional>, which is a dressed-down | |
336 | version of M<Log::Report>. | |
337 | ||
338 | =subsection configuring your own formatter | |
339 | ||
340 | [0.91] The C<PRINTI> is a special constants for M<configure(formatter)>, and | |
341 | will use M<String::Print> function C<printi()>, with the standard tricks. | |
342 | ||
343 | textdomain 'some-domain' | |
344 | formatter => | |
345 | { class => 'String::Print' # default | |
346 | , method => 'sprinti' # default | |
347 | , %options # constructor options for the class | |
348 | ); | |
349 | ||
350 | When you want your own formatter, or configuration of C<String::Print>, | |
351 | you need to pass a CODE. Be aware that you may loose magic added by | |
352 | M<Log::Report> and other layers, like M<Log::Report::Template>: | |
353 | ||
354 | textdomain 'some-domain' | |
355 | , formatter => \&my_formatter; | |
356 | ||
357 | =subsection configuring global values | |
358 | ||
359 | Say, you log for a (Dancer) webserver, where you wish to include the website | |
360 | name in some of the log lines. For this, (ab)use the translation context: | |
361 | ||
362 | ### first enabled translation contexts | |
363 | use Log::Report 'my-domain', context_rules => {}; | |
364 | # or | |
365 | use Log::Report 'my-domain'; | |
366 | textdomain->configure(context_rules => {}); | |
367 | # or | |
368 | textdomain 'my-domain' | |
369 | , content_rules => {}; | |
370 | ||
371 | ### every time you start working for a different virtual host | |
372 | (textdomain 'my-domain')->setContext(host => $host); | |
373 | ||
374 | ### now you can use that in your code | |
375 | package My::Package; | |
376 | use Log::Report 'my-domain'; | |
377 | error __x"in {_context.host} not logged-in {user}", user => $username; | |
378 | ||
379 | =cut |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Domain - administer one text-domain | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Domain | |
9 | is a Log::Report::Minimal::Domain | |
10 | ||
11 | Log::Report::Domain is extended by | |
12 | Log::Report::Template::Textdomain | |
13 | ||
14 | =head1 SYNOPSIS | |
15 | ||
16 | # internal usage | |
17 | use Log::Report::Domain; | |
18 | my $domain = Log::Report::Domain->new(name => $name); | |
19 | ||
20 | # find a ::Domain object | |
21 | use Log::Report 'my-domain'; | |
22 | my $domain = textdomain 'my-domain'; # find domain config | |
23 | my $domain = textdomain; # config of this package | |
24 | ||
25 | # explicit domain configuration | |
26 | package My::Package; | |
27 | use Log::Report 'my-domain'; # set textdomain for package | |
28 | ||
29 | textdomain $name, %configure; # set config, once per program | |
30 | (textdomain $name)->configure(%configure); # same | |
31 | textdomain->configure(%configure); # same if current package in $name | |
32 | ||
33 | # implicit domain configuration | |
34 | package My::Package; | |
35 | use Log::Report 'my-domain', %configure; | |
36 | ||
37 | # external file for configuration (perl or json format) | |
38 | use Log::Report 'my-domain', config => $filename; | |
39 | ||
40 | use Log::Report 'my-domain'; | |
41 | textdomain->configure(config => $filename); | |
42 | ||
43 | =head1 DESCRIPTION | |
44 | ||
45 | L<Log::Report> can handle multiple sets of packages at the same | |
46 | time: in the usual case a program consists of more than one software | |
47 | distribution, each containing a number of packages. Each module | |
48 | in an application belongs to one of these sets, by default the domain set | |
49 | 'default'. | |
50 | ||
51 | For C<Log::Report>, those packags sets are differentiated via the | |
52 | text-domain value in the C<use> statement: | |
53 | ||
54 | use Log::Report 'my-domain'; | |
55 | ||
56 | There are many things you can configure per (text)domain. This is not | |
57 | only related to translations, but also -for instance- for text formatting | |
58 | configuration. The administration for the configuration is managed in | |
59 | this package. | |
60 | ||
61 | Extends L<"DESCRIPTION" in Log::Report::Minimal::Domain|Log::Report::Minimal::Domain/"DESCRIPTION">. | |
62 | ||
63 | =head1 METHODS | |
64 | ||
65 | Extends L<"METHODS" in Log::Report::Minimal::Domain|Log::Report::Minimal::Domain/"METHODS">. | |
66 | ||
67 | =head2 Constructors | |
68 | ||
69 | Extends L<"Constructors" in Log::Report::Minimal::Domain|Log::Report::Minimal::Domain/"Constructors">. | |
70 | ||
71 | =over 4 | |
72 | ||
73 | =item Log::Report::Domain-E<gt>B<new>(%options) | |
74 | ||
75 | Create a new Domain object. | |
76 | ||
77 | -Option--Defined in --Default | |
78 | name Log::Report::Minimal::Domain <required> | |
79 | ||
80 | =over 2 | |
81 | ||
82 | =item name => STRING | |
83 | ||
84 | =back | |
85 | ||
86 | =back | |
87 | ||
88 | =head2 Attributes | |
89 | ||
90 | Extends L<"Attributes" in Log::Report::Minimal::Domain|Log::Report::Minimal::Domain/"Attributes">. | |
91 | ||
92 | =over 4 | |
93 | ||
94 | =item $obj-E<gt>B<configure>(%options) | |
95 | ||
96 | The import is automatically called when the package is compiled. For all | |
97 | but one packages in your distribution, it will only contain the name of | |
98 | the DOMAIN. For one package, it will contain configuration information. | |
99 | These %options are used for all packages which use the same DOMAIN. | |
100 | See chapter L</Configuring> below. | |
101 | ||
102 | -Option --Defined in --Default | |
103 | config undef | |
104 | context_rules undef | |
105 | formatter PRINTI | |
106 | native_language 'en_US' | |
107 | translator created internally | |
108 | where Log::Report::Minimal::Domain <required> | |
109 | ||
110 | =over 2 | |
111 | ||
112 | =item config => FILENAME | |
113 | ||
114 | Read the settings from the file. The parameters found in the file are | |
115 | used as default for the parameters above. This parameter is especially | |
116 | useful for the C<context_rules>, which need to be shared between the | |
117 | running application and F<xgettext-perl>. See L<readConfig()|Log::Report::Domain/"Attributes"> | |
118 | ||
119 | =item context_rules => HASH|OBJECT | |
120 | ||
121 | When rules are provided, the translator will use the C<msgctxt> fields | |
122 | as provided by PO-files (gettext). This parameter is used to initialize | |
123 | a L<Log::Report::Translator::Context|Log::Report::Translator::Context> helper object. | |
124 | ||
125 | =item formatter => CODE|HASH|'PRINTI' | |
126 | ||
127 | Selects the formatter used for the errors messages. The default is C<PRINTI>, | |
128 | which will use L<String::Print::printi()|String::Print/"FUNCTIONS">: interpolation with curly | |
129 | braces around the variable names. | |
130 | ||
131 | =item native_language => CODESET | |
132 | ||
133 | This is the language which you have used to write the translatable and | |
134 | the non-translatable messages in. In case no translation is needed, | |
135 | you still wish the system error messages to be in the same language | |
136 | as the report. Of course, each textdomain can define its own. | |
137 | ||
138 | =item translator => L<Log::Report::Translator|Log::Report::Translator>|HASH | |
139 | ||
140 | Set the object which will do the translations for this domain. | |
141 | ||
142 | =item where => ARRAY | |
143 | ||
144 | =back | |
145 | ||
146 | =item $obj-E<gt>B<contextRules>() | |
147 | ||
148 | =item $obj-E<gt>B<defaultContext>() | |
149 | ||
150 | Returns the current default translation context settings as HASH. You should | |
151 | not modify the content of that HASH: change it by called L<setContext()|Log::Report::Domain/"Attributes"> or | |
152 | L<updateContext()|Log::Report::Domain/"Attributes">. | |
153 | ||
154 | =item $obj-E<gt>B<isConfigured>() | |
155 | ||
156 | Inherited, see L<Log::Report::Minimal::Domain/"Attributes"> | |
157 | ||
158 | =item $obj-E<gt>B<name>() | |
159 | ||
160 | Inherited, see L<Log::Report::Minimal::Domain/"Attributes"> | |
161 | ||
162 | =item $obj-E<gt>B<nativeLanguage>() | |
163 | ||
164 | =item $obj-E<gt>B<readConfig>($filename) | |
165 | ||
166 | =item Log::Report::Domain-E<gt>B<readConfig>($filename) | |
167 | ||
168 | Helper method, which simply parses the content $filename into a HASH to be | |
169 | used as parameters to L<configure()|Log::Report::Domain/"Attributes">. The filename must end on '.pl', | |
170 | to indicate that it uses perl syntax (can be processed with Perl's C<do> | |
171 | command) or end on '.json'. See also chapter L</Configuring> below. | |
172 | ||
173 | Currently, this file can be in Perl native format (when ending on C<.pl>) | |
174 | or JSON (when it ends with C<.json>). Various modules may explain parts | |
175 | of what can be found in these files, for instance | |
176 | L<Log::Report::Translator::Context|Log::Report::Translator::Context>. | |
177 | ||
178 | =item $obj-E<gt>B<setContext>(STRING|HASH|ARRAY|PAIRS) | |
179 | ||
180 | Temporary set the default translation context for messages. This is used | |
181 | when the message is created without a C<_context> parameter. The context | |
182 | can be retrieved with L<defaultContext()|Log::Report::Domain/"Attributes">. | |
183 | ||
184 | Contexts are totally ignored then there are no C<context_rules>. When | |
185 | you do not wish to change settings, you may simply provide a HASH. | |
186 | ||
187 | example: | |
188 | ||
189 | use Log::Report 'my-domain', context_rules => {}; | |
190 | ||
191 | =item $obj-E<gt>B<translator>() | |
192 | ||
193 | =item $obj-E<gt>B<updateContext>(STRING|HASH|ARRAY|PAIRS) | |
194 | ||
195 | [1.10] Make changes and additions to the active context (see L<setContext()|Log::Report::Domain/"Attributes">). | |
196 | ||
197 | =back | |
198 | ||
199 | =head2 Action | |
200 | ||
201 | Extends L<"Action" in Log::Report::Minimal::Domain|Log::Report::Minimal::Domain/"Action">. | |
202 | ||
203 | =over 4 | |
204 | ||
205 | =item $obj-E<gt>B<interpolate>( $msgid, [$args] ) | |
206 | ||
207 | Inherited, see L<Log::Report::Minimal::Domain/"Action"> | |
208 | ||
209 | =item $obj-E<gt>B<translate>($message, $language) | |
210 | ||
211 | Translate the $message into the $language. | |
212 | ||
213 | =back | |
214 | ||
215 | =head1 DETAILS | |
216 | ||
217 | =head2 Configuring | |
218 | ||
219 | Configuration of a domain can happen in many ways: either explicitly or | |
220 | implicitly. The explicit form: | |
221 | ||
222 | package My::Package; | |
223 | use Log::Report 'my-domain'; | |
224 | ||
225 | textdomain 'my-domain', %configuration; | |
226 | textdomain->configure(%configuration); | |
227 | textdomain->configure(\%configuration); | |
228 | ||
229 | textdomain->configure(conf => $filename); | |
230 | ||
231 | The implicit form is (no variables possible, only constants!) | |
232 | ||
233 | package My::Package; | |
234 | use Log::Report 'my-domain', %configuration; | |
235 | use Log::Report 'my-domain', conf => '/filename'; | |
236 | ||
237 | You can only configure your domain in one place in your program. The | |
238 | textdomain setup is then used for all packages in the same domain. | |
239 | ||
240 | This also works for L<Log::Report::Optional|Log::Report::Optional>, which is a dressed-down | |
241 | version of L<Log::Report|Log::Report>. | |
242 | ||
243 | =head3 configuring your own formatter | |
244 | ||
245 | [0.91] The C<PRINTI> is a special constants for L<configure(formatter)|Log::Report::Domain/"Attributes">, and | |
246 | will use L<String::Print|String::Print> function C<printi()>, with the standard tricks. | |
247 | ||
248 | textdomain 'some-domain' | |
249 | formatter => | |
250 | { class => 'String::Print' # default | |
251 | , method => 'sprinti' # default | |
252 | , %options # constructor options for the class | |
253 | ); | |
254 | ||
255 | When you want your own formatter, or configuration of C<String::Print>, | |
256 | you need to pass a CODE. Be aware that you may loose magic added by | |
257 | L<Log::Report|Log::Report> and other layers, like L<Log::Report::Template|Log::Report::Template>: | |
258 | ||
259 | textdomain 'some-domain' | |
260 | , formatter => \&my_formatter; | |
261 | ||
262 | =head3 configuring global values | |
263 | ||
264 | Say, you log for a (Dancer) webserver, where you wish to include the website | |
265 | name in some of the log lines. For this, (ab)use the translation context: | |
266 | ||
267 | ### first enabled translation contexts | |
268 | use Log::Report 'my-domain', context_rules => {}; | |
269 | # or | |
270 | use Log::Report 'my-domain'; | |
271 | textdomain->configure(context_rules => {}); | |
272 | # or | |
273 | textdomain 'my-domain' | |
274 | , content_rules => {}; | |
275 | ||
276 | ### every time you start working for a different virtual host | |
277 | (textdomain 'my-domain')->setContext(host => $host); | |
278 | ||
279 | ### now you can use that in your code | |
280 | package My::Package; | |
281 | use Log::Report 'my-domain'; | |
282 | error __x"in {_context.host} not logged-in {user}", user => $username; | |
283 | ||
284 | =head1 SEE ALSO | |
285 | ||
286 | This module is part of Log-Report distribution version 1.32, | |
287 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
288 | ||
289 | =head1 LICENSE | |
290 | ||
291 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
292 | ||
293 | This program is free software; you can redistribute it and/or modify it | |
294 | under the same terms as Perl itself. | |
295 | See F<http://dev.perl.org/licenses/> | |
296 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Exception; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | |
13 | 6 | use warnings; |
14 | 7 | use strict; |
18 | 11 | use POSIX qw/locale_h/; |
19 | 12 | use Scalar::Util qw/blessed/; |
20 | 13 | |
14 | =chapter NAME | |
15 | Log::Report::Exception - a collected report | |
16 | ||
17 | =chapter SYNOPSIS | |
18 | # created within a try block | |
19 | try { error "help!" }; | |
20 | my $exception = $@->wasFatal; | |
21 | $exception->throw if $exception; | |
22 | ||
23 | $@->reportFatal; # combination of above two lines | |
24 | ||
25 | my $message = $exception->message; # the Log::Report::Message | |
26 | ||
27 | if($message->inClass('die')) ... | |
28 | if($exception->inClass('die')) ... # same | |
29 | if($@->wasFatal(class => 'die')) ... # same | |
30 | ||
31 | =chapter DESCRIPTION | |
32 | In Log::Report, exceptions are not as extended as available in | |
33 | languages as Java: you do not create classes for them. The only | |
34 | thing an exception object does, is capture some information about | |
35 | an (untranslated) report. | |
36 | ||
37 | =chapter OVERLOADING | |
38 | ||
39 | =overload stringification | |
40 | Produces "reason: message". | |
41 | =cut | |
21 | 42 | |
22 | 43 | use overload |
23 | 44 | '""' => 'toString' |
24 | 45 | , 'bool' => sub {1} # avoid accidental serialization of message |
25 | 46 | , fallback => 1; |
26 | 47 | |
48 | =chapter METHODS | |
49 | ||
50 | =section Constructors | |
51 | =c_method new %options | |
52 | ||
53 | =option report_opts HASH | |
54 | =default report_opts {} | |
55 | ||
56 | =requires reason REASON | |
57 | =requires message Log::Report::Message | |
58 | =cut | |
27 | 59 | |
28 | 60 | sub new($@) |
29 | 61 | { my ($class, %args) = @_; |
32 | 64 | } |
33 | 65 | |
34 | 66 | #---------------- |
67 | =section Accessors | |
68 | ||
69 | =method report_opts | |
70 | =cut | |
35 | 71 | |
36 | 72 | sub report_opts() {shift->{report_opts}} |
37 | 73 | |
74 | =method reason [$reason] | |
75 | =cut | |
38 | 76 | |
39 | 77 | sub reason(;$) |
40 | 78 | { my $self = shift; |
41 | 79 | @_ ? $self->{reason} = uc(shift) : $self->{reason}; |
42 | 80 | } |
43 | 81 | |
82 | =method isFatal | |
83 | Returns whether this exception has a severity which makes it fatal | |
84 | when thrown. See M<Log::Report::Util::is_fatal()>. | |
85 | =example | |
86 | if($ex->isFatal) { $ex->throw(reason => 'ALERT') } | |
87 | else { $ex->throw } | |
88 | =cut | |
44 | 89 | |
45 | 90 | sub isFatal() { is_fatal shift->{reason} } |
46 | 91 | |
92 | =method message [$message] | |
93 | Change the $message of the exception, must be a M<Log::Report::Message> | |
94 | object. | |
95 | ||
96 | When you use a C<Log::Report::Message> object, you will get a new one | |
97 | returned. Therefore, if you want to modify the message in an exception, | |
98 | you have to re-assign the result of the modification. | |
99 | ||
100 | =examples | |
101 | $e->message->concat('!!')); # will not work! | |
102 | $e->message($e->message->concat('!!')); | |
103 | $e->message(__x"some message {msg}", msg => $xyz); | |
104 | =cut | |
47 | 105 | |
48 | 106 | sub message(;$) |
49 | 107 | { my $self = shift; |
56 | 114 | } |
57 | 115 | |
58 | 116 | #---------------- |
117 | =section Processing | |
118 | ||
119 | =method inClass $class|Regexp | |
120 | Check whether any of the classes listed in the message match $class | |
121 | (string) or the Regexp. This uses M<Log::Report::Message::inClass()>. | |
122 | =cut | |
59 | 123 | |
60 | 124 | sub inClass($) { $_[0]->message->inClass($_[1]) } |
61 | 125 | |
126 | =method throw %options | |
127 | Insert the message contained in the exception into the currently | |
128 | defined dispatchers. The C<throw> name is commonly known | |
129 | exception related terminology for C<report>. | |
130 | ||
131 | The %options overrule the captured options to M<Log::Report::report()>. | |
132 | This can be used to overrule a destination. Also, the reason can | |
133 | be changed. | |
134 | ||
135 | =example overrule defaults to report | |
136 | try { print {to => 'stderr'}, ERROR => 'oops!' }; | |
137 | $@->reportFatal(to => 'syslog'); | |
138 | ||
139 | $exception->throw(to => 'syslog'); | |
140 | ||
141 | $@->wasFatal->throw(reason => 'WARNING'); | |
142 | =cut | |
62 | 143 | |
63 | 144 | sub throw(@) |
64 | 145 | { my $self = shift; |
81 | 162 | # where the throw is handled is not interesting |
82 | 163 | sub PROPAGATE($$) {shift} |
83 | 164 | |
165 | =method toString [$locale] | |
166 | Prints the reason and the message. Differently from M<throw()>, this | |
167 | only represents the textual content: it does not re-cast the exceptions to | |
168 | higher levels. | |
169 | ||
170 | =examples printing exceptions | |
171 | print $_->toString for $@->exceptions; | |
172 | print $_ for $@->exceptions; # via overloading | |
173 | =cut | |
84 | 174 | |
85 | 175 | sub toString(;$) |
86 | 176 | { my ($self, $locale) = @_; |
88 | 178 | lc($self->{reason}).': '.(ref $msg ? $msg->toString($locale) : $msg)."\n"; |
89 | 179 | } |
90 | 180 | |
181 | =method toHTML [$locale] | |
182 | [1.11] as M<toString()>, and escape HTML volatile characters. | |
183 | =cut | |
91 | 184 | |
92 | 185 | sub toHTML(;$) { to_html($_[0]->toString($_[1])) } |
93 | 186 | |
187 | =method print [$fh] | |
188 | The default filehandle is STDOUT. | |
189 | ||
190 | =examples | |
191 | print $exception; # via overloading | |
192 | $exception->print; # OO style | |
193 | =cut | |
94 | 194 | |
95 | 195 | sub print(;$) |
96 | 196 | { my $self = shift; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Exception - a collected report | |
5 | ||
6 | =head1 SYNOPSIS | |
7 | ||
8 | # created within a try block | |
9 | try { error "help!" }; | |
10 | my $exception = $@->wasFatal; | |
11 | $exception->throw if $exception; | |
12 | ||
13 | $@->reportFatal; # combination of above two lines | |
14 | ||
15 | my $message = $exception->message; # the Log::Report::Message | |
16 | ||
17 | if($message->inClass('die')) ... | |
18 | if($exception->inClass('die')) ... # same | |
19 | if($@->wasFatal(class => 'die')) ... # same | |
20 | ||
21 | =head1 DESCRIPTION | |
22 | ||
23 | In Log::Report, exceptions are not as extended as available in | |
24 | languages as Java: you do not create classes for them. The only | |
25 | thing an exception object does, is capture some information about | |
26 | an (untranslated) report. | |
27 | ||
28 | =head1 METHODS | |
29 | ||
30 | =head2 Constructors | |
31 | ||
32 | =over 4 | |
33 | ||
34 | =item Log::Report::Exception-E<gt>B<new>(%options) | |
35 | ||
36 | -Option --Default | |
37 | message <required> | |
38 | reason <required> | |
39 | report_opts {} | |
40 | ||
41 | =over 2 | |
42 | ||
43 | =item message => Log::Report::Message | |
44 | ||
45 | =item reason => REASON | |
46 | ||
47 | =item report_opts => HASH | |
48 | ||
49 | =back | |
50 | ||
51 | =back | |
52 | ||
53 | =head2 Accessors | |
54 | ||
55 | =over 4 | |
56 | ||
57 | =item $obj-E<gt>B<isFatal>() | |
58 | ||
59 | Returns whether this exception has a severity which makes it fatal | |
60 | when thrown. See L<Log::Report::Util::is_fatal()|Log::Report::Util/"Reasons">. | |
61 | ||
62 | example: | |
63 | ||
64 | if($ex->isFatal) { $ex->throw(reason => 'ALERT') } | |
65 | else { $ex->throw } | |
66 | ||
67 | =item $obj-E<gt>B<message>( [$message] ) | |
68 | ||
69 | Change the $message of the exception, must be a L<Log::Report::Message|Log::Report::Message> | |
70 | object. | |
71 | ||
72 | When you use a C<Log::Report::Message> object, you will get a new one | |
73 | returned. Therefore, if you want to modify the message in an exception, | |
74 | you have to re-assign the result of the modification. | |
75 | ||
76 | example: | |
77 | ||
78 | $e->message->concat('!!')); # will not work! | |
79 | $e->message($e->message->concat('!!')); | |
80 | $e->message(__x"some message {msg}", msg => $xyz); | |
81 | ||
82 | =item $obj-E<gt>B<reason>( [$reason] ) | |
83 | ||
84 | =item $obj-E<gt>B<report_opts>() | |
85 | ||
86 | =back | |
87 | ||
88 | =head2 Processing | |
89 | ||
90 | =over 4 | |
91 | ||
92 | =item $obj-E<gt>B<inClass>($class|Regexp) | |
93 | ||
94 | Check whether any of the classes listed in the message match $class | |
95 | (string) or the Regexp. This uses L<Log::Report::Message::inClass()|Log::Report::Message/"Processing">. | |
96 | ||
97 | =item $obj-E<gt>B<print>( [$fh] ) | |
98 | ||
99 | The default filehandle is STDOUT. | |
100 | ||
101 | example: | |
102 | ||
103 | print $exception; # via overloading | |
104 | $exception->print; # OO style | |
105 | ||
106 | =item $obj-E<gt>B<throw>(%options) | |
107 | ||
108 | Insert the message contained in the exception into the currently | |
109 | defined dispatchers. The C<throw> name is commonly known | |
110 | exception related terminology for C<report>. | |
111 | ||
112 | The %options overrule the captured options to L<Log::Report::report()|Log::Report/"Report Production and Configuration">. | |
113 | This can be used to overrule a destination. Also, the reason can | |
114 | be changed. | |
115 | ||
116 | example: overrule defaults to report | |
117 | ||
118 | try { print {to => 'stderr'}, ERROR => 'oops!' }; | |
119 | $@->reportFatal(to => 'syslog'); | |
120 | ||
121 | $exception->throw(to => 'syslog'); | |
122 | ||
123 | $@->wasFatal->throw(reason => 'WARNING'); | |
124 | ||
125 | =item $obj-E<gt>B<toHTML>( [$locale] ) | |
126 | ||
127 | [1.11] as L<toString()|Log::Report::Exception/"Processing">, and escape HTML volatile characters. | |
128 | ||
129 | =item $obj-E<gt>B<toString>( [$locale] ) | |
130 | ||
131 | Prints the reason and the message. Differently from L<throw()|Log::Report::Exception/"Processing">, this | |
132 | only represents the textual content: it does not re-cast the exceptions to | |
133 | higher levels. | |
134 | ||
135 | example: printing exceptions | |
136 | ||
137 | print $_->toString for $@->exceptions; | |
138 | print $_ for $@->exceptions; # via overloading | |
139 | ||
140 | =back | |
141 | ||
142 | =head1 OVERLOADING | |
143 | ||
144 | =over 4 | |
145 | ||
146 | =item overload: B<stringification> | |
147 | ||
148 | Produces "reason: message". | |
149 | ||
150 | =back | |
151 | ||
152 | =head1 SEE ALSO | |
153 | ||
154 | This module is part of Log-Report distribution version 1.32, | |
155 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
156 | ||
157 | =head1 LICENSE | |
158 | ||
159 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
160 | ||
161 | This program is free software; you can redistribute it and/or modify it | |
162 | under the same terms as Perl itself. | |
163 | See F<http://dev.perl.org/licenses/> | |
164 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Message; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | |
13 | 6 | use warnings; |
14 | 7 | use strict; |
26 | 19 | *LC_MESSAGES = sub(){5} if $@; |
27 | 20 | } |
28 | 21 | |
22 | =chapter NAME | |
23 | Log::Report::Message - a piece of text to be translated | |
24 | ||
25 | =chapter SYNOPSIS | |
26 | # Objects created by Log::Report's __ functions | |
27 | # Full feature description in the DETAILS section | |
28 | ||
29 | # no interpolation | |
30 | __"Hello, World"; | |
31 | ||
32 | # with interpolation | |
33 | __x"age {years}", years => 12; | |
34 | ||
35 | # interpolation for one or many | |
36 | my $nr_files = @files; | |
37 | __nx"one file", "{_count} files", $nr_files; | |
38 | __nx"one file", "{_count} files", \@files; | |
39 | ||
40 | # interpolation of arrays | |
41 | __x"price-list: {prices%.2f}", prices => \@prices, _join => ', '; | |
42 | ||
43 | # white-spacing on msgid preserved | |
44 | print __"\tCongratulations,\n"; | |
45 | print "\t", __("Congratulations,"), "\n"; # same | |
46 | ||
47 | =chapter DESCRIPTION | |
48 | Any use of a translation function exported by M<Log::Report>, like | |
49 | C<__()> (the function is named underscore-underscore) or C<__x()> | |
50 | (underscore-underscore-x) will result in this object. It will capture | |
51 | some environmental information, and delay the translation until it | |
52 | is needed. | |
53 | ||
54 | Creating an object first and translating it later, is slower than | |
55 | translating it immediately. However, on the location where the message | |
56 | is produced, we do not yet know in what language to translate it to: | |
57 | that depends on the front-end, the log dispatcher. | |
58 | ||
59 | ||
60 | =chapter OVERLOADING | |
61 | ||
62 | =overload stringification | |
63 | When the object is used in string context, it will get translated. | |
64 | Implemented as M<toString()>. | |
65 | ||
66 | =overload as $function | |
67 | When the object is used to call as $function, a new object is | |
68 | created with the data from the original one but updated with the | |
69 | new parameters. Implemented in C<clone()>. | |
70 | ||
71 | =overload concatenation | |
72 | An (accidental) use of concatenation (a dot where a comma should be | |
73 | used) would immediately stringify the object. This is avoided by | |
74 | overloading that operation. | |
75 | =cut | |
29 | 76 | |
30 | 77 | use overload |
31 | 78 | '""' => 'toString' |
33 | 80 | , '.' => 'concat' |
34 | 81 | , fallback => 1; |
35 | 82 | |
83 | =chapter METHODS | |
84 | ||
85 | =section Constructors | |
86 | ||
87 | =c_method new %options | |
88 | B<End-users: do not use this method directly>, but use M<Log::Report::__()> | |
89 | and friends. The %options is a mixed list of object initiation parameters | |
90 | (all with a leading underscore) and variables to be filled in into the | |
91 | translated C<_msgid> string. | |
92 | ||
93 | =option _expand BOOLEAN | |
94 | =default _expand C<false> | |
95 | Indicates whether variables are to be filled-in. | |
96 | ||
97 | =option _domain STRING | |
98 | =default _domain <from "use Log::Report"> | |
99 | The text-domain (translation table) to which this C<_msgid> belongs. | |
100 | ||
101 | With this parameter, your can "borrow" translations from other textdomains. | |
102 | Be very careful with this (although there are good use-cases) The xgettext | |
103 | msgid extractor may add the used msgid to this namespace as well. To | |
104 | avoid that, add a harmless '+': | |
105 | ||
106 | print __x(+"errors", _domain => 'global'); | |
107 | ||
108 | The extractor will not take the msgid when it is an expression. The '+' | |
109 | has no effect on the string at runtime. | |
110 | ||
111 | =option _count INTEGER|ARRAY|HASH | |
112 | =default _count C<undef> | |
113 | When defined, the C<_plural> need to be defined as well. When an | |
114 | ARRAY is provided, the length of the ARRAY is taken. When a HASH | |
115 | is given, the number of keys in the HASH is used. | |
116 | ||
117 | =option _plural MSGID | |
118 | =default _plural C<undef> | |
119 | Can be used together with C<_count>. This plural form of the C<_msgid> | |
120 | text is used to simplify the work of translators, and as fallback when | |
121 | no translation is possible: therefore, this can best resemble an | |
122 | English message. | |
123 | ||
124 | White-space at the beginning and end of the string are stripped off. | |
125 | The white-space provided by the C<_msgid> will be used. | |
126 | ||
127 | =option _msgid MSGID | |
128 | =default _msgid C<undef> | |
129 | The message label, which refers to some translation information. | |
130 | Usually a string which is close the English version of the message. | |
131 | This will also be used if there is no translation possible/known. | |
132 | ||
133 | Leading white-space C<\s> will be added to C<_prepend>. Trailing | |
134 | white-space will be added before C<_append>. | |
135 | ||
136 | =option _category INTEGER | |
137 | =default _category C<undef> | |
138 | The category when the real gettext library is used, for instance | |
139 | LC_MESSAGES. | |
140 | ||
141 | =option _prepend STRING|MESSAGE | |
142 | =default _prepend C<undef> | |
143 | Text as STRING or MESSAGE object to be displayed before the display | |
144 | of this message. | |
145 | ||
146 | =option _append STRING|MESSAGE | |
147 | =default _append C<undef> | |
148 | Text as STRING or MESSAGE object to be displayed after the display | |
149 | of this message. | |
150 | ||
151 | =option _class STRING|ARRAY | |
152 | =default _class [] | |
153 | When messages are used for exception based programming, you add | |
154 | C<_class> parameters to the argument list. Later, with for instance | |
155 | M<Log::Report::Dispatcher::Try::wasFatal(class)>, you can check the | |
156 | category of the message. | |
157 | ||
158 | One message can be part of multiple classes. The STRING is used as | |
159 | comma- and/or blank separated list of class tokens (barewords), the | |
160 | ARRAY lists all tokens separately. See M<classes()>. | |
161 | ||
162 | =option _classes STRING|ARRAY | |
163 | =default _classes [] | |
164 | Alternative for C<_class>, which cannot be used at the same time. | |
165 | ||
166 | =option _to NAME | |
167 | =default _to <undef> | |
168 | Specify the NAME of a dispatcher as destination explicitly. Short | |
169 | for C<< report {to => NAME}, ... >> See M<to()> | |
170 | ||
171 | =option _join STRING | |
172 | =default _join C<$"> C<$LIST_SEPARATOR> | |
173 | Which STRING to be used then an ARRAY is being filled-in. | |
174 | ||
175 | =option _lang ISO | |
176 | =default _lang <from locale> | |
177 | [1.00] Override language setting from locale, for instance because that | |
178 | is not configured correctly (yet). This does not extend to prepended | |
179 | or appended translated message object. | |
180 | ||
181 | =option _context WORDS|ARRAY | |
182 | =default _context C<undef> | |
183 | [1.00] Set keywords which can be used to select alternatives | |
184 | between translations. Read the DETAILS section in | |
185 | M<Log::Report::Translator::Context> | |
186 | ||
187 | =option _msgctxt STRING | |
188 | =default _msgctxt C<undef> | |
189 | [1.22] Message context in the translation file, the traditional use. Cannot | |
190 | be combined with C<_context> on the same msgids. | |
191 | =cut | |
36 | 192 | |
37 | 193 | sub new($@) |
38 | 194 | { my ($class, %s) = @_; |
62 | 218 | # internal use only: to simplify __*p* functions |
63 | 219 | sub _msgctxt($) {$_[0]->{_msgctxt} = $_[1]; $_[0]} |
64 | 220 | |
221 | =method clone %options, $variables | |
222 | Returns a new object which copies info from original, and updates it | |
223 | with the specified %options and $variables. The advantage is that the | |
224 | cached translations are shared between the objects. | |
225 | ||
226 | =examples use of clone() | |
227 | my $s = __x "found {nr} files", nr => 5; | |
228 | my $t = $s->clone(nr => 3); | |
229 | my $t = $s->(nr => 3); # equivalent | |
230 | print $s; # found 5 files | |
231 | print $t; # found 3 files | |
232 | =cut | |
65 | 233 | |
66 | 234 | sub clone(@) |
67 | 235 | { my $self = shift; |
68 | 236 | (ref $self)->new(%$self, @_); |
69 | 237 | } |
70 | 238 | |
239 | =c_method fromTemplateToolkit $domain, $msgid, $params | |
240 | See M<Log::Report::Extract::Template> on the details how to integrate | |
241 | Log::Report translations with Template::Toolkit (version 1 and 2) | |
242 | =cut | |
71 | 243 | |
72 | 244 | sub fromTemplateToolkit($$;@) |
73 | 245 | { my ($class, $domain, $msgid) = splice @_, 0, 3; |
90 | 262 | } |
91 | 263 | |
92 | 264 | #---------------- |
265 | =section Accessors | |
266 | ||
267 | =method prepend | |
268 | Returns the string which is prepended to this one. Usually C<undef>. | |
269 | ||
270 | =method msgid | |
271 | Returns the msgid which will later be translated. | |
272 | ||
273 | =method append | |
274 | Returns the string or M<Log::Report::Message> object which is appended | |
275 | after this one. Usually C<undef>. | |
276 | ||
277 | =method domain | |
278 | Returns the domain of the first translatable string in the structure. | |
279 | ||
280 | =method count | |
281 | Returns the count, which is used to select the translation | |
282 | alternatives. | |
283 | ||
284 | =method context | |
285 | Returns an HASH if there is a context defined for this message. | |
286 | ||
287 | =method msgctxt | |
288 | The message context for the translation table lookup. | |
289 | =cut | |
93 | 290 | |
94 | 291 | sub prepend() {shift->{_prepend}} |
95 | 292 | sub msgid() {shift->{_msgid}} |
99 | 296 | sub context() {shift->{_context}} |
100 | 297 | sub msgctxt() {shift->{_msgctxt}} |
101 | 298 | |
299 | =method classes | |
300 | Returns the LIST of classes which are defined for this message; message | |
301 | group indicators, as often found in exception-based programming. | |
302 | =cut | |
102 | 303 | |
103 | 304 | sub classes() |
104 | 305 | { my $class = $_[0]->{_class} || $_[0]->{_classes} || []; |
105 | 306 | ref $class ? @$class : split(/[\s,]+/, $class); |
106 | 307 | } |
107 | 308 | |
309 | =method to [$name] | |
310 | Returns the $name of a dispatcher if explicitly specified with | |
311 | the '_to' key. Can also be used to set it. Usually, this will | |
312 | return undef, because usually all dispatchers get all messages. | |
313 | =cut | |
108 | 314 | |
109 | 315 | sub to(;$) |
110 | 316 | { my $self = shift; |
111 | 317 | @_ ? $self->{_to} = shift : $self->{_to}; |
112 | 318 | } |
113 | 319 | |
320 | =method valueOf $parameter | |
321 | Lookup the named $parameter for the message. All pre-defined names | |
322 | have their own method which should be used with preference. | |
323 | ||
324 | =example | |
325 | When the message was produced with | |
326 | ||
327 | my @files = qw/one two three/; | |
328 | my $msg = __xn "found one file: {file}" | |
329 | , "found {nrfiles} files: {files}" | |
330 | , scalar @files | |
331 | , file => $files[0] | |
332 | , files => \@files | |
333 | , nrfiles => @files+0 | |
334 | , _class => 'IO, files' | |
335 | , _join => ', '; | |
336 | ||
337 | then the values can be takes from the produced message as | |
338 | ||
339 | my $files = $msg->valueOf('files'); # returns ARRAY reference | |
340 | print @$files; # 3 | |
341 | my $count = $msg->count; # 3 | |
342 | my @class = $msg->classes; # 'IO', 'files' | |
343 | if($msg->inClass('files')) # true | |
344 | ||
345 | Simplified, the above example can also be written as: | |
346 | ||
347 | local $" = ', '; | |
348 | my $msg = __xn "found one file: {files}" | |
349 | , "found {_count} files: {files}" | |
350 | , @files # has scalar context | |
351 | , files => \@files | |
352 | , _class => 'IO, files'; | |
353 | ||
354 | ||
355 | =cut | |
114 | 356 | |
115 | 357 | sub valueOf($) { $_[0]->{$_[1]} } |
116 | 358 | |
117 | 359 | #-------------- |
360 | =section Processing | |
361 | ||
362 | =method inClass $class|Regexp | |
363 | Returns true if the message is in the specified $class (string) or | |
364 | matches the Regexp. The trueth value is the (first matching) class. | |
365 | =cut | |
118 | 366 | |
119 | 367 | sub inClass($) |
120 | 368 | { my @classes = shift->classes; |
123 | 371 | : (first { $_ eq $_[0] } @classes); |
124 | 372 | } |
125 | 373 | |
374 | =method toString [$locale] | |
375 | Translate a message. If not specified, the default locale is used. | |
376 | =cut | |
126 | 377 | |
127 | 378 | sub toString(;$) |
128 | 379 | { my ($self, $locale) = @_; |
169 | 420 | } |
170 | 421 | |
171 | 422 | |
423 | =method toHTML [$locale] | |
424 | [1.11] Translate the message, and then entity encode HTML volatile characters. | |
425 | ||
426 | [1.20] When used in combination with a templating system, you may want to | |
427 | use C<<content_for => 'HTML'>> in M<Log::Report::Domain::configure(formatter)>. | |
428 | ||
429 | =example | |
430 | ||
431 | print $msg->toHTML('NL'); | |
432 | ||
433 | =cut | |
172 | 434 | |
173 | 435 | my %tohtml = qw/ > gt < lt " quot & amp /; |
174 | 436 | |
175 | 437 | sub toHTML(;$) { to_html($_[0]->toString($_[1])) } |
176 | 438 | |
439 | =method untranslated | |
440 | Return the concatenation of the prepend, msgid, and append strings. Variable | |
441 | expansions within the msgid is not performed. | |
442 | =cut | |
177 | 443 | |
178 | 444 | sub untranslated() |
179 | 445 | { my $self = shift; |
182 | 448 | . (defined $self->{_append} ? $self->{_append} : ''); |
183 | 449 | } |
184 | 450 | |
451 | =method concat STRING|$object, [$prepend] | |
452 | This method implements the overloading of concatenation, which is needed | |
453 | to delay translations even longer. When $prepend is true, the STRING | |
454 | or $object (other C<Log::Report::Message>) needs to prepended, otherwise | |
455 | it is appended. | |
456 | ||
457 | =examples of concatenation | |
458 | print __"Hello" . ' ' . __"World!"; | |
459 | print __("Hello")->concat(' ')->concat(__"World!")->concat("\n"); | |
460 | ||
461 | =cut | |
185 | 462 | |
186 | 463 | sub concat($;$) |
187 | 464 | { my ($self, $what, $reversed) = @_; |
195 | 472 | } |
196 | 473 | |
197 | 474 | #---------------- |
475 | =chapter DETAILS | |
476 | ||
477 | =section OPTIONS and VARIABLES | |
478 | The M<Log::Report> functions which define translation request can all | |
479 | have OPTIONS. Some can have VARIABLES to be interpolated in the string as | |
480 | well. To distinguish between the OPTIONS and VARIABLES (both a list | |
481 | of key-value pairs), the keys of the OPTIONS start with an underscore C<_>. | |
482 | As result of this, please avoid the use of keys which start with an | |
483 | underscore in variable names. On the other hand, you are allowed to | |
484 | interpolate OPTION values in your strings. | |
485 | ||
486 | =subsection Interpolating | |
487 | With the C<__x()> or C<__nx()>, interpolation will take place on the | |
488 | translated MSGID string. The translation can contain the VARIABLE | |
489 | and OPTION names between curly brackets. Text between curly brackets | |
490 | which is not a known parameter will be left untouched. | |
491 | ||
492 | fault __x"cannot open open {filename}", filename => $fn; | |
493 | ||
494 | print __xn"directory {dir} contains one file" | |
495 | ,"directory {dir} contains {nr_files} files" | |
496 | , scalar(@files) # (1) (2) | |
497 | , nr_files => scalar @files # (3) | |
498 | , dir => $dir; | |
499 | ||
500 | (1) this required third parameter is used to switch between the different | |
501 | plural forms. English has only two forms, but some languages have many | |
502 | more. | |
503 | ||
504 | (2) the "scalar" keyword is not needed, because the third parameter is | |
505 | in SCALAR context. You may also pass C< \@files > there, because ARRAYs | |
506 | will be converted into their length. A HASH will be converted into the | |
507 | number of keys in the HASH. | |
508 | ||
509 | (3) the C<scalar> keyword is required here, because it is LIST context: | |
510 | otherwise all filenames will be filled-in as parameters to C<__xn()>. | |
511 | See below for the available C<_count> valure, to see how the C<nr_files> | |
512 | parameter can disappear. | |
513 | ||
514 | =subsection Interpolation of VARIABLES | |
515 | ||
516 | C<Log::Report> uses L<String::Print> to interpolate values in(translated) | |
517 | messages. This is a very powerful syntax, and you should certainly read | |
518 | that manual-page. Here, we only described additional features, specific | |
519 | to the usage of C<String::Print> in C<Log::Report::Message> objects. | |
520 | ||
521 | There is no way of checking beforehand whether you have provided all | |
522 | required values, to be interpolated in the translated string. | |
523 | ||
524 | For interpolating, the following rules apply: | |
525 | =over 4 | |
526 | =item * | |
527 | Simple scalar values are interpolated "as is" | |
528 | =item * | |
529 | References to SCALARs will collect the value on the moment that the | |
530 | output is made. The C<Log::Report::Message> object which is created with | |
531 | the C<__xn> can be seen as a closure. The translation can be reused. | |
532 | See example below. | |
533 | =item * | |
534 | Code references can be used to create the data "under fly". The | |
535 | C<Log::Report::Message> object which is being handled is passed as | |
536 | only argument. This is a hash in which all OPTIONS and VARIABLES | |
537 | can be found. | |
538 | =item * | |
539 | When the value is an ARRAY, all members will be interpolated with C<$"> | |
540 | between the elements. Alternatively (maybe nicer), you can pass an | |
541 | interpolation parameter via the C<_join> OPTION. | |
542 | =back | |
543 | ||
544 | local $" = ', '; | |
545 | error __x"matching files: {files}", files => \@files; | |
546 | ||
547 | error __x"matching files: {files}", files => \@files, _join => ', '; | |
548 | ||
549 | =subsection Interpolation of OPTIONS | |
550 | ||
551 | You are permitted the interpolate OPTION values in your string. This may | |
552 | simplify your coding. The useful names are: | |
553 | ||
554 | =over 4 | |
555 | =item _msgid | |
556 | The MSGID as provided with M<Log::Report::__()> and M<Log::Report::__x()> | |
557 | ||
558 | =item _plural, _count | |
559 | The PLURAL MSGIDs, respectively the COUNT as used with | |
560 | M<Log::Report::__n()> and M<Log::Report::__nx()> | |
561 | ||
562 | =item _textdomain | |
563 | The label of the textdomain in which the translation takes place. | |
564 | ||
565 | =item _class or _classes | |
566 | Are to be used to group reports, and can be queried with M<inClass()>, | |
567 | M<Log::Report::Exception::inClass()>, or | |
568 | M<Log::Report::Dispatcher::Try::wasFatal()>. | |
569 | =back | |
570 | ||
571 | =example using the _count | |
572 | With M<Locale::TextDomain>, you have to do | |
573 | ||
574 | use Locale::TextDomain; | |
575 | print __nx ( "One file has been deleted.\n" | |
576 | , "{num} files have been deleted.\n" | |
577 | , $num_files | |
578 | , num => $num_files | |
579 | ); | |
580 | ||
581 | With C<Log::Report>, you can do | |
582 | ||
583 | use Log::Report; | |
584 | print __nx ( "One file has been deleted.\n" | |
585 | , "{_count} files have been deleted.\n" | |
586 | , $num_files | |
587 | ); | |
588 | ||
589 | Of course, you need to be aware that the name used to reference the | |
590 | counter is fixed to C<_count>. The first example works as well, but | |
591 | is more verbose. | |
592 | ||
593 | =subsection Handling white-spaces | |
594 | ||
595 | In above examples, the msgid and plural form have a trailing new-line. | |
596 | In general, it is much easier to write | |
597 | ||
598 | print __x"Hello, World!\n"; | |
599 | ||
600 | than | |
601 | ||
602 | print __x("Hello, World!") . "\n"; | |
603 | ||
604 | For the translation tables, however, that trailing new-line is "over | |
605 | information"; it is an layout issue, not a translation issue. | |
606 | ||
607 | Therefore, the first form will automatically be translated into the | |
608 | second. All leading and trailing white-space (blanks, new-lines, tabs, | |
609 | ...) are removed from the msgid before the look-up, and then added to | |
610 | the translated string. | |
611 | ||
612 | Leading and trailing white-space on the plural form will also be | |
613 | removed. However, after translation the spacing of the msgid will | |
614 | be used. | |
615 | ||
616 | =subsection Avoiding repetative translations | |
617 | ||
618 | This way of translating is somewhat expensive, because an object to | |
619 | handle the C<__x()> is created each time. | |
620 | ||
621 | for my $i (1..100_000) | |
622 | { print __x "Hello World {i}\n", i => $i; | |
623 | } | |
624 | ||
625 | The suggestion that M<Locale::TextDomain> makes to improve performance, | |
626 | is to get the translation outside the loop, which only works without | |
627 | interpolation: | |
628 | ||
629 | use Locale::TextDomain; | |
630 | my $i = 42; | |
631 | my $s = __x("Hello World {i}\n", i => $i); | |
632 | foreach $i (1..100_000) | |
633 | { print $s; | |
634 | } | |
635 | ||
636 | Oops, not what you mean because the first value of C<$i> is captured | |
637 | in the initial message object. With Log::Report, you can do it (except | |
638 | when you use contexts) | |
639 | ||
640 | use Log::Report; | |
641 | my $i; | |
642 | my $s = __x("Hello World {i}\n", i => \$i); | |
643 | foreach $i (1..100_000) | |
644 | { print $s; | |
645 | } | |
646 | ||
647 | Mind you not to write: C<for my $i> in above case!!!! | |
648 | ||
649 | You can also write an incomplete translation: | |
650 | ||
651 | use Log::Report; | |
652 | my $s = __x "Hello World {i}\n"; | |
653 | foreach my $i (1..100_000) | |
654 | { print $s->(i => $i); | |
655 | } | |
656 | ||
657 | In either case, the translation will be looked-up only once. | |
658 | ||
659 | =cut | |
198 | 660 | |
199 | 661 | 1; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Message - a piece of text to be translated | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Message is extended by | |
9 | Dancer2::Plugin::LogReport::Message | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | # Objects created by Log::Report's __ functions | |
14 | # Full feature description in the DETAILS section | |
15 | ||
16 | # no interpolation | |
17 | __"Hello, World"; | |
18 | ||
19 | # with interpolation | |
20 | __x"age {years}", years => 12; | |
21 | ||
22 | # interpolation for one or many | |
23 | my $nr_files = @files; | |
24 | __nx"one file", "{_count} files", $nr_files; | |
25 | __nx"one file", "{_count} files", \@files; | |
26 | ||
27 | # interpolation of arrays | |
28 | __x"price-list: {prices%.2f}", prices => \@prices, _join => ', '; | |
29 | ||
30 | # white-spacing on msgid preserved | |
31 | print __"\tCongratulations,\n"; | |
32 | print "\t", __("Congratulations,"), "\n"; # same | |
33 | ||
34 | =head1 DESCRIPTION | |
35 | ||
36 | Any use of a translation function exported by L<Log::Report|Log::Report>, like | |
37 | C<__()> (the function is named underscore-underscore) or C<__x()> | |
38 | (underscore-underscore-x) will result in this object. It will capture | |
39 | some environmental information, and delay the translation until it | |
40 | is needed. | |
41 | ||
42 | Creating an object first and translating it later, is slower than | |
43 | translating it immediately. However, on the location where the message | |
44 | is produced, we do not yet know in what language to translate it to: | |
45 | that depends on the front-end, the log dispatcher. | |
46 | ||
47 | =head1 METHODS | |
48 | ||
49 | =head2 Constructors | |
50 | ||
51 | =over 4 | |
52 | ||
53 | =item $obj-E<gt>B<clone>(%options, $variables) | |
54 | ||
55 | Returns a new object which copies info from original, and updates it | |
56 | with the specified %options and $variables. The advantage is that the | |
57 | cached translations are shared between the objects. | |
58 | ||
59 | example: use of clone() | |
60 | ||
61 | my $s = __x "found {nr} files", nr => 5; | |
62 | my $t = $s->clone(nr => 3); | |
63 | my $t = $s->(nr => 3); # equivalent | |
64 | print $s; # found 5 files | |
65 | print $t; # found 3 files | |
66 | ||
67 | =item Log::Report::Message-E<gt>B<fromTemplateToolkit>($domain, $msgid, $params) | |
68 | ||
69 | See L<Log::Report::Extract::Template|Log::Report::Extract::Template> on the details how to integrate | |
70 | Log::Report translations with Template::Toolkit (version 1 and 2) | |
71 | ||
72 | =item Log::Report::Message-E<gt>B<new>(%options) | |
73 | ||
74 | B<End-users: do not use this method directly>, but use L<Log::Report::__()|Log::Report/"Messages (optionally translatable)"> | |
75 | and friends. The %options is a mixed list of object initiation parameters | |
76 | (all with a leading underscore) and variables to be filled in into the | |
77 | translated C<_msgid> string. | |
78 | ||
79 | -Option --Default | |
80 | _append undef | |
81 | _category undef | |
82 | _class [] | |
83 | _classes [] | |
84 | _context undef | |
85 | _count undef | |
86 | _domain <from "use Log::Report"> | |
87 | _expand false | |
88 | _join $" $LIST_SEPARATOR | |
89 | _lang <from locale> | |
90 | _msgctxt undef | |
91 | _msgid undef | |
92 | _plural undef | |
93 | _prepend undef | |
94 | _to <undef> | |
95 | ||
96 | =over 2 | |
97 | ||
98 | =item _append => STRING|MESSAGE | |
99 | ||
100 | Text as STRING or MESSAGE object to be displayed after the display | |
101 | of this message. | |
102 | ||
103 | =item _category => INTEGER | |
104 | ||
105 | The category when the real gettext library is used, for instance | |
106 | LC_MESSAGES. | |
107 | ||
108 | =item _class => STRING|ARRAY | |
109 | ||
110 | When messages are used for exception based programming, you add | |
111 | C<_class> parameters to the argument list. Later, with for instance | |
112 | L<Log::Report::Dispatcher::Try::wasFatal(class)|Log::Report::Dispatcher::Try/"Status">, you can check the | |
113 | category of the message. | |
114 | ||
115 | One message can be part of multiple classes. The STRING is used as | |
116 | comma- and/or blank separated list of class tokens (barewords), the | |
117 | ARRAY lists all tokens separately. See L<classes()|Log::Report::Message/"Accessors">. | |
118 | ||
119 | =item _classes => STRING|ARRAY | |
120 | ||
121 | Alternative for C<_class>, which cannot be used at the same time. | |
122 | ||
123 | =item _context => WORDS|ARRAY | |
124 | ||
125 | [1.00] Set keywords which can be used to select alternatives | |
126 | between translations. Read the DETAILS section in | |
127 | L<Log::Report::Translator::Context|Log::Report::Translator::Context> | |
128 | ||
129 | =item _count => INTEGER|ARRAY|HASH | |
130 | ||
131 | When defined, the C<_plural> need to be defined as well. When an | |
132 | ARRAY is provided, the length of the ARRAY is taken. When a HASH | |
133 | is given, the number of keys in the HASH is used. | |
134 | ||
135 | =item _domain => STRING | |
136 | ||
137 | The text-domain (translation table) to which this C<_msgid> belongs. | |
138 | ||
139 | With this parameter, your can "borrow" translations from other textdomains. | |
140 | Be very careful with this (although there are good use-cases) The xgettext | |
141 | msgid extractor may add the used msgid to this namespace as well. To | |
142 | avoid that, add a harmless '+': | |
143 | ||
144 | print __x(+"errors", _domain => 'global'); | |
145 | ||
146 | The extractor will not take the msgid when it is an expression. The '+' | |
147 | has no effect on the string at runtime. | |
148 | ||
149 | =item _expand => BOOLEAN | |
150 | ||
151 | Indicates whether variables are to be filled-in. | |
152 | ||
153 | =item _join => STRING | |
154 | ||
155 | Which STRING to be used then an ARRAY is being filled-in. | |
156 | ||
157 | =item _lang => ISO | |
158 | ||
159 | [1.00] Override language setting from locale, for instance because that | |
160 | is not configured correctly (yet). This does not extend to prepended | |
161 | or appended translated message object. | |
162 | ||
163 | =item _msgctxt => STRING | |
164 | ||
165 | [1.22] Message context in the translation file, the traditional use. Cannot | |
166 | be combined with C<_context> on the same msgids. | |
167 | ||
168 | =item _msgid => MSGID | |
169 | ||
170 | The message label, which refers to some translation information. | |
171 | Usually a string which is close the English version of the message. | |
172 | This will also be used if there is no translation possible/known. | |
173 | ||
174 | Leading white-space C<\s> will be added to C<_prepend>. Trailing | |
175 | white-space will be added before C<_append>. | |
176 | ||
177 | =item _plural => MSGID | |
178 | ||
179 | Can be used together with C<_count>. This plural form of the C<_msgid> | |
180 | text is used to simplify the work of translators, and as fallback when | |
181 | no translation is possible: therefore, this can best resemble an | |
182 | English message. | |
183 | ||
184 | White-space at the beginning and end of the string are stripped off. | |
185 | The white-space provided by the C<_msgid> will be used. | |
186 | ||
187 | =item _prepend => STRING|MESSAGE | |
188 | ||
189 | Text as STRING or MESSAGE object to be displayed before the display | |
190 | of this message. | |
191 | ||
192 | =item _to => NAME | |
193 | ||
194 | Specify the NAME of a dispatcher as destination explicitly. Short | |
195 | for C<< report {to => NAME}, ... >> See L<to()|Log::Report::Message/"Accessors"> | |
196 | ||
197 | =back | |
198 | ||
199 | =back | |
200 | ||
201 | =head2 Accessors | |
202 | ||
203 | =over 4 | |
204 | ||
205 | =item $obj-E<gt>B<append>() | |
206 | ||
207 | Returns the string or L<Log::Report::Message|Log::Report::Message> object which is appended | |
208 | after this one. Usually C<undef>. | |
209 | ||
210 | =item $obj-E<gt>B<classes>() | |
211 | ||
212 | Returns the LIST of classes which are defined for this message; message | |
213 | group indicators, as often found in exception-based programming. | |
214 | ||
215 | =item $obj-E<gt>B<context>() | |
216 | ||
217 | Returns an HASH if there is a context defined for this message. | |
218 | ||
219 | =item $obj-E<gt>B<count>() | |
220 | ||
221 | Returns the count, which is used to select the translation | |
222 | alternatives. | |
223 | ||
224 | =item $obj-E<gt>B<domain>() | |
225 | ||
226 | Returns the domain of the first translatable string in the structure. | |
227 | ||
228 | =item $obj-E<gt>B<msgctxt>() | |
229 | ||
230 | The message context for the translation table lookup. | |
231 | ||
232 | =item $obj-E<gt>B<msgid>() | |
233 | ||
234 | Returns the msgid which will later be translated. | |
235 | ||
236 | =item $obj-E<gt>B<prepend>() | |
237 | ||
238 | Returns the string which is prepended to this one. Usually C<undef>. | |
239 | ||
240 | =item $obj-E<gt>B<to>( [$name] ) | |
241 | ||
242 | Returns the $name of a dispatcher if explicitly specified with | |
243 | the '_to' key. Can also be used to set it. Usually, this will | |
244 | return undef, because usually all dispatchers get all messages. | |
245 | ||
246 | =item $obj-E<gt>B<valueOf>($parameter) | |
247 | ||
248 | Lookup the named $parameter for the message. All pre-defined names | |
249 | have their own method which should be used with preference. | |
250 | ||
251 | example: | |
252 | ||
253 | When the message was produced with | |
254 | ||
255 | my @files = qw/one two three/; | |
256 | my $msg = __xn "found one file: {file}" | |
257 | , "found {nrfiles} files: {files}" | |
258 | , scalar @files | |
259 | , file => $files[0] | |
260 | , files => \@files | |
261 | , nrfiles => @files+0 | |
262 | , _class => 'IO, files' | |
263 | , _join => ', '; | |
264 | ||
265 | then the values can be takes from the produced message as | |
266 | ||
267 | my $files = $msg->valueOf('files'); # returns ARRAY reference | |
268 | print @$files; # 3 | |
269 | my $count = $msg->count; # 3 | |
270 | my @class = $msg->classes; # 'IO', 'files' | |
271 | if($msg->inClass('files')) # true | |
272 | ||
273 | Simplified, the above example can also be written as: | |
274 | ||
275 | local $" = ', '; | |
276 | my $msg = __xn "found one file: {files}" | |
277 | , "found {_count} files: {files}" | |
278 | , @files # has scalar context | |
279 | , files => \@files | |
280 | , _class => 'IO, files'; | |
281 | ||
282 | =back | |
283 | ||
284 | =head2 Processing | |
285 | ||
286 | =over 4 | |
287 | ||
288 | =item $obj-E<gt>B<concat>( STRING|$object, [$prepend] ) | |
289 | ||
290 | This method implements the overloading of concatenation, which is needed | |
291 | to delay translations even longer. When $prepend is true, the STRING | |
292 | or $object (other C<Log::Report::Message>) needs to prepended, otherwise | |
293 | it is appended. | |
294 | ||
295 | example: of concatenation | |
296 | ||
297 | print __"Hello" . ' ' . __"World!"; | |
298 | print __("Hello")->concat(' ')->concat(__"World!")->concat("\n"); | |
299 | ||
300 | =item $obj-E<gt>B<inClass>($class|Regexp) | |
301 | ||
302 | Returns true if the message is in the specified $class (string) or | |
303 | matches the Regexp. The trueth value is the (first matching) class. | |
304 | ||
305 | =item $obj-E<gt>B<toHTML>( [$locale] ) | |
306 | ||
307 | [1.11] Translate the message, and then entity encode HTML volatile characters. | |
308 | ||
309 | [1.20] When used in combination with a templating system, you may want to | |
310 | use C<<content_for => 'HTML'>> in L<Log::Report::Domain::configure(formatter)|Log::Report::Domain/"Attributes">. | |
311 | ||
312 | example: | |
313 | ||
314 | print $msg->toHTML('NL'); | |
315 | ||
316 | =item $obj-E<gt>B<toString>( [$locale] ) | |
317 | ||
318 | Translate a message. If not specified, the default locale is used. | |
319 | ||
320 | =item $obj-E<gt>B<untranslated>() | |
321 | ||
322 | Return the concatenation of the prepend, msgid, and append strings. Variable | |
323 | expansions within the msgid is not performed. | |
324 | ||
325 | =back | |
326 | ||
327 | =head1 DETAILS | |
328 | ||
329 | =head2 OPTIONS and VARIABLES | |
330 | ||
331 | The L<Log::Report|Log::Report> functions which define translation request can all | |
332 | have OPTIONS. Some can have VARIABLES to be interpolated in the string as | |
333 | well. To distinguish between the OPTIONS and VARIABLES (both a list | |
334 | of key-value pairs), the keys of the OPTIONS start with an underscore C<_>. | |
335 | As result of this, please avoid the use of keys which start with an | |
336 | underscore in variable names. On the other hand, you are allowed to | |
337 | interpolate OPTION values in your strings. | |
338 | ||
339 | =head3 Interpolating | |
340 | ||
341 | With the C<__x()> or C<__nx()>, interpolation will take place on the | |
342 | translated MSGID string. The translation can contain the VARIABLE | |
343 | and OPTION names between curly brackets. Text between curly brackets | |
344 | which is not a known parameter will be left untouched. | |
345 | ||
346 | fault __x"cannot open open {filename}", filename => $fn; | |
347 | ||
348 | print __xn"directory {dir} contains one file" | |
349 | ,"directory {dir} contains {nr_files} files" | |
350 | , scalar(@files) # (1) (2) | |
351 | , nr_files => scalar @files # (3) | |
352 | , dir => $dir; | |
353 | ||
354 | (1) this required third parameter is used to switch between the different | |
355 | plural forms. English has only two forms, but some languages have many | |
356 | more. | |
357 | ||
358 | (2) the "scalar" keyword is not needed, because the third parameter is | |
359 | in SCALAR context. You may also pass C< \@files > there, because ARRAYs | |
360 | will be converted into their length. A HASH will be converted into the | |
361 | number of keys in the HASH. | |
362 | ||
363 | (3) the C<scalar> keyword is required here, because it is LIST context: | |
364 | otherwise all filenames will be filled-in as parameters to C<__xn()>. | |
365 | See below for the available C<_count> valure, to see how the C<nr_files> | |
366 | parameter can disappear. | |
367 | ||
368 | =head3 Interpolation of VARIABLES | |
369 | ||
370 | C<Log::Report> uses L<String::Print> to interpolate values in(translated) | |
371 | messages. This is a very powerful syntax, and you should certainly read | |
372 | that manual-page. Here, we only described additional features, specific | |
373 | to the usage of C<String::Print> in C<Log::Report::Message> objects. | |
374 | ||
375 | There is no way of checking beforehand whether you have provided all | |
376 | required values, to be interpolated in the translated string. | |
377 | ||
378 | For interpolating, the following rules apply: | |
379 | ||
380 | =over 4 | |
381 | ||
382 | =item * | |
383 | ||
384 | Simple scalar values are interpolated "as is" | |
385 | ||
386 | =item * | |
387 | ||
388 | References to SCALARs will collect the value on the moment that the | |
389 | output is made. The C<Log::Report::Message> object which is created with | |
390 | the C<__xn> can be seen as a closure. The translation can be reused. | |
391 | See example below. | |
392 | ||
393 | =item * | |
394 | ||
395 | Code references can be used to create the data "under fly". The | |
396 | C<Log::Report::Message> object which is being handled is passed as | |
397 | only argument. This is a hash in which all OPTIONS and VARIABLES | |
398 | can be found. | |
399 | ||
400 | =item * | |
401 | ||
402 | When the value is an ARRAY, all members will be interpolated with C<$"> | |
403 | between the elements. Alternatively (maybe nicer), you can pass an | |
404 | interpolation parameter via the C<_join> OPTION. | |
405 | ||
406 | =back | |
407 | ||
408 | local $" = ', '; | |
409 | error __x"matching files: {files}", files => \@files; | |
410 | ||
411 | error __x"matching files: {files}", files => \@files, _join => ', '; | |
412 | ||
413 | =head3 Interpolation of OPTIONS | |
414 | ||
415 | You are permitted the interpolate OPTION values in your string. This may | |
416 | simplify your coding. The useful names are: | |
417 | ||
418 | =over 4 | |
419 | ||
420 | =item _msgid | |
421 | ||
422 | The MSGID as provided with L<Log::Report::__()|Log::Report/"Messages (optionally translatable)"> and L<Log::Report::__x()|Log::Report/"Messages (optionally translatable)"> | |
423 | ||
424 | =item _plural, _count | |
425 | ||
426 | The PLURAL MSGIDs, respectively the COUNT as used with | |
427 | L<Log::Report::__n()|Log::Report/"Messages (optionally translatable)"> and L<Log::Report::__nx()|Log::Report/"Messages (optionally translatable)"> | |
428 | ||
429 | =item _textdomain | |
430 | ||
431 | The label of the textdomain in which the translation takes place. | |
432 | ||
433 | =item _class or _classes | |
434 | ||
435 | Are to be used to group reports, and can be queried with L<inClass()|Log::Report::Message/"Processing">, | |
436 | L<Log::Report::Exception::inClass()|Log::Report::Exception/"Processing">, or | |
437 | L<Log::Report::Dispatcher::Try::wasFatal()|Log::Report::Dispatcher::Try/"Status">. | |
438 | ||
439 | =back | |
440 | ||
441 | B<. Example: using the _count> | |
442 | ||
443 | With Locale::TextDomain, you have to do | |
444 | ||
445 | use Locale::TextDomain; | |
446 | print __nx ( "One file has been deleted.\n" | |
447 | , "{num} files have been deleted.\n" | |
448 | , $num_files | |
449 | , num => $num_files | |
450 | ); | |
451 | ||
452 | With C<Log::Report>, you can do | |
453 | ||
454 | use Log::Report; | |
455 | print __nx ( "One file has been deleted.\n" | |
456 | , "{_count} files have been deleted.\n" | |
457 | , $num_files | |
458 | ); | |
459 | ||
460 | Of course, you need to be aware that the name used to reference the | |
461 | counter is fixed to C<_count>. The first example works as well, but | |
462 | is more verbose. | |
463 | ||
464 | =head3 Handling white-spaces | |
465 | ||
466 | In above examples, the msgid and plural form have a trailing new-line. | |
467 | In general, it is much easier to write | |
468 | ||
469 | print __x"Hello, World!\n"; | |
470 | ||
471 | than | |
472 | ||
473 | print __x("Hello, World!") . "\n"; | |
474 | ||
475 | For the translation tables, however, that trailing new-line is "over | |
476 | information"; it is an layout issue, not a translation issue. | |
477 | ||
478 | Therefore, the first form will automatically be translated into the | |
479 | second. All leading and trailing white-space (blanks, new-lines, tabs, | |
480 | ...) are removed from the msgid before the look-up, and then added to | |
481 | the translated string. | |
482 | ||
483 | Leading and trailing white-space on the plural form will also be | |
484 | removed. However, after translation the spacing of the msgid will | |
485 | be used. | |
486 | ||
487 | =head3 Avoiding repetative translations | |
488 | ||
489 | This way of translating is somewhat expensive, because an object to | |
490 | handle the C<__x()> is created each time. | |
491 | ||
492 | for my $i (1..100_000) | |
493 | { print __x "Hello World {i}\n", i => $i; | |
494 | } | |
495 | ||
496 | The suggestion that Locale::TextDomain makes to improve performance, | |
497 | is to get the translation outside the loop, which only works without | |
498 | interpolation: | |
499 | ||
500 | use Locale::TextDomain; | |
501 | my $i = 42; | |
502 | my $s = __x("Hello World {i}\n", i => $i); | |
503 | foreach $i (1..100_000) | |
504 | { print $s; | |
505 | } | |
506 | ||
507 | Oops, not what you mean because the first value of C<$i> is captured | |
508 | in the initial message object. With Log::Report, you can do it (except | |
509 | when you use contexts) | |
510 | ||
511 | use Log::Report; | |
512 | my $i; | |
513 | my $s = __x("Hello World {i}\n", i => \$i); | |
514 | foreach $i (1..100_000) | |
515 | { print $s; | |
516 | } | |
517 | ||
518 | Mind you not to write: C<for my $i> in above case!!!! | |
519 | ||
520 | You can also write an incomplete translation: | |
521 | ||
522 | use Log::Report; | |
523 | my $s = __x "Hello World {i}\n"; | |
524 | foreach my $i (1..100_000) | |
525 | { print $s->(i => $i); | |
526 | } | |
527 | ||
528 | In either case, the translation will be looked-up only once. | |
529 | ||
530 | =head1 OVERLOADING | |
531 | ||
532 | =over 4 | |
533 | ||
534 | =item overload: B<as $function> | |
535 | ||
536 | When the object is used to call as $function, a new object is | |
537 | created with the data from the original one but updated with the | |
538 | new parameters. Implemented in C<clone()>. | |
539 | ||
540 | =item overload: B<concatenation> | |
541 | ||
542 | An (accidental) use of concatenation (a dot where a comma should be | |
543 | used) would immediately stringify the object. This is avoided by | |
544 | overloading that operation. | |
545 | ||
546 | =item overload: B<stringification> | |
547 | ||
548 | When the object is used in string context, it will get translated. | |
549 | Implemented as L<toString()|Log::Report::Message/"Processing">. | |
550 | ||
551 | =back | |
552 | ||
553 | =head1 SEE ALSO | |
554 | ||
555 | This module is part of Log-Report distribution version 1.32, | |
556 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
557 | ||
558 | =head1 LICENSE | |
559 | ||
560 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
561 | ||
562 | This program is free software; you can redistribute it and/or modify it | |
563 | under the same terms as Perl itself. | |
564 | See F<http://dev.perl.org/licenses/> | |
565 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report::Translator; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | |
13 | 6 | use warnings; |
14 | 7 | use strict; |
15 | 8 | |
16 | 9 | use Log::Report 'log-report'; |
17 | 10 | |
11 | =chapter NAME | |
12 | Log::Report::Translator - base implementation for translating messages | |
13 | ||
14 | =chapter SYNOPSIS | |
15 | # internal infrastructure | |
16 | my $msg = Log::Report::Message->new(_msgid => "Hello World\n"); | |
17 | print Log::Report::Translator->new(...)->translate($msg); | |
18 | ||
19 | # normal use | |
20 | textdomain 'my-domain' | |
21 | , translator => Log::Report::Translator->new; # default | |
22 | print __"Hello World\n"; | |
23 | ||
24 | =chapter DESCRIPTION | |
25 | A module (or distribution) has a certain way of translating messages, | |
26 | usually C<gettext>. The translator is based on some C<textdomain> | |
27 | for the message, which can be specified as option per text element, | |
28 | but usually is package scoped. | |
29 | ||
30 | This base class does not translate at all: it will use the MSGID | |
31 | (and MSGID_PLURAL if available). It's a nice fallback if the | |
32 | language packs are not installed. | |
33 | ||
34 | =chapter METHODS | |
35 | ||
36 | =section Constructors | |
37 | ||
38 | =c_method new %options | |
39 | ||
40 | =cut | |
18 | 41 | |
19 | 42 | sub new(@) { my $class = shift; (bless {}, $class)->init({@_}) } |
20 | 43 | sub init($) { shift } |
21 | 44 | |
22 | 45 | #------------ |
46 | =section Accessors | |
47 | ||
48 | =cut | |
23 | 49 | |
24 | 50 | #------------ |
51 | =section Translating | |
52 | ||
53 | =method translate $message, [$language, $ctxt] | |
54 | Returns the translation of the $message, a C<Log::Report::Message> object, | |
55 | based on the current locale. | |
56 | ||
57 | Translators are permitted to peek into the internal HASH of the | |
58 | message object, for performance reasons. | |
59 | =cut | |
25 | 60 | |
26 | 61 | # this is called as last resort: if a translator cannot find |
27 | 62 | # any lexicon or has no matching language. |
33 | 68 | : $msg->{_msgid}; |
34 | 69 | } |
35 | 70 | |
71 | =method load $domain, $locale | |
72 | Load the translation information in the text $domain for the indicated $locale. | |
73 | Multiple calls to M<load()> should not cost significant performance: the | |
74 | data must be cached. | |
75 | =cut | |
36 | 76 | |
37 | 77 | sub load($@) { undef } |
38 | 78 |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report::Translator - base implementation for translating messages | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report::Translator is extended by | |
9 | Log::Report::Translator::Gettext | |
10 | Log::Report::Translator::POT | |
11 | ||
12 | =head1 SYNOPSIS | |
13 | ||
14 | # internal infrastructure | |
15 | my $msg = Log::Report::Message->new(_msgid => "Hello World\n"); | |
16 | print Log::Report::Translator->new(...)->translate($msg); | |
17 | ||
18 | # normal use | |
19 | textdomain 'my-domain' | |
20 | , translator => Log::Report::Translator->new; # default | |
21 | print __"Hello World\n"; | |
22 | ||
23 | =head1 DESCRIPTION | |
24 | ||
25 | A module (or distribution) has a certain way of translating messages, | |
26 | usually C<gettext>. The translator is based on some C<textdomain> | |
27 | for the message, which can be specified as option per text element, | |
28 | but usually is package scoped. | |
29 | ||
30 | This base class does not translate at all: it will use the MSGID | |
31 | (and MSGID_PLURAL if available). It's a nice fallback if the | |
32 | language packs are not installed. | |
33 | ||
34 | =head1 METHODS | |
35 | ||
36 | =head2 Constructors | |
37 | ||
38 | =over 4 | |
39 | ||
40 | =item Log::Report::Translator-E<gt>B<new>(%options) | |
41 | ||
42 | =back | |
43 | ||
44 | =head2 Accessors | |
45 | ||
46 | =head2 Translating | |
47 | ||
48 | =over 4 | |
49 | ||
50 | =item $obj-E<gt>B<load>($domain, $locale) | |
51 | ||
52 | Load the translation information in the text $domain for the indicated $locale. | |
53 | Multiple calls to L<load()|Log::Report::Translator/"Translating"> should not cost significant performance: the | |
54 | data must be cached. | |
55 | ||
56 | =item $obj-E<gt>B<translate>( $message, [$language, $ctxt] ) | |
57 | ||
58 | Returns the translation of the $message, a C<Log::Report::Message> object, | |
59 | based on the current locale. | |
60 | ||
61 | Translators are permitted to peek into the internal HASH of the | |
62 | message object, for performance reasons. | |
63 | ||
64 | =back | |
65 | ||
66 | =head1 SEE ALSO | |
67 | ||
68 | This module is part of Log-Report distribution version 1.32, | |
69 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
70 | ||
71 | =head1 LICENSE | |
72 | ||
73 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
74 | ||
75 | This program is free software; you can redistribute it and/or modify it | |
76 | under the same terms as Perl itself. | |
77 | See F<http://dev.perl.org/licenses/> | |
78 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package Log::Report; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use base 'Exporter'; |
13 | 6 | |
14 | 7 | use warnings; |
58 | 51 | |
59 | 52 | my $default_dispatcher = dispatcher PERL => 'default', accept => 'NOTICE-'; |
60 | 53 | |
54 | =chapter NAME | |
55 | Log::Report - report a problem, with exceptions and translation support | |
56 | ||
57 | =chapter SYNOPSIS | |
58 | # Invocation with 'mode' to get trace and verbose messages | |
59 | use Log::Report mode => 'DEBUG'; | |
60 | ||
61 | # Usually invoked with a domain, which groups packages for translation | |
62 | use Log::Report 'my-domain', %options; | |
63 | ||
64 | # Interpolation syntax via String::Print | |
65 | # First step to translations, once you need it. | |
66 | print __x"my name is {name}", name => $n; # print, so no exception | |
67 | print __"Hello World\n"; # no interpolation, optional translation | |
68 | print __x'Hello World'; # SYNTAX ERROR!! ' is alternative for :: | |
69 | ||
70 | # Functions replacing die/warn/carp, casting exceptions. | |
71 | error "oops"; # exception like die(), no translation | |
72 | -f $config or panic "Help!"; # alert/error/fault/info/...more | |
73 | ||
74 | # Combined exception, interpolation, and optional translation | |
75 | error __x"Help!"; # __x() creates ::Message object | |
76 | error __x('gettext msgid', param => $value, ...) | |
77 | if $condition; | |
78 | ||
79 | # Also non fatal "exceptions" find their way to dispatchers | |
80 | info __x"started {pid}", pid => $$; # translatable | |
81 | debug "$i was here!"; # you probably do not want to translate debug | |
82 | panic "arrghhh"; # like Carp::Confess | |
83 | ||
84 | # Many destinations for an exception message (may exist in parallel) | |
85 | dispatcher PERL => 'default' # see Log::Report::Dispatcher: use die/warn | |
86 | , reasons => 'NOTICE-'; # this dispatcher is already present at start | |
87 | ||
88 | dispatcher SYSLOG => 'syslog'# also send to syslog | |
89 | , charset => 'iso-8859-1' # explicit character conversions | |
90 | , locale => 'en_US'; # overrule user's locale | |
91 | ||
92 | dispatcher close => 'default'; # stop default die/warn dispatcher | |
93 | ||
94 | # Fill-in values, like Locale::TextDomain and gettext | |
95 | # See Log::Report::Message section DETAILS | |
96 | fault __x"cannot allocate {size} bytes", size => $size; | |
97 | fault "cannot allocate $size bytes"; # no translation, ok | |
98 | fault __x"cannot allocate $size bytes"; # not translatable, wrong | |
99 | ||
100 | # Translation depending on count | |
101 | # Leading and trailing whitespace stay magically outside translation | |
102 | # tables. @files in scalar context. Special parameter with _ | |
103 | print __xn"found one file\n", "found {_count} files", @files; | |
104 | ||
105 | # Borrow from an other text-domain (see M<Log::Report::Message>) | |
106 | print __x(+"errors in {line}", _domain => 'global', line => $line); | |
107 | ||
108 | # catch errors (implements hidden eval/die) | |
109 | try { error }; | |
110 | if($@) {...} # $@ isa Log::Report::Dispatcher::Try | |
111 | if(my $exception = $@->wasFatal) # ::Exception object | |
112 | ||
113 | # Language translations at the output component | |
114 | # Translation management via Log::Report::Lexicon | |
115 | use POSIX::1003::Locale qw/setlocale LC_ALL/; | |
116 | setlocale(LC_ALL, 'nl_NL'); | |
117 | info __"Hello World!"; # in Dutch, if translation table found | |
118 | ||
119 | # Exception classes, see Log::Report::Exception | |
120 | try { error __x"something", _class => 'parsing,schema' }; | |
121 | if($@->wasFatal->inClass('parsing')) ... | |
122 | ||
123 | =chapter DESCRIPTION | |
124 | Get messages to users and logs. C<Log::Report> combines three tasks | |
125 | which are closely related in one: | |
126 | =over 4 | |
127 | =item . logging (like L<Log::Log4Perl> and syslog), and | |
128 | =item . exceptions (like error and info), with | |
129 | =item . translations (like C<gettext> and L<Locale::TextDomain>) | |
130 | =back | |
131 | You B<do not need> to use this module for all three reasons: pick what | |
132 | you need now, maybe extend the usage later. Read more about how and | |
133 | why in the L</DETAILS> section, below. Especially, you should B<read | |
134 | about the REASON parameter>. | |
135 | ||
136 | Also, you can study this module swiftly via the article published in | |
137 | the German Perl C<$foo-magazine>. English version: | |
138 | F<http://perl.overmeer.net/log-report/papers/201306-PerlMagazine-article-en.html> | |
139 | ||
140 | =chapter FUNCTIONS | |
141 | ||
142 | =section Report Production and Configuration | |
143 | ||
144 | =function report [%options], $reason, $message|<STRING,$params>, | |
145 | ||
146 | The C<report> function is sending (for some $reason) a $message to be | |
147 | displayed or logged (by a `dispatcher'). This function is the core | |
148 | for M<error()>, M<info()> etc functions, which are nicer names for this | |
149 | exception throwing: better use those short names. | |
150 | ||
151 | The $reason is a string like 'ERROR' (for function C<error()>). | |
152 | The $message is a M<Log::Report::Message> object (which are created with | |
153 | the special translation syntax like M<__x()>). The $message may also | |
154 | be a plain string, or an M<Log::Report::Exception> object. The optional | |
155 | first parameter is a HASH which can be used to influence the dispatchers. | |
156 | ||
157 | The optional %options are listed below. Quite differently from other | |
158 | functions and methods, they have to be passed in a HASH as first parameter. | |
159 | ||
160 | This function returns the LIST of dispatchers which accepted the $message. | |
161 | When empty, no back-end has accepted it so the $message was "lost". | |
162 | Even when no back-end needs the message, the program will still exit | |
163 | when there is a $reason to C<die()>. | |
164 | ||
165 | =option to NAME|ARRAY-of-NAMEs | |
166 | =default to C<undef> | |
167 | Sent the $message only to the NAMEd dispatchers. Ignore unknown NAMEs. | |
168 | Still, the dispatcher needs to be enabled and accept the REASONs. | |
169 | ||
170 | =option errno INTEGER | |
171 | =default errno C<$!> or C<1> | |
172 | When the $reason includes the error text (See L</Run modes>), you can | |
173 | overrule the error code kept in C<$!>. In other cases, the return code | |
174 | defaults to C<1> (historical UNIX behavior). When the message $reason | |
175 | (combined with the run-mode) is severe enough to stop the program, | |
176 | this value as return code of the program. The use of this option itself | |
177 | will not trigger an C<die()>. | |
178 | ||
179 | =option stack ARRAY | |
180 | =default stack C<undef> | |
181 | When defined, that data is used to display the call stack. Otherwise, | |
182 | it is collected via C<caller()> if needed. | |
183 | ||
184 | =option location STRING | |
185 | =default location C<undef> | |
186 | When defined, this location is used in the display. Otherwise, it | |
187 | is determined automatically if needed. An empty string will disable | |
188 | any attempt to display this line. | |
189 | ||
190 | =option locale LOCALE | |
191 | =default locale C<undef> | |
192 | Use this specific locale, in stead of the user's preference. | |
193 | ||
194 | =option is_fatal BOOLEAN | |
195 | =default is_fatal <depends on reason> | |
196 | Some logged exceptions are fatal, other aren't. The default usually | |
197 | is correct. However, you may want an error to be caught (usually with | |
198 | M<try()>), redispatch it to syslog, but without it killing the main | |
199 | program. | |
200 | ||
201 | =examples for use of M<report()> | |
202 | # long syntax example | |
203 | report TRACE => "start processing now"; | |
204 | report INFO => '500: ' . __'Internal Server Error'; | |
205 | ||
206 | # explicit dispatcher, no translation | |
207 | report {to => 'syslog'}, NOTICE => "started process $$"; | |
208 | notice "started process $$", _to => 'syslog'; # same | |
209 | ||
210 | # short syntax examples | |
211 | trace "start processing now"; | |
212 | warning __x'Disk {percent%.2f}% full', percent => $p | |
213 | if $p > 97; | |
214 | ||
215 | # error message, overruled to be printed in Brazilian | |
216 | report {locale => 'pt_BR'} | |
217 | , WARNING => "do this at home!"; | |
218 | ||
219 | =cut | |
61 | 220 | |
62 | 221 | sub report($@) |
63 | 222 | { my $opts = ref $_[0] eq 'HASH' ? +{ %{ (shift) } } : {}; |
169 | 328 | @disp; |
170 | 329 | } |
171 | 330 | |
331 | =function dispatcher <$type, $name, %options>|<$command, @names> | |
332 | ||
333 | The C<dispatcher> function controls access to dispatchers: the back-ends | |
334 | which process messages, do the logging. Dispatchers are global entities, | |
335 | addressed by a symbolic $name. Please read M<Log::Report::Dispatcher> as | |
336 | well. | |
337 | ||
338 | The C<Log::Report> suite has its own dispatcher @types, but also connects | |
339 | to external dispatching frameworks. Each need some (minor) conversions, | |
340 | especially with respect to translation of REASONS of the reports | |
341 | into log-levels as the back-end understands. | |
342 | ||
343 | [1.10] When you open a dispatcher with a $name which is already in use, | |
344 | that existing dispatcher gets closed. Except when you have given an | |
345 | 'dispatcher "do-not-reopen"' earlier, in which case the first object | |
346 | stays alive, and the second attempt ignored. [1.11] The automatically | |
347 | created default dispatcher will get replaced, even when this option | |
348 | is given, by another dispatcher which is named 'default'. | |
349 | ||
350 | The %options are a mixture of parameters needed for the | |
351 | Log::Report dispatcher wrapper and the settings of the back-end. | |
352 | See M<Log::Report::Dispatcher>, the documentation for the back-end | |
353 | specific wrappers, and the back-ends for more details. | |
354 | ||
355 | Implemented COMMANDs are C<close>, C<find>, C<list>, C<disable>, | |
356 | C<enable>, C<mode>, C<filter>, C<needs>, C<active-try>, and C<do-not-reopen>. | |
357 | ||
358 | Most commands are followed by a LIST of dispatcher @names to be addressed. | |
359 | For C<mode> see section L</Run modes>; it requires a MODE argument | |
360 | before the LIST of NAMEs. Non-existing names will be ignored. When | |
361 | C<ALL> is specified, then all existing dispatchers will get addressed. | |
362 | For C<filter> see L<Log::Report::Dispatcher/Filters>; it requires a CODE | |
363 | reference before the @names of the dispatchers which will have the it | |
364 | applied (defaults to all). | |
365 | ||
366 | With C<needs>, you only provide a REASON: it will return the list of | |
367 | dispatchers which need to be called in case of a message with the REASON | |
368 | is triggered. The C<active-try> [1.09] returns the closest surrounding | |
369 | exception catcher, a M<Log::Report::Dispatcher::Try> object. | |
370 | ||
371 | For both the creation as COMMANDs version of this method, all objects | |
372 | involved are returned as LIST, non-existing ones skipped. In SCALAR | |
373 | context with only one name, the one object is returned. | |
374 | ||
375 | =examples play with dispatchers | |
376 | dispatcher Log::Dispatcher::File => mylog => | |
377 | , accept => 'MISTAKE-' # for wrapper | |
378 | , locale => 'pt_BR' # other language | |
379 | , filename => 'logfile'; # for back-end | |
380 | ||
381 | dispatcher close => 'mylog'; # cleanup | |
382 | my $obj = dispatcher find => 'mylog'; | |
383 | my @obj = dispatcher 'list'; | |
384 | dispatcher disable => 'syslog'; | |
385 | dispatcher enable => 'mylog', 'syslog'; # more at a time | |
386 | dispatcher mode => 'DEBUG', 'mylog'; | |
387 | dispatcher mode => 'DEBUG', 'ALL'; | |
388 | my $catcher = dispatcher 'active-try'; | |
389 | dispatcher 'do-not-reopen'; | |
390 | ||
391 | my @need_info = dispatcher needs => 'INFO'; | |
392 | if(dispatcher needs => 'INFO') ... # anyone needs INFO | |
393 | ||
394 | # Getopt::Long integration: see Log::Report::Dispatcher::mode() | |
395 | dispatcher PERL => 'default', mode => 'DEBUG', accept => 'ALL' | |
396 | if $debug; | |
397 | ||
398 | =error in SCALAR context, only one dispatcher name accepted | |
399 | The M<dispatcher()> method returns the M<Log::Report::Dispatcher> | |
400 | objects which it has accessed. When multiple names where given, it | |
401 | wishes to return a LIST of objects, not the count of them. | |
402 | =cut | |
172 | 403 | |
173 | 404 | my %disp_actions = map +($_ => 1), qw/ |
174 | 405 | close find list disable enable mode needs filter active-try do-not-reopen |
285 | 516 | $reporter->{needs} = \%needs; |
286 | 517 | } |
287 | 518 | |
519 | =function try CODE, %options | |
520 | ||
521 | Execute the CODE while blocking all dispatchers as long as it is running. | |
522 | The exceptions which occur while running the CODE are caught until it | |
523 | has finished. When there where no fatal errors, the result of the CODE | |
524 | execution is returned. | |
525 | ||
526 | After the CODE was tried, the C<$@> will contain a | |
527 | M<Log::Report::Dispatcher::Try> object, which contains the collected | |
528 | messages. | |
529 | ||
530 | Run-time errors from Perl and die's, croak's and confess's within the | |
531 | program (which shouldn't appear, but you never know) are collected into an | |
532 | M<Log::Report::Message> object, using M<Log::Report::Die>. | |
533 | ||
534 | The %options are passed to the constructor of the try-dispatcher, see | |
535 | M<Log::Report::Dispatcher::Try::new()>. For instance, you may like to | |
536 | add C<< mode => 'DEBUG' >>, or C<< accept => 'ERROR-' >>. | |
537 | ||
538 | B<Be warned> that the parameter to C<try> is a CODE reference. This means | |
539 | that you shall not use a comma after the block when there are %options | |
540 | specified. On the other hand, you shall use a semi-colon after the | |
541 | block if there are no arguments. | |
542 | ||
543 | B<Be warned> that the {} are interpreted as subroutine, which means that, | |
544 | for instance, it has its own C<@_>. The manual-page of M<Try::Tiny> | |
545 | lists a few more side-effects of this. | |
546 | ||
547 | =examples | |
548 | my $x = try { 3/$x }; # mind the ';' !! | |
549 | if($@) { # signals something went wrong | |
550 | ||
551 | if(try {...}) { # block ended normally, returns bool | |
552 | ||
553 | try { ... } # no comma!! | |
554 | mode => 'DEBUG', accept => 'ERROR-'; | |
555 | ||
556 | try sub { ... }, # with comma, also \&function | |
557 | mode => 'DEBUG', accept => 'ALL'; | |
558 | ||
559 | my $response = try { $ua->request($request) }; | |
560 | if(my $e = $@->wasFatal) ... | |
561 | ||
562 | =cut | |
288 | 563 | |
289 | 564 | sub try(&@) |
290 | 565 | { my $code = shift; |
313 | 588 | my $is_exception = blessed $err && $err->isa('Log::Report::Exception'); |
314 | 589 | if(!$is_exception && $err && !$disp->wasFatal) |
315 | 590 | { # Decode exceptions which do not origin from Log::Report reports |
316 | ($err, my($opts, $reason, $text)) = blessed $err | |
591 | my($opts, $reason, $text) = blessed $err | |
317 | 592 | ? Log::Report::Die::exception_decode($err) |
318 | 593 | : Log::Report::Die::die_decode($err, on_die => $disp->die2reason); |
319 | 594 | |
329 | 604 | } |
330 | 605 | |
331 | 606 | #------------ |
607 | =section Abbreviations for report() | |
608 | ||
609 | The following functions are all wrappers for calls to M<report()>, | |
610 | and available when "syntax is SHORT" (by default, see M<import()>). | |
611 | You cannot specify additional options to influence the behavior of | |
612 | C<report()>, which are usually not needed anyway. | |
613 | ||
614 | =function trace $message | |
615 | Short for C<< report TRACE => $message >> | |
616 | =function assert $message | |
617 | Short for C<< report ASSERT => $message >> | |
618 | =function info $message | |
619 | Short for C<< report INFO => $message >> | |
620 | =function notice $message | |
621 | Short for C<< report NOTICE => $message >> | |
622 | =function warning $message | |
623 | Short for C<< report WARNING => $message >> | |
624 | =function mistake $message | |
625 | Short for C<< report MISTAKE => $message >> | |
626 | =function error $message | |
627 | Short for C<< report ERROR => $message >> | |
628 | =function fault $message | |
629 | Short for C<< report FAULT => $message >> | |
630 | =function alert $message | |
631 | Short for C<< report ALERT => $message >> | |
632 | =function failure $message | |
633 | Short for C<< report FAILURE => $message >> | |
634 | =function panic $message | |
635 | Short for C<< report PANIC => $message >> | |
636 | =cut | |
332 | 637 | |
333 | 638 | sub trace(@) {report TRACE => @_} |
334 | 639 | sub assert(@) {report ASSERT => @_} |
343 | 648 | sub panic(@) {report PANIC => @_} |
344 | 649 | |
345 | 650 | #------------- |
651 | =section Messages (optionally translatable) | |
652 | ||
653 | Even when you do not support translations (yet) you may want to use | |
654 | message objects to improve the logging feature. For instance, | |
655 | you get very powerful interpolation from M<String::Print>. | |
656 | ||
657 | The language translations are initiate by limited set of functions | |
658 | which contain B<two under-scores> (C<__>) in their name. Most | |
659 | of them return a M<Log::Report::Message> object. | |
660 | ||
661 | B<Be warned(1)> that -in general- its considered very bad practice to | |
662 | combine multiple translations into one message: translating may also | |
663 | affect the order of the translated components. Besides, when the person | |
664 | which translates only sees smaller parts of the text, his (or her) job | |
665 | becomes more complex. So: | |
666 | ||
667 | print __"Hello" . ', ' . __"World!"; # works, but to be avoided | |
668 | print __"Hello, World!"; # preferred, complete sentence | |
669 | ||
670 | The the former case, tricks with overloading used by the | |
671 | M<Log::Report::Message> objects will still make delayed translations | |
672 | work. | |
673 | ||
674 | In normal situations, it is not a problem to translate interpolated | |
675 | values: | |
676 | ||
677 | print __"the color is {c}", c => __"red"; | |
678 | ||
679 | B<Be warned(2)> that using C<< __'Hello' >> will produce a syntax error like | |
680 | "String found where operator expected at .... Can't find string terminator | |
681 | "'" anywhere before EOF". The first quote is the cause of the complaint, | |
682 | but the second generates the error. In the early days of Perl, the single | |
683 | quote was used to separate package name from function name, a role which | |
684 | was later replaced by a double-colon. So C<< __'Hello' >> gets interpreted | |
685 | as C<< __::Hello ' >>. Then, there is a trailing single quote which has | |
686 | no counterpart. | |
687 | ||
688 | =function __ $msgid | |
689 | This function (name is B<two> under-score characters) will cause the $msgid | |
690 | to be replaced by the translations when doing the actual output. Returned | |
691 | is a M<Log::Report::Message> object, which will be used in translation | |
692 | later. Translating is invoked when the object gets stringified. When | |
693 | you have no translation tables, the $msgid will be shown untranslated. | |
694 | ||
695 | If you need options for M<Log::Report::Message::new()> then use M<__x()>; | |
696 | the prototype of this function does not permit parameters: it is a | |
697 | prefix operator! | |
698 | ||
699 | =examples how to use __() | |
700 | print __"Hello World"; # translated into user's language | |
701 | print __'Hello World'; # syntax error! | |
702 | print __('Hello World'); # ok, translated | |
703 | print __"Hello", " World"; # World not translated | |
704 | ||
705 | my $s = __"Hello World"; # creates object, not yet translated | |
706 | print ref $s; # Log::Report::Message | |
707 | print $s; # ok, translated | |
708 | print $s->toString('fr'); # ok, forced into French | |
709 | =cut | |
346 | 710 | |
347 | 711 | |
348 | 712 | sub __($) |
354 | 718 | ); |
355 | 719 | } |
356 | 720 | |
721 | =function __x $msgid, PAIRS | |
722 | Translate the $msgid and then interpolate the VARIABLES in that string. | |
723 | Of course, translation and interpolation is delayed as long as possible. | |
724 | Both OPTIONS and VARIABLES are key-value pairs. | |
725 | ||
726 | The PAIRS are options for M<Log::Report::Message::new()> and variables | |
727 | to be filled in. | |
728 | =cut | |
357 | 729 | |
358 | 730 | # label "msgid" added before first argument |
359 | 731 | sub __x($@) |
371 | 743 | ); |
372 | 744 | } |
373 | 745 | |
746 | =function __n $msgid, $plural_msgid, $count, PAIRS | |
747 | It depends on the value of $count (and the selected language) which | |
748 | text will be displayed. When translations can not be performed, then | |
749 | $msgid will be used when $count is 1, and PLURAL_MSGSID in other cases. | |
750 | However, some languages have more complex schemes than English. | |
751 | ||
752 | The PAIRS are options for M<Log::Report::Message::new()> and variables | |
753 | to be filled in. | |
754 | ||
755 | =examples how to use __n() | |
756 | print __n "one", "more", $a; | |
757 | print __n("one", "more", $a), "\n"; | |
758 | print +(__n "one", "more", $a), "\n"; | |
759 | ||
760 | # new-lines are ignore at lookup, but printed. | |
761 | print __n "one\n", "more\n", $a; | |
762 | ||
763 | # count is in scalar context | |
764 | # the value is also available as _count | |
765 | print __n "found one\n", "found {_count}\n", @r; | |
766 | ||
767 | # ARRAYs and HASHes are counted | |
768 | print __n "one", "more", \@r; | |
769 | =cut | |
374 | 770 | |
375 | 771 | sub __n($$$@) |
376 | 772 | { my ($single, $plural, $count) = (shift, shift, shift); |
385 | 781 | ); |
386 | 782 | } |
387 | 783 | |
784 | =function __nx $msgid, $plural_msgid, $count, PAIRS | |
785 | It depends on the value of $count (and the selected language) which | |
786 | text will be displayed. See details in M<__n()>. After translation, | |
787 | the VARIABLES will be filled-in. | |
788 | ||
789 | The PAIRS are options for M<Log::Report::Message::new()> and variables | |
790 | to be filled in. | |
791 | ||
792 | =examples how to use __nx() | |
793 | print __nx "one file", "{_count} files", $nr_files; | |
794 | print __nx "one file", "{_count} files", @files; | |
795 | ||
796 | local $" = ', '; | |
797 | print __nx "one file: {f}", "{_count} files: {f}", @files, f => \@files; | |
798 | =cut | |
388 | 799 | |
389 | 800 | sub __nx($$$@) |
390 | 801 | { my ($single, $plural, $count) = (shift, shift, shift); |
400 | 811 | ); |
401 | 812 | } |
402 | 813 | |
814 | =function __xn $single_msgid, $plural_msgid, $count, $paurs | |
815 | Same as M<__nx()>, because we have no preferred order for 'x' and 'n'. | |
816 | =cut | |
403 | 817 | |
404 | 818 | sub __xn($$$@) # repeated for prototype |
405 | 819 | { my ($single, $plural, $count) = (shift, shift, shift); |
415 | 829 | ); |
416 | 830 | } |
417 | 831 | |
832 | =function N__ $msgid | |
833 | Label to indicate that the string is a text which will be translated | |
834 | later. The function itself does nothing. See also M<N__w()>. | |
835 | ||
836 | This no-op function is used as label to the xgettext program to build the | |
837 | translation tables. | |
838 | ||
839 | =example how to use N__() | |
840 | # add three msgids to the translation table | |
841 | my @colors = (N__"red", N__"green", N__"blue"); | |
842 | my @colors = N__w "red green blue"; # same | |
843 | print __ $colors[1]; # translate green | |
844 | ||
845 | # using M<__()>, would work as well | |
846 | my @colors = (__"red", __"green", __"blue"); | |
847 | print $colors[1]; | |
848 | # however: this will always create all M<Log::Report::Message> objects, | |
849 | # where maybe only one is used. | |
850 | =cut | |
418 | 851 | |
419 | 852 | sub N__($) { $_[0] } |
420 | 853 | |
854 | =function N__n $single_msgid, $plural_msgid | |
855 | Label to indicate that the two MSGIDs are related, the first as | |
856 | single, the seconds as its plural. Only used to find the text | |
857 | fragments to be translated. The function itself does nothing. | |
858 | =examples how to use M<N__n()> | |
859 | my @save = N__n "save file", "save files"; | |
860 | my @save = (N__n "save file", "save files"); | |
861 | my @save = N__n("save file", "save files"); | |
862 | ||
863 | # be warned about SCALARs in prototype! | |
864 | print __n @save, $nr_files; # wrong! | |
865 | print __n $save[0], $save[1], @files, %vars; | |
866 | =cut | |
421 | 867 | |
422 | 868 | sub N__n($$) {@_} |
423 | 869 | |
870 | =function N__w STRING | |
871 | This extension to the M<Locale::TextDomain> syntax, is a combined | |
872 | C<qw> (list of quoted words) and M<N__()> into a list of translatable | |
873 | words. | |
874 | ||
875 | =example of M<N__w()> | |
876 | my @colors = (N__"red", N__"green", N__"blue"); | |
877 | my @colors = N__w"red green blue"; # same | |
878 | print __ $colors[1]; | |
879 | =cut | |
424 | 880 | |
425 | 881 | sub N__w(@) {split " ", $_[0]} |
426 | 882 | |
427 | 883 | |
428 | 884 | #------------- |
885 | =subsection Messages with msgctxt | |
886 | ||
887 | In Log::Report, the message context (mgsctxt in the PO-files --in the | |
888 | translation tables) can be used in a very powerful way. Read all about | |
889 | it in M<Log::Report::Translator::Context> | |
890 | ||
891 | The msgctxt versions of the tranditional gettext infrastructure are far | |
892 | less useful for Log::Report, because we can easily work with different | |
893 | text domains within the same program. That should avoid most of the | |
894 | accidental translation conflicts between components of the code. | |
895 | ||
896 | Just for compatibility with M<Locale::TextDomain> and completeness, the | |
897 | 'p' versions of above methods are supported. See examples for these | |
898 | functions in M<Locale::TextDomain>. | |
899 | ||
900 | B<Warnings:> Functions C<N__p()> and C<N__np()> seem not to be usable in | |
901 | reality, hence not implemented. The script xgettext-perl and | |
902 | M<Log::Report::Extract::PerlPPI> (both in the M<Log::Report::Lexicon> | |
903 | distribution) do not yet support these functions. | |
904 | ||
905 | =function __p $msgctxt, $msgid | |
906 | =function __px $msgctxt, $msgid, PAIRS | |
907 | =function __np $msgctxt, $msgid, $plural, count | |
908 | =function __npx $msgctxt, $msgid, $plural, count, PAIRS | |
909 | ||
910 | =cut | |
429 | 911 | |
430 | 912 | sub __p($$) { __($_[0])->_msgctxt($_[1]) } |
431 | 913 | sub __px($$@) |
444 | 926 | } |
445 | 927 | |
446 | 928 | #------------- |
929 | =section Configuration | |
930 | ||
931 | =method import [$level,][$domain,] %options | |
932 | The import is automatically called when the package is compiled. For all | |
933 | packages but one in your distribution, it will only contain the name of | |
934 | the $domain. | |
935 | ||
936 | For one package, the import list may additionally contain textdomain | |
937 | configuration %options. These %options are used for all packages which | |
938 | use the same $domain. These are alternatives: | |
939 | ||
940 | # Do not use variables in the %*config! They are not yet initialized | |
941 | # when Log::Report->import is run!!! | |
942 | use Log::Report 'my-domain', %config, %domain_config; | |
943 | ||
944 | use Log::Report 'my-domain', %config; | |
945 | textdomain 'my-domain', %domain_config; # vars allowed | |
946 | ||
947 | The latter syntax has major advantages, when the configuration of the | |
948 | domain is determined at run-time. It is probably also easier to understand. | |
949 | ||
950 | See M<Log::Report::Domain::configure()>, for the B<list of %options> | |
951 | for the domain configuration. Here, we only list the options which are | |
952 | related to the normal import behavior. | |
953 | ||
954 | The export $level is a plus (+) followed by a number, for instance C<+1>, | |
955 | to indicate to on which caller level we need to work. This is used | |
956 | in M<Log::Report::Optional>. It defaults to '0': my direct caller. | |
957 | ||
958 | =option syntax 'REPORT'|'SHORT'|'LONG' | |
959 | =default syntax 'SHORT' | |
960 | The SHORT syntax will add the report abbreviations (like function | |
961 | M<error()>) to your name-space. Otherwise, each message must be produced | |
962 | with M<report()>. C<LONG> is an alternative to C<REPORT>: both do not | |
963 | pollute your namespace with the useful abbrev functions. | |
964 | ||
965 | =option mode LEVEL | |
966 | =default mode 'NORMAL' | |
967 | This sets the default mode for all created dispatchers. You can | |
968 | also selectively change the output mode, like | |
969 | dispatcher PERL => 'default', mode => 3 | |
970 | ||
971 | =option import FUNCTION|ARRAY | |
972 | =default import C<undef> | |
973 | [0.998] When not specified, the C<syntax> option determines the list | |
974 | of functions which are being exported. With this option, the C<syntax> | |
975 | option is ignored and only the specified FUNCTION(s) are imported. | |
976 | ||
977 | =option message_class CLASS | |
978 | =default message_class C<Log::Report::Message> | |
979 | [1.08] Use a more powerful message object class, for instance because | |
980 | your messages need extra attributes. The provided CLASS must extend | |
981 | M<Log::Report::Message> | |
982 | ||
983 | =examples of import | |
984 | use Log::Report mode => 3; # '3' or 'DEBUG' | |
985 | ||
986 | use Log::Report 'my-domain'; # in each package producing messages | |
987 | ||
988 | use Log::Report 'my-domain' # in one package, top of distr | |
989 | , mode => 'VERBOSE' | |
990 | , syntax => 'REPORT' # report ERROR, not error() | |
991 | , translator => Log::Report::Translator::POT->new | |
992 | ( lexicon => '/home/mine/locale' # translation tables | |
993 | ) | |
994 | , native_language => 'nl_NL'; # untranslated msgs are Dutch | |
995 | ||
996 | use Log::Report import => 'try'; # or ARRAY of functions | |
997 | ||
998 | =cut | |
447 | 999 | |
448 | 1000 | sub import(@) |
449 | 1001 | { my $class = shift; |
537 | 1089 | $domain->configure(translator => $translator, where => [$pkg, $fn, $line]); |
538 | 1090 | } |
539 | 1091 | |
1092 | =function textdomain <[$name],$config>|<$name, 'DELETE'|'EXISTS'>|$domain | |
1093 | [1.00] Without CONFIGuration, this returns the M<Log::Report::Domain> object | |
1094 | which administers the $domain, by default the domain effective in the scope | |
1095 | of the package. | |
1096 | ||
1097 | A very special case is "DELETE", which will remove the domain | |
1098 | configuration. [1.20] "EXISTS" will check for existence: when it exists, | |
1099 | it will be returned, but a domain will not be automagically created. | |
1100 | ||
1101 | [1.20] You may also pass a pre-configured domain. | |
1102 | =cut | |
540 | 1103 | |
541 | 1104 | sub textdomain(@) |
542 | 1105 | { if(@_==1 && blessed $_[0]) |
560 | 1123 | } |
561 | 1124 | |
562 | 1125 | #-------------- |
1126 | =section Reasons | |
1127 | ||
1128 | =c_method needs $reason, [$reasons] | |
1129 | Returns true when the reporter needs any of the $reasons, when any of | |
1130 | the active dispatchers is collecting messages in the specified level. | |
1131 | This is useful when the processing of data for the message is relatively | |
1132 | expensive, but for instance only required in debug mode. | |
1133 | ||
1134 | =example | |
1135 | if(Log::Report->needs('TRACE')) | |
1136 | { my @args = ...expensive calculation...; | |
1137 | trace "your options are: @args"; | |
1138 | } | |
1139 | =cut | |
563 | 1140 | |
564 | 1141 | sub needs(@) |
565 | 1142 | { my $thing = shift; |
567 | 1144 | first {$self->{needs}{$_}} @_; |
568 | 1145 | } |
569 | 1146 | |
1147 | =chapter DETAILS | |
1148 | ||
1149 | =section Introduction | |
1150 | ||
1151 | Getting messages to users and logs. The distincting concept of this module, | |
1152 | is that three tasks which are strongly related are merged into one simple | |
1153 | syntax. The three tasks: | |
1154 | ||
1155 | =over 4 | |
1156 | =item produce some text on a certain condition, | |
1157 | =item translate it to the proper language, and | |
1158 | =item deliver it in some way to a user. | |
1159 | =back | |
1160 | ||
1161 | Text messages in Perl are produced by commands like C<print>, C<die>, | |
1162 | C<warn>, C<carp>, or C<croak>. But where is that output directed to? | |
1163 | Translations is hard. There is no clean exception mechanism. | |
1164 | ||
1165 | Besides, the C<print>/C<warn>/C<die> together produce only three different | |
1166 | output "levels" with a message. Think of the variation syslog offers: | |
1167 | more than 7 levels. Many people manually implement their own tricks to | |
1168 | get additional levels, like verbose and debug flags. Log::Report offers | |
1169 | that variety. | |
1170 | ||
1171 | The (optional) translations use the beautiful syntax defined by | |
1172 | M<Locale::TextDomain>, with some own extensions (of course). A very | |
1173 | important difference is that translations are delayed till the delivery | |
1174 | step: until a dispatcher actually writes your message into a file, sends | |
1175 | it to syslog, or shows it on the screen. This means that the pop-up in | |
1176 | the graphical interface of the user may show the text in the language | |
1177 | of the user --say Chinese in utf8--, but at the same time syslog may | |
1178 | write the latin1 English version of the same message. | |
1179 | ||
1180 | =section Background ideas | |
1181 | ||
1182 | The following ideas are the base of this implementation: | |
1183 | ||
1184 | =over 4 | |
1185 | ||
1186 | =item . simplification | |
1187 | Handling errors and warnings is probably the most labor-intensive | |
1188 | task for a programmer: when programs are written correctly, up-to | |
1189 | three-quarters of the code is related to testing, reporting, and | |
1190 | handling (problem) conditions. Simplifying the way to create reports, | |
1191 | simplifies programming and maintenance. | |
1192 | ||
1193 | =item . multiple dispatchers | |
1194 | It is not the location where the (for instance) error occurs which | |
1195 | determines what will happen with the text, but the main application which | |
1196 | uses the the complaining module has control. Messages have a reason. | |
1197 | Based on the `reason' classification, they can get ignored, send to one | |
1198 | or multiple dispatchers, like M<Log::Dispatch>, M<Log::Log4perl>, | |
1199 | or UNIX syslog. | |
1200 | ||
1201 | =item . delayed translations | |
1202 | The background ideas are that of M<Locale::TextDomain>, based | |
1203 | on C<gettext()>. However, in the C<Log::Report> infrastructure, | |
1204 | translations are postponed until the text is dispatched to a screen | |
1205 | or log-file; the same report can be sent to syslog in (for instance) | |
1206 | English and to the user interface in Dutch. | |
1207 | ||
1208 | =item . context sensitive | |
1209 | Using contexts, you can set-up how to translate or rewrite messages, | |
1210 | to improve messages. A typical problem is whether to use gender in | |
1211 | text (use 'his' or 'her'): you can set a gender in a context, and the | |
1212 | use translation tables to pick the right one. | |
1213 | =back | |
1214 | ||
1215 | =section Error handling models | |
1216 | ||
1217 | There are two approaches to handling errors and warnings. In the first | |
1218 | approach, as produced by C<die>, C<warn> and the C<carp> family of | |
1219 | commands, the program handles the problem immediately on the location | |
1220 | where the problem appears. In the second approach, an I<exception> | |
1221 | is thrown on the spot where the problem is created, and then somewhere | |
1222 | else in the program the condition is handled. | |
1223 | ||
1224 | The implementation of exceptions in Perl5 is done with a eval-die pair: | |
1225 | on the spot where the problem occurs, C<die> is called. But, because of | |
1226 | the execution of that routine is placed within an C<eval>, the program | |
1227 | as a whole will not die, just the execution of a part of the program | |
1228 | will seize. However, what if the condition which caused the routine to die | |
1229 | is solvable on a higher level? Or what if the user of the code doesn't | |
1230 | bother that a part fails, because it has implemented alternatives for | |
1231 | that situation? Exception handling is quite clumsy in Perl5. | |
1232 | ||
1233 | The C<Log::Report> set of distributions let modules concentrate on the | |
1234 | program flow, and let the main program decide on the report handling | |
1235 | model. The infrastructure to translate messages into multiple languages, | |
1236 | whether to create exceptions or carp/die, to collect longer explanations | |
1237 | with the messages, to log to mail or syslog, and so on, is decided in | |
1238 | pluggable back-ends. | |
1239 | ||
1240 | =subsection The Reason for the report | |
1241 | ||
1242 | Traditionally, perl has a very simple view on error reports: you | |
1243 | either have a warning or an error. However, it would be much clearer | |
1244 | for user's and module-using applications, when a distinction is made | |
1245 | between various causes. For instance, a configuration error is quite | |
1246 | different from a disk-full situation. In C<Log::Report>, the produced | |
1247 | reports in the code tell I<what> is wrong. The main application defines | |
1248 | loggers, which interpret the cause into (syslog) levels. | |
1249 | ||
1250 | Defined by C<Log::Report> are | |
1251 | ||
1252 | =over 4 | |
1253 | =item . trace (debug, program) | |
1254 | The message will be used when some logger has debugging enabled. The | |
1255 | messages show steps taken by the program, which are of interest by the | |
1256 | developers and maintainers of the code, but not for end-users. | |
1257 | ||
1258 | =item . assert (program) | |
1259 | Shows an unexpected condition, but continues to run. When you want the | |
1260 | program to abort in such situation, that use C<panic>. | |
1261 | ||
1262 | =item . info (verbose, program) | |
1263 | These messages show larger steps in the execution of the program. | |
1264 | Experienced users of the program usually do not want to see all these | |
1265 | intermediate steps. Most programs will display info messages (and | |
1266 | higher) when some C<verbose> flag is given on the command-line. | |
1267 | ||
1268 | =item . notice (program) | |
1269 | An user may need to be aware of the program's accidental smart behavior, | |
1270 | for instance, that it initializes a lasting C<Desktop> directory in your | |
1271 | home directory. Notices should be sparse. | |
1272 | ||
1273 | =item . warning (program) | |
1274 | The program encountered some problems, but was able to work around it | |
1275 | by smart behavior. For instance, the program does not understand a | |
1276 | line from a log-file, but simply skips the line. | |
1277 | ||
1278 | =item . mistake (user) | |
1279 | When a user does something wrong, but what is correctable by smart | |
1280 | behavior of the program. For instance, in some configuration file, | |
1281 | you can fill-in "yes" or "no", but the user wrote "yeah". The program | |
1282 | interprets this as "yes", producing a mistake message as warning. | |
1283 | ||
1284 | It is much nicer to tell someone that he/she made a mistake, than | |
1285 | to call that an error. | |
1286 | ||
1287 | =item . error (user) | |
1288 | The user did something wrong, which is not automatically correctable | |
1289 | or the program is not willing to correct it automatically for reasons | |
1290 | of code quality. For instance, an unknown option flag is given on the | |
1291 | command-line. These are configuration issues, and have no useful | |
1292 | value in C<$!>. The program will be stopped, usually before taken off. | |
1293 | ||
1294 | =item . fault (system) | |
1295 | The program encountered a situation where it has no work-around. For | |
1296 | instance, a file cannot be opened to be written. The cause of that | |
1297 | problem can be some user error (i.e. wrong filename), or external | |
1298 | (you accidentally removed a directory yesterday). In any case, the | |
1299 | C<$!> (C<$ERRNO>) variable is set here. | |
1300 | ||
1301 | =item . alert (system) | |
1302 | Some external cause disturbs the execution of the program, but the | |
1303 | program stays alive and will try to continue operation. For instance, | |
1304 | the connection to the database is lost. After a few attempts, the | |
1305 | database can be reached and the program continues as if nothing happened. | |
1306 | The cause is external, so C<$!> is set. Usually, a system administrator | |
1307 | needs to be informed about the problem. | |
1308 | ||
1309 | =item . failure (system) | |
1310 | Some external cause makes it impossible for this program to continue. | |
1311 | C<$!> is set, and usually the system administrator wants to be | |
1312 | informed. The program will die. | |
1313 | ||
1314 | The difference with C<fault> is subtile and not always clear. A fault | |
1315 | reports an error returned by an operating system call, where the failure | |
1316 | would report an operational problem, like a failing mount. | |
1317 | ||
1318 | =item . panic (program) | |
1319 | All above report classes are expected: some predictable situation | |
1320 | is encountered, and therefore a message is produced. However, programs | |
1321 | often do some internal checking. Of course, these conditions should | |
1322 | never be triggered, but if they do... then we can only stop. | |
1323 | ||
1324 | For instance, in an OO perl module, the base class requires all | |
1325 | sub-classes to implement a certain method. The base class will produce | |
1326 | a stub method with triggers a panic when called. The non-dieing version | |
1327 | of this test C<assert>. | |
1328 | =back | |
1329 | ||
1330 | I<Debugging> or being C<verbose> are run-time behaviors, and have nothing | |
1331 | directly to do with the type of message which is produced. These two | |
1332 | are B<modes> which can be set on the dispatchers: one dispatcher may | |
1333 | be more verbose that some other. | |
1334 | ||
1335 | On purpose, we do not use the terms C<die> or C<fatal>, because the | |
1336 | dispatcher can be configured what to do in cause of which condition. | |
1337 | For instance, it may decide to stop execution on warnings as well. | |
1338 | ||
1339 | The terms C<carp> and C<croak> are avoided, because the program cause | |
1340 | versus user cause distinction (warn vs carp) is reflected in the use | |
1341 | of different reasons. There is no need for C<confess> and C<croak> | |
1342 | either, because the dispatcher can be configured to produce stack-trace | |
1343 | information (for a limited sub-set of dispatchers) | |
1344 | ||
1345 | =subsection Report levels | |
1346 | Various frameworks used with perl programs define different labels | |
1347 | to indicate the reason for the message to be produced. | |
1348 | ||
1349 | Perl5 Log::Dispatch Syslog Log4Perl Log::Report | |
1350 | print 0,debug debug debug trace | |
1351 | print 0,debug debug debug assert | |
1352 | print 1,info info info info | |
1353 | warn\n 2,notice notice info notice | |
1354 | warn 3,warning warn warn mistake | |
1355 | carp 3,warning warn warn warning | |
1356 | die\n 4,error err error error | |
1357 | die 5,critical crit fatal fault | |
1358 | croak 6,alert alert fatal alert | |
1359 | croak 7,emergency emerg fatal failure | |
1360 | confess 7,emergency emerg fatal panic | |
1361 | ||
1362 | =subsection Run modes | |
1363 | The run-mode change which messages are passed to a dispatcher, but | |
1364 | from a different angle than the dispatch filters; the mode changes | |
1365 | behavioral aspects of the messages, which are described in detail in | |
1366 | L<Log::Report::Dispatcher/Processing the message>. However, it should | |
1367 | behave as you expect: the DEBUG mode shows more than the VERBOSE mode, | |
1368 | and both show more than the NORMAL mode. | |
1369 | ||
1370 | =example extract run mode from Getopt::Long | |
1371 | The C<GetOptions()> function will count the number of C<v> options | |
1372 | on the command-line when a C<+> is after the option name. | |
1373 | ||
1374 | use Log::Report; | |
1375 | use Getopt::Long qw(:config no_ignore_case bundling); | |
1376 | ||
1377 | my $mode; # defaults to NORMAL | |
1378 | GetOptions 'v+' => \$mode | |
1379 | , 'verbose=i' => \$mode | |
1380 | , 'mode=s' => \$mode | |
1381 | or exit 1; | |
1382 | ||
1383 | dispatcher 'PERL', 'default', mode => $mode; | |
1384 | ||
1385 | Now, C<-vv> will set C<$mode> to C<2>, as will C<--verbose 2> and | |
1386 | C<--verbose=2> and C<--mode=ASSERT>. Of course, you do not need to | |
1387 | provide all these options to the user: make a choice. | |
1388 | ||
1389 | =example the mode of a dispatcher | |
1390 | my $mode = dispatcher(find => 'myname')->mode; | |
1391 | ||
1392 | =example run-time change mode of a dispatcher | |
1393 | To change the running mode of the dispatcher, you can do | |
1394 | dispatcher mode => DEBUG => 'myname'; | |
1395 | ||
1396 | However, be warned that this does not change the types of messages | |
1397 | accepted by the dispatcher! So: probably you will not receive | |
1398 | the trace, assert, and info messages after all. So, probably you | |
1399 | need to replace the dispatcher with a new one with the same name: | |
1400 | dispatcher FILE => 'myname', to => ..., mode => 'DEBUG'; | |
1401 | ||
1402 | This may reopen connections (depends on the actual dispatcher), which | |
1403 | might be not what you wish to happened. In that case, you must take | |
1404 | the following approach: | |
1405 | ||
1406 | # at the start of your program | |
1407 | dispatcher FILE => 'myname', to => ... | |
1408 | , accept => 'ALL'; # overrule the default 'NOTICE-' !! | |
1409 | ||
1410 | # now it works | |
1411 | dispatcher mode => DEBUG => 'myname'; # debugging on | |
1412 | ... | |
1413 | dispatcher mode => NORMAL => 'myname'; # debugging off | |
1414 | ||
1415 | Of course, this comes with a small overall performance penalty. | |
1416 | ||
1417 | =subsection Exceptions | |
1418 | ||
1419 | The simple view on live says: you 're dead when you die. However, | |
1420 | more complex situations try to revive the dead. Typically, the "die" | |
1421 | is considered a terminating exception, but not terminating the whole | |
1422 | program, but only some logical block. Of course, a wrapper round | |
1423 | that block must decide what to do with these emerging problems. | |
1424 | ||
1425 | Java-like languages do not "die" but throw exceptions which contain the | |
1426 | information about what went wrong. Perl modules like C<Exception::Class> | |
1427 | simulate this. It's a hassle to create exception class objects for each | |
1428 | emerging problem, and the same amount of work to walk through all the | |
1429 | options. | |
1430 | ||
1431 | Log::Report follows a simpler scheme. Fatal messages will "die", which is | |
1432 | caught with "eval", just the Perl way (used invisible to you). However, | |
1433 | the wrapper gets its hands on the message as the user has specified it: | |
1434 | untranslated, with all unprocessed parameters still at hand. | |
1435 | ||
1436 | try { fault __x "cannot open file {file}", file => $fn }; | |
1437 | if($@) # is Log::Report::Dispatcher::Try | |
1438 | { my $cause = $@->wasFatal; # is Log::Report::Exception | |
1439 | $cause->throw if $cause->message->msgid =~ m/ open /; | |
1440 | # all other problems ignored | |
1441 | } | |
1442 | ||
1443 | See M<Log::Report::Dispatcher::Try> and M<Log::Report::Exception>. | |
1444 | ||
1445 | =section Comparison | |
1446 | ||
1447 | Some notes on differences between the Log::Report approach and other | |
1448 | Perl concepts. | |
1449 | ||
1450 | =subsection die/warn/Carp | |
1451 | ||
1452 | Perl's built-in exception system is very primitive: "die" and "warn". | |
1453 | Most programming languages provide a much more detailed exception | |
1454 | mechanism. | |
1455 | ||
1456 | A typical perl program can look like this: | |
1457 | ||
1458 | my $dir = '/etc'; | |
1459 | ||
1460 | File::Spec->file_name is_absolute($dir) | |
1461 | or die "ERROR: directory name must be absolute.\n"; | |
1462 | ||
1463 | -d $dir | |
1464 | or die "ERROR: what platform are you on?"; | |
1465 | ||
1466 | until(opendir DIR, $dir) | |
1467 | { warn "ERROR: cannot read system directory $dir: $!"; | |
1468 | sleep 60; | |
1469 | } | |
1470 | ||
1471 | print "Processing directory $dir\n" | |
1472 | if $verbose; | |
1473 | ||
1474 | while(defined(my $file = readdir DIR)) | |
1475 | { if($file =~ m/\.bak$/) | |
1476 | { warn "WARNING: found backup file $dir/$f\n"; | |
1477 | next; | |
1478 | } | |
1479 | ||
1480 | die "ERROR: file $dir/$file is binary" | |
1481 | if $debug && -B "$dir/$file"; | |
1482 | ||
1483 | print "DEBUG: processing file $dir/$file\n" | |
1484 | if $debug; | |
1485 | ||
1486 | open FILE, "<", "$dir/$file" | |
1487 | or die "ERROR: cannot read from $dir/$f: $!"; | |
1488 | ||
1489 | close FILE | |
1490 | or croak "ERROR: read errors in $dir/$file: $!"; | |
1491 | } | |
1492 | ||
1493 | Where C<die>, C<warn>, and C<print> are used for various tasks. With | |
1494 | C<Log::Report>, you would write | |
1495 | ||
1496 | use Log::Report; | |
1497 | ||
1498 | # can be left-out when there is no debug/verbose | |
1499 | dispatcher PERL => 'default', mode => 'DEBUG'; | |
1500 | ||
1501 | my $dir = '/etc'; | |
1502 | ||
1503 | File::Spec->file_name is_absolute($dir) | |
1504 | or mistake "directory name must be absolute"; | |
1505 | ||
1506 | -d $dir | |
1507 | or panic "what platform are you on?"; | |
1508 | ||
1509 | until(opendir DIR, $dir) | |
1510 | { alert "cannot read system directory $dir"; | |
1511 | sleep 60; | |
1512 | } | |
1513 | ||
1514 | info "Processing directory $dir"; | |
1515 | ||
1516 | while(defined(my $file = readdir DIR)) | |
1517 | { if($file =~ m/\.bak$/) | |
1518 | { notice "found backup file $dir/$f"; | |
1519 | next; | |
1520 | } | |
1521 | ||
1522 | assert "file $dir/$file is binary" | |
1523 | if -B "$dir/$file"; | |
1524 | ||
1525 | trace "processing file $dir/$file"; | |
1526 | ||
1527 | unless(open FILE, "<", "$dir/$file") | |
1528 | { error "no permission to read from $dir/$f" | |
1529 | if $!==ENOPERM; | |
1530 | fault "unable to read from $dir/$f"; | |
1531 | } | |
1532 | ||
1533 | close FILE | |
1534 | or failure "read errors in $dir/$file"; | |
1535 | } | |
1536 | ||
1537 | A lot of things are quite visibly different, and there are a few smaller | |
1538 | changes. There is no need for a new-line after the text of the message. | |
1539 | When applicable (error about system problem), then the C<$!> is added | |
1540 | automatically. | |
1541 | ||
1542 | =subsection Log::Dispatch and Log::Log4perl | |
1543 | The two major logging frameworks for Perl are M<Log::Dispatch> and | |
1544 | M<Log::Log4perl>; both provide a pluggable logging interface. | |
1545 | ||
1546 | Both frameworks do not have (gettext or maketext) language translation | |
1547 | support, which has various consequences. When you wish for to report | |
1548 | in some other language, it must be translated before the logging | |
1549 | function is called. This may mean that an error message is produced | |
1550 | in Chinese, and therefore also ends-up in the syslog file in Chinese. | |
1551 | When this is not your language, you have a problem. | |
1552 | ||
1553 | Log::Report translates only in the back-end, which means that the user may | |
1554 | get the message in Chinese, but you get your report in your beloved Dutch. | |
1555 | When no dispatcher needs to report the message, then no time is lost in | |
1556 | translating. | |
1557 | ||
1558 | With both logging frameworks, you use terminology comparable to | |
1559 | syslog: the module programmer determines the seriousness of the | |
1560 | error message, not the application which integrates multiple modules. | |
1561 | This is the way perl programs usually work, but often the cause for | |
1562 | inconsequent user interaction. | |
1563 | ||
1564 | =subsection Locale::gettext and Locate::TextDomain | |
1565 | ||
1566 | Both on GNU gettext based implementations can be used as translation | |
1567 | frameworks. M<Locale::TextDomain> syntax is supported, with quite some | |
1568 | extensions. Read the excellent documentation of Locale::Textdomain. | |
1569 | Only the tried access via C<$__> and C<%__> are not supported. | |
1570 | ||
1571 | The main difference with these modules is the moment when the translation | |
1572 | takes place. In M<Locale::TextDomain>, an C<__x()> will result in an | |
1573 | immediate translation request via C<gettext()>. C<Log::Report>'s version | |
1574 | of C<__x()> will only capture what needs to be translated in an object. | |
1575 | When the object is used in a print statement, only then the translation | |
1576 | will take place. This is needed to offer ways to send different | |
1577 | translations of the message to different destinations. | |
1578 | ||
1579 | To be able to postpone translation, objects are returned which stringify | |
1580 | into the translated text. | |
1581 | ||
1582 | =cut | |
570 | 1583 | |
571 | 1584 | 1; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | Log::Report - report a problem, with exceptions and translation support | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | Log::Report | |
9 | is a Exporter | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | # Invocation with 'mode' to get trace and verbose messages | |
14 | use Log::Report mode => 'DEBUG'; | |
15 | ||
16 | # Usually invoked with a domain, which groups packages for translation | |
17 | use Log::Report 'my-domain', %options; | |
18 | ||
19 | # Interpolation syntax via String::Print | |
20 | # First step to translations, once you need it. | |
21 | print __x"my name is {name}", name => $n; # print, so no exception | |
22 | print __"Hello World\n"; # no interpolation, optional translation | |
23 | print __x'Hello World'; # SYNTAX ERROR!! ' is alternative for :: | |
24 | ||
25 | # Functions replacing die/warn/carp, casting exceptions. | |
26 | error "oops"; # exception like die(), no translation | |
27 | -f $config or panic "Help!"; # alert/error/fault/info/...more | |
28 | ||
29 | # Combined exception, interpolation, and optional translation | |
30 | error __x"Help!"; # __x() creates ::Message object | |
31 | error __x('gettext msgid', param => $value, ...) | |
32 | if $condition; | |
33 | ||
34 | # Also non fatal "exceptions" find their way to dispatchers | |
35 | info __x"started {pid}", pid => $$; # translatable | |
36 | debug "$i was here!"; # you probably do not want to translate debug | |
37 | panic "arrghhh"; # like Carp::Confess | |
38 | ||
39 | # Many destinations for an exception message (may exist in parallel) | |
40 | dispatcher PERL => 'default' # see Log::Report::Dispatcher: use die/warn | |
41 | , reasons => 'NOTICE-'; # this dispatcher is already present at start | |
42 | ||
43 | dispatcher SYSLOG => 'syslog'# also send to syslog | |
44 | , charset => 'iso-8859-1' # explicit character conversions | |
45 | , locale => 'en_US'; # overrule user's locale | |
46 | ||
47 | dispatcher close => 'default'; # stop default die/warn dispatcher | |
48 | ||
49 | # Fill-in values, like Locale::TextDomain and gettext | |
50 | # See Log::Report::Message section DETAILS | |
51 | fault __x"cannot allocate {size} bytes", size => $size; | |
52 | fault "cannot allocate $size bytes"; # no translation, ok | |
53 | fault __x"cannot allocate $size bytes"; # not translatable, wrong | |
54 | ||
55 | # Translation depending on count | |
56 | # Leading and trailing whitespace stay magically outside translation | |
57 | # tables. @files in scalar context. Special parameter with _ | |
58 | print __xn"found one file\n", "found {_count} files", @files; | |
59 | ||
60 | # Borrow from an other text-domain (see Log::Report::Message) | |
61 | print __x(+"errors in {line}", _domain => 'global', line => $line); | |
62 | ||
63 | # catch errors (implements hidden eval/die) | |
64 | try { error }; | |
65 | if($@) {...} # $@ isa Log::Report::Dispatcher::Try | |
66 | if(my $exception = $@->wasFatal) # ::Exception object | |
67 | ||
68 | # Language translations at the output component | |
69 | # Translation management via Log::Report::Lexicon | |
70 | use POSIX::1003::Locale qw/setlocale LC_ALL/; | |
71 | setlocale(LC_ALL, 'nl_NL'); | |
72 | info __"Hello World!"; # in Dutch, if translation table found | |
73 | ||
74 | # Exception classes, see Log::Report::Exception | |
75 | try { error __x"something", _class => 'parsing,schema' }; | |
76 | if($@->wasFatal->inClass('parsing')) ... | |
77 | ||
78 | =head1 DESCRIPTION | |
79 | ||
80 | Get messages to users and logs. C<Log::Report> combines three tasks | |
81 | which are closely related in one: | |
82 | ||
83 | =over 4 | |
84 | ||
85 | =item . logging (like L<Log::Log4Perl> and syslog), and | |
86 | ||
87 | =item . exceptions (like error and info), with | |
88 | ||
89 | =item . translations (like C<gettext> and L<Locale::TextDomain>) | |
90 | ||
91 | =back | |
92 | ||
93 | You B<do not need> to use this module for all three reasons: pick what | |
94 | you need now, maybe extend the usage later. Read more about how and | |
95 | why in the L</DETAILS> section, below. Especially, you should B<read | |
96 | about the REASON parameter>. | |
97 | ||
98 | Also, you can study this module swiftly via the article published in | |
99 | the German Perl C<$foo-magazine>. English version: | |
100 | F<http://perl.overmeer.net/log-report/papers/201306-PerlMagazine-article-en.html> | |
101 | ||
102 | =head1 FUNCTIONS | |
103 | ||
104 | =head2 Report Production and Configuration | |
105 | ||
106 | =over 4 | |
107 | ||
108 | =item B<dispatcher>( <$type, $name, %options>|<$command, @names> ) | |
109 | ||
110 | The C<dispatcher> function controls access to dispatchers: the back-ends | |
111 | which process messages, do the logging. Dispatchers are global entities, | |
112 | addressed by a symbolic $name. Please read L<Log::Report::Dispatcher|Log::Report::Dispatcher> as | |
113 | well. | |
114 | ||
115 | The C<Log::Report> suite has its own dispatcher @types, but also connects | |
116 | to external dispatching frameworks. Each need some (minor) conversions, | |
117 | especially with respect to translation of REASONS of the reports | |
118 | into log-levels as the back-end understands. | |
119 | ||
120 | [1.10] When you open a dispatcher with a $name which is already in use, | |
121 | that existing dispatcher gets closed. Except when you have given an | |
122 | 'dispatcher "do-not-reopen"' earlier, in which case the first object | |
123 | stays alive, and the second attempt ignored. [1.11] The automatically | |
124 | created default dispatcher will get replaced, even when this option | |
125 | is given, by another dispatcher which is named 'default'. | |
126 | ||
127 | The %options are a mixture of parameters needed for the | |
128 | Log::Report dispatcher wrapper and the settings of the back-end. | |
129 | See L<Log::Report::Dispatcher|Log::Report::Dispatcher>, the documentation for the back-end | |
130 | specific wrappers, and the back-ends for more details. | |
131 | ||
132 | Implemented COMMANDs are C<close>, C<find>, C<list>, C<disable>, | |
133 | C<enable>, C<mode>, C<filter>, C<needs>, C<active-try>, and C<do-not-reopen>. | |
134 | ||
135 | Most commands are followed by a LIST of dispatcher @names to be addressed. | |
136 | For C<mode> see section L</Run modes>; it requires a MODE argument | |
137 | before the LIST of NAMEs. Non-existing names will be ignored. When | |
138 | C<ALL> is specified, then all existing dispatchers will get addressed. | |
139 | For C<filter> see L<Log::Report::Dispatcher/Filters>; it requires a CODE | |
140 | reference before the @names of the dispatchers which will have the it | |
141 | applied (defaults to all). | |
142 | ||
143 | With C<needs>, you only provide a REASON: it will return the list of | |
144 | dispatchers which need to be called in case of a message with the REASON | |
145 | is triggered. The C<active-try> [1.09] returns the closest surrounding | |
146 | exception catcher, a L<Log::Report::Dispatcher::Try|Log::Report::Dispatcher::Try> object. | |
147 | ||
148 | For both the creation as COMMANDs version of this method, all objects | |
149 | involved are returned as LIST, non-existing ones skipped. In SCALAR | |
150 | context with only one name, the one object is returned. | |
151 | ||
152 | example: play with dispatchers | |
153 | ||
154 | dispatcher Log::Dispatcher::File => mylog => | |
155 | , accept => 'MISTAKE-' # for wrapper | |
156 | , locale => 'pt_BR' # other language | |
157 | , filename => 'logfile'; # for back-end | |
158 | ||
159 | dispatcher close => 'mylog'; # cleanup | |
160 | my $obj = dispatcher find => 'mylog'; | |
161 | my @obj = dispatcher 'list'; | |
162 | dispatcher disable => 'syslog'; | |
163 | dispatcher enable => 'mylog', 'syslog'; # more at a time | |
164 | dispatcher mode => 'DEBUG', 'mylog'; | |
165 | dispatcher mode => 'DEBUG', 'ALL'; | |
166 | my $catcher = dispatcher 'active-try'; | |
167 | dispatcher 'do-not-reopen'; | |
168 | ||
169 | my @need_info = dispatcher needs => 'INFO'; | |
170 | if(dispatcher needs => 'INFO') ... # anyone needs INFO | |
171 | ||
172 | # Getopt::Long integration: see Log::Report::Dispatcher::mode() | |
173 | dispatcher PERL => 'default', mode => 'DEBUG', accept => 'ALL' | |
174 | if $debug; | |
175 | ||
176 | =item B<report>( [%options], $reason, $message|<STRING,$params>, ) | |
177 | ||
178 | The C<report> function is sending (for some $reason) a $message to be | |
179 | displayed or logged (by a `dispatcher'). This function is the core | |
180 | for L<error()|Log::Report/"Abbreviations for report()">, L<info()|Log::Report/"Abbreviations for report()"> etc functions, which are nicer names for this | |
181 | exception throwing: better use those short names. | |
182 | ||
183 | The $reason is a string like 'ERROR' (for function C<error()>). | |
184 | The $message is a L<Log::Report::Message|Log::Report::Message> object (which are created with | |
185 | the special translation syntax like L<__x()|Log::Report/"Messages (optionally translatable)">). The $message may also | |
186 | be a plain string, or an L<Log::Report::Exception|Log::Report::Exception> object. The optional | |
187 | first parameter is a HASH which can be used to influence the dispatchers. | |
188 | ||
189 | The optional %options are listed below. Quite differently from other | |
190 | functions and methods, they have to be passed in a HASH as first parameter. | |
191 | ||
192 | This function returns the LIST of dispatchers which accepted the $message. | |
193 | When empty, no back-end has accepted it so the $message was "lost". | |
194 | Even when no back-end needs the message, the program will still exit | |
195 | when there is a $reason to C<die()>. | |
196 | ||
197 | -Option --Default | |
198 | errno $! or 1 | |
199 | is_fatal <depends on reason> | |
200 | locale undef | |
201 | location undef | |
202 | stack undef | |
203 | to undef | |
204 | ||
205 | =over 2 | |
206 | ||
207 | =item errno => INTEGER | |
208 | ||
209 | When the $reason includes the error text (See L</Run modes>), you can | |
210 | overrule the error code kept in C<$!>. In other cases, the return code | |
211 | defaults to C<1> (historical UNIX behavior). When the message $reason | |
212 | (combined with the run-mode) is severe enough to stop the program, | |
213 | this value as return code of the program. The use of this option itself | |
214 | will not trigger an C<die()>. | |
215 | ||
216 | =item is_fatal => BOOLEAN | |
217 | ||
218 | Some logged exceptions are fatal, other aren't. The default usually | |
219 | is correct. However, you may want an error to be caught (usually with | |
220 | L<try()|Log::Report/"Report Production and Configuration">), redispatch it to syslog, but without it killing the main | |
221 | program. | |
222 | ||
223 | =item locale => LOCALE | |
224 | ||
225 | Use this specific locale, in stead of the user's preference. | |
226 | ||
227 | =item location => STRING | |
228 | ||
229 | When defined, this location is used in the display. Otherwise, it | |
230 | is determined automatically if needed. An empty string will disable | |
231 | any attempt to display this line. | |
232 | ||
233 | =item stack => ARRAY | |
234 | ||
235 | When defined, that data is used to display the call stack. Otherwise, | |
236 | it is collected via C<caller()> if needed. | |
237 | ||
238 | =item to => NAME|ARRAY-of-NAMEs | |
239 | ||
240 | Sent the $message only to the NAMEd dispatchers. Ignore unknown NAMEs. | |
241 | Still, the dispatcher needs to be enabled and accept the REASONs. | |
242 | ||
243 | =back | |
244 | ||
245 | example: for use of L<report()|Log::Report/"Report Production and Configuration"> | |
246 | ||
247 | # long syntax example | |
248 | report TRACE => "start processing now"; | |
249 | report INFO => '500: ' . __'Internal Server Error'; | |
250 | ||
251 | # explicit dispatcher, no translation | |
252 | report {to => 'syslog'}, NOTICE => "started process $$"; | |
253 | notice "started process $$", _to => 'syslog'; # same | |
254 | ||
255 | # short syntax examples | |
256 | trace "start processing now"; | |
257 | warning __x'Disk {percent%.2f}% full', percent => $p | |
258 | if $p > 97; | |
259 | ||
260 | # error message, overruled to be printed in Brazilian | |
261 | report {locale => 'pt_BR'} | |
262 | , WARNING => "do this at home!"; | |
263 | ||
264 | =item B<try>(CODE, %options) | |
265 | ||
266 | Execute the CODE while blocking all dispatchers as long as it is running. | |
267 | The exceptions which occur while running the CODE are caught until it | |
268 | has finished. When there where no fatal errors, the result of the CODE | |
269 | execution is returned. | |
270 | ||
271 | After the CODE was tried, the C<$@> will contain a | |
272 | L<Log::Report::Dispatcher::Try|Log::Report::Dispatcher::Try> object, which contains the collected | |
273 | messages. | |
274 | ||
275 | Run-time errors from Perl and die's, croak's and confess's within the | |
276 | program (which shouldn't appear, but you never know) are collected into an | |
277 | L<Log::Report::Message|Log::Report::Message> object, using L<Log::Report::Die|Log::Report::Die>. | |
278 | ||
279 | The %options are passed to the constructor of the try-dispatcher, see | |
280 | L<Log::Report::Dispatcher::Try::new()|Log::Report::Dispatcher::Try/"Constructors">. For instance, you may like to | |
281 | add C<< mode => 'DEBUG' >>, or C<< accept => 'ERROR-' >>. | |
282 | ||
283 | B<Be warned> that the parameter to C<try> is a CODE reference. This means | |
284 | that you shall not use a comma after the block when there are %options | |
285 | specified. On the other hand, you shall use a semi-colon after the | |
286 | block if there are no arguments. | |
287 | ||
288 | B<Be warned> that the {} are interpreted as subroutine, which means that, | |
289 | for instance, it has its own C<@_>. The manual-page of Try::Tiny | |
290 | lists a few more side-effects of this. | |
291 | ||
292 | example: | |
293 | ||
294 | my $x = try { 3/$x }; # mind the ';' !! | |
295 | if($@) { # signals something went wrong | |
296 | ||
297 | if(try {...}) { # block ended normally, returns bool | |
298 | ||
299 | try { ... } # no comma!! | |
300 | mode => 'DEBUG', accept => 'ERROR-'; | |
301 | ||
302 | try sub { ... }, # with comma, also \&function | |
303 | mode => 'DEBUG', accept => 'ALL'; | |
304 | ||
305 | my $response = try { $ua->request($request) }; | |
306 | if(my $e = $@->wasFatal) ... | |
307 | ||
308 | =back | |
309 | ||
310 | =head2 Abbreviations for report() | |
311 | ||
312 | The following functions are all wrappers for calls to L<report()|Log::Report/"Report Production and Configuration">, | |
313 | and available when "syntax is SHORT" (by default, see L<import()|Log::Report/"Configuration">). | |
314 | You cannot specify additional options to influence the behavior of | |
315 | C<report()>, which are usually not needed anyway. | |
316 | ||
317 | =over 4 | |
318 | ||
319 | =item B<alert>($message) | |
320 | ||
321 | Short for C<< report ALERT => $message >> | |
322 | ||
323 | =item B<assert>($message) | |
324 | ||
325 | Short for C<< report ASSERT => $message >> | |
326 | ||
327 | =item B<error>($message) | |
328 | ||
329 | Short for C<< report ERROR => $message >> | |
330 | ||
331 | =item B<failure>($message) | |
332 | ||
333 | Short for C<< report FAILURE => $message >> | |
334 | ||
335 | =item B<fault>($message) | |
336 | ||
337 | Short for C<< report FAULT => $message >> | |
338 | ||
339 | =item B<info>($message) | |
340 | ||
341 | Short for C<< report INFO => $message >> | |
342 | ||
343 | =item B<mistake>($message) | |
344 | ||
345 | Short for C<< report MISTAKE => $message >> | |
346 | ||
347 | =item B<notice>($message) | |
348 | ||
349 | Short for C<< report NOTICE => $message >> | |
350 | ||
351 | =item B<panic>($message) | |
352 | ||
353 | Short for C<< report PANIC => $message >> | |
354 | ||
355 | =item B<trace>($message) | |
356 | ||
357 | Short for C<< report TRACE => $message >> | |
358 | ||
359 | =item B<warning>($message) | |
360 | ||
361 | Short for C<< report WARNING => $message >> | |
362 | ||
363 | =back | |
364 | ||
365 | =head2 Messages (optionally translatable) | |
366 | ||
367 | Even when you do not support translations (yet) you may want to use | |
368 | message objects to improve the logging feature. For instance, | |
369 | you get very powerful interpolation from L<String::Print|String::Print>. | |
370 | ||
371 | The language translations are initiate by limited set of functions | |
372 | which contain B<two under-scores> (C<__>) in their name. Most | |
373 | of them return a L<Log::Report::Message|Log::Report::Message> object. | |
374 | ||
375 | B<Be warned(1)> that -in general- its considered very bad practice to | |
376 | combine multiple translations into one message: translating may also | |
377 | affect the order of the translated components. Besides, when the person | |
378 | which translates only sees smaller parts of the text, his (or her) job | |
379 | becomes more complex. So: | |
380 | ||
381 | print __"Hello" . ', ' . __"World!"; # works, but to be avoided | |
382 | print __"Hello, World!"; # preferred, complete sentence | |
383 | ||
384 | The the former case, tricks with overloading used by the | |
385 | L<Log::Report::Message|Log::Report::Message> objects will still make delayed translations | |
386 | work. | |
387 | ||
388 | In normal situations, it is not a problem to translate interpolated | |
389 | values: | |
390 | ||
391 | print __"the color is {c}", c => __"red"; | |
392 | ||
393 | B<Be warned(2)> that using C<< __'Hello' >> will produce a syntax error like | |
394 | "String found where operator expected at .... Can't find string terminator | |
395 | "'" anywhere before EOF". The first quote is the cause of the complaint, | |
396 | but the second generates the error. In the early days of Perl, the single | |
397 | quote was used to separate package name from function name, a role which | |
398 | was later replaced by a double-colon. So C<< __'Hello' >> gets interpreted | |
399 | as C<< __::Hello ' >>. Then, there is a trailing single quote which has | |
400 | no counterpart. | |
401 | ||
402 | =over 4 | |
403 | ||
404 | =item B<N__>($msgid) | |
405 | ||
406 | Label to indicate that the string is a text which will be translated | |
407 | later. The function itself does nothing. See also L<N__w()|Log::Report/"Messages (optionally translatable)">. | |
408 | ||
409 | This no-op function is used as label to the xgettext program to build the | |
410 | translation tables. | |
411 | ||
412 | example: how to use N__() | |
413 | ||
414 | # add three msgids to the translation table | |
415 | my @colors = (N__"red", N__"green", N__"blue"); | |
416 | my @colors = N__w "red green blue"; # same | |
417 | print __ $colors[1]; # translate green | |
418 | ||
419 | # using __(), would work as well | |
420 | my @colors = (__"red", __"green", __"blue"); | |
421 | print $colors[1]; | |
422 | # however: this will always create all Log::Report::Message objects, | |
423 | # where maybe only one is used. | |
424 | ||
425 | =item B<N__n>($single_msgid, $plural_msgid) | |
426 | ||
427 | Label to indicate that the two MSGIDs are related, the first as | |
428 | single, the seconds as its plural. Only used to find the text | |
429 | fragments to be translated. The function itself does nothing. | |
430 | ||
431 | example: how to use L<N__n()|Log::Report/"Messages (optionally translatable)"> | |
432 | ||
433 | my @save = N__n "save file", "save files"; | |
434 | my @save = (N__n "save file", "save files"); | |
435 | my @save = N__n("save file", "save files"); | |
436 | ||
437 | # be warned about SCALARs in prototype! | |
438 | print __n @save, $nr_files; # wrong! | |
439 | print __n $save[0], $save[1], @files, %vars; | |
440 | ||
441 | =item B<N__w>(STRING) | |
442 | ||
443 | This extension to the Locale::TextDomain syntax, is a combined | |
444 | C<qw> (list of quoted words) and L<N__()|Log::Report/"Messages (optionally translatable)"> into a list of translatable | |
445 | words. | |
446 | ||
447 | example: of L<N__w()|Log::Report/"Messages (optionally translatable)"> | |
448 | ||
449 | my @colors = (N__"red", N__"green", N__"blue"); | |
450 | my @colors = N__w"red green blue"; # same | |
451 | print __ $colors[1]; | |
452 | ||
453 | =item B<__>($msgid) | |
454 | ||
455 | This function (name is B<two> under-score characters) will cause the $msgid | |
456 | to be replaced by the translations when doing the actual output. Returned | |
457 | is a L<Log::Report::Message|Log::Report::Message> object, which will be used in translation | |
458 | later. Translating is invoked when the object gets stringified. When | |
459 | you have no translation tables, the $msgid will be shown untranslated. | |
460 | ||
461 | If you need options for L<Log::Report::Message::new()|Log::Report::Message/"Constructors"> then use L<__x()|Log::Report/"Messages (optionally translatable)">; | |
462 | the prototype of this function does not permit parameters: it is a | |
463 | prefix operator! | |
464 | ||
465 | example: how to use __() | |
466 | ||
467 | print __"Hello World"; # translated into user's language | |
468 | print __'Hello World'; # syntax error! | |
469 | print __('Hello World'); # ok, translated | |
470 | print __"Hello", " World"; # World not translated | |
471 | ||
472 | my $s = __"Hello World"; # creates object, not yet translated | |
473 | print ref $s; # Log::Report::Message | |
474 | print $s; # ok, translated | |
475 | print $s->toString('fr'); # ok, forced into French | |
476 | ||
477 | =item B<__n>($msgid, $plural_msgid, $count, PAIRS) | |
478 | ||
479 | It depends on the value of $count (and the selected language) which | |
480 | text will be displayed. When translations can not be performed, then | |
481 | $msgid will be used when $count is 1, and PLURAL_MSGSID in other cases. | |
482 | However, some languages have more complex schemes than English. | |
483 | ||
484 | The PAIRS are options for L<Log::Report::Message::new()|Log::Report::Message/"Constructors"> and variables | |
485 | to be filled in. | |
486 | ||
487 | example: how to use __n() | |
488 | ||
489 | print __n "one", "more", $a; | |
490 | print __n("one", "more", $a), "\n"; | |
491 | print +(__n "one", "more", $a), "\n"; | |
492 | ||
493 | # new-lines are ignore at lookup, but printed. | |
494 | print __n "one\n", "more\n", $a; | |
495 | ||
496 | # count is in scalar context | |
497 | # the value is also available as _count | |
498 | print __n "found one\n", "found {_count}\n", @r; | |
499 | ||
500 | # ARRAYs and HASHes are counted | |
501 | print __n "one", "more", \@r; | |
502 | ||
503 | =item B<__nx>($msgid, $plural_msgid, $count, PAIRS) | |
504 | ||
505 | It depends on the value of $count (and the selected language) which | |
506 | text will be displayed. See details in L<__n()|Log::Report/"Messages (optionally translatable)">. After translation, | |
507 | the VARIABLES will be filled-in. | |
508 | ||
509 | The PAIRS are options for L<Log::Report::Message::new()|Log::Report::Message/"Constructors"> and variables | |
510 | to be filled in. | |
511 | ||
512 | example: how to use __nx() | |
513 | ||
514 | print __nx "one file", "{_count} files", $nr_files; | |
515 | print __nx "one file", "{_count} files", @files; | |
516 | ||
517 | local $" = ', '; | |
518 | print __nx "one file: {f}", "{_count} files: {f}", @files, f => \@files; | |
519 | ||
520 | =item B<__x>($msgid, PAIRS) | |
521 | ||
522 | Translate the $msgid and then interpolate the VARIABLES in that string. | |
523 | Of course, translation and interpolation is delayed as long as possible. | |
524 | Both OPTIONS and VARIABLES are key-value pairs. | |
525 | ||
526 | The PAIRS are options for L<Log::Report::Message::new()|Log::Report::Message/"Constructors"> and variables | |
527 | to be filled in. | |
528 | ||
529 | =item B<__xn>($single_msgid, $plural_msgid, $count, $paurs) | |
530 | ||
531 | Same as L<__nx()|Log::Report/"Messages (optionally translatable)">, because we have no preferred order for 'x' and 'n'. | |
532 | ||
533 | =back | |
534 | ||
535 | =head3 Messages with msgctxt | |
536 | ||
537 | In Log::Report, the message context (mgsctxt in the PO-files --in the | |
538 | translation tables) can be used in a very powerful way. Read all about | |
539 | it in L<Log::Report::Translator::Context|Log::Report::Translator::Context> | |
540 | ||
541 | The msgctxt versions of the tranditional gettext infrastructure are far | |
542 | less useful for Log::Report, because we can easily work with different | |
543 | text domains within the same program. That should avoid most of the | |
544 | accidental translation conflicts between components of the code. | |
545 | ||
546 | Just for compatibility with Locale::TextDomain and completeness, the | |
547 | 'p' versions of above methods are supported. See examples for these | |
548 | functions in Locale::TextDomain. | |
549 | ||
550 | B<Warnings:> Functions C<N__p()> and C<N__np()> seem not to be usable in | |
551 | reality, hence not implemented. The script xgettext-perl and | |
552 | L<Log::Report::Extract::PerlPPI|Log::Report::Extract::PerlPPI> (both in the L<Log::Report::Lexicon|Log::Report::Lexicon> | |
553 | distribution) do not yet support these functions. | |
554 | ||
555 | =over 4 | |
556 | ||
557 | =item B<__np>($msgctxt, $msgid, $plural, count) | |
558 | ||
559 | =item B<__npx>($msgctxt, $msgid, $plural, count, PAIRS) | |
560 | ||
561 | =item B<__p>($msgctxt, $msgid) | |
562 | ||
563 | =item B<__px>($msgctxt, $msgid, PAIRS) | |
564 | ||
565 | =back | |
566 | ||
567 | =head2 Configuration | |
568 | ||
569 | =over 4 | |
570 | ||
571 | =item $obj-E<gt>B<import>( [$level,][$domain,] %options ) | |
572 | ||
573 | The import is automatically called when the package is compiled. For all | |
574 | packages but one in your distribution, it will only contain the name of | |
575 | the $domain. | |
576 | ||
577 | For one package, the import list may additionally contain textdomain | |
578 | configuration %options. These %options are used for all packages which | |
579 | use the same $domain. These are alternatives: | |
580 | ||
581 | # Do not use variables in the %*config! They are not yet initialized | |
582 | # when Log::Report->import is run!!! | |
583 | use Log::Report 'my-domain', %config, %domain_config; | |
584 | ||
585 | use Log::Report 'my-domain', %config; | |
586 | textdomain 'my-domain', %domain_config; # vars allowed | |
587 | ||
588 | The latter syntax has major advantages, when the configuration of the | |
589 | domain is determined at run-time. It is probably also easier to understand. | |
590 | ||
591 | See L<Log::Report::Domain::configure()|Log::Report::Domain/"Attributes">, for the B<list of %options> | |
592 | for the domain configuration. Here, we only list the options which are | |
593 | related to the normal import behavior. | |
594 | ||
595 | The export $level is a plus (+) followed by a number, for instance C<+1>, | |
596 | to indicate to on which caller level we need to work. This is used | |
597 | in L<Log::Report::Optional|Log::Report::Optional>. It defaults to '0': my direct caller. | |
598 | ||
599 | -Option --Default | |
600 | import undef | |
601 | message_class Log::Report::Message | |
602 | mode 'NORMAL' | |
603 | syntax 'SHORT' | |
604 | ||
605 | =over 2 | |
606 | ||
607 | =item import => FUNCTION|ARRAY | |
608 | ||
609 | [0.998] When not specified, the C<syntax> option determines the list | |
610 | of functions which are being exported. With this option, the C<syntax> | |
611 | option is ignored and only the specified FUNCTION(s) are imported. | |
612 | ||
613 | =item message_class => CLASS | |
614 | ||
615 | [1.08] Use a more powerful message object class, for instance because | |
616 | your messages need extra attributes. The provided CLASS must extend | |
617 | L<Log::Report::Message|Log::Report::Message> | |
618 | ||
619 | =item mode => LEVEL | |
620 | ||
621 | This sets the default mode for all created dispatchers. You can | |
622 | also selectively change the output mode, like | |
623 | dispatcher PERL => 'default', mode => 3 | |
624 | ||
625 | =item syntax => 'REPORT'|'SHORT'|'LONG' | |
626 | ||
627 | The SHORT syntax will add the report abbreviations (like function | |
628 | L<error()|Log::Report/"Abbreviations for report()">) to your name-space. Otherwise, each message must be produced | |
629 | with L<report()|Log::Report/"Report Production and Configuration">. C<LONG> is an alternative to C<REPORT>: both do not | |
630 | pollute your namespace with the useful abbrev functions. | |
631 | ||
632 | =back | |
633 | ||
634 | example: of import | |
635 | ||
636 | use Log::Report mode => 3; # '3' or 'DEBUG' | |
637 | ||
638 | use Log::Report 'my-domain'; # in each package producing messages | |
639 | ||
640 | use Log::Report 'my-domain' # in one package, top of distr | |
641 | , mode => 'VERBOSE' | |
642 | , syntax => 'REPORT' # report ERROR, not error() | |
643 | , translator => Log::Report::Translator::POT->new | |
644 | ( lexicon => '/home/mine/locale' # translation tables | |
645 | ) | |
646 | , native_language => 'nl_NL'; # untranslated msgs are Dutch | |
647 | ||
648 | use Log::Report import => 'try'; # or ARRAY of functions | |
649 | ||
650 | =item B<textdomain>( <[$name],$config>|<$name, 'DELETE'|'EXISTS'>|$domain ) | |
651 | ||
652 | [1.00] Without CONFIGuration, this returns the L<Log::Report::Domain|Log::Report::Domain> object | |
653 | which administers the $domain, by default the domain effective in the scope | |
654 | of the package. | |
655 | ||
656 | A very special case is "DELETE", which will remove the domain | |
657 | configuration. [1.20] "EXISTS" will check for existence: when it exists, | |
658 | it will be returned, but a domain will not be automagically created. | |
659 | ||
660 | [1.20] You may also pass a pre-configured domain. | |
661 | ||
662 | =back | |
663 | ||
664 | =head2 Reasons | |
665 | ||
666 | =over 4 | |
667 | ||
668 | =item Log::Report-E<gt>B<needs>( $reason, [$reasons] ) | |
669 | ||
670 | Returns true when the reporter needs any of the $reasons, when any of | |
671 | the active dispatchers is collecting messages in the specified level. | |
672 | This is useful when the processing of data for the message is relatively | |
673 | expensive, but for instance only required in debug mode. | |
674 | ||
675 | example: | |
676 | ||
677 | if(Log::Report->needs('TRACE')) | |
678 | { my @args = ...expensive calculation...; | |
679 | trace "your options are: @args"; | |
680 | } | |
681 | ||
682 | =back | |
683 | ||
684 | =head1 DETAILS | |
685 | ||
686 | =head2 Introduction | |
687 | ||
688 | Getting messages to users and logs. The distincting concept of this module, | |
689 | is that three tasks which are strongly related are merged into one simple | |
690 | syntax. The three tasks: | |
691 | ||
692 | =over 4 | |
693 | ||
694 | =item produce some text on a certain condition, | |
695 | ||
696 | =item translate it to the proper language, and | |
697 | ||
698 | =item deliver it in some way to a user. | |
699 | ||
700 | =back | |
701 | ||
702 | Text messages in Perl are produced by commands like C<print>, C<die>, | |
703 | C<warn>, C<carp>, or C<croak>. But where is that output directed to? | |
704 | Translations is hard. There is no clean exception mechanism. | |
705 | ||
706 | Besides, the C<print>/C<warn>/C<die> together produce only three different | |
707 | output "levels" with a message. Think of the variation syslog offers: | |
708 | more than 7 levels. Many people manually implement their own tricks to | |
709 | get additional levels, like verbose and debug flags. Log::Report offers | |
710 | that variety. | |
711 | ||
712 | The (optional) translations use the beautiful syntax defined by | |
713 | Locale::TextDomain, with some own extensions (of course). A very | |
714 | important difference is that translations are delayed till the delivery | |
715 | step: until a dispatcher actually writes your message into a file, sends | |
716 | it to syslog, or shows it on the screen. This means that the pop-up in | |
717 | the graphical interface of the user may show the text in the language | |
718 | of the user --say Chinese in utf8--, but at the same time syslog may | |
719 | write the latin1 English version of the same message. | |
720 | ||
721 | =head2 Background ideas | |
722 | ||
723 | The following ideas are the base of this implementation: | |
724 | ||
725 | =over 4 | |
726 | ||
727 | =item . simplification | |
728 | ||
729 | Handling errors and warnings is probably the most labor-intensive | |
730 | task for a programmer: when programs are written correctly, up-to | |
731 | three-quarters of the code is related to testing, reporting, and | |
732 | handling (problem) conditions. Simplifying the way to create reports, | |
733 | simplifies programming and maintenance. | |
734 | ||
735 | =item . multiple dispatchers | |
736 | ||
737 | It is not the location where the (for instance) error occurs which | |
738 | determines what will happen with the text, but the main application which | |
739 | uses the the complaining module has control. Messages have a reason. | |
740 | Based on the `reason' classification, they can get ignored, send to one | |
741 | or multiple dispatchers, like Log::Dispatch, Log::Log4perl, | |
742 | or UNIX syslog. | |
743 | ||
744 | =item . delayed translations | |
745 | ||
746 | The background ideas are that of Locale::TextDomain, based | |
747 | on C<gettext()>. However, in the C<Log::Report> infrastructure, | |
748 | translations are postponed until the text is dispatched to a screen | |
749 | or log-file; the same report can be sent to syslog in (for instance) | |
750 | English and to the user interface in Dutch. | |
751 | ||
752 | =item . context sensitive | |
753 | ||
754 | Using contexts, you can set-up how to translate or rewrite messages, | |
755 | to improve messages. A typical problem is whether to use gender in | |
756 | text (use 'his' or 'her'): you can set a gender in a context, and the | |
757 | use translation tables to pick the right one. | |
758 | ||
759 | =back | |
760 | ||
761 | =head2 Error handling models | |
762 | ||
763 | There are two approaches to handling errors and warnings. In the first | |
764 | approach, as produced by C<die>, C<warn> and the C<carp> family of | |
765 | commands, the program handles the problem immediately on the location | |
766 | where the problem appears. In the second approach, an I<exception> | |
767 | is thrown on the spot where the problem is created, and then somewhere | |
768 | else in the program the condition is handled. | |
769 | ||
770 | The implementation of exceptions in Perl5 is done with a eval-die pair: | |
771 | on the spot where the problem occurs, C<die> is called. But, because of | |
772 | the execution of that routine is placed within an C<eval>, the program | |
773 | as a whole will not die, just the execution of a part of the program | |
774 | will seize. However, what if the condition which caused the routine to die | |
775 | is solvable on a higher level? Or what if the user of the code doesn't | |
776 | bother that a part fails, because it has implemented alternatives for | |
777 | that situation? Exception handling is quite clumsy in Perl5. | |
778 | ||
779 | The C<Log::Report> set of distributions let modules concentrate on the | |
780 | program flow, and let the main program decide on the report handling | |
781 | model. The infrastructure to translate messages into multiple languages, | |
782 | whether to create exceptions or carp/die, to collect longer explanations | |
783 | with the messages, to log to mail or syslog, and so on, is decided in | |
784 | pluggable back-ends. | |
785 | ||
786 | =head3 The Reason for the report | |
787 | ||
788 | Traditionally, perl has a very simple view on error reports: you | |
789 | either have a warning or an error. However, it would be much clearer | |
790 | for user's and module-using applications, when a distinction is made | |
791 | between various causes. For instance, a configuration error is quite | |
792 | different from a disk-full situation. In C<Log::Report>, the produced | |
793 | reports in the code tell I<what> is wrong. The main application defines | |
794 | loggers, which interpret the cause into (syslog) levels. | |
795 | ||
796 | Defined by C<Log::Report> are | |
797 | ||
798 | =over 4 | |
799 | ||
800 | =item . trace (debug, program) | |
801 | ||
802 | The message will be used when some logger has debugging enabled. The | |
803 | messages show steps taken by the program, which are of interest by the | |
804 | developers and maintainers of the code, but not for end-users. | |
805 | ||
806 | =item . assert (program) | |
807 | ||
808 | Shows an unexpected condition, but continues to run. When you want the | |
809 | program to abort in such situation, that use C<panic>. | |
810 | ||
811 | =item . info (verbose, program) | |
812 | ||
813 | These messages show larger steps in the execution of the program. | |
814 | Experienced users of the program usually do not want to see all these | |
815 | intermediate steps. Most programs will display info messages (and | |
816 | higher) when some C<verbose> flag is given on the command-line. | |
817 | ||
818 | =item . notice (program) | |
819 | ||
820 | An user may need to be aware of the program's accidental smart behavior, | |
821 | for instance, that it initializes a lasting C<Desktop> directory in your | |
822 | home directory. Notices should be sparse. | |
823 | ||
824 | =item . warning (program) | |
825 | ||
826 | The program encountered some problems, but was able to work around it | |
827 | by smart behavior. For instance, the program does not understand a | |
828 | line from a log-file, but simply skips the line. | |
829 | ||
830 | =item . mistake (user) | |
831 | ||
832 | When a user does something wrong, but what is correctable by smart | |
833 | behavior of the program. For instance, in some configuration file, | |
834 | you can fill-in "yes" or "no", but the user wrote "yeah". The program | |
835 | interprets this as "yes", producing a mistake message as warning. | |
836 | ||
837 | It is much nicer to tell someone that he/she made a mistake, than | |
838 | to call that an error. | |
839 | ||
840 | =item . error (user) | |
841 | ||
842 | The user did something wrong, which is not automatically correctable | |
843 | or the program is not willing to correct it automatically for reasons | |
844 | of code quality. For instance, an unknown option flag is given on the | |
845 | command-line. These are configuration issues, and have no useful | |
846 | value in C<$!>. The program will be stopped, usually before taken off. | |
847 | ||
848 | =item . fault (system) | |
849 | ||
850 | The program encountered a situation where it has no work-around. For | |
851 | instance, a file cannot be opened to be written. The cause of that | |
852 | problem can be some user error (i.e. wrong filename), or external | |
853 | (you accidentally removed a directory yesterday). In any case, the | |
854 | C<$!> (C<$ERRNO>) variable is set here. | |
855 | ||
856 | =item . alert (system) | |
857 | ||
858 | Some external cause disturbs the execution of the program, but the | |
859 | program stays alive and will try to continue operation. For instance, | |
860 | the connection to the database is lost. After a few attempts, the | |
861 | database can be reached and the program continues as if nothing happened. | |
862 | The cause is external, so C<$!> is set. Usually, a system administrator | |
863 | needs to be informed about the problem. | |
864 | ||
865 | =item . failure (system) | |
866 | ||
867 | Some external cause makes it impossible for this program to continue. | |
868 | C<$!> is set, and usually the system administrator wants to be | |
869 | informed. The program will die. | |
870 | ||
871 | The difference with C<fault> is subtile and not always clear. A fault | |
872 | reports an error returned by an operating system call, where the failure | |
873 | would report an operational problem, like a failing mount. | |
874 | ||
875 | =item . panic (program) | |
876 | ||
877 | All above report classes are expected: some predictable situation | |
878 | is encountered, and therefore a message is produced. However, programs | |
879 | often do some internal checking. Of course, these conditions should | |
880 | never be triggered, but if they do... then we can only stop. | |
881 | ||
882 | For instance, in an OO perl module, the base class requires all | |
883 | sub-classes to implement a certain method. The base class will produce | |
884 | a stub method with triggers a panic when called. The non-dieing version | |
885 | of this test C<assert>. | |
886 | ||
887 | =back | |
888 | ||
889 | I<Debugging> or being C<verbose> are run-time behaviors, and have nothing | |
890 | directly to do with the type of message which is produced. These two | |
891 | are B<modes> which can be set on the dispatchers: one dispatcher may | |
892 | be more verbose that some other. | |
893 | ||
894 | On purpose, we do not use the terms C<die> or C<fatal>, because the | |
895 | dispatcher can be configured what to do in cause of which condition. | |
896 | For instance, it may decide to stop execution on warnings as well. | |
897 | ||
898 | The terms C<carp> and C<croak> are avoided, because the program cause | |
899 | versus user cause distinction (warn vs carp) is reflected in the use | |
900 | of different reasons. There is no need for C<confess> and C<croak> | |
901 | either, because the dispatcher can be configured to produce stack-trace | |
902 | information (for a limited sub-set of dispatchers) | |
903 | ||
904 | =head3 Report levels | |
905 | ||
906 | Various frameworks used with perl programs define different labels | |
907 | to indicate the reason for the message to be produced. | |
908 | ||
909 | Perl5 Log::Dispatch Syslog Log4Perl Log::Report | |
910 | print 0,debug debug debug trace | |
911 | print 0,debug debug debug assert | |
912 | print 1,info info info info | |
913 | warn\n 2,notice notice info notice | |
914 | warn 3,warning warn warn mistake | |
915 | carp 3,warning warn warn warning | |
916 | die\n 4,error err error error | |
917 | die 5,critical crit fatal fault | |
918 | croak 6,alert alert fatal alert | |
919 | croak 7,emergency emerg fatal failure | |
920 | confess 7,emergency emerg fatal panic | |
921 | ||
922 | =head3 Run modes | |
923 | ||
924 | The run-mode change which messages are passed to a dispatcher, but | |
925 | from a different angle than the dispatch filters; the mode changes | |
926 | behavioral aspects of the messages, which are described in detail in | |
927 | L<Log::Report::Dispatcher/Processing the message>. However, it should | |
928 | behave as you expect: the DEBUG mode shows more than the VERBOSE mode, | |
929 | and both show more than the NORMAL mode. | |
930 | ||
931 | B<. Example: extract run mode from Getopt::Long> | |
932 | ||
933 | The C<GetOptions()> function will count the number of C<v> options | |
934 | on the command-line when a C<+> is after the option name. | |
935 | ||
936 | use Log::Report; | |
937 | use Getopt::Long qw(:config no_ignore_case bundling); | |
938 | ||
939 | my $mode; # defaults to NORMAL | |
940 | GetOptions 'v+' => \$mode | |
941 | , 'verbose=i' => \$mode | |
942 | , 'mode=s' => \$mode | |
943 | or exit 1; | |
944 | ||
945 | dispatcher 'PERL', 'default', mode => $mode; | |
946 | ||
947 | Now, C<-vv> will set C<$mode> to C<2>, as will C<--verbose 2> and | |
948 | C<--verbose=2> and C<--mode=ASSERT>. Of course, you do not need to | |
949 | provide all these options to the user: make a choice. | |
950 | ||
951 | B<. Example: the mode of a dispatcher> | |
952 | ||
953 | my $mode = dispatcher(find => 'myname')->mode; | |
954 | ||
955 | B<. Example: run-time change mode of a dispatcher> | |
956 | ||
957 | To change the running mode of the dispatcher, you can do | |
958 | dispatcher mode => DEBUG => 'myname'; | |
959 | ||
960 | However, be warned that this does not change the types of messages | |
961 | accepted by the dispatcher! So: probably you will not receive | |
962 | the trace, assert, and info messages after all. So, probably you | |
963 | need to replace the dispatcher with a new one with the same name: | |
964 | dispatcher FILE => 'myname', to => ..., mode => 'DEBUG'; | |
965 | ||
966 | This may reopen connections (depends on the actual dispatcher), which | |
967 | might be not what you wish to happened. In that case, you must take | |
968 | the following approach: | |
969 | ||
970 | # at the start of your program | |
971 | dispatcher FILE => 'myname', to => ... | |
972 | , accept => 'ALL'; # overrule the default 'NOTICE-' !! | |
973 | ||
974 | # now it works | |
975 | dispatcher mode => DEBUG => 'myname'; # debugging on | |
976 | ... | |
977 | dispatcher mode => NORMAL => 'myname'; # debugging off | |
978 | ||
979 | Of course, this comes with a small overall performance penalty. | |
980 | ||
981 | =head3 Exceptions | |
982 | ||
983 | The simple view on live says: you 're dead when you die. However, | |
984 | more complex situations try to revive the dead. Typically, the "die" | |
985 | is considered a terminating exception, but not terminating the whole | |
986 | program, but only some logical block. Of course, a wrapper round | |
987 | that block must decide what to do with these emerging problems. | |
988 | ||
989 | Java-like languages do not "die" but throw exceptions which contain the | |
990 | information about what went wrong. Perl modules like C<Exception::Class> | |
991 | simulate this. It's a hassle to create exception class objects for each | |
992 | emerging problem, and the same amount of work to walk through all the | |
993 | options. | |
994 | ||
995 | Log::Report follows a simpler scheme. Fatal messages will "die", which is | |
996 | caught with "eval", just the Perl way (used invisible to you). However, | |
997 | the wrapper gets its hands on the message as the user has specified it: | |
998 | untranslated, with all unprocessed parameters still at hand. | |
999 | ||
1000 | try { fault __x "cannot open file {file}", file => $fn }; | |
1001 | if($@) # is Log::Report::Dispatcher::Try | |
1002 | { my $cause = $@->wasFatal; # is Log::Report::Exception | |
1003 | $cause->throw if $cause->message->msgid =~ m/ open /; | |
1004 | # all other problems ignored | |
1005 | } | |
1006 | ||
1007 | See L<Log::Report::Dispatcher::Try|Log::Report::Dispatcher::Try> and L<Log::Report::Exception|Log::Report::Exception>. | |
1008 | ||
1009 | =head2 Comparison | |
1010 | ||
1011 | Some notes on differences between the Log::Report approach and other | |
1012 | Perl concepts. | |
1013 | ||
1014 | =head3 die/warn/Carp | |
1015 | ||
1016 | Perl's built-in exception system is very primitive: "die" and "warn". | |
1017 | Most programming languages provide a much more detailed exception | |
1018 | mechanism. | |
1019 | ||
1020 | A typical perl program can look like this: | |
1021 | ||
1022 | my $dir = '/etc'; | |
1023 | ||
1024 | File::Spec->file_name is_absolute($dir) | |
1025 | or die "ERROR: directory name must be absolute.\n"; | |
1026 | ||
1027 | -d $dir | |
1028 | or die "ERROR: what platform are you on?"; | |
1029 | ||
1030 | until(opendir DIR, $dir) | |
1031 | { warn "ERROR: cannot read system directory $dir: $!"; | |
1032 | sleep 60; | |
1033 | } | |
1034 | ||
1035 | print "Processing directory $dir\n" | |
1036 | if $verbose; | |
1037 | ||
1038 | while(defined(my $file = readdir DIR)) | |
1039 | { if($file =~ m/\.bak$/) | |
1040 | { warn "WARNING: found backup file $dir/$f\n"; | |
1041 | next; | |
1042 | } | |
1043 | ||
1044 | die "ERROR: file $dir/$file is binary" | |
1045 | if $debug && -B "$dir/$file"; | |
1046 | ||
1047 | print "DEBUG: processing file $dir/$file\n" | |
1048 | if $debug; | |
1049 | ||
1050 | open FILE, "<", "$dir/$file" | |
1051 | or die "ERROR: cannot read from $dir/$f: $!"; | |
1052 | ||
1053 | close FILE | |
1054 | or croak "ERROR: read errors in $dir/$file: $!"; | |
1055 | } | |
1056 | ||
1057 | Where C<die>, C<warn>, and C<print> are used for various tasks. With | |
1058 | C<Log::Report>, you would write | |
1059 | ||
1060 | use Log::Report; | |
1061 | ||
1062 | # can be left-out when there is no debug/verbose | |
1063 | dispatcher PERL => 'default', mode => 'DEBUG'; | |
1064 | ||
1065 | my $dir = '/etc'; | |
1066 | ||
1067 | File::Spec->file_name is_absolute($dir) | |
1068 | or mistake "directory name must be absolute"; | |
1069 | ||
1070 | -d $dir | |
1071 | or panic "what platform are you on?"; | |
1072 | ||
1073 | until(opendir DIR, $dir) | |
1074 | { alert "cannot read system directory $dir"; | |
1075 | sleep 60; | |
1076 | } | |
1077 | ||
1078 | info "Processing directory $dir"; | |
1079 | ||
1080 | while(defined(my $file = readdir DIR)) | |
1081 | { if($file =~ m/\.bak$/) | |
1082 | { notice "found backup file $dir/$f"; | |
1083 | next; | |
1084 | } | |
1085 | ||
1086 | assert "file $dir/$file is binary" | |
1087 | if -B "$dir/$file"; | |
1088 | ||
1089 | trace "processing file $dir/$file"; | |
1090 | ||
1091 | unless(open FILE, "<", "$dir/$file") | |
1092 | { error "no permission to read from $dir/$f" | |
1093 | if $!==ENOPERM; | |
1094 | fault "unable to read from $dir/$f"; | |
1095 | } | |
1096 | ||
1097 | close FILE | |
1098 | or failure "read errors in $dir/$file"; | |
1099 | } | |
1100 | ||
1101 | A lot of things are quite visibly different, and there are a few smaller | |
1102 | changes. There is no need for a new-line after the text of the message. | |
1103 | When applicable (error about system problem), then the C<$!> is added | |
1104 | automatically. | |
1105 | ||
1106 | =head3 Log::Dispatch and Log::Log4perl | |
1107 | ||
1108 | The two major logging frameworks for Perl are Log::Dispatch and | |
1109 | Log::Log4perl; both provide a pluggable logging interface. | |
1110 | ||
1111 | Both frameworks do not have (gettext or maketext) language translation | |
1112 | support, which has various consequences. When you wish for to report | |
1113 | in some other language, it must be translated before the logging | |
1114 | function is called. This may mean that an error message is produced | |
1115 | in Chinese, and therefore also ends-up in the syslog file in Chinese. | |
1116 | When this is not your language, you have a problem. | |
1117 | ||
1118 | Log::Report translates only in the back-end, which means that the user may | |
1119 | get the message in Chinese, but you get your report in your beloved Dutch. | |
1120 | When no dispatcher needs to report the message, then no time is lost in | |
1121 | translating. | |
1122 | ||
1123 | With both logging frameworks, you use terminology comparable to | |
1124 | syslog: the module programmer determines the seriousness of the | |
1125 | error message, not the application which integrates multiple modules. | |
1126 | This is the way perl programs usually work, but often the cause for | |
1127 | inconsequent user interaction. | |
1128 | ||
1129 | =head3 Locale::gettext and Locate::TextDomain | |
1130 | ||
1131 | Both on GNU gettext based implementations can be used as translation | |
1132 | frameworks. Locale::TextDomain syntax is supported, with quite some | |
1133 | extensions. Read the excellent documentation of Locale::Textdomain. | |
1134 | Only the tried access via C<$__> and C<%__> are not supported. | |
1135 | ||
1136 | The main difference with these modules is the moment when the translation | |
1137 | takes place. In Locale::TextDomain, an C<__x()> will result in an | |
1138 | immediate translation request via C<gettext()>. C<Log::Report>'s version | |
1139 | of C<__x()> will only capture what needs to be translated in an object. | |
1140 | When the object is used in a print statement, only then the translation | |
1141 | will take place. This is needed to offer ways to send different | |
1142 | translations of the message to different destinations. | |
1143 | ||
1144 | To be able to postpone translation, objects are returned which stringify | |
1145 | into the translated text. | |
1146 | ||
1147 | =head1 DIAGNOSTICS | |
1148 | ||
1149 | =over 4 | |
1150 | ||
1151 | =item Error: in SCALAR context, only one dispatcher name accepted | |
1152 | ||
1153 | The L<dispatcher()|Log::Report/"Report Production and Configuration"> method returns the L<Log::Report::Dispatcher|Log::Report::Dispatcher> | |
1154 | objects which it has accessed. When multiple names where given, it | |
1155 | wishes to return a LIST of objects, not the count of them. | |
1156 | ||
1157 | =back | |
1158 | ||
1159 | =head1 SEE ALSO | |
1160 | ||
1161 | This module is part of Log-Report distribution version 1.32, | |
1162 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
1163 | ||
1164 | =head1 LICENSE | |
1165 | ||
1166 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
1167 | ||
1168 | This program is free software; you can redistribute it and/or modify it | |
1169 | under the same terms as Perl itself. | |
1170 | See F<http://dev.perl.org/licenses/> | |
1171 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | # This code is part of distribution Log-Report. Meta-POD processed with |
5 | 1 | # OODoc into POD and HTML manual-pages. See README.md |
6 | 2 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
7 | 3 | |
8 | 4 | package MojoX::Log::Report; |
9 | use vars '$VERSION'; | |
10 | $VERSION = '1.32'; | |
11 | ||
12 | 5 | use Mojo::Base 'Mojo::Log'; # implies use strict etc |
13 | 6 | |
14 | 7 | use Log::Report 'log-report', import => 'report'; |
15 | 8 | |
9 | =chapter NAME | |
10 | ||
11 | MojoX::Log::Report - divert log messages into Log::Report | |
12 | ||
13 | =chapter SYNOPSIS | |
14 | ||
15 | use MojoX::Log::Report; | |
16 | my $log = MojoX::Log::Report->new(%options); | |
17 | $app->log($log); # install logger in the Mojo::App | |
18 | ||
19 | =chapter DESCRIPTION | |
20 | ||
21 | [Included since Log::Report v1.00] | |
22 | Mojo likes to log messages directly into a file, by default. Log::Report | |
23 | constructs a M<Log::Report::Exception> object first. | |
24 | ||
25 | Be aware that this extension does catch the messages to be logged, | |
26 | but that the dispatching of the error follows a different route now. | |
27 | For instance, you cannot use C<$ENV{MOJO_LOG_LEVEL}> to control the output | |
28 | level, but you need to use M<Log::Report::dispatcher()> action C<mode>. | |
29 | ||
30 | Mojo defines five "levels" of messages, which map onto Log::Report's | |
31 | reasons this way: | |
32 | ||
33 | debug TRACE | |
34 | info INFO | |
35 | warn WARNING | |
36 | error ERROR | |
37 | fatal ALERT | |
38 | ||
39 | =chapter METHODS | |
40 | ||
41 | =section Constructors | |
42 | ||
43 | =c_method new %options | |
44 | Inherited %options C<path> and C<level> are ignored. | |
45 | =cut | |
16 | 46 | |
17 | 47 | sub new(@) { |
18 | 48 | my $class = shift; |
0 | =encoding utf8 | |
1 | ||
2 | =head1 NAME | |
3 | ||
4 | MojoX::Log::Report - divert log messages into Log::Report | |
5 | ||
6 | =head1 INHERITANCE | |
7 | ||
8 | MojoX::Log::Report | |
9 | is a Mojo::Log | |
10 | ||
11 | =head1 SYNOPSIS | |
12 | ||
13 | use MojoX::Log::Report; | |
14 | my $log = MojoX::Log::Report->new(%options); | |
15 | $app->log($log); # install logger in the Mojo::App | |
16 | ||
17 | =head1 DESCRIPTION | |
18 | ||
19 | [Included since Log::Report v1.00] | |
20 | Mojo likes to log messages directly into a file, by default. Log::Report | |
21 | constructs a L<Log::Report::Exception|Log::Report::Exception> object first. | |
22 | ||
23 | Be aware that this extension does catch the messages to be logged, | |
24 | but that the dispatching of the error follows a different route now. | |
25 | For instance, you cannot use C<$ENV{MOJO_LOG_LEVEL}> to control the output | |
26 | level, but you need to use L<Log::Report::dispatcher()|Log::Report/"Report Production and Configuration"> action C<mode>. | |
27 | ||
28 | Mojo defines five "levels" of messages, which map onto Log::Report's | |
29 | reasons this way: | |
30 | ||
31 | debug TRACE | |
32 | info INFO | |
33 | warn WARNING | |
34 | error ERROR | |
35 | fatal ALERT | |
36 | ||
37 | =head1 METHODS | |
38 | ||
39 | =head2 Constructors | |
40 | ||
41 | =over 4 | |
42 | ||
43 | =item MojoX::Log::Report-E<gt>B<new>(%options) | |
44 | ||
45 | Inherited %options C<path> and C<level> are ignored. | |
46 | ||
47 | =back | |
48 | ||
49 | =head1 SEE ALSO | |
50 | ||
51 | This module is part of Log-Report distribution version 1.32, | |
52 | built on January 26, 2021. Website: F<http://perl.overmeer.net/CPAN/> | |
53 | ||
54 | =head1 LICENSE | |
55 | ||
56 | Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog. | |
57 | ||
58 | This program is free software; you can redistribute it and/or modify it | |
59 | under the same terms as Perl itself. | |
60 | See F<http://dev.perl.org/licenses/> | |
61 |
24 | 24 | __WITHOUT_STACKTRACE |
25 | 25 | |
26 | 26 | is_deeply [ exception_decode(exception $dbix1) ] |
27 | , [ 'caught DBIx::Class::Exception' | |
28 | , { location => [ $0, '/tmp/a.pl', '6', undef ] } | |
27 | , [ { location => [ $0, '/tmp/a.pl', '6', undef ] } | |
29 | 28 | , 'ERROR' |
30 | 29 | , 'help' |
31 | 30 | ], 'set 1'; |
37 | 36 | __WITH_STACKTRACE |
38 | 37 | |
39 | 38 | is_deeply [ exception_decode(exception $dbix2) ] |
40 | , [ 'caught DBIx::Class::Exception' | |
41 | , { location => [ 'main', '/tmp/a.pl', '6', 'f' ] | |
39 | , [ { location => [ 'main', '/tmp/a.pl', '6', 'f' ] | |
42 | 40 | , stack => [ [ 'main::f', '/tmp/a.pl', '8' ] |
43 | 41 | , [ 'main::g', '/tmp/a.pl', '10' ] |
44 | 42 | ] |
52 | 50 | __WITHOUT_STACKTRACE |
53 | 51 | |
54 | 52 | is_deeply [ exception_decode(exception $dbix3) ] |
55 | , [ 'caught DBIx::Class::Exception' | |
56 | , { location => [ $0, '/tmp/a.pl', '6', undef ] } | |
53 | , [ { location => [ $0, '/tmp/a.pl', '6', undef ] } | |
57 | 54 | , 'ERROR' |
58 | 55 | , 'help' |
59 | 56 | ], 'set 3'; |
65 | 62 | #warn "DBIx4:", Dumper exception_decode(exception $dbix4); |
66 | 63 | |
67 | 64 | is_deeply [ exception_decode(exception $dbix4) ] |
68 | , [ 'caught DBIx::Class::Exception' | |
69 | , { location => | |
65 | , [ { location => | |
70 | 66 | [ 'DBIx::Class::Storage::DBI' |
71 | 67 | , '/home/abeverley/git/Isaas/bin/../lib/Isaas/DBIC.pm' |
72 | 68 | , '18' |
29 | 29 | my $msg = pop @dec; |
30 | 30 | |
31 | 31 | # error code changed from libxml2 2.9.9 to 2.9.10 |
32 | my $rc = delete $dec[1]{errno}; | |
33 | $dec[1]{errno} = 'RC'; | |
32 | my $rc = delete $dec[0]{errno}; | |
33 | $dec[0]{errno} = 'RC'; | |
34 | 34 | cmp_ok $rc, '>', 13000, 'error code'; |
35 | 35 | |
36 | 36 | is_deeply \@dec, |
37 | , [ 'caught XML::LibXML::Error' | |
38 | , { location => [ 'libxml', '', '1', 'parser' ], errno => 'RC' } | |
37 | , [ { location => [ 'libxml', '', '1', 'parser' ], errno => 'RC' } | |
39 | 38 | , 'ERROR' |
40 | 39 | ], 'error 1'; |
41 | 40 |
0 | # Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. | |
1 | # For other contributors see ChangeLog. | |
2 | # See the manual pages for details on the licensing terms. | |
3 | # Pod stripped from pm file by OODoc 2.02. | |
4 | 0 | package DieTests; |
5 | use vars '$VERSION'; | |
6 | $VERSION = '1.32'; | |
7 | ||
8 | 1 | use warnings; |
9 | 2 | use strict; |
10 | 3 | |
28 | 21 | my $errstr = "$!"; |
29 | 22 | |
30 | 23 | sub process($) |
31 | { | |
32 | my ($err, $opt, $reason, $message) = die_decode shift; | |
33 | $err =~ s/\d+\.?$/XX/; | |
24 | { my $err = shift; | |
25 | my ($opt, $reason, $message) = die_decode $err; | |
26 | # $err =~ s/\d+\.?$/XX/; | |
34 | 27 | my $errno = $opt->{errno} || 'no errno'; |
35 | 28 | my $loc = $opt->{location}; |
36 | 29 | my $loca = $loc ? "$loc->[1]#XX" : 'no location'; |
37 | 30 | my $stack = join "\n", |
38 | 31 | map { join '#', $_->[0], $_->[1], 'XX' } |
39 | 32 | @{$opt->{stack}}; |
33 | ||
40 | 34 | my $r = <<__RESULT; |
41 | 35 | $reason: $message ($errno) |
42 | $err | |
43 | 36 | $loca |
44 | 37 | $stack |
45 | 38 | __RESULT |
62 | 55 | my $die_text1 = $@; |
63 | 56 | is(process($die_text1), <<__OUT, "die"); |
64 | 57 | ERROR: ouch (no errno) |
65 | ouch at t/DieTests.pm line XX | |
66 | 58 | t/DieTests.pm#XX |
67 | 59 | |
68 | 60 | __OUT |
71 | 63 | my $die_text2 = $@; |
72 | 64 | is(process($die_text2), <<__OUT, "die"); |
73 | 65 | ERROR: ouch (no errno) |
74 | ouch | |
75 | 66 | no location |
76 | 67 | |
77 | 68 | __OUT |
80 | 71 | my $die_text3 = $@; |
81 | 72 | is(process($die_text3), <<__OUT, "die"); |
82 | 73 | FAULT: ouch (3) |
83 | ouch No such process at t/DieTests.pm line XX | |
84 | 74 | t/DieTests.pm#XX |
85 | 75 | |
86 | 76 | __OUT |
89 | 79 | my $die_text4 = $@; |
90 | 80 | is(process($die_text4), <<__OUT, "die"); |
91 | 81 | FAULT: ouch (3) |
92 | ouch No such process | |
93 | 82 | no location |
94 | 83 | |
95 | 84 | __OUT |
100 | 89 | my $croak_text1 = $@; |
101 | 90 | is(process($croak_text1), <<__OUT, "croak"); |
102 | 91 | ERROR: ouch (no errno) |
103 | ouch at t/41die.t line XX | |
104 | 92 | t/41die.t#XX |
105 | 93 | |
106 | 94 | __OUT |
109 | 97 | my $croak_text2 = $@; |
110 | 98 | is(process($croak_text2), <<__OUT, "croak"); |
111 | 99 | ERROR: ouch (no errno) |
112 | ouch | |
113 | 100 | t/41die.t#XX |
114 | 101 | |
115 | 102 | __OUT |
118 | 105 | my $croak_text3 = $@; |
119 | 106 | is(process($croak_text3), <<__OUT, "croak"); |
120 | 107 | FAULT: ouch (3) |
121 | ouch No such process at t/41die.t line XX | |
122 | 108 | t/41die.t#XX |
123 | 109 | |
124 | 110 | __OUT |
127 | 113 | my $croak_text4 = $@; |
128 | 114 | is(process($croak_text4), <<__OUT, "croak"); |
129 | 115 | FAULT: ouch (3) |
130 | ouch No such process | |
131 | 116 | t/41die.t#XX |
132 | 117 | |
133 | 118 | __OUT |
138 | 123 | my $confess_text1 = $@; |
139 | 124 | is(process($confess_text1), <<__OUT, "confess"); |
140 | 125 | PANIC: ouch (no errno) |
141 | ouch at t/DieTests.pm line XX | |
142 | 126 | t/DieTests.pm#XX |
143 | 127 | eval {...}#t/DieTests.pm#XX |
144 | 128 | DieTests::run_tests()#t/41die.t#XX |
149 | 133 | my $confess_text2 = $@; |
150 | 134 | is(process($confess_text2), <<__OUT, "confess"); |
151 | 135 | PANIC: ouch (no errno) |
152 | ouch | |
153 | 136 | t/DieTests.pm#XX |
154 | 137 | eval {...}#t/DieTests.pm#XX |
155 | 138 | DieTests::run_tests()#t/41die.t#XX |
160 | 143 | my $confess_text3 = $@; |
161 | 144 | is(process($confess_text3), <<__OUT, "confess"); |
162 | 145 | FAULT: ouch (3) |
163 | ouch No such process at t/DieTests.pm line XX | |
164 | 146 | t/DieTests.pm#XX |
165 | 147 | eval {...}#t/DieTests.pm#XX |
166 | 148 | DieTests::run_tests()#t/41die.t#XX |
179 | 161 | my $confess_text4 = $@; |
180 | 162 | is(process($confess_text4), <<__OUT, "confess"); |
181 | 163 | FAULT: ouch (3) |
182 | ouch No such process | |
183 | 164 | t/DieTests.pm#XX |
184 | 165 | eval {...}#t/DieTests.pm#XX |
185 | 166 | DieTests::run_tests()#t/41die.t#XX |