perltidy code and add .perltidyrc to repo
[p5sagit/Log-Contextual.git] / lib / Log / Contextual.pm
CommitLineData
0daa11f3 1package Log::Contextual;
2
a2777569 3use strict;
4use warnings;
2033c911 5
0c180ced 6our $VERSION = '0.004202';
2033c911 7
ae9785e2 8my @levels = qw(debug trace warn info error fatal);
9
675503c7 10use Exporter::Declare;
11use Exporter::Declare::Export::Generator;
f11f9542 12use Data::Dumper::Concise;
5b094c87 13use Scalar::Util 'blessed';
2033c911 14
b144ba01 15eval {
16 require Log::Log4perl;
17 die if $Log::Log4perl::VERSION < 1.29;
18 Log::Log4perl->wrapper_register(__PACKAGE__)
19};
20
5fd26f45 21# ____ is because tags must have at least one export and we don't want to
22# export anything but the levels selected
6ae293d7 23sub ____ { }
5fd26f45 24
6ae293d7 25exports(qw(____ set_logger with_logger ));
f11f9542 26
5fd26f45 27export_tag dlog => ('____');
28export_tag log => ('____');
675503c7 29import_arguments qw(logger package_logger default_logger);
30
139ded54 31sub router {
0092c26a 32 our $Router_Instance ||= do {
33 require Log::Contextual::Router;
34 Log::Contextual::Router->new
6ae293d7 35 }
0092c26a 36}
37
6ae293d7 38sub arg_logger { $_[1] }
39sub arg_levels { $_[1] || [qw(debug trace warn info error fatal)] }
8112b699 40sub arg_package_logger { $_[1] }
41sub arg_default_logger { $_[1] }
42
675503c7 43sub before_import {
44 my ($class, $importer, $spec) = @_;
6ae293d7 45 my $router = $class->router;
46 my $exports = $spec->exports;
47 my %router_args = (
48 exporter => $class,
49 target => $importer,
50 arguments => $spec->argument_info
51 );
f11f9542 52
f11f9542 53 die 'Log::Contextual does not have a default import list'
6ae293d7 54 if $spec->config->{default};
675503c7 55
a5454e75 56 $router->before_import(%router_args);
8112b699 57
6ae293d7 58 $spec->add_export(
59 '&set_logger',
60 sub {
61 my $router = $class->router;
4d605164 62
6ae293d7 63 die ref($router) . " does not support set_logger()"
64 unless $router->does('Log::Contextual::Role::Router::SetLogger');
4d605164 65
6ae293d7 66 return $router->set_logger(@_);
67 }) if $exports->{'&set_logger'};
4d605164 68
6ae293d7 69 $spec->add_export(
70 '&with_logger',
71 sub {
72 my $router = $class->router;
4d605164 73
6ae293d7 74 die ref($router) . " does not support with_logger()"
75 unless $router->does('Log::Contextual::Role::Router::WithLogger');
4d605164 76
6ae293d7 77 return $router->with_logger(@_);
78 }) if $exports->{'&with_logger'};
4d605164 79
5fd26f45 80 my @levels = @{$class->arg_levels($spec->config->{levels})};
675503c7 81 for my $level (@levels) {
82 if ($spec->config->{log}) {
6ae293d7 83 $spec->add_export(
84 "&log_$level",
85 sub (&@) {
86 my ($code, @args) = @_;
87 $router->handle_log_request(
88 exporter => $class,
89 caller_package => scalar(caller),
90 caller_level => 1,
91 message_level => $level,
92 message_sub => $code,
93 message_args => \@args,
94 );
95 return @args;
96 });
97 $spec->add_export(
98 "&logS_$level",
99 sub (&@) {
100 my ($code, @args) = @_;
101 $router->handle_log_request(
102 exporter => $class,
103 caller_package => scalar(caller),
104 caller_level => 1,
105 message_level => $level,
106 message_sub => $code,
107 message_args => \@args,
108 );
109 return $args[0];
110 });
675503c7 111 }
112 if ($spec->config->{dlog}) {
6ae293d7 113 $spec->add_export(
114 "&Dlog_$level",
115 sub (&@) {
116 my ($code, @args) = @_;
117 my $wrapped = sub {
118 local $_ = (@_ ? Data::Dumper::Concise::Dumper @_ : '()');
119 &$code;
120 };
121 $router->handle_log_request(
122 exporter => $class,
123 caller_package => scalar(caller),
124 caller_level => 1,
125 message_level => $level,
126 message_sub => $wrapped,
127 message_args => \@args,
128 );
129 return @args;
130 });
131 $spec->add_export(
132 "&DlogS_$level",
133 sub (&$) {
134 my ($code, $ref) = @_;
135 my $wrapped = sub {
136 local $_ = Data::Dumper::Concise::Dumper($_[0]);
137 &$code;
138 };
139 $router->handle_log_request(
140 exporter => $class,
141 caller_package => scalar(caller),
142 caller_level => 1,
143 message_level => $level,
144 message_sub => $wrapped,
145 message_args => [$ref],
146 );
147 return $ref;
148 });
a2777569 149 }
150 }
675503c7 151}
152
a5454e75 153sub after_import {
154 my ($class, $importer, $spec) = @_;
6ae293d7 155 my %router_args = (
156 exporter => $class,
157 target => $importer,
158 arguments => $spec->argument_info
159 );
a5454e75 160 $class->router->after_import(%router_args);
161}
709d11fe 162
0daa11f3 1631;
0a3750e2 164
165__END__
166
2daff231 167=head1 NAME
168
8bc568d2 169Log::Contextual - Simple logging interface with a contextual log
2daff231 170
171=head1 SYNOPSIS
172
9b8e24d5 173 use Log::Contextual qw( :log :dlog set_logger with_logger );
5b094c87 174 use Log::Contextual::SimpleLogger;
175 use Log::Log4perl ':easy';
176 Log::Log4perl->easy_init($DEBUG);
2daff231 177
5b094c87 178 my $logger = Log::Log4perl->get_logger;
179
180 set_logger $logger;
2daff231 181
9b8e24d5 182 log_debug { 'program started' };
2daff231 183
184 sub foo {
f9bf084b 185
186 my $minilogger = Log::Contextual::SimpleLogger->new({
187 levels => [qw( trace debug )]
188 });
189
190 with_logger $minilogger => sub {
21431192 191 log_trace { 'foo entered' };
9b8e24d5 192 my ($foo, $bar) = Dlog_trace { "params for foo: $_" } @_;
2daff231 193 # ...
21431192 194 log_trace { 'foo left' };
f9bf084b 195 };
2daff231 196 }
197
5b094c87 198 foo();
199
9fe4eeb3 200Beginning with version 1.008 L<Log::Dispatchouli> also works out of the box
201with C<Log::Contextual>:
202
203 use Log::Contextual qw( :log :dlog set_logger );
204 use Log::Dispatchouli;
205 my $ld = Log::Dispatchouli->new({
206 ident => 'slrtbrfst',
207 to_stderr => 1,
208 debug => 1,
209 });
210
211 set_logger $ld;
212
213 log_debug { 'program started' };
214
2daff231 215=head1 DESCRIPTION
216
30d7027a 217Major benefits:
218
219=over 2
220
221=item * Efficient
222
223The logging functions take blocks, so if a log level is disabled, the
224block will not run:
225
226 # the following won't run if debug is off
227 log_debug { "the new count in the database is " . $rs->count };
228
229Similarly, the C<D> prefixed methods only C<Dumper> the input if the level is
230enabled.
231
232=item * Handy
233
234The logging functions return their arguments, so you can stick them in
235the middle of expressions:
236
237 for (log_debug { "downloading:\n" . join qq(\n), @_ } @urls) { ... }
238
239=item * Generic
240
241C<Log::Contextual> is an interface for all major loggers. If you log through
242C<Log::Contextual> you will be able to swap underlying loggers later.
243
244=item * Powerful
245
39cd2f65 246C<Log::Contextual> chooses which logger to use based on L<< user defined C<CodeRef>s|/LOGGER CODEREF >>.
30d7027a 247Normally you don't need to know this, but you can take advantage of it when you
248need to later
249
250=item * Scalable
251
252If you just want to add logging to your extremely basic application, start with
253L<Log::Contextual::SimpleLogger> and then as your needs grow you can switch to
254L<Log::Dispatchouli> or L<Log::Dispatch> or L<Log::Log4perl> or whatever else.
255
256=back
257
258This module is a simple interface to extensible logging. It exists to
259abstract your logging interface so that logging is as painless as possible,
260while still allowing you to switch from one logger to another.
3dc9bd3c 261
30d7027a 262It is bundled with a really basic logger, L<Log::Contextual::SimpleLogger>,
263but in general you should use a real logger instead of that. For something
264more serious but not overly complicated, try L<Log::Dispatchouli> (see
265L</SYNOPSIS> for example.)
a2af6976 266
e36f2183 267=head1 A WORK IN PROGRESS
268
269This module is certainly not complete, but we will not break the interface
270lightly, so I would say it's safe to use in production code. The main result
271from that at this point is that doing:
272
273 use Log::Contextual;
274
275will die as we do not yet know what the defaults should be. If it turns out
276that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
277probably make C<:log> the default. But only time and usage will tell.
278
279=head1 IMPORT OPTIONS
280
281See L</SETTING DEFAULT IMPORT OPTIONS> for information on setting these project
282wide.
3dc9bd3c 283
c154d18a 284=head2 -logger
285
3dc9bd3c 286When you import this module you may use C<-logger> as a shortcut for
287L<set_logger>, for example:
288
289 use Log::Contextual::SimpleLogger;
9b8e24d5 290 use Log::Contextual qw( :dlog ),
291 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw( debug )] });
3dc9bd3c 292
293sometimes you might want to have the logger handy for other stuff, in which
294case you might try something like the following:
295
296 my $var_log;
297 BEGIN { $var_log = VarLogger->new }
9b8e24d5 298 use Log::Contextual qw( :dlog ), -logger => $var_log;
3dc9bd3c 299
5fd26f45 300=head2 -levels
301
302The C<-levels> import option allows you to define exactly which levels your
303logger supports. So the default,
304C<< [qw(debug trace warn info error fatal)] >>, works great for
305L<Log::Log4perl>, but it doesn't support the levels for L<Log::Dispatch>. But
306supporting those levels is as easy as doing
307
308 use Log::Contextual
309 -levels => [qw( debug info notice warning error critical alert emergency )];
310
e2b4b29c 311=head2 -package_logger
312
313The C<-package_logger> import option is similar to the C<-logger> import option
314except C<-package_logger> sets the the logger for the current package.
315
316Unlike L</-default_logger>, C<-package_logger> cannot be overridden with
317L</set_logger>.
318
319 package My::Package;
320 use Log::Contextual::SimpleLogger;
321 use Log::Contextual qw( :log ),
322 -package_logger => Log::Contextual::WarnLogger->new({
323 env_prefix => 'MY_PACKAGE'
324 });
325
326If you are interested in using this package for a module you are putting on
327CPAN we recommend L<Log::Contextual::WarnLogger> for your package logger.
328
c154d18a 329=head2 -default_logger
330
331The C<-default_logger> import option is similar to the C<-logger> import option
e2b4b29c 332except C<-default_logger> sets the the B<default> logger for the current package.
c154d18a 333
334Basically it sets the logger to be used if C<set_logger> is never called; so
335
336 package My::Package;
337 use Log::Contextual::SimpleLogger;
338 use Log::Contextual qw( :log ),
339 -default_logger => Log::Contextual::WarnLogger->new({
ae59bbe3 340 env_prefix => 'MY_PACKAGE'
c154d18a 341 });
342
e36f2183 343=head1 SETTING DEFAULT IMPORT OPTIONS
3dc9bd3c 344
e36f2183 345Eventually you will get tired of writing the following in every single one of
346your packages:
3dc9bd3c 347
e36f2183 348 use Log::Log4perl;
349 use Log::Log4perl ':easy';
350 BEGIN { Log::Log4perl->easy_init($DEBUG) }
3dc9bd3c 351
e36f2183 352 use Log::Contextual -logger => Log::Log4perl->get_logger;
353
354You can set any of the import options for your whole project if you define your
355own C<Log::Contextual> subclass as follows:
356
357 package MyApp::Log::Contextual;
358
359 use base 'Log::Contextual';
360
361 use Log::Log4perl ':easy';
362 Log::Log4perl->easy_init($DEBUG)
363
2b40dee5 364 sub arg_default_logger { $_[1] || Log::Log4perl->get_logger }
e36f2183 365 sub arg_levels { [qw(debug trace warn info error fatal custom_level)] }
366
2b40dee5 367 # or maybe instead of default_logger
e36f2183 368 sub arg_package_logger { $_[1] }
e36f2183 369
2b40dee5 370 # and almost definitely not this, which is only here for completeness
371 sub arg_logger { $_[1] }
e36f2183 372
2b40dee5 373Note the C<< $_[1] || >> in C<arg_default_logger>. All of these methods are
374passed the values passed in from the arguments to the subclass, so you can
375either throw them away, honor them, die on usage, or whatever. To be clear,
376if you define your subclass, and someone uses it as follows:
e36f2183 377
2b40dee5 378 use MyApp::Log::Contextual -default_logger => $foo,
379 -levels => [qw(bar baz biff)];
380
381Your C<arg_default_logger> method will get C<$foo> and your C<arg_levels>
e36f2183 382will get C<[qw(bar baz biff)]>;
2daff231 383
384=head1 FUNCTIONS
385
386=head2 set_logger
387
388 my $logger = WarnLogger->new;
21431192 389 set_logger $logger;
390
27141a7a 391Arguments: L</LOGGER CODEREF>
2daff231 392
21431192 393C<set_logger> will just set the current logger to whatever you pass it. It
394expects a C<CodeRef>, but if you pass it something else it will wrap it in a
06e908c3 395C<CodeRef> for you. C<set_logger> is really meant only to be called from a
396top-level script. To avoid foot-shooting the function will warn if you call it
397more than once.
2daff231 398
399=head2 with_logger
400
401 my $logger = WarnLogger->new;
21431192 402 with_logger $logger => sub {
2daff231 403 if (1 == 0) {
404 log_fatal { 'Non Logical Universe Detected' };
405 } else {
406 log_info { 'All is good' };
407 }
80c3e48b 408 };
2daff231 409
27141a7a 410Arguments: L</LOGGER CODEREF>, C<CodeRef $to_execute>
2daff231 411
21431192 412C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
0e13e261 413As with L</set_logger>, C<with_logger> will wrap C<$returning_logger> with a
21431192 414C<CodeRef> if needed.
2daff231 415
21431192 416=head2 log_$level
2daff231 417
0e13e261 418Import Tag: C<:log>
3dc9bd3c 419
0e13e261 420Arguments: C<CodeRef $returning_message, @args>
2daff231 421
a4d67519 422C<log_$level> functions all work the same except that a different method
21431192 423is called on the underlying C<$logger> object. The basic pattern is:
2daff231 424
0e13e261 425 sub log_$level (&@) {
21431192 426 if ($logger->is_$level) {
0e13e261 427 $logger->$level(shift->(@_));
21431192 428 }
0e13e261 429 @_
21431192 430 }
2daff231 431
0e13e261 432Note that the function returns it's arguments. This can be used in a number of
433ways, but often it's convenient just for partial inspection of passthrough data
434
435 my @friends = log_trace {
436 'friends list being generated, data from first friend: ' .
437 Dumper($_[0]->TO_JSON)
438 } generate_friend_list();
439
440If you want complete inspection of passthrough data, take a look at the
441L</Dlog_$level> functions.
442
a4d67519 443Which functions are exported depends on what was passed to L</-levels>. The
444default (no C<-levels> option passed) would export:
2daff231 445
a4d67519 446=over 2
2daff231 447
a4d67519 448=item log_trace
2daff231 449
a4d67519 450=item log_debug
2daff231 451
a4d67519 452=item log_info
2daff231 453
a4d67519 454=item log_warn
2daff231 455
a4d67519 456=item log_error
2daff231 457
a4d67519 458=item log_fatal
2daff231 459
a4d67519 460=back
2daff231 461
0e13e261 462=head2 logS_$level
463
464Import Tag: C<:log>
465
466Arguments: C<CodeRef $returning_message, Item $arg>
467
468This is really just a special case of the L</log_$level> functions. It forces
469scalar context when that is what you need. Other than that it works exactly
470same:
471
472 my $friend = logS_trace {
473 'I only have one friend: ' . Dumper($_[0]->TO_JSON)
474 } friend();
475
476See also: L</DlogS_$level>.
477
21431192 478=head2 Dlog_$level
479
0e13e261 480Import Tag: C<:dlog>
3dc9bd3c 481
0e13e261 482Arguments: C<CodeRef $returning_message, @args>
2daff231 483
0e13e261 484All of the following six functions work the same as their L</log_$level>
9b8e24d5 485brethren, except they return what is passed into them and put the stringified
21431192 486(with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
487you can do cool things like the following:
488
489 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
490
491and the output might look something like:
492
493 names: "fREW"
494 "fRIOUX"
495 "fROOH"
496 "fRUE"
497 "fiSMBoC"
498
a4d67519 499Which functions are exported depends on what was passed to L</-levels>. The
500default (no C<-levels> option passed) would export:
21431192 501
a4d67519 502=over 2
21431192 503
a4d67519 504=item Dlog_trace
21431192 505
a4d67519 506=item Dlog_debug
21431192 507
a4d67519 508=item Dlog_info
21431192 509
a4d67519 510=item Dlog_warn
21431192 511
a4d67519 512=item Dlog_error
2daff231 513
a4d67519 514=item Dlog_fatal
2daff231 515
a4d67519 516=back
2daff231 517
83b33eb5 518=head2 DlogS_$level
519
0e13e261 520Import Tag: C<:dlog>
3dc9bd3c 521
0e13e261 522Arguments: C<CodeRef $returning_message, Item $arg>
83b33eb5 523
0e13e261 524Like L</logS_$level>, these functions are a special case of L</Dlog_$level>.
525They only take a single scalar after the C<$returning_message> instead of
526slurping up (and also setting C<wantarray>) all the C<@args>
83b33eb5 527
528 my $pals_rs = DlogS_debug { "pals resultset: $_" }
529 $schema->resultset('Pals')->search({ perlers => 1 });
530
27141a7a 531=head1 LOGGER CODEREF
532
533Anywhere a logger object can be passed, a coderef is accepted. This is so
534that the user can use different logger objects based on runtime information.
535The logger coderef is passed the package of the caller the caller level the
536coderef needs to use if it wants more caller information. The latter is in
537a hashref to allow for more options in the future.
538
37a8266a 539Here is a basic example of a logger that exploits C<caller> to reproduce the
540output of C<warn> with a logger:
541
542 my @caller_info;
543 my $var_log = Log::Contextual::SimpleLogger->new({
544 levels => [qw(trace debug info warn error fatal)],
545 coderef => sub { chomp($_[0]); warn "$_[0] at $caller_info[1] line $caller_info[2].\n" }
546 });
547 my $warn_faker = sub {
548 my ($package, $args) = @_;
549 @caller_info = caller($args->{caller_level});
550 $var_log
551 };
552 set_logger($warn_faker);
553 log_debug { 'test' };
554
27141a7a 555The following is an example that uses the information passed to the logger
556coderef. It sets the global logger to C<$l3>, the logger for the C<A1>
557package to C<$l1>, except the C<lol> method in C<A1> which uses the C<$l2>
558logger and lastly the logger for the C<A2> package to C<$l2>.
559
37a8266a 560Note that it increases the caller level as it dispatches based on where
561the caller of the log function, not the log function itself.
562
27141a7a 563 my $complex_dispatcher = do {
564
565 my $l1 = ...;
566 my $l2 = ...;
567 my $l3 = ...;
568
569 my %registry = (
570 -logger => $l3,
571 A1 => {
572 -logger => $l1,
573 lol => $l2,
574 },
575 A2 => { -logger => $l2 },
576 );
577
578 sub {
579 my ( $package, $info ) = @_;
580
581 my $logger = $registry{'-logger'};
582 if (my $r = $registry{$package}) {
583 $logger = $r->{'-logger'} if $r->{'-logger'};
37a8266a 584 my (undef, undef, undef, $sub) = caller($info->{caller_level} + 1);
27141a7a 585 $sub =~ s/^\Q$package\E:://g;
586 $logger = $r->{$sub} if $r->{$sub};
587 }
588 return $logger;
589 }
590 };
591
592 set_logger $complex_dispatcher;
593
3dc9bd3c 594=head1 LOGGER INTERFACE
595
596Because this module is ultimately pretty looking glue (glittery?) with the
597awesome benefit of the Contextual part, users will often want to make their
598favorite logger work with it. The following are the methods that should be
599implemented in the logger:
600
601 is_trace
602 is_debug
603 is_info
604 is_warn
605 is_error
606 is_fatal
607 trace
608 debug
609 info
610 warn
611 error
612 fatal
613
614The first six merely need to return true if that level is enabled. The latter
615six take the results of whatever the user returned from their coderef and log
616them. For a basic example see L<Log::Contextual::SimpleLogger>.
617
eab2ca3c 618=head1 LOG ROUTING
619
a5454e75 620In between the loggers and the log functions is a log router that is responsible for
eab2ca3c 621finding a logger to handle the log event and passing the log information to the
a5454e75 622logger. This relationship is described in the documentation for C<Log::Contextual::Role::Router>.
eab2ca3c 623
a5454e75 624C<Log::Contextual> and packages that extend it will by default share a router singleton that
625implements the with_logger() and set_logger() functions and also respects the -logger,
626-package_logger, and -default_logger import options with their associated default value
627functions. The router singleton is available as the return value of the router() function. Users
628of Log::Contextual may overload router() to return instances of custom log routers that
629could for example work with loggers that use a different interface.
eab2ca3c 630
a5454e75 631=head1 AUTHOR
2daff231 632
633frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
634
a5454e75 635=head1 CONTRIBUTORS
636
eab2ca3c 637triddle - Tyler Riddle <t.riddle@shadowcat.co.uk>
638
2daff231 639=head1 DESIGNER
640
641mst - Matt S. Trout <mst@shadowcat.co.uk>
642
643=head1 COPYRIGHT
644
a6e29e27 645Copyright (c) 2012 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
2daff231 646above.
647
648=head1 LICENSE
649
650This library is free software and may be distributed under the same terms as
651Perl 5 itself.
652
653=cut
654