1 package Log::Contextual;
6 our $VERSION = '0.00101';
9 use Data::Dumper::Concise;
10 use Scalar::Util 'blessed';
12 BEGIN { our @ISA = qw(Exporter) }
15 Dlog_debug DlogS_debug
16 Dlog_trace DlogS_trace
19 Dlog_error DlogS_error
20 Dlog_fatal DlogS_fatal
34 qw( set_logger with_logger )
45 die 'Log::Contextual does not have a default import list'
48 for my $idx ( 0 .. $#_ ) {
49 if ( $_[$idx] eq '-logger' ) {
50 set_logger($_[$idx + 1]);
55 $package->export_to_level(1, $package, @_);
62 if(ref $logger ne 'CODE') {
63 die 'logger was not a CodeRef or a logger object. Please try again.'
64 unless blessed($logger);
65 $logger = do { my $l = $logger; sub { $l } }
67 $Get_Logger = $logger;
72 if(ref $logger ne 'CODE') {
73 die 'logger was not a CodeRef or a logger object. Please try again.'
74 unless blessed($logger);
75 $logger = do { my $l = $logger; sub { $l } }
77 local $Get_Logger = $logger;
84 my $log = $Get_Logger->();
86 $log->trace($code->(@_))
92 my $log = $Get_Logger->();
94 $log->debug($code->(@_))
100 my $log = $Get_Logger->();
102 $log->info($code->(@_))
108 my $log = $Get_Logger->();
110 $log->warn($code->(@_))
116 my $log = $Get_Logger->();
118 $log->error($code->(@_))
124 my $log = $Get_Logger->();
126 $log->fatal($code->(@_))
132 sub logS_trace (&$) {
133 my $log = $Get_Logger->();
136 $log->trace($code->($value))
141 sub logS_debug (&$) {
142 my $log = $Get_Logger->();
145 $log->debug($code->($value))
151 my $log = $Get_Logger->();
154 $log->info($code->($value))
160 my $log = $Get_Logger->();
163 $log->warn($code->($value))
168 sub logS_error (&$) {
169 my $log = $Get_Logger->();
172 $log->error($code->($value))
177 sub logS_fatal (&$) {
178 my $log = $Get_Logger->();
181 $log->fatal($code->($value))
188 sub Dlog_trace (&@) {
193 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
195 do { local $_ = '()'; $code->() };
200 sub Dlog_debug (&@) {
205 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
207 do { local $_ = '()'; $code->() };
217 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
219 do { local $_ = '()'; $code->() };
229 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
231 do { local $_ = '()'; $code->() };
236 sub Dlog_error (&@) {
241 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
243 do { local $_ = '()'; $code->() };
248 sub Dlog_fatal (&@) {
253 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
255 do { local $_ = '()'; $code->() };
262 sub DlogS_trace (&$) {
266 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
270 sub DlogS_debug (&$) {
274 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
278 sub DlogS_info (&$) {
282 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
286 sub DlogS_warn (&$) {
290 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
294 sub DlogS_error (&$) {
298 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
302 sub DlogS_fatal (&$) {
306 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
316 Log::Contextual - Simple logging interface with a contextual log
320 use Log::Contextual qw( :log :dlog set_logger with_logger );
321 use Log::Contextual::SimpleLogger;
322 use Log::Log4perl ':easy';
323 Log::Log4perl->easy_init($DEBUG);
326 my $logger = Log::Log4perl->get_logger;
330 log_debug { 'program started' };
333 with_logger(Log::Contextual::SimpleLogger->new({
334 levels => [qw( trace debug )]
336 log_trace { 'foo entered' };
337 my ($foo, $bar) = Dlog_trace { "params for foo: $_" } @_;
339 log_trace { 'foo left' };
347 This module is a simple interface to extensible logging. It is bundled with a
348 really basic logger, L<Log::Contextual::SimpleLogger>, but in general you
349 should use a real logger instead of that. For something more serious but not
350 overly complicated, take a look at L<Log::Dispatchouli>.
354 When you import this module you may use C<-logger> as a shortcut for
355 L<set_logger>, for example:
357 use Log::Contextual::SimpleLogger;
358 use Log::Contextual qw( :dlog ),
359 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw( debug )] });
361 sometimes you might want to have the logger handy for other stuff, in which
362 case you might try something like the following:
365 BEGIN { $var_log = VarLogger->new }
366 use Log::Contextual qw( :dlog ), -logger => $var_log;
368 =head1 A WORK IN PROGRESS
370 This module is certainly not complete, but we will not break the interface
371 lightly, so I would say it's safe to use in production code. The main result
372 from that at this point is that doing:
376 will die as we do not yet know what the defaults should be. If it turns out
377 that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
378 probably make C<:log> the default. But only time and usage will tell.
384 my $logger = WarnLogger->new;
387 Arguments: C<Ref|CodeRef $returning_logger>
389 C<set_logger> will just set the current logger to whatever you pass it. It
390 expects a C<CodeRef>, but if you pass it something else it will wrap it in a
395 my $logger = WarnLogger->new;
396 with_logger $logger => sub {
398 log_fatal { 'Non Logical Universe Detected' };
400 log_info { 'All is good' };
404 Arguments: C<Ref|CodeRef $returning_logger, CodeRef $to_execute>
406 C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
407 As with L</set_logger>, C<with_logger> will wrap C<$returning_logger> with a
408 C<CodeRef> if needed.
414 Arguments: C<CodeRef $returning_message, @args>
416 All of the following six functions work the same except that a different method
417 is called on the underlying C<$logger> object. The basic pattern is:
419 sub log_$level (&@) {
420 if ($logger->is_$level) {
421 $logger->$level(shift->(@_));
426 Note that the function returns it's arguments. This can be used in a number of
427 ways, but often it's convenient just for partial inspection of passthrough data
429 my @friends = log_trace {
430 'friends list being generated, data from first friend: ' .
431 Dumper($_[0]->TO_JSON)
432 } generate_friend_list();
434 If you want complete inspection of passthrough data, take a look at the
435 L</Dlog_$level> functions.
439 log_trace { 'entered method foo with args ' join q{,}, @args };
443 log_debug { 'entered method foo' };
447 log_info { 'started process foo' };
451 log_warn { 'possible misconfiguration at line 10' };
455 log_error { 'non-numeric user input!' };
459 log_fatal { '1 is never equal to 0!' };
465 Arguments: C<CodeRef $returning_message, Item $arg>
467 This is really just a special case of the L</log_$level> functions. It forces
468 scalar context when that is what you need. Other than that it works exactly
471 my $friend = logS_trace {
472 'I only have one friend: ' . Dumper($_[0]->TO_JSON)
475 See also: L</DlogS_$level>.
481 Arguments: C<CodeRef $returning_message, @args>
483 All of the following six functions work the same as their L</log_$level>
484 brethren, except they return what is passed into them and put the stringified
485 (with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
486 you can do cool things like the following:
488 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
490 and the output might look something like:
500 my ($foo, $bar) = Dlog_trace { "entered method foo with args: $_" } @_;
504 Dlog_debug { "random data structure: $_" } { foo => $bar };
508 return Dlog_info { "html from method returned: $_" } "<html>...</html>";
512 Dlog_warn { "probably invalid value: $_" } $foo;
516 Dlog_error { "non-numeric user input! ($_)" } $port;
520 Dlog_fatal { '1 is never equal to 0!' } 'ZOMG ZOMG' if 1 == 0;
526 Arguments: C<CodeRef $returning_message, Item $arg>
528 Like L</logS_$level>, these functions are a special case of L</Dlog_$level>.
529 They only take a single scalar after the C<$returning_message> instead of
530 slurping up (and also setting C<wantarray>) all the C<@args>
532 my $pals_rs = DlogS_debug { "pals resultset: $_" }
533 $schema->resultset('Pals')->search({ perlers => 1 });
535 =head1 LOGGER INTERFACE
537 Because this module is ultimately pretty looking glue (glittery?) with the
538 awesome benefit of the Contextual part, users will often want to make their
539 favorite logger work with it. The following are the methods that should be
540 implemented in the logger:
555 The first six merely need to return true if that level is enabled. The latter
556 six take the results of whatever the user returned from their coderef and log
557 them. For a basic example see L<Log::Contextual::SimpleLogger>.
561 frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
565 mst - Matt S. Trout <mst@shadowcat.co.uk>
569 Copyright (c) 2010 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
574 This library is free software and may be distributed under the same terms as