1 # add example for Log::Dispatchouli
2 # make wrapper for Log::Log4perl that fixes callstack:
3 # < mst> sub debug { local $Log::Log4perl::caller_depth =
4 # $Log::Log4perl::caller_depth + 3; shift->{l4p}->debug(@_) }
7 # < mst> there are two cases
8 # < mst> (1) application code: expects an app logger to be set and fuck you if it
10 # < mst> (i.e. die screaming if it gets called without a logger setup)
12 # < mst> (2) library code: uses an app logger IF exists, but if not, needs to do ...
14 # < mst> but doesn't want to affect the rest of the world doing so
15 # < frew> sounds like library code wants default_logger which is a packageish logger?
17 # make basic warn logger
20 package Log::Contextual;
25 our $VERSION = '0.00101';
28 use Data::Dumper::Concise;
29 use Scalar::Util 'blessed';
31 BEGIN { our @ISA = qw(Exporter) }
34 Dlog_debug DlogS_debug
35 Dlog_trace DlogS_trace
38 Dlog_error DlogS_error
39 Dlog_fatal DlogS_fatal
53 qw( set_logger with_logger )
64 die 'Log::Contextual does not have a default import list'
67 for my $idx ( 0 .. $#_ ) {
68 if ( $_[$idx] eq '-logger' ) {
69 set_logger($_[$idx + 1]);
74 $package->export_to_level(1, $package, @_);
84 $Default_Logger{$package} ||
85 die q( no logger set! you can't try to log something without a logger! )
91 if(ref $logger ne 'CODE') {
92 die 'logger was not a CodeRef or a logger object. Please try again.'
93 unless blessed($logger);
94 $logger = do { my $l = $logger; sub { $l } }
97 warn 'set_logger (or -logger) called more than once! This is a bad idea!'
99 $Get_Logger = $logger;
104 if(ref $logger ne 'CODE') {
105 die 'logger was not a CodeRef or a logger object. Please try again.'
106 unless blessed($logger);
107 $logger = do { my $l = $logger; sub { $l } }
109 local $Get_Logger = $logger;
116 my $log = _get_logger( caller );
118 $log->trace($code->(@_))
124 my $log = _get_logger( caller );
126 $log->debug($code->(@_))
132 my $log = _get_logger( caller );
134 $log->info($code->(@_))
140 my $log = _get_logger( caller );
142 $log->warn($code->(@_))
148 my $log = _get_logger( caller );
150 $log->error($code->(@_))
156 my $log = _get_logger( caller );
158 $log->fatal($code->(@_))
164 sub logS_trace (&$) {
165 my $log = _get_logger( caller );
168 $log->trace($code->($value))
173 sub logS_debug (&$) {
174 my $log = _get_logger( caller );
177 $log->debug($code->($value))
183 my $log = _get_logger( caller );
186 $log->info($code->($value))
192 my $log = _get_logger( caller );
195 $log->warn($code->($value))
200 sub logS_error (&$) {
201 my $log = _get_logger( caller );
204 $log->error($code->($value))
209 sub logS_fatal (&$) {
210 my $log = _get_logger( caller );
213 $log->fatal($code->($value))
220 sub Dlog_trace (&@) {
225 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
227 do { local $_ = '()'; $code->() };
232 sub Dlog_debug (&@) {
237 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
239 do { local $_ = '()'; $code->() };
249 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
251 do { local $_ = '()'; $code->() };
261 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
263 do { local $_ = '()'; $code->() };
268 sub Dlog_error (&@) {
273 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
275 do { local $_ = '()'; $code->() };
280 sub Dlog_fatal (&@) {
285 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
287 do { local $_ = '()'; $code->() };
294 sub DlogS_trace (&$) {
298 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
302 sub DlogS_debug (&$) {
306 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
310 sub DlogS_info (&$) {
314 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
318 sub DlogS_warn (&$) {
322 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
326 sub DlogS_error (&$) {
330 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
334 sub DlogS_fatal (&$) {
338 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
348 Log::Contextual - Simple logging interface with a contextual log
352 use Log::Contextual qw( :log :dlog set_logger with_logger );
353 use Log::Contextual::SimpleLogger;
354 use Log::Log4perl ':easy';
355 Log::Log4perl->easy_init($DEBUG);
358 my $logger = Log::Log4perl->get_logger;
362 log_debug { 'program started' };
365 with_logger(Log::Contextual::SimpleLogger->new({
366 levels => [qw( trace debug )]
368 log_trace { 'foo entered' };
369 my ($foo, $bar) = Dlog_trace { "params for foo: $_" } @_;
371 log_trace { 'foo left' };
379 This module is a simple interface to extensible logging. It is bundled with a
380 really basic logger, L<Log::Contextual::SimpleLogger>, but in general you
381 should use a real logger instead of that. For something more serious but not
382 overly complicated, take a look at L<Log::Dispatchouli>.
386 When you import this module you may use C<-logger> as a shortcut for
387 L<set_logger>, for example:
389 use Log::Contextual::SimpleLogger;
390 use Log::Contextual qw( :dlog ),
391 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw( debug )] });
393 sometimes you might want to have the logger handy for other stuff, in which
394 case you might try something like the following:
397 BEGIN { $var_log = VarLogger->new }
398 use Log::Contextual qw( :dlog ), -logger => $var_log;
400 =head1 A WORK IN PROGRESS
402 This module is certainly not complete, but we will not break the interface
403 lightly, so I would say it's safe to use in production code. The main result
404 from that at this point is that doing:
408 will die as we do not yet know what the defaults should be. If it turns out
409 that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
410 probably make C<:log> the default. But only time and usage will tell.
416 my $logger = WarnLogger->new;
419 Arguments: C<Ref|CodeRef $returning_logger>
421 C<set_logger> will just set the current logger to whatever you pass it. It
422 expects a C<CodeRef>, but if you pass it something else it will wrap it in a
427 my $logger = WarnLogger->new;
428 with_logger $logger => sub {
430 log_fatal { 'Non Logical Universe Detected' };
432 log_info { 'All is good' };
436 Arguments: C<Ref|CodeRef $returning_logger, CodeRef $to_execute>
438 C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
439 As with L</set_logger>, C<with_logger> will wrap C<$returning_logger> with a
440 C<CodeRef> if needed.
446 Arguments: C<CodeRef $returning_message, @args>
448 All of the following six functions work the same except that a different method
449 is called on the underlying C<$logger> object. The basic pattern is:
451 sub log_$level (&@) {
452 if ($logger->is_$level) {
453 $logger->$level(shift->(@_));
458 Note that the function returns it's arguments. This can be used in a number of
459 ways, but often it's convenient just for partial inspection of passthrough data
461 my @friends = log_trace {
462 'friends list being generated, data from first friend: ' .
463 Dumper($_[0]->TO_JSON)
464 } generate_friend_list();
466 If you want complete inspection of passthrough data, take a look at the
467 L</Dlog_$level> functions.
471 log_trace { 'entered method foo with args ' join q{,}, @args };
475 log_debug { 'entered method foo' };
479 log_info { 'started process foo' };
483 log_warn { 'possible misconfiguration at line 10' };
487 log_error { 'non-numeric user input!' };
491 log_fatal { '1 is never equal to 0!' };
497 Arguments: C<CodeRef $returning_message, Item $arg>
499 This is really just a special case of the L</log_$level> functions. It forces
500 scalar context when that is what you need. Other than that it works exactly
503 my $friend = logS_trace {
504 'I only have one friend: ' . Dumper($_[0]->TO_JSON)
507 See also: L</DlogS_$level>.
513 Arguments: C<CodeRef $returning_message, @args>
515 All of the following six functions work the same as their L</log_$level>
516 brethren, except they return what is passed into them and put the stringified
517 (with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
518 you can do cool things like the following:
520 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
522 and the output might look something like:
532 my ($foo, $bar) = Dlog_trace { "entered method foo with args: $_" } @_;
536 Dlog_debug { "random data structure: $_" } { foo => $bar };
540 return Dlog_info { "html from method returned: $_" } "<html>...</html>";
544 Dlog_warn { "probably invalid value: $_" } $foo;
548 Dlog_error { "non-numeric user input! ($_)" } $port;
552 Dlog_fatal { '1 is never equal to 0!' } 'ZOMG ZOMG' if 1 == 0;
558 Arguments: C<CodeRef $returning_message, Item $arg>
560 Like L</logS_$level>, these functions are a special case of L</Dlog_$level>.
561 They only take a single scalar after the C<$returning_message> instead of
562 slurping up (and also setting C<wantarray>) all the C<@args>
564 my $pals_rs = DlogS_debug { "pals resultset: $_" }
565 $schema->resultset('Pals')->search({ perlers => 1 });
567 =head1 LOGGER INTERFACE
569 Because this module is ultimately pretty looking glue (glittery?) with the
570 awesome benefit of the Contextual part, users will often want to make their
571 favorite logger work with it. The following are the methods that should be
572 implemented in the logger:
587 The first six merely need to return true if that level is enabled. The latter
588 six take the results of whatever the user returned from their coderef and log
589 them. For a basic example see L<Log::Contextual::SimpleLogger>.
593 frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
597 mst - Matt S. Trout <mst@shadowcat.co.uk>
601 Copyright (c) 2010 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
606 This library is free software and may be distributed under the same terms as