1 # add example for Log::Dispatchouli
3 # make basic warn logger
6 package Log::Contextual;
11 our $VERSION = '0.00101';
14 use Data::Dumper::Concise;
15 use Scalar::Util 'blessed';
17 BEGIN { our @ISA = qw(Exporter) }
20 Dlog_debug DlogS_debug
21 Dlog_trace DlogS_trace
24 Dlog_error DlogS_error
25 Dlog_fatal DlogS_fatal
39 qw( set_logger with_logger )
50 die 'Log::Contextual does not have a default import list'
53 for my $idx ( 0 .. $#_ ) {
55 if ( defined $val && $val eq '-logger' ) {
56 set_logger($_[$idx + 1]);
58 } elsif ( defined $val && $val eq '-default_logger' ) {
59 _set_default_logger_for(scalar caller, $_[$idx + 1]);
63 $package->export_to_level(1, $package, @_);
69 sub _set_default_logger_for {
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 } }
76 $Default_Logger{$_[0]} = $logger
83 $Default_Logger{$package} ||
84 die q( no logger set! you can't try to log something without a logger! )
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 } }
96 warn 'set_logger (or -logger) called more than once! This is a bad idea!'
98 $Get_Logger = $logger;
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 } }
108 local $Get_Logger = $logger;
115 my $log = _get_logger( caller );
117 $log->trace($code->(@_))
123 my $log = _get_logger( caller );
125 $log->debug($code->(@_))
131 my $log = _get_logger( caller );
133 $log->info($code->(@_))
139 my $log = _get_logger( caller );
141 $log->warn($code->(@_))
147 my $log = _get_logger( caller );
149 $log->error($code->(@_))
155 my $log = _get_logger( caller );
157 $log->fatal($code->(@_))
163 sub logS_trace (&$) {
164 my $log = _get_logger( caller );
167 $log->trace($code->($value))
172 sub logS_debug (&$) {
173 my $log = _get_logger( caller );
176 $log->debug($code->($value))
182 my $log = _get_logger( caller );
185 $log->info($code->($value))
191 my $log = _get_logger( caller );
194 $log->warn($code->($value))
199 sub logS_error (&$) {
200 my $log = _get_logger( caller );
203 $log->error($code->($value))
208 sub logS_fatal (&$) {
209 my $log = _get_logger( caller );
212 $log->fatal($code->($value))
219 sub Dlog_trace (&@) {
224 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
226 do { local $_ = '()'; $code->() };
231 sub Dlog_debug (&@) {
236 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
238 do { local $_ = '()'; $code->() };
248 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
250 do { local $_ = '()'; $code->() };
260 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
262 do { local $_ = '()'; $code->() };
267 sub Dlog_error (&@) {
272 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
274 do { local $_ = '()'; $code->() };
279 sub Dlog_fatal (&@) {
284 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
286 do { local $_ = '()'; $code->() };
293 sub DlogS_trace (&$) {
297 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
301 sub DlogS_debug (&$) {
305 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
309 sub DlogS_info (&$) {
313 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
317 sub DlogS_warn (&$) {
321 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
325 sub DlogS_error (&$) {
329 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
333 sub DlogS_fatal (&$) {
337 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
347 Log::Contextual - Simple logging interface with a contextual log
351 use Log::Contextual qw( :log :dlog set_logger with_logger );
352 use Log::Contextual::SimpleLogger;
353 use Log::Log4perl ':easy';
354 Log::Log4perl->easy_init($DEBUG);
357 my $logger = Log::Log4perl->get_logger;
361 log_debug { 'program started' };
364 with_logger(Log::Contextual::SimpleLogger->new({
365 levels => [qw( trace debug )]
367 log_trace { 'foo entered' };
368 my ($foo, $bar) = Dlog_trace { "params for foo: $_" } @_;
370 log_trace { 'foo left' };
378 This module is a simple interface to extensible logging. It is bundled with a
379 really basic logger, L<Log::Contextual::SimpleLogger>, but in general you
380 should use a real logger instead of that. For something more serious but not
381 overly complicated, take a look at L<Log::Dispatchouli>.
387 When you import this module you may use C<-logger> as a shortcut for
388 L<set_logger>, for example:
390 use Log::Contextual::SimpleLogger;
391 use Log::Contextual qw( :dlog ),
392 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw( debug )] });
394 sometimes you might want to have the logger handy for other stuff, in which
395 case you might try something like the following:
398 BEGIN { $var_log = VarLogger->new }
399 use Log::Contextual qw( :dlog ), -logger => $var_log;
401 =head2 -default_logger
403 The C<-default_logger> import option is similar to the C<-logger> import option
404 except C<-default_logger> sets the the default logger for the current package.
406 Basically it sets the logger to be used if C<set_logger> is never called; so
409 use Log::Contextual::SimpleLogger;
410 use Log::Contextual qw( :log ),
411 -default_logger => Log::Contextual::WarnLogger->new({
412 env_var => 'MY_PACKAGE'
415 If you are interested in using this package for a module you are putting on
416 CPAN we recommend L<Log::Contextual::WarnLogger> for your default logger.
418 =head1 A WORK IN PROGRESS
420 This module is certainly not complete, but we will not break the interface
421 lightly, so I would say it's safe to use in production code. The main result
422 from that at this point is that doing:
426 will die as we do not yet know what the defaults should be. If it turns out
427 that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
428 probably make C<:log> the default. But only time and usage will tell.
434 my $logger = WarnLogger->new;
437 Arguments: C<Ref|CodeRef $returning_logger>
439 C<set_logger> will just set the current logger to whatever you pass it. It
440 expects a C<CodeRef>, but if you pass it something else it will wrap it in a
441 C<CodeRef> for you. C<set_logger> is really meant only to be called from a
442 top-level script. To avoid foot-shooting the function will warn if you call it
447 my $logger = WarnLogger->new;
448 with_logger $logger => sub {
450 log_fatal { 'Non Logical Universe Detected' };
452 log_info { 'All is good' };
456 Arguments: C<Ref|CodeRef $returning_logger, CodeRef $to_execute>
458 C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
459 As with L</set_logger>, C<with_logger> will wrap C<$returning_logger> with a
460 C<CodeRef> if needed.
466 Arguments: C<CodeRef $returning_message, @args>
468 All of the following six functions work the same except that a different method
469 is called on the underlying C<$logger> object. The basic pattern is:
471 sub log_$level (&@) {
472 if ($logger->is_$level) {
473 $logger->$level(shift->(@_));
478 Note that the function returns it's arguments. This can be used in a number of
479 ways, but often it's convenient just for partial inspection of passthrough data
481 my @friends = log_trace {
482 'friends list being generated, data from first friend: ' .
483 Dumper($_[0]->TO_JSON)
484 } generate_friend_list();
486 If you want complete inspection of passthrough data, take a look at the
487 L</Dlog_$level> functions.
491 log_trace { 'entered method foo with args ' join q{,}, @args };
495 log_debug { 'entered method foo' };
499 log_info { 'started process foo' };
503 log_warn { 'possible misconfiguration at line 10' };
507 log_error { 'non-numeric user input!' };
511 log_fatal { '1 is never equal to 0!' };
517 Arguments: C<CodeRef $returning_message, Item $arg>
519 This is really just a special case of the L</log_$level> functions. It forces
520 scalar context when that is what you need. Other than that it works exactly
523 my $friend = logS_trace {
524 'I only have one friend: ' . Dumper($_[0]->TO_JSON)
527 See also: L</DlogS_$level>.
533 Arguments: C<CodeRef $returning_message, @args>
535 All of the following six functions work the same as their L</log_$level>
536 brethren, except they return what is passed into them and put the stringified
537 (with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
538 you can do cool things like the following:
540 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
542 and the output might look something like:
552 my ($foo, $bar) = Dlog_trace { "entered method foo with args: $_" } @_;
556 Dlog_debug { "random data structure: $_" } { foo => $bar };
560 return Dlog_info { "html from method returned: $_" } "<html>...</html>";
564 Dlog_warn { "probably invalid value: $_" } $foo;
568 Dlog_error { "non-numeric user input! ($_)" } $port;
572 Dlog_fatal { '1 is never equal to 0!' } 'ZOMG ZOMG' if 1 == 0;
578 Arguments: C<CodeRef $returning_message, Item $arg>
580 Like L</logS_$level>, these functions are a special case of L</Dlog_$level>.
581 They only take a single scalar after the C<$returning_message> instead of
582 slurping up (and also setting C<wantarray>) all the C<@args>
584 my $pals_rs = DlogS_debug { "pals resultset: $_" }
585 $schema->resultset('Pals')->search({ perlers => 1 });
587 =head1 LOGGER INTERFACE
589 Because this module is ultimately pretty looking glue (glittery?) with the
590 awesome benefit of the Contextual part, users will often want to make their
591 favorite logger work with it. The following are the methods that should be
592 implemented in the logger:
607 The first six merely need to return true if that level is enabled. The latter
608 six take the results of whatever the user returned from their coderef and log
609 them. For a basic example see L<Log::Contextual::SimpleLogger>.
613 frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
617 mst - Matt S. Trout <mst@shadowcat.co.uk>
621 Copyright (c) 2010 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
626 This library is free software and may be distributed under the same terms as