… | |
… | |
57 | The design goal behind this module was to keep it simple (and small), |
57 | The design goal behind this module was to keep it simple (and small), |
58 | but make it powerful enough to be potentially useful for any module, and |
58 | but make it powerful enough to be potentially useful for any module, and |
59 | extensive enough for the most common tasks, such as logging to multiple |
59 | extensive enough for the most common tasks, such as logging to multiple |
60 | targets, or being able to log into a database. |
60 | targets, or being able to log into a database. |
61 | |
61 | |
|
|
62 | The amount of documentation might indicate otherwise, but the module is |
|
|
63 | still just 240 lines or so. |
|
|
64 | |
62 | =head1 LOGGING FUNCTIONS |
65 | =head1 LOGGING FUNCTIONS |
63 | |
66 | |
64 | These functions allow you to log messages. They always use the caller's |
67 | These functions allow you to log messages. They always use the caller's |
65 | package as a "logging module/source". Also, the main logging function is |
68 | package as a "logging module/source". Also, the main logging function is |
66 | callable as C<AnyEvent::log> or C<AE::log> when the C<AnyEvent> module is |
69 | callable as C<AnyEvent::log> or C<AE::log> when the C<AnyEvent> module is |
… | |
… | |
75 | use Carp (); |
78 | use Carp (); |
76 | use POSIX (); |
79 | use POSIX (); |
77 | |
80 | |
78 | use AnyEvent (); BEGIN { AnyEvent::common_sense } |
81 | use AnyEvent (); BEGIN { AnyEvent::common_sense } |
79 | use AnyEvent::Util (); |
82 | use AnyEvent::Util (); |
|
|
83 | |
|
|
84 | our $VERSION = $AnyEvent::VERSION; |
80 | |
85 | |
81 | our ($now_int, $now_str1, $now_str2); |
86 | our ($now_int, $now_str1, $now_str2); |
82 | |
87 | |
83 | # Format Time, not public - yet? |
88 | # Format Time, not public - yet? |
84 | sub ft($) { |
89 | sub ft($) { |
… | |
… | |
303 | |
308 | |
304 | $$renabled = 1; # TODO |
309 | $$renabled = 1; # TODO |
305 | } |
310 | } |
306 | } |
311 | } |
307 | |
312 | |
308 | sub _logger($;$) { |
313 | sub _logger { |
309 | my ($ctx, $level, $renabled) = @_; |
314 | my ($ctx, $level, $renabled) = @_; |
310 | |
|
|
311 | $renabled ||= \my $enabled; |
|
|
312 | |
315 | |
313 | $$renabled = 1; |
316 | $$renabled = 1; |
314 | |
317 | |
315 | my $logger = [$ctx, $level, $renabled]; |
318 | my $logger = [$ctx, $level, $renabled]; |
316 | |
319 | |
… | |
… | |
388 | All other (anonymous) contexts have no parents and an empty title by |
391 | All other (anonymous) contexts have no parents and an empty title by |
389 | default. |
392 | default. |
390 | |
393 | |
391 | When the module is loaded it creates the default context called |
394 | When the module is loaded it creates the default context called |
392 | C<AnyEvent::Log::Default> (also stored in C<$AnyEvent::Log::Default>), |
395 | C<AnyEvent::Log::Default> (also stored in C<$AnyEvent::Log::Default>), |
393 | which simply logs everything to STDERR and doesn't propagate anything |
396 | which simply logs everything via C<warn> and doesn't propagate anything |
394 | anywhere by default. The purpose of the default context is to provide |
397 | anywhere by default. The purpose of the default context is to provide |
395 | a convenient place to override the global logging target or to attach |
398 | a convenient place to override the global logging target or to attach |
396 | additional log targets. It's not meant for filtering. |
399 | additional log targets. It's not meant for filtering. |
397 | |
400 | |
398 | It then creates the root context called C<AnyEvent::Log::Root> (also |
401 | It then creates the root context called C<AnyEvent::Log::Root> (also |
… | |
… | |
412 | C<AE::Log::Top>. |
415 | C<AE::Log::Top>. |
413 | |
416 | |
414 | The effect of all this is that log messages, by default, wander up |
417 | The effect of all this is that log messages, by default, wander up |
415 | to the root context where log messages with lower priority then |
418 | to the root context where log messages with lower priority then |
416 | C<$ENV{PERL_ANYEVENT_VERBOSE}> will be filtered away and then to the |
419 | C<$ENV{PERL_ANYEVENT_VERBOSE}> will be filtered away and then to the |
417 | AnyEvent::Log::Default context to be logged to STDERR. |
420 | AnyEvent::Log::Default context to be passed to C<warn>. |
418 | |
421 | |
419 | Splitting the top level context into three contexts makes it easy to set |
422 | Splitting the top level context into three contexts makes it easy to set |
420 | a global logging level (by modifying the root context), but still allow |
423 | a global logging level (by modifying the root context), but still allow |
421 | other contexts to log, for example, their debug and trace messages to the |
424 | other contexts to log, for example, their debug and trace messages to the |
422 | default target despite the global logging level, or to attach additional |
425 | default target despite the global logging level, or to attach additional |
423 | log targets that log messages, regardless of the global logging level. |
426 | log targets that log messages, regardless of the global logging level. |
424 | |
427 | |
425 | It also makes it easy to replace the default STDERR-logger by something |
428 | It also makes it easy to replace the default warn-logger by something that |
426 | that logs to a file, or to attach additional logging targets. |
429 | logs to a file, or to attach additional logging targets. |
427 | |
430 | |
428 | =head2 CREATING/FINDING/DESTROYING CONTEXTS |
431 | =head2 CREATING/FINDING/DESTROYING CONTEXTS |
429 | |
432 | |
430 | =over 4 |
433 | =over 4 |
431 | |
434 | |
… | |
… | |
453 | : bless [undef, (1 << 10) - 1 - 1], "AnyEvent::Log::Ctx" |
456 | : bless [undef, (1 << 10) - 1 - 1], "AnyEvent::Log::Ctx" |
454 | } |
457 | } |
455 | |
458 | |
456 | =item AnyEvent::Log::reset |
459 | =item AnyEvent::Log::reset |
457 | |
460 | |
458 | Deletes all contexts and recreates the default hierarchy, i.e. resets the |
461 | Resets all package contexts contexts and recreates the default hierarchy |
459 | logging subsystem to defaults. |
462 | if necessary, i.e. resets the logging subsystem to defaults. |
460 | |
463 | |
461 | This can be used to implement config-file (re-)loading: before loading a |
464 | This can be used to implement config-file (re-)loading: before loading a |
462 | configuration, reset all contexts. |
465 | configuration, reset all contexts. |
463 | |
466 | |
|
|
467 | Note that this currently destroys all logger callbacks - bug me if you |
|
|
468 | need this fixed :) |
|
|
469 | |
464 | =cut |
470 | =cut |
465 | |
471 | |
466 | sub reset { |
472 | sub reset { |
467 | @$_ = () for values %CTX; # just to be sure - to kill circular logging dependencies |
473 | # hard to kill complex data structures |
468 | %CTX = (); |
474 | # we recreate all package loggers and reset the hierarchy |
|
|
475 | while (my ($k, $v) = each %CTX) { |
|
|
476 | @$v = ($k, (1 << 10) - 1 - 1, { }); |
469 | |
477 | |
470 | my $default = ctx undef; |
478 | my $pkg = $k =~ /^(.+)::/ ? $1 : "AE::Log::Top"; |
|
|
479 | $v->attach ($CTX{$pkg}); |
|
|
480 | } |
|
|
481 | |
|
|
482 | $AnyEvent::Log::Default->parents; |
471 | $default->title ("AnyEvent::Log::Default"); |
483 | $AnyEvent::Log::Default->title ("AnyEvent::Log::Default"); |
472 | $default->log_cb (sub { |
484 | $AnyEvent::Log::Default->log_cb (sub { |
473 | print STDERR shift; |
485 | warn shift; |
474 | 0 |
486 | 0 |
475 | }); |
487 | }); |
476 | $AnyEvent::Log::Default = $CTX{"AnyEvent::Log::Default"} = $CTX{"AE::Log::Default"} = $default; |
488 | $CTX{"AnyEvent::Log::Default"} = $CTX{"AE::Log::Default"} = $AnyEvent::Log::Default; |
477 | |
489 | |
478 | my $root = ctx undef; |
490 | $AnyEvent::Log::Root->parents ($AnyEvent::Log::Default); |
479 | $root->title ("AnyEvent::Log::Root"); |
491 | $AnyEvent::Log::Root->title ("AnyEvent::Log::Root"); |
480 | $root->level ($AnyEvent::VERBOSE); |
492 | $AnyEvent::Log::Root->level ($AnyEvent::VERBOSE); |
481 | $root->attach ($default); |
|
|
482 | $AnyEvent::Log::Root = $CTX{"AnyEvent::Log::Root"} = $CTX{"AE::Log::Root"} = $root; |
493 | $CTX{"AnyEvent::Log::Root"} = $CTX{"AE::Log::Root"} = $AnyEvent::Log::Root; |
483 | |
494 | |
484 | my $top = ctx undef; |
495 | $AnyEvent::Log::Top->parents ($AnyEvent::Log::Root); |
485 | $top->title ("AnyEvent::Log::Top"); |
496 | $AnyEvent::Log::Top->title ("AnyEvent::Log::Top"); |
486 | $top->attach ($root); |
|
|
487 | $AnyEvent::Log::Top = $CTX{"AnyEvent::Log::Top"} = $CTX{"AE::Log::Top"} = $top; |
497 | $CTX{"AnyEvent::Log::Top"} = $CTX{"AE::Log::Top"} = $AnyEvent::Log::Top; |
|
|
498 | |
|
|
499 | _reassess; |
488 | } |
500 | } |
|
|
501 | |
|
|
502 | # create the default logger contexts |
|
|
503 | $AnyEvent::Log::Default = ctx undef; |
|
|
504 | $AnyEvent::Log::Root = ctx undef; |
|
|
505 | $AnyEvent::Log::Top = ctx undef; |
489 | |
506 | |
490 | AnyEvent::Log::reset; |
507 | AnyEvent::Log::reset; |
491 | |
508 | |
492 | # hello, CPAN, please catch me |
509 | # hello, CPAN, please catch me |
493 | package AnyEvent::Log::Default; |
510 | package AnyEvent::Log::Default; |
… | |
… | |
854 | |
871 | |
855 | my $debug = AnyEvent::Debug->AnyEvent::Log::ctx; |
872 | my $debug = AnyEvent::Debug->AnyEvent::Log::ctx; |
856 | $debug->attach ($AnyEvent::Log::Default); |
873 | $debug->attach ($AnyEvent::Log::Default); |
857 | $debug->levels ("trace"); # not "level"! |
874 | $debug->levels ("trace"); # not "level"! |
858 | |
875 | |
|
|
876 | This of course works for any package. |
|
|
877 | |
859 | =back |
878 | =back |
860 | |
879 | |
861 | =head1 AUTHOR |
880 | =head1 AUTHOR |
862 | |
881 | |
863 | Marc Lehmann <schmorp@schmorp.de> |
882 | Marc Lehmann <schmorp@schmorp.de> |