1 # add example for Log::Dispatchouli
4 # < mst> there are two cases
5 # < mst> (1) application code: expects an app logger to be set and fuck you if it
7 # < mst> (i.e. die screaming if it gets called without a logger setup)
9 # < mst> (2) library code: uses an app logger IF exists, but if not, needs to do ...
11 # < mst> but doesn't want to affect the rest of the world doing so
12 # < frew> sounds like library code wants default_logger which is a packageish logger?
14 # make basic warn logger
17 package Log::Contextual;
22 our $VERSION = '0.00101';
25 use Data::Dumper::Concise;
26 use Scalar::Util 'blessed';
28 BEGIN { our @ISA = qw(Exporter) }
31 Dlog_debug DlogS_debug
32 Dlog_trace DlogS_trace
35 Dlog_error DlogS_error
36 Dlog_fatal DlogS_fatal
50 qw( set_logger with_logger )
61 die 'Log::Contextual does not have a default import list'
64 for my $idx ( 0 .. $#_ ) {
65 if ( $_[$idx] eq '-logger' ) {
66 set_logger($_[$idx + 1]);
71 $package->export_to_level(1, $package, @_);
81 $Default_Logger{$package} ||
82 die q( no logger set! you can't try to log something without a logger! )
88 if(ref $logger ne 'CODE') {
89 die 'logger was not a CodeRef or a logger object. Please try again.'
90 unless blessed($logger);
91 $logger = do { my $l = $logger; sub { $l } }
94 warn 'set_logger (or -logger) called more than once! This is a bad idea!'
96 $Get_Logger = $logger;
101 if(ref $logger ne 'CODE') {
102 die 'logger was not a CodeRef or a logger object. Please try again.'
103 unless blessed($logger);
104 $logger = do { my $l = $logger; sub { $l } }
106 local $Get_Logger = $logger;
113 my $log = _get_logger( caller );
115 $log->trace($code->(@_))
121 my $log = _get_logger( caller );
123 $log->debug($code->(@_))
129 my $log = _get_logger( caller );
131 $log->info($code->(@_))
137 my $log = _get_logger( caller );
139 $log->warn($code->(@_))
145 my $log = _get_logger( caller );
147 $log->error($code->(@_))
153 my $log = _get_logger( caller );
155 $log->fatal($code->(@_))
161 sub logS_trace (&$) {
162 my $log = _get_logger( caller );
165 $log->trace($code->($value))
170 sub logS_debug (&$) {
171 my $log = _get_logger( caller );
174 $log->debug($code->($value))
180 my $log = _get_logger( caller );
183 $log->info($code->($value))
189 my $log = _get_logger( caller );
192 $log->warn($code->($value))
197 sub logS_error (&$) {
198 my $log = _get_logger( caller );
201 $log->error($code->($value))
206 sub logS_fatal (&$) {
207 my $log = _get_logger( caller );
210 $log->fatal($code->($value))
217 sub Dlog_trace (&@) {
222 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
224 do { local $_ = '()'; $code->() };
229 sub Dlog_debug (&@) {
234 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
236 do { local $_ = '()'; $code->() };
246 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
248 do { local $_ = '()'; $code->() };
258 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
260 do { local $_ = '()'; $code->() };
265 sub Dlog_error (&@) {
270 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
272 do { local $_ = '()'; $code->() };
277 sub Dlog_fatal (&@) {
282 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
284 do { local $_ = '()'; $code->() };
291 sub DlogS_trace (&$) {
295 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
299 sub DlogS_debug (&$) {
303 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
307 sub DlogS_info (&$) {
311 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
315 sub DlogS_warn (&$) {
319 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
323 sub DlogS_error (&$) {
327 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
331 sub DlogS_fatal (&$) {
335 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
345 Log::Contextual - Simple logging interface with a contextual log
349 use Log::Contextual qw( :log :dlog set_logger with_logger );
350 use Log::Contextual::SimpleLogger;
351 use Log::Log4perl ':easy';
352 Log::Log4perl->easy_init($DEBUG);
355 my $logger = Log::Log4perl->get_logger;
359 log_debug { 'program started' };
362 with_logger(Log::Contextual::SimpleLogger->new({
363 levels => [qw( trace debug )]
365 log_trace { 'foo entered' };
366 my ($foo, $bar) = Dlog_trace { "params for foo: $_" } @_;
368 log_trace { 'foo left' };
376 This module is a simple interface to extensible logging. It is bundled with a
377 really basic logger, L<Log::Contextual::SimpleLogger>, but in general you
378 should use a real logger instead of that. For something more serious but not
379 overly complicated, take a look at L<Log::Dispatchouli>.
383 When you import this module you may use C<-logger> as a shortcut for
384 L<set_logger>, for example:
386 use Log::Contextual::SimpleLogger;
387 use Log::Contextual qw( :dlog ),
388 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw( debug )] });
390 sometimes you might want to have the logger handy for other stuff, in which
391 case you might try something like the following:
394 BEGIN { $var_log = VarLogger->new }
395 use Log::Contextual qw( :dlog ), -logger => $var_log;
397 =head1 A WORK IN PROGRESS
399 This module is certainly not complete, but we will not break the interface
400 lightly, so I would say it's safe to use in production code. The main result
401 from that at this point is that doing:
405 will die as we do not yet know what the defaults should be. If it turns out
406 that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
407 probably make C<:log> the default. But only time and usage will tell.
413 my $logger = WarnLogger->new;
416 Arguments: C<Ref|CodeRef $returning_logger>
418 C<set_logger> will just set the current logger to whatever you pass it. It
419 expects a C<CodeRef>, but if you pass it something else it will wrap it in a
424 my $logger = WarnLogger->new;
425 with_logger $logger => sub {
427 log_fatal { 'Non Logical Universe Detected' };
429 log_info { 'All is good' };
433 Arguments: C<Ref|CodeRef $returning_logger, CodeRef $to_execute>
435 C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
436 As with L</set_logger>, C<with_logger> will wrap C<$returning_logger> with a
437 C<CodeRef> if needed.
443 Arguments: C<CodeRef $returning_message, @args>
445 All of the following six functions work the same except that a different method
446 is called on the underlying C<$logger> object. The basic pattern is:
448 sub log_$level (&@) {
449 if ($logger->is_$level) {
450 $logger->$level(shift->(@_));
455 Note that the function returns it's arguments. This can be used in a number of
456 ways, but often it's convenient just for partial inspection of passthrough data
458 my @friends = log_trace {
459 'friends list being generated, data from first friend: ' .
460 Dumper($_[0]->TO_JSON)
461 } generate_friend_list();
463 If you want complete inspection of passthrough data, take a look at the
464 L</Dlog_$level> functions.
468 log_trace { 'entered method foo with args ' join q{,}, @args };
472 log_debug { 'entered method foo' };
476 log_info { 'started process foo' };
480 log_warn { 'possible misconfiguration at line 10' };
484 log_error { 'non-numeric user input!' };
488 log_fatal { '1 is never equal to 0!' };
494 Arguments: C<CodeRef $returning_message, Item $arg>
496 This is really just a special case of the L</log_$level> functions. It forces
497 scalar context when that is what you need. Other than that it works exactly
500 my $friend = logS_trace {
501 'I only have one friend: ' . Dumper($_[0]->TO_JSON)
504 See also: L</DlogS_$level>.
510 Arguments: C<CodeRef $returning_message, @args>
512 All of the following six functions work the same as their L</log_$level>
513 brethren, except they return what is passed into them and put the stringified
514 (with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
515 you can do cool things like the following:
517 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
519 and the output might look something like:
529 my ($foo, $bar) = Dlog_trace { "entered method foo with args: $_" } @_;
533 Dlog_debug { "random data structure: $_" } { foo => $bar };
537 return Dlog_info { "html from method returned: $_" } "<html>...</html>";
541 Dlog_warn { "probably invalid value: $_" } $foo;
545 Dlog_error { "non-numeric user input! ($_)" } $port;
549 Dlog_fatal { '1 is never equal to 0!' } 'ZOMG ZOMG' if 1 == 0;
555 Arguments: C<CodeRef $returning_message, Item $arg>
557 Like L</logS_$level>, these functions are a special case of L</Dlog_$level>.
558 They only take a single scalar after the C<$returning_message> instead of
559 slurping up (and also setting C<wantarray>) all the C<@args>
561 my $pals_rs = DlogS_debug { "pals resultset: $_" }
562 $schema->resultset('Pals')->search({ perlers => 1 });
564 =head1 LOGGER INTERFACE
566 Because this module is ultimately pretty looking glue (glittery?) with the
567 awesome benefit of the Contextual part, users will often want to make their
568 favorite logger work with it. The following are the methods that should be
569 implemented in the logger:
584 The first six merely need to return true if that level is enabled. The latter
585 six take the results of whatever the user returned from their coderef and log
586 them. For a basic example see L<Log::Contextual::SimpleLogger>.
590 frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
594 mst - Matt S. Trout <mst@shadowcat.co.uk>
598 Copyright (c) 2010 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
603 This library is free software and may be distributed under the same terms as