1 # add example for Log::Dispatchouli
3 package Log::Contextual;
8 our $VERSION = '0.00101';
11 use Data::Dumper::Concise;
12 use Scalar::Util 'blessed';
14 BEGIN { our @ISA = qw(Exporter) }
17 Dlog_debug DlogS_debug
18 Dlog_trace DlogS_trace
21 Dlog_error DlogS_error
22 Dlog_fatal DlogS_fatal
36 qw( set_logger with_logger )
47 die 'Log::Contextual does not have a default import list'
50 for my $idx ( 0 .. $#_ ) {
52 if ( defined $val && $val eq '-logger' ) {
53 set_logger($_[$idx + 1]);
55 } elsif ( defined $val && $val eq '-default_logger' ) {
56 _set_default_logger_for(scalar caller, $_[$idx + 1]);
60 $package->export_to_level(1, $package, @_);
66 sub _set_default_logger_for {
68 if(ref $logger ne 'CODE') {
69 die 'logger was not a CodeRef or a logger object. Please try again.'
70 unless blessed($logger);
71 $logger = do { my $l = $logger; sub { $l } }
73 $Default_Logger{$_[0]} = $logger
80 $Default_Logger{$package} ||
81 die q( no logger set! you can't try to log something without a logger! )
87 if(ref $logger ne 'CODE') {
88 die 'logger was not a CodeRef or a logger object. Please try again.'
89 unless blessed($logger);
90 $logger = do { my $l = $logger; sub { $l } }
93 warn 'set_logger (or -logger) called more than once! This is a bad idea!'
95 $Get_Logger = $logger;
100 if(ref $logger ne 'CODE') {
101 die 'logger was not a CodeRef or a logger object. Please try again.'
102 unless blessed($logger);
103 $logger = do { my $l = $logger; sub { $l } }
105 local $Get_Logger = $logger;
112 my $log = _get_logger( caller );
114 $log->trace($code->(@_))
120 my $log = _get_logger( caller );
122 $log->debug($code->(@_))
128 my $log = _get_logger( caller );
130 $log->info($code->(@_))
136 my $log = _get_logger( caller );
138 $log->warn($code->(@_))
144 my $log = _get_logger( caller );
146 $log->error($code->(@_))
152 my $log = _get_logger( caller );
154 $log->fatal($code->(@_))
160 sub logS_trace (&$) {
161 my $log = _get_logger( caller );
164 $log->trace($code->($value))
169 sub logS_debug (&$) {
170 my $log = _get_logger( caller );
173 $log->debug($code->($value))
179 my $log = _get_logger( caller );
182 $log->info($code->($value))
188 my $log = _get_logger( caller );
191 $log->warn($code->($value))
196 sub logS_error (&$) {
197 my $log = _get_logger( caller );
200 $log->error($code->($value))
205 sub logS_fatal (&$) {
206 my $log = _get_logger( caller );
209 $log->fatal($code->($value))
216 sub Dlog_trace (&@) {
221 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
223 do { local $_ = '()'; $code->() };
228 sub Dlog_debug (&@) {
233 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
235 do { local $_ = '()'; $code->() };
245 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
247 do { local $_ = '()'; $code->() };
257 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
259 do { local $_ = '()'; $code->() };
264 sub Dlog_error (&@) {
269 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
271 do { local $_ = '()'; $code->() };
276 sub Dlog_fatal (&@) {
281 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
283 do { local $_ = '()'; $code->() };
290 sub DlogS_trace (&$) {
294 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
298 sub DlogS_debug (&$) {
302 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
306 sub DlogS_info (&$) {
310 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
314 sub DlogS_warn (&$) {
318 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
322 sub DlogS_error (&$) {
326 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
330 sub DlogS_fatal (&$) {
334 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
344 Log::Contextual - Simple logging interface with a contextual log
348 use Log::Contextual qw( :log :dlog set_logger with_logger );
349 use Log::Contextual::SimpleLogger;
350 use Log::Log4perl ':easy';
351 Log::Log4perl->easy_init($DEBUG);
354 my $logger = Log::Log4perl->get_logger;
358 log_debug { 'program started' };
361 with_logger(Log::Contextual::SimpleLogger->new({
362 levels => [qw( trace debug )]
364 log_trace { 'foo entered' };
365 my ($foo, $bar) = Dlog_trace { "params for foo: $_" } @_;
367 log_trace { 'foo left' };
375 This module is a simple interface to extensible logging. It is bundled with a
376 really basic logger, L<Log::Contextual::SimpleLogger>, but in general you
377 should use a real logger instead of that. For something more serious but not
378 overly complicated, take a look at L<Log::Dispatchouli>.
384 When you import this module you may use C<-logger> as a shortcut for
385 L<set_logger>, for example:
387 use Log::Contextual::SimpleLogger;
388 use Log::Contextual qw( :dlog ),
389 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw( debug )] });
391 sometimes you might want to have the logger handy for other stuff, in which
392 case you might try something like the following:
395 BEGIN { $var_log = VarLogger->new }
396 use Log::Contextual qw( :dlog ), -logger => $var_log;
398 =head2 -default_logger
400 The C<-default_logger> import option is similar to the C<-logger> import option
401 except C<-default_logger> sets the the default logger for the current package.
403 Basically it sets the logger to be used if C<set_logger> is never called; so
406 use Log::Contextual::SimpleLogger;
407 use Log::Contextual qw( :log ),
408 -default_logger => Log::Contextual::WarnLogger->new({
409 env_prefix => 'MY_PACKAGE'
412 If you are interested in using this package for a module you are putting on
413 CPAN we recommend L<Log::Contextual::WarnLogger> for your default logger.
415 =head1 A WORK IN PROGRESS
417 This module is certainly not complete, but we will not break the interface
418 lightly, so I would say it's safe to use in production code. The main result
419 from that at this point is that doing:
423 will die as we do not yet know what the defaults should be. If it turns out
424 that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
425 probably make C<:log> the default. But only time and usage will tell.
431 my $logger = WarnLogger->new;
434 Arguments: C<Ref|CodeRef $returning_logger>
436 C<set_logger> will just set the current logger to whatever you pass it. It
437 expects a C<CodeRef>, but if you pass it something else it will wrap it in a
438 C<CodeRef> for you. C<set_logger> is really meant only to be called from a
439 top-level script. To avoid foot-shooting the function will warn if you call it
444 my $logger = WarnLogger->new;
445 with_logger $logger => sub {
447 log_fatal { 'Non Logical Universe Detected' };
449 log_info { 'All is good' };
453 Arguments: C<Ref|CodeRef $returning_logger, CodeRef $to_execute>
455 C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
456 As with L</set_logger>, C<with_logger> will wrap C<$returning_logger> with a
457 C<CodeRef> if needed.
463 Arguments: C<CodeRef $returning_message, @args>
465 All of the following six functions work the same except that a different method
466 is called on the underlying C<$logger> object. The basic pattern is:
468 sub log_$level (&@) {
469 if ($logger->is_$level) {
470 $logger->$level(shift->(@_));
475 Note that the function returns it's arguments. This can be used in a number of
476 ways, but often it's convenient just for partial inspection of passthrough data
478 my @friends = log_trace {
479 'friends list being generated, data from first friend: ' .
480 Dumper($_[0]->TO_JSON)
481 } generate_friend_list();
483 If you want complete inspection of passthrough data, take a look at the
484 L</Dlog_$level> functions.
488 log_trace { 'entered method foo with args ' join q{,}, @args };
492 log_debug { 'entered method foo' };
496 log_info { 'started process foo' };
500 log_warn { 'possible misconfiguration at line 10' };
504 log_error { 'non-numeric user input!' };
508 log_fatal { '1 is never equal to 0!' };
514 Arguments: C<CodeRef $returning_message, Item $arg>
516 This is really just a special case of the L</log_$level> functions. It forces
517 scalar context when that is what you need. Other than that it works exactly
520 my $friend = logS_trace {
521 'I only have one friend: ' . Dumper($_[0]->TO_JSON)
524 See also: L</DlogS_$level>.
530 Arguments: C<CodeRef $returning_message, @args>
532 All of the following six functions work the same as their L</log_$level>
533 brethren, except they return what is passed into them and put the stringified
534 (with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
535 you can do cool things like the following:
537 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
539 and the output might look something like:
549 my ($foo, $bar) = Dlog_trace { "entered method foo with args: $_" } @_;
553 Dlog_debug { "random data structure: $_" } { foo => $bar };
557 return Dlog_info { "html from method returned: $_" } "<html>...</html>";
561 Dlog_warn { "probably invalid value: $_" } $foo;
565 Dlog_error { "non-numeric user input! ($_)" } $port;
569 Dlog_fatal { '1 is never equal to 0!' } 'ZOMG ZOMG' if 1 == 0;
575 Arguments: C<CodeRef $returning_message, Item $arg>
577 Like L</logS_$level>, these functions are a special case of L</Dlog_$level>.
578 They only take a single scalar after the C<$returning_message> instead of
579 slurping up (and also setting C<wantarray>) all the C<@args>
581 my $pals_rs = DlogS_debug { "pals resultset: $_" }
582 $schema->resultset('Pals')->search({ perlers => 1 });
584 =head1 LOGGER INTERFACE
586 Because this module is ultimately pretty looking glue (glittery?) with the
587 awesome benefit of the Contextual part, users will often want to make their
588 favorite logger work with it. The following are the methods that should be
589 implemented in the logger:
604 The first six merely need to return true if that level is enabled. The latter
605 six take the results of whatever the user returned from their coderef and log
606 them. For a basic example see L<Log::Contextual::SimpleLogger>.
610 frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
614 mst - Matt S. Trout <mst@shadowcat.co.uk>
618 Copyright (c) 2010 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
623 This library is free software and may be distributed under the same terms as