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