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