add doc for -default_logger
[p5sagit/Log-Contextual.git] / lib / Log / Contextual.pm
CommitLineData
5d8f2b84 1# add example for Log::Dispatchouli
5d8f2b84 2#
5d8f2b84 3# make basic warn logger
4
5
0daa11f3 6package Log::Contextual;
7
a2777569 8use strict;
9use warnings;
2033c911 10
1b3aa6c8 11our $VERSION = '0.00101';
2033c911 12
13require Exporter;
f11f9542 14use Data::Dumper::Concise;
5b094c87 15use Scalar::Util 'blessed';
2033c911 16
a2777569 17BEGIN { our @ISA = qw(Exporter) }
2033c911 18
9b8e24d5 19my @dlog = (qw(
f11f9542 20 Dlog_debug DlogS_debug
21 Dlog_trace DlogS_trace
22 Dlog_warn DlogS_warn
23 Dlog_info DlogS_info
24 Dlog_error DlogS_error
25 Dlog_fatal DlogS_fatal
9b8e24d5 26 ));
f11f9542 27
9b8e24d5 28my @log = (qw(
9061df76 29 log_debug logS_debug
30 log_trace logS_trace
31 log_warn logS_warn
32 log_info logS_info
33 log_error logS_error
34 log_fatal logS_fatal
9b8e24d5 35 ));
f11f9542 36
a2777569 37our @EXPORT_OK = (
f11f9542 38 @dlog, @log,
9b8e24d5 39 qw( set_logger with_logger )
f11f9542 40);
41
a2777569 42our %EXPORT_TAGS = (
f11f9542 43 dlog => \@dlog,
44 log => \@log,
3dc9bd3c 45 all => [@dlog, @log],
f11f9542 46);
47
48sub import {
a2777569 49 my $package = shift;
f11f9542 50 die 'Log::Contextual does not have a default import list'
a2777569 51 unless @_;
52
53 for my $idx ( 0 .. $#_ ) {
3ccc9c47 54 my $val = $_[$idx];
55 if ( defined $val && $val eq '-logger' ) {
a2777569 56 set_logger($_[$idx + 1]);
57 splice @_, $idx, 2;
3ccc9c47 58 } elsif ( defined $val && $val eq '-default_logger' ) {
59 _set_default_logger_for(scalar caller, $_[$idx + 1]);
06e908c3 60 splice @_, $idx, 2;
a2777569 61 }
62 }
63 $package->export_to_level(1, $package, @_);
f11f9542 64}
2033c911 65
7cec609c 66our $Get_Logger;
5d8f2b84 67our %Default_Logger;
68
3ccc9c47 69sub _set_default_logger_for {
70 my $logger = $_[1];
71 if(ref $logger ne 'CODE') {
72 die 'logger was not a CodeRef or a logger object. Please try again.'
73 unless blessed($logger);
74 $logger = do { my $l = $logger; sub { $l } }
75 }
76 $Default_Logger{$_[0]} = $logger
77}
06e908c3 78
5d8f2b84 79sub _get_logger($) {
80 my $package = shift;
81 (
82 $Get_Logger ||
83 $Default_Logger{$package} ||
84 die q( no logger set! you can't try to log something without a logger! )
06e908c3 85 )->($package);
5d8f2b84 86}
7cec609c 87
8dc5a747 88sub set_logger {
89 my $logger = $_[0];
5b094c87 90 if(ref $logger ne 'CODE') {
91 die 'logger was not a CodeRef or a logger object. Please try again.'
92 unless blessed($logger);
93 $logger = do { my $l = $logger; sub { $l } }
94 }
5d8f2b84 95
96 warn 'set_logger (or -logger) called more than once! This is a bad idea!'
97 if $Get_Logger;
8dc5a747 98 $Get_Logger = $logger;
7cec609c 99}
100
98833ffb 101sub with_logger {
102 my $logger = $_[0];
5b094c87 103 if(ref $logger ne 'CODE') {
104 die 'logger was not a CodeRef or a logger object. Please try again.'
105 unless blessed($logger);
106 $logger = do { my $l = $logger; sub { $l } }
107 }
98833ffb 108 local $Get_Logger = $logger;
80c3e48b 109 $_[1]->();
2daff231 110}
111
a4273dbf 112
113
4d8ea78d 114sub log_trace (&@) {
5d8f2b84 115 my $log = _get_logger( caller );
4d8ea78d 116 my $code = shift;
117 $log->trace($code->(@_))
6dc6632a 118 if $log->is_trace;
4d8ea78d 119 @_
6dc6632a 120}
121
4d8ea78d 122sub log_debug (&@) {
5d8f2b84 123 my $log = _get_logger( caller );
4d8ea78d 124 my $code = shift;
125 $log->debug($code->(@_))
7cec609c 126 if $log->is_debug;
4d8ea78d 127 @_
7cec609c 128}
129
4d8ea78d 130sub log_info (&@) {
5d8f2b84 131 my $log = _get_logger( caller );
4d8ea78d 132 my $code = shift;
133 $log->info($code->(@_))
6dc6632a 134 if $log->is_info;
4d8ea78d 135 @_
6dc6632a 136}
137
4d8ea78d 138sub log_warn (&@) {
5d8f2b84 139 my $log = _get_logger( caller );
4d8ea78d 140 my $code = shift;
141 $log->warn($code->(@_))
6dc6632a 142 if $log->is_warn;
4d8ea78d 143 @_
6dc6632a 144}
145
4d8ea78d 146sub log_error (&@) {
5d8f2b84 147 my $log = _get_logger( caller );
4d8ea78d 148 my $code = shift;
149 $log->error($code->(@_))
6dc6632a 150 if $log->is_error;
4d8ea78d 151 @_
6dc6632a 152}
153
4d8ea78d 154sub log_fatal (&@) {
5d8f2b84 155 my $log = _get_logger( caller );
4d8ea78d 156 my $code = shift;
157 $log->fatal($code->(@_))
6dc6632a 158 if $log->is_fatal;
4d8ea78d 159 @_
6dc6632a 160}
161
f11f9542 162
709d11fe 163sub logS_trace (&$) {
5d8f2b84 164 my $log = _get_logger( caller );
709d11fe 165 my $code = shift;
166 my $value = shift;
167 $log->trace($code->($value))
168 if $log->is_trace;
169 $value
170}
171
172sub logS_debug (&$) {
5d8f2b84 173 my $log = _get_logger( caller );
709d11fe 174 my $code = shift;
175 my $value = shift;
176 $log->debug($code->($value))
177 if $log->is_debug;
178 $value
179}
180
181sub logS_info (&$) {
5d8f2b84 182 my $log = _get_logger( caller );
709d11fe 183 my $code = shift;
184 my $value = shift;
185 $log->info($code->($value))
186 if $log->is_info;
187 $value
188}
189
190sub logS_warn (&$) {
5d8f2b84 191 my $log = _get_logger( caller );
709d11fe 192 my $code = shift;
193 my $value = shift;
194 $log->warn($code->($value))
195 if $log->is_warn;
196 $value
197}
198
199sub logS_error (&$) {
5d8f2b84 200 my $log = _get_logger( caller );
709d11fe 201 my $code = shift;
202 my $value = shift;
203 $log->error($code->($value))
204 if $log->is_error;
205 $value
206}
207
208sub logS_fatal (&$) {
5d8f2b84 209 my $log = _get_logger( caller );
709d11fe 210 my $code = shift;
211 my $value = shift;
212 $log->fatal($code->($value))
213 if $log->is_fatal;
214 $value
215}
216
217
f11f9542 218
219sub Dlog_trace (&@) {
220 my $code = shift;
221 my @values = @_;
5a1c7d54 222 return log_trace {
db70b0a5 223 if (@values) {
224 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
225 } else {
226 do { local $_ = '()'; $code->() };
227 }
5a1c7d54 228 } @values
f11f9542 229}
230
a4273dbf 231sub Dlog_debug (&@) {
232 my $code = shift;
233 my @values = @_;
234 log_debug {
db70b0a5 235 if (@values) {
236 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
237 } else {
238 do { local $_ = '()'; $code->() };
239 }
a4273dbf 240 } @values
241}
242
243sub Dlog_info (&@) {
244 my $code = shift;
245 my @values = @_;
246 log_info {
db70b0a5 247 if (@values) {
248 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
249 } else {
250 do { local $_ = '()'; $code->() };
251 }
a4273dbf 252 } @values
253}
254
255sub Dlog_warn (&@) {
256 my $code = shift;
257 my @values = @_;
258 log_warn {
db70b0a5 259 if (@values) {
260 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
261 } else {
262 do { local $_ = '()'; $code->() };
263 }
a4273dbf 264 } @values
265}
266
267sub Dlog_error (&@) {
268 my $code = shift;
269 my @values = @_;
270 log_error {
db70b0a5 271 if (@values) {
272 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
273 } else {
274 do { local $_ = '()'; $code->() };
275 }
a4273dbf 276 } @values
277}
278
279sub Dlog_fatal (&@) {
280 my $code = shift;
281 my @values = @_;
282 log_fatal {
db70b0a5 283 if (@values) {
284 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
285 } else {
286 do { local $_ = '()'; $code->() };
287 }
a4273dbf 288 } @values
289}
290
291
292
f11f9542 293sub DlogS_trace (&$) {
294 my $code = $_[0];
295 my $value = $_[1];
709d11fe 296 logS_trace {
f11f9542 297 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
709d11fe 298 } $value
f11f9542 299}
300
f11f9542 301sub DlogS_debug (&$) {
302 my $code = $_[0];
303 my $value = $_[1];
709d11fe 304 logS_debug {
f11f9542 305 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
709d11fe 306 } $value
f11f9542 307}
308
f11f9542 309sub DlogS_info (&$) {
310 my $code = $_[0];
311 my $value = $_[1];
709d11fe 312 logS_info {
f11f9542 313 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
709d11fe 314 } $value
f11f9542 315}
316
f11f9542 317sub DlogS_warn (&$) {
318 my $code = $_[0];
319 my $value = $_[1];
709d11fe 320 logS_warn {
f11f9542 321 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
709d11fe 322 } $value
f11f9542 323}
324
f11f9542 325sub DlogS_error (&$) {
326 my $code = $_[0];
327 my $value = $_[1];
709d11fe 328 logS_error {
f11f9542 329 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
709d11fe 330 } $value
f11f9542 331}
332
f11f9542 333sub DlogS_fatal (&$) {
334 my $code = $_[0];
335 my $value = $_[1];
709d11fe 336 logS_fatal {
f11f9542 337 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
709d11fe 338 } $value
f11f9542 339}
340
0daa11f3 3411;
0a3750e2 342
343__END__
344
2daff231 345=head1 NAME
346
8bc568d2 347Log::Contextual - Simple logging interface with a contextual log
2daff231 348
349=head1 SYNOPSIS
350
9b8e24d5 351 use Log::Contextual qw( :log :dlog set_logger with_logger );
5b094c87 352 use Log::Contextual::SimpleLogger;
353 use Log::Log4perl ':easy';
354 Log::Log4perl->easy_init($DEBUG);
2daff231 355
2daff231 356
5b094c87 357 my $logger = Log::Log4perl->get_logger;
358
359 set_logger $logger;
2daff231 360
9b8e24d5 361 log_debug { 'program started' };
2daff231 362
363 sub foo {
9b8e24d5 364 with_logger(Log::Contextual::SimpleLogger->new({
365 levels => [qw( trace debug )]
21431192 366 }) => sub {
367 log_trace { 'foo entered' };
9b8e24d5 368 my ($foo, $bar) = Dlog_trace { "params for foo: $_" } @_;
2daff231 369 # ...
21431192 370 log_trace { 'foo left' };
9b8e24d5 371 });
2daff231 372 }
373
5b094c87 374 foo();
375
2daff231 376=head1 DESCRIPTION
377
3dc9bd3c 378This module is a simple interface to extensible logging. It is bundled with a
379really basic logger, L<Log::Contextual::SimpleLogger>, but in general you
380should use a real logger instead of that. For something more serious but not
381overly complicated, take a look at L<Log::Dispatchouli>.
382
383=head1 OPTIONS
384
c154d18a 385=head2 -logger
386
3dc9bd3c 387When you import this module you may use C<-logger> as a shortcut for
388L<set_logger>, for example:
389
390 use Log::Contextual::SimpleLogger;
9b8e24d5 391 use Log::Contextual qw( :dlog ),
392 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw( debug )] });
3dc9bd3c 393
394sometimes you might want to have the logger handy for other stuff, in which
395case you might try something like the following:
396
397 my $var_log;
398 BEGIN { $var_log = VarLogger->new }
9b8e24d5 399 use Log::Contextual qw( :dlog ), -logger => $var_log;
3dc9bd3c 400
c154d18a 401=head2 -default_logger
402
403The C<-default_logger> import option is similar to the C<-logger> import option
404except C<-default_logger> sets the the default logger for the current package.
405
406Basically it sets the logger to be used if C<set_logger> is never called; so
407
408 package My::Package;
409 use Log::Contextual::SimpleLogger;
410 use Log::Contextual qw( :log ),
411 -default_logger => Log::Contextual::WarnLogger->new({
412 env_var => 'MY_PACKAGE'
413 });
414
415If you are interested in using this package for a module you are putting on
416CPAN we recommend L<Log::Contextual::WarnLogger> for your default logger.
417
3dc9bd3c 418=head1 A WORK IN PROGRESS
419
420This module is certainly not complete, but we will not break the interface
421lightly, so I would say it's safe to use in production code. The main result
422from that at this point is that doing:
423
424 use Log::Contextual;
425
426will die as we do not yet know what the defaults should be. If it turns out
427that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
9b8e24d5 428probably make C<:log> the default. But only time and usage will tell.
2daff231 429
430=head1 FUNCTIONS
431
432=head2 set_logger
433
434 my $logger = WarnLogger->new;
21431192 435 set_logger $logger;
436
0e13e261 437Arguments: C<Ref|CodeRef $returning_logger>
2daff231 438
21431192 439C<set_logger> will just set the current logger to whatever you pass it. It
440expects a C<CodeRef>, but if you pass it something else it will wrap it in a
06e908c3 441C<CodeRef> for you. C<set_logger> is really meant only to be called from a
442top-level script. To avoid foot-shooting the function will warn if you call it
443more than once.
2daff231 444
445=head2 with_logger
446
447 my $logger = WarnLogger->new;
21431192 448 with_logger $logger => sub {
2daff231 449 if (1 == 0) {
450 log_fatal { 'Non Logical Universe Detected' };
451 } else {
452 log_info { 'All is good' };
453 }
80c3e48b 454 };
2daff231 455
0e13e261 456Arguments: C<Ref|CodeRef $returning_logger, CodeRef $to_execute>
2daff231 457
21431192 458C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
0e13e261 459As with L</set_logger>, C<with_logger> will wrap C<$returning_logger> with a
21431192 460C<CodeRef> if needed.
2daff231 461
21431192 462=head2 log_$level
2daff231 463
0e13e261 464Import Tag: C<:log>
3dc9bd3c 465
0e13e261 466Arguments: C<CodeRef $returning_message, @args>
2daff231 467
21431192 468All of the following six functions work the same except that a different method
469is called on the underlying C<$logger> object. The basic pattern is:
2daff231 470
0e13e261 471 sub log_$level (&@) {
21431192 472 if ($logger->is_$level) {
0e13e261 473 $logger->$level(shift->(@_));
21431192 474 }
0e13e261 475 @_
21431192 476 }
2daff231 477
0e13e261 478Note that the function returns it's arguments. This can be used in a number of
479ways, but often it's convenient just for partial inspection of passthrough data
480
481 my @friends = log_trace {
482 'friends list being generated, data from first friend: ' .
483 Dumper($_[0]->TO_JSON)
484 } generate_friend_list();
485
486If you want complete inspection of passthrough data, take a look at the
487L</Dlog_$level> functions.
488
21431192 489=head3 log_trace
2daff231 490
21431192 491 log_trace { 'entered method foo with args ' join q{,}, @args };
2daff231 492
21431192 493=head3 log_debug
2daff231 494
21431192 495 log_debug { 'entered method foo' };
2daff231 496
21431192 497=head3 log_info
2daff231 498
21431192 499 log_info { 'started process foo' };
2daff231 500
21431192 501=head3 log_warn
2daff231 502
21431192 503 log_warn { 'possible misconfiguration at line 10' };
2daff231 504
21431192 505=head3 log_error
2daff231 506
21431192 507 log_error { 'non-numeric user input!' };
2daff231 508
21431192 509=head3 log_fatal
2daff231 510
511 log_fatal { '1 is never equal to 0!' };
512
0e13e261 513=head2 logS_$level
514
515Import Tag: C<:log>
516
517Arguments: C<CodeRef $returning_message, Item $arg>
518
519This is really just a special case of the L</log_$level> functions. It forces
520scalar context when that is what you need. Other than that it works exactly
521same:
522
523 my $friend = logS_trace {
524 'I only have one friend: ' . Dumper($_[0]->TO_JSON)
525 } friend();
526
527See also: L</DlogS_$level>.
528
21431192 529=head2 Dlog_$level
530
0e13e261 531Import Tag: C<:dlog>
3dc9bd3c 532
0e13e261 533Arguments: C<CodeRef $returning_message, @args>
2daff231 534
0e13e261 535All of the following six functions work the same as their L</log_$level>
9b8e24d5 536brethren, except they return what is passed into them and put the stringified
21431192 537(with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
538you can do cool things like the following:
539
540 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
541
542and the output might look something like:
543
544 names: "fREW"
545 "fRIOUX"
546 "fROOH"
547 "fRUE"
548 "fiSMBoC"
549
550=head3 Dlog_trace
551
9b8e24d5 552 my ($foo, $bar) = Dlog_trace { "entered method foo with args: $_" } @_;
21431192 553
554=head3 Dlog_debug
555
556 Dlog_debug { "random data structure: $_" } { foo => $bar };
557
558=head3 Dlog_info
559
560 return Dlog_info { "html from method returned: $_" } "<html>...</html>";
561
562=head3 Dlog_warn
563
564 Dlog_warn { "probably invalid value: $_" } $foo;
565
566=head3 Dlog_error
567
568 Dlog_error { "non-numeric user input! ($_)" } $port;
2daff231 569
21431192 570=head3 Dlog_fatal
2daff231 571
21431192 572 Dlog_fatal { '1 is never equal to 0!' } 'ZOMG ZOMG' if 1 == 0;
2daff231 573
83b33eb5 574=head2 DlogS_$level
575
0e13e261 576Import Tag: C<:dlog>
3dc9bd3c 577
0e13e261 578Arguments: C<CodeRef $returning_message, Item $arg>
83b33eb5 579
0e13e261 580Like L</logS_$level>, these functions are a special case of L</Dlog_$level>.
581They only take a single scalar after the C<$returning_message> instead of
582slurping up (and also setting C<wantarray>) all the C<@args>
83b33eb5 583
584 my $pals_rs = DlogS_debug { "pals resultset: $_" }
585 $schema->resultset('Pals')->search({ perlers => 1 });
586
3dc9bd3c 587=head1 LOGGER INTERFACE
588
589Because this module is ultimately pretty looking glue (glittery?) with the
590awesome benefit of the Contextual part, users will often want to make their
591favorite logger work with it. The following are the methods that should be
592implemented in the logger:
593
594 is_trace
595 is_debug
596 is_info
597 is_warn
598 is_error
599 is_fatal
600 trace
601 debug
602 info
603 warn
604 error
605 fatal
606
607The first six merely need to return true if that level is enabled. The latter
608six take the results of whatever the user returned from their coderef and log
609them. For a basic example see L<Log::Contextual::SimpleLogger>.
610
2daff231 611=head1 AUTHOR
612
613frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
614
615=head1 DESIGNER
616
617mst - Matt S. Trout <mst@shadowcat.co.uk>
618
619=head1 COPYRIGHT
620
621Copyright (c) 2010 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
622above.
623
624=head1 LICENSE
625
626This library is free software and may be distributed under the same terms as
627Perl 5 itself.
628
629=cut
630