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 .. $#_ ) {
54 if ( $_[$idx] eq '-logger' ) {
55 set_logger($_[$idx + 1]);
57 } elsif ( $_[$idx] eq '-default_logger' ) {
58 set_default_logger_for(scalar caller, $_[$idx + 1]);
62 $package->export_to_level(1, $package, @_);
68 sub _set_default_logger_for { $Default_Logger{$_[0]} = $_[1] }
74 $Default_Logger{$package} ||
75 die q( no logger set! you can't try to log something without a logger! )
81 if(ref $logger ne 'CODE') {
82 die 'logger was not a CodeRef or a logger object. Please try again.'
83 unless blessed($logger);
84 $logger = do { my $l = $logger; sub { $l } }
87 warn 'set_logger (or -logger) called more than once! This is a bad idea!'
89 $Get_Logger = $logger;
94 if(ref $logger ne 'CODE') {
95 die 'logger was not a CodeRef or a logger object. Please try again.'
96 unless blessed($logger);
97 $logger = do { my $l = $logger; sub { $l } }
99 local $Get_Logger = $logger;
106 my $log = _get_logger( caller );
108 $log->trace($code->(@_))
114 my $log = _get_logger( caller );
116 $log->debug($code->(@_))
122 my $log = _get_logger( caller );
124 $log->info($code->(@_))
130 my $log = _get_logger( caller );
132 $log->warn($code->(@_))
138 my $log = _get_logger( caller );
140 $log->error($code->(@_))
146 my $log = _get_logger( caller );
148 $log->fatal($code->(@_))
154 sub logS_trace (&$) {
155 my $log = _get_logger( caller );
158 $log->trace($code->($value))
163 sub logS_debug (&$) {
164 my $log = _get_logger( caller );
167 $log->debug($code->($value))
173 my $log = _get_logger( caller );
176 $log->info($code->($value))
182 my $log = _get_logger( caller );
185 $log->warn($code->($value))
190 sub logS_error (&$) {
191 my $log = _get_logger( caller );
194 $log->error($code->($value))
199 sub logS_fatal (&$) {
200 my $log = _get_logger( caller );
203 $log->fatal($code->($value))
210 sub Dlog_trace (&@) {
215 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
217 do { local $_ = '()'; $code->() };
222 sub Dlog_debug (&@) {
227 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
229 do { local $_ = '()'; $code->() };
239 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
241 do { local $_ = '()'; $code->() };
251 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
253 do { local $_ = '()'; $code->() };
258 sub Dlog_error (&@) {
263 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
265 do { local $_ = '()'; $code->() };
270 sub Dlog_fatal (&@) {
275 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
277 do { local $_ = '()'; $code->() };
284 sub DlogS_trace (&$) {
288 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
292 sub DlogS_debug (&$) {
296 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
300 sub DlogS_info (&$) {
304 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
308 sub DlogS_warn (&$) {
312 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
316 sub DlogS_error (&$) {
320 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
324 sub DlogS_fatal (&$) {
328 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
338 Log::Contextual - Simple logging interface with a contextual log
342 use Log::Contextual qw( :log :dlog set_logger with_logger );
343 use Log::Contextual::SimpleLogger;
344 use Log::Log4perl ':easy';
345 Log::Log4perl->easy_init($DEBUG);
348 my $logger = Log::Log4perl->get_logger;
352 log_debug { 'program started' };
355 with_logger(Log::Contextual::SimpleLogger->new({
356 levels => [qw( trace debug )]
358 log_trace { 'foo entered' };
359 my ($foo, $bar) = Dlog_trace { "params for foo: $_" } @_;
361 log_trace { 'foo left' };
369 This module is a simple interface to extensible logging. It is bundled with a
370 really basic logger, L<Log::Contextual::SimpleLogger>, but in general you
371 should use a real logger instead of that. For something more serious but not
372 overly complicated, take a look at L<Log::Dispatchouli>.
376 When you import this module you may use C<-logger> as a shortcut for
377 L<set_logger>, for example:
379 use Log::Contextual::SimpleLogger;
380 use Log::Contextual qw( :dlog ),
381 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw( debug )] });
383 sometimes you might want to have the logger handy for other stuff, in which
384 case you might try something like the following:
387 BEGIN { $var_log = VarLogger->new }
388 use Log::Contextual qw( :dlog ), -logger => $var_log;
390 =head1 A WORK IN PROGRESS
392 This module is certainly not complete, but we will not break the interface
393 lightly, so I would say it's safe to use in production code. The main result
394 from that at this point is that doing:
398 will die as we do not yet know what the defaults should be. If it turns out
399 that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
400 probably make C<:log> the default. But only time and usage will tell.
406 my $logger = WarnLogger->new;
409 Arguments: C<Ref|CodeRef $returning_logger>
411 C<set_logger> will just set the current logger to whatever you pass it. It
412 expects a C<CodeRef>, but if you pass it something else it will wrap it in a
413 C<CodeRef> for you. C<set_logger> is really meant only to be called from a
414 top-level script. To avoid foot-shooting the function will warn if you call it
419 my $logger = WarnLogger->new;
420 with_logger $logger => sub {
422 log_fatal { 'Non Logical Universe Detected' };
424 log_info { 'All is good' };
428 Arguments: C<Ref|CodeRef $returning_logger, CodeRef $to_execute>
430 C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
431 As with L</set_logger>, C<with_logger> will wrap C<$returning_logger> with a
432 C<CodeRef> if needed.
438 Arguments: C<CodeRef $returning_message, @args>
440 All of the following six functions work the same except that a different method
441 is called on the underlying C<$logger> object. The basic pattern is:
443 sub log_$level (&@) {
444 if ($logger->is_$level) {
445 $logger->$level(shift->(@_));
450 Note that the function returns it's arguments. This can be used in a number of
451 ways, but often it's convenient just for partial inspection of passthrough data
453 my @friends = log_trace {
454 'friends list being generated, data from first friend: ' .
455 Dumper($_[0]->TO_JSON)
456 } generate_friend_list();
458 If you want complete inspection of passthrough data, take a look at the
459 L</Dlog_$level> functions.
463 log_trace { 'entered method foo with args ' join q{,}, @args };
467 log_debug { 'entered method foo' };
471 log_info { 'started process foo' };
475 log_warn { 'possible misconfiguration at line 10' };
479 log_error { 'non-numeric user input!' };
483 log_fatal { '1 is never equal to 0!' };
489 Arguments: C<CodeRef $returning_message, Item $arg>
491 This is really just a special case of the L</log_$level> functions. It forces
492 scalar context when that is what you need. Other than that it works exactly
495 my $friend = logS_trace {
496 'I only have one friend: ' . Dumper($_[0]->TO_JSON)
499 See also: L</DlogS_$level>.
505 Arguments: C<CodeRef $returning_message, @args>
507 All of the following six functions work the same as their L</log_$level>
508 brethren, except they return what is passed into them and put the stringified
509 (with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
510 you can do cool things like the following:
512 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
514 and the output might look something like:
524 my ($foo, $bar) = Dlog_trace { "entered method foo with args: $_" } @_;
528 Dlog_debug { "random data structure: $_" } { foo => $bar };
532 return Dlog_info { "html from method returned: $_" } "<html>...</html>";
536 Dlog_warn { "probably invalid value: $_" } $foo;
540 Dlog_error { "non-numeric user input! ($_)" } $port;
544 Dlog_fatal { '1 is never equal to 0!' } 'ZOMG ZOMG' if 1 == 0;
550 Arguments: C<CodeRef $returning_message, Item $arg>
552 Like L</logS_$level>, these functions are a special case of L</Dlog_$level>.
553 They only take a single scalar after the C<$returning_message> instead of
554 slurping up (and also setting C<wantarray>) all the C<@args>
556 my $pals_rs = DlogS_debug { "pals resultset: $_" }
557 $schema->resultset('Pals')->search({ perlers => 1 });
559 =head1 LOGGER INTERFACE
561 Because this module is ultimately pretty looking glue (glittery?) with the
562 awesome benefit of the Contextual part, users will often want to make their
563 favorite logger work with it. The following are the methods that should be
564 implemented in the logger:
579 The first six merely need to return true if that level is enabled. The latter
580 six take the results of whatever the user returned from their coderef and log
581 them. For a basic example see L<Log::Contextual::SimpleLogger>.
585 frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
589 mst - Matt S. Trout <mst@shadowcat.co.uk>
593 Copyright (c) 2010 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
598 This library is free software and may be distributed under the same terms as