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