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>.
385 When you import this module you may use C<-logger> as a shortcut for
386 L<set_logger>, for example:
388 use Log::Contextual::SimpleLogger;
389 use Log::Contextual qw( :dlog ),
390 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw( debug )] });
392 sometimes you might want to have the logger handy for other stuff, in which
393 case you might try something like the following:
396 BEGIN { $var_log = VarLogger->new }
397 use Log::Contextual qw( :dlog ), -logger => $var_log;
399 =head1 A WORK IN PROGRESS
401 This module is certainly not complete, but we will not break the interface
402 lightly, so I would say it's safe to use in production code. The main result
403 from that at this point is that doing:
407 will die as we do not yet know what the defaults should be. If it turns out
408 that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
409 probably make C<:log> the default. But only time and usage will tell.
415 my $logger = WarnLogger->new;
418 Arguments: C<Ref|CodeRef $returning_logger>
420 C<set_logger> will just set the current logger to whatever you pass it. It
421 expects a C<CodeRef>, but if you pass it something else it will wrap it in a
422 C<CodeRef> for you. C<set_logger> is really meant only to be called from a
423 top-level script. To avoid foot-shooting the function will warn if you call it
428 my $logger = WarnLogger->new;
429 with_logger $logger => sub {
431 log_fatal { 'Non Logical Universe Detected' };
433 log_info { 'All is good' };
437 Arguments: C<Ref|CodeRef $returning_logger, CodeRef $to_execute>
439 C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
440 As with L</set_logger>, C<with_logger> will wrap C<$returning_logger> with a
441 C<CodeRef> if needed.
447 Arguments: C<CodeRef $returning_message, @args>
449 All of the following six functions work the same except that a different method
450 is called on the underlying C<$logger> object. The basic pattern is:
452 sub log_$level (&@) {
453 if ($logger->is_$level) {
454 $logger->$level(shift->(@_));
459 Note that the function returns it's arguments. This can be used in a number of
460 ways, but often it's convenient just for partial inspection of passthrough data
462 my @friends = log_trace {
463 'friends list being generated, data from first friend: ' .
464 Dumper($_[0]->TO_JSON)
465 } generate_friend_list();
467 If you want complete inspection of passthrough data, take a look at the
468 L</Dlog_$level> functions.
472 log_trace { 'entered method foo with args ' join q{,}, @args };
476 log_debug { 'entered method foo' };
480 log_info { 'started process foo' };
484 log_warn { 'possible misconfiguration at line 10' };
488 log_error { 'non-numeric user input!' };
492 log_fatal { '1 is never equal to 0!' };
498 Arguments: C<CodeRef $returning_message, Item $arg>
500 This is really just a special case of the L</log_$level> functions. It forces
501 scalar context when that is what you need. Other than that it works exactly
504 my $friend = logS_trace {
505 'I only have one friend: ' . Dumper($_[0]->TO_JSON)
508 See also: L</DlogS_$level>.
514 Arguments: C<CodeRef $returning_message, @args>
516 All of the following six functions work the same as their L</log_$level>
517 brethren, except they return what is passed into them and put the stringified
518 (with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
519 you can do cool things like the following:
521 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
523 and the output might look something like:
533 my ($foo, $bar) = Dlog_trace { "entered method foo with args: $_" } @_;
537 Dlog_debug { "random data structure: $_" } { foo => $bar };
541 return Dlog_info { "html from method returned: $_" } "<html>...</html>";
545 Dlog_warn { "probably invalid value: $_" } $foo;
549 Dlog_error { "non-numeric user input! ($_)" } $port;
553 Dlog_fatal { '1 is never equal to 0!' } 'ZOMG ZOMG' if 1 == 0;
559 Arguments: C<CodeRef $returning_message, Item $arg>
561 Like L</logS_$level>, these functions are a special case of L</Dlog_$level>.
562 They only take a single scalar after the C<$returning_message> instead of
563 slurping up (and also setting C<wantarray>) all the C<@args>
565 my $pals_rs = DlogS_debug { "pals resultset: $_" }
566 $schema->resultset('Pals')->search({ perlers => 1 });
568 =head1 LOGGER INTERFACE
570 Because this module is ultimately pretty looking glue (glittery?) with the
571 awesome benefit of the Contextual part, users will often want to make their
572 favorite logger work with it. The following are the methods that should be
573 implemented in the logger:
588 The first six merely need to return true if that level is enabled. The latter
589 six take the results of whatever the user returned from their coderef and log
590 them. For a basic example see L<Log::Contextual::SimpleLogger>.
594 frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
598 mst - Matt S. Trout <mst@shadowcat.co.uk>
602 Copyright (c) 2010 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
607 This library is free software and may be distributed under the same terms as