ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Log.pm
(Generate patch)

Comparing AnyEvent/lib/AnyEvent/Log.pm (file contents):
Revision 1.7 by root, Thu Aug 18 18:02:11 2011 UTC vs.
Revision 1.11 by root, Sat Aug 20 01:03:09 2011 UTC

2 2
3AnyEvent::Log - simple logging "framework" 3AnyEvent::Log - simple logging "framework"
4 4
5=head1 SYNOPSIS 5=head1 SYNOPSIS
6 6
7 # simple use
8 use AnyEvent;
9
10 AE::log debug => "hit my knee";
11 AE::log warn => "it's a bit too hot";
12 AE::log error => "the flag was false!";
13 AE::log fatal => "the bit toggled! run!";
14
15 # "complex" use
7 use AnyEvent::Log; 16 use AnyEvent::Log;
17
18 my $tracer = AnyEvent::Log::logger trace => \$my $trace;
19
20 $tracer->("i am here") if $trace;
21 $tracer->(sub { "lots of data: " . Dumper $self }) if $trace;
22
23 # configuration
24
25 # set logging for this package to maximum
26 AnyEvent::Log::ctx->level ("all");
27
28 # set logging globally to anything below debug
29 (AnyEvent::Log::ctx "")->level ("notice");
30
31 # see also EXAMPLES, below
32
33 # disable logging for package "AnyEvent" and all packages below it
34 AnyEvent->AnyEvent::Log::ctx->level (0);
35
36 # log everything below debug to a file, for the whole program
37 my $ctx = AnyEvent::Log::ctx;
38 $ctx->log_cb (sub { print FILE shift; 0 });
39 (AnyEvent::Log::ctx "")->add ($ctx);
8 40
9=head1 DESCRIPTION 41=head1 DESCRIPTION
10 42
11This module implements a relatively simple "logging framework". It doesn't 43This module implements a relatively simple "logging framework". It doesn't
12attempt to be "the" logging solution or even "a" logging solution for 44attempt to be "the" logging solution or even "a" logging solution for
13AnyEvent - AnyEvent simply creates logging messages internally, and this 45AnyEvent - AnyEvent simply creates logging messages internally, and this
14module more or less exposes the mechanism, with some extra spiff to allow 46module more or less exposes the mechanism, with some extra spiff to allow
15using it from other modules as well. 47using it from other modules as well.
16 48
17Remember that the default verbosity level is C<0>, so nothing will be 49Remember that the default verbosity level is C<0>, so nothing will be
18logged, ever, unless you set C<PERL_ANYEVENT_VERBOSE> to a higher number 50logged, unless you set C<PERL_ANYEVENT_VERBOSE> to a higher number before
19before starting your program.#TODO 51starting your program, or change the logging level at runtime with
52something like:
20 53
21Possible future extensions are to allow custom log targets (where the 54 use AnyEvent;
22level is an object), log filtering based on package, formatting, aliasing 55 (AnyEvent::Log::ctx "")->level ("info");
23or package groups.
24 56
57The design goal behind this module was to keep it simple (and small),
58but make it powerful enough to be potentially useful for any module, and
59extensive enough for the most common tasks, such as logging to multiple
60targets, or being able to log into a database.
61
25=head1 LOG FUNCTIONS 62=head1 LOGGING FUNCTIONS
26 63
27These functions allow you to log messages. They always use the caller's 64These functions allow you to log messages. They always use the caller's
28package as a "logging module/source". Also, the main logging function is 65package as a "logging module/source". Also, the main logging function is
29callable as C<AnyEvent::log> or C<AE::log> when the C<AnyEvent> module is 66callable as C<AnyEvent::log> or C<AE::log> when the C<AnyEvent> module is
30loaded. 67loaded.
54 "$now_str1$f$now_str2" 91 "$now_str1$f$now_str2"
55} 92}
56 93
57our %CTX; # all logging contexts 94our %CTX; # all logging contexts
58 95
96# creates a default package context object for the given package
97sub _pkg_ctx($) {
98 my $ctx = bless [$_[0], (1 << 10) - 1 - 1, {}], "AnyEvent::Log::Ctx";
99
100 # link "parent" package
101 my $pkg = $_[0] =~ /^(.+)::/ ? $1 : "AE::Log::Top";
102
103 $pkg = $CTX{$pkg} ||= &_pkg_ctx ($pkg);
104 $ctx->[2]{$pkg+0} = $pkg;
105
106 $ctx
107}
108
59=item AnyEvent::Log::log $level, $msg[, @args] 109=item AnyEvent::Log::log $level, $msg[, @args]
60 110
61Requests logging of the given C<$msg> with the given log level (1..9). 111Requests logging of the given C<$msg> with the given log level (1..9).
62You can also use the following strings as log level: C<fatal> (1), 112You can also use the following strings as log level: C<fatal> (1),
63C<alert> (2), C<critical> (3), C<error> (4), C<warn> (5), C<note> (6), 113C<alert> (2), C<critical> (3), C<error> (4), C<warn> (5), C<note> (6),
78 128
79Whether the given message will be logged depends on the maximum log level 129Whether the given message will be logged depends on the maximum log level
80and the caller's package. 130and the caller's package.
81 131
82Note that you can (and should) call this function as C<AnyEvent::log> or 132Note that you can (and should) call this function as C<AnyEvent::log> or
83C<AE::log>, without C<use>-ing this module if possible, as those functions 133C<AE::log>, without C<use>-ing this module if possible (i.e. you don't
84will laod the logging module on demand only. 134need any additional functionality), as those functions will load the
135logging module on demand only. They are also much shorter to write.
136
137Also, if you optionally generate a lot of debug messages (such as when
138tracing some code), you should look into using a logger callback and a
139boolean enabler (see C<logger>, below).
85 140
86Example: log something at error level. 141Example: log something at error level.
87 142
88 AE::log error => "something"; 143 AE::log error => "something";
89 144
109 debug => 8, 164 debug => 8,
110 trace => 9, 165 trace => 9,
111); 166);
112 167
113sub now () { time } 168sub now () { time }
169
114AnyEvent::post_detect { 170AnyEvent::post_detect {
115 *now = \&AE::now; 171 *now = \&AE::now;
116}; 172};
117 173
118our @LEVEL2STR = qw(0 fatal alert crit error warn note info debug trace); 174our @LEVEL2STR = qw(0 fatal alert crit error warn note info debug trace);
119 175
176# time, ctx, level, msg
177sub _format($$$$) {
178 my $ts = ft $_[0];
179 my $ct = " ";
180
181 my @res;
182
183 for (split /\n/, sprintf "%-5s %s: %s", $LEVEL2STR[$_[2]], $_[1][0], $_[3]) {
184 push @res, "$ts$ct$_\n";
185 $ct = " + ";
186 }
187
188 join "", @res
189}
190
120sub _log { 191sub _log {
121 my ($pkg, $targ, $msg, @args) = @_; 192 my ($ctx, $level, $format, @args) = @_;
122 193
123 my $level = ref $targ ? die "Can't use reference as logging level (yet)" 194 $level = $level > 0 && $level <= 9
124 : $targ > 0 && $targ <= 9 ? $targ+0 195 ? $level+0
125 : $STR2LEVEL{$targ} || Carp::croak "$targ: not a valid logging level, caught"; 196 : $STR2LEVEL{$level} || Carp::croak "$level: not a valid logging level, caught";
126 197
127 #TODO: find actual targets, see if we even have to log 198 my $mask = 1 << $level;
128 199
129 return unless $level <= $AnyEvent::VERBOSE; 200 my (%seen, @ctx, $now, $fmt);
130 201
131 $msg = $msg->() if ref $msg; 202 do
132 $msg = sprintf $msg, @args if @args; 203 {
133 $msg =~ s/\n$//; 204 # skip if masked
205 if ($ctx->[1] & $mask && !$seen{$ctx+0}++) {
206 if ($ctx->[3]) {
207 # logging target found
134 208
135 # now we have a message, log it 209 # now get raw message, unless we have it already
210 unless ($now) {
211 $format = $format->() if ref $format;
212 $format = sprintf $format, @args if @args;
213 $format =~ s/\n$//;
214 $now = AE::now;
215 };
136 216
137 # TODO: writers/processors/filters/formatters? 217 # format msg
218 my $str = $ctx->[4]
219 ? $ctx->[4]($now, $_[0], $level, $format)
220 : $fmt ||= _format $now, $_[0], $level, $format;
138 221
139 $msg = sprintf "%-5s %s: %s", $LEVEL2STR[$level], $pkg, $msg; 222 $ctx->[3]($str);
140 my $pfx = ft now; 223 }
141 224
142 for (split /\n/, $msg) { 225 # not masked, not consumed - propagate to parent contexts
143 printf STDERR "$pfx $_\n"; 226 push @ctx, values %{ $ctx->[2] };
144 $pfx = "\t"; 227 }
145 } 228 }
229 while $ctx = pop @ctx;
146 230
147 exit 1 if $level <= 1; 231 exit 1 if $level <= 1;
148} 232}
149 233
150sub log($$;@) { 234sub log($$;@) {
151 _log +(caller)[0], @_; 235 _log
236 $CTX{ (caller)[0] } ||= _pkg_ctx +(caller)[0],
237 @_;
152} 238}
153 239
154*AnyEvent::log = *AE::log = \&log; 240*AnyEvent::log = *AE::log = \&log;
155 241
156=item $logger = AnyEvent::Log::logger $level[, \$enabled] 242=item $logger = AnyEvent::Log::logger $level[, \$enabled]
199our %LOGGER; 285our %LOGGER;
200 286
201# re-assess logging status for all loggers 287# re-assess logging status for all loggers
202sub _reassess { 288sub _reassess {
203 for (@_ ? $LOGGER{$_[0]} : values %LOGGER) { 289 for (@_ ? $LOGGER{$_[0]} : values %LOGGER) {
204 my ($pkg, $level, $renabled) = @$_; 290 my ($ctx, $level, $renabled) = @$_;
205 291
206 # to detetc whether a message would be logged, we # actually 292 # to detect whether a message would be logged, we # actually
207 # try to log one and die. this isn't # fast, but we can be 293 # try to log one and die. this isn't fast, but we can be
208 # sure that the logging decision is correct :) 294 # sure that the logging decision is correct :)
209 295
210 $$renabled = !eval { 296 $$renabled = !eval {
211 local $SIG{__DIE__}; 297 local $SIG{__DIE__};
212 298
213 _log $pkg, $level, sub { die }; 299 _log $ctx, $level, sub { die };
214 300
215 1 301 1
216 }; 302 };
217 303
218 $$renabled = 1; # TODO 304 $$renabled = 1; # TODO
219 } 305 }
220} 306}
221 307
222sub logger($;$) { 308sub _logger($;$) {
223 my ($level, $renabled) = @_; 309 my ($ctx, $level, $renabled) = @_;
224 310
225 $renabled ||= \my $enabled; 311 $renabled ||= \my $enabled;
226 my $pkg = (caller)[0];
227 312
228 $$renabled = 1; 313 $$renabled = 1;
229 314
230 my $logger = [$pkg, $level, $renabled]; 315 my $logger = [$ctx, $level, $renabled];
231 316
232 $LOGGER{$logger+0} = $logger; 317 $LOGGER{$logger+0} = $logger;
233 318
234 _reassess $logger+0; 319 _reassess $logger+0;
235 320
239 }; 324 };
240 325
241 sub { 326 sub {
242 $guard if 0; # keep guard alive, but don't cause runtime overhead 327 $guard if 0; # keep guard alive, but don't cause runtime overhead
243 328
244 _log $pkg, $level, @_ 329 _log $ctx, $level, @_
245 if $$renabled; 330 if $$renabled;
246 } 331 }
247} 332}
248 333
249#TODO 334sub logger($;$) {
335 _logger
336 $CTX{ (caller)[0] } ||= _pkg_ctx +(caller)[0],
337 @_
338}
250 339
251=back 340=back
252 341
253=head1 CONFIGURATION FUNCTIONALITY 342=head1 LOGGING CONTEXTS
254 343
255None, yet, except for C<PERL_ANYEVENT_VERBOSE>, described in the L<AnyEvent> manpage. 344This module associates every log message with a so-called I<logging
256#TODO 345context>, based on the package of the caller. Every perl package has its
346own logging context.
347
348A logging context has three major responsibilities: filtering, logging and
349propagating the message.
350
351For the first purpose, filtering, each context has a set of logging
352levels, called the log level mask. Messages not in the set will be ignored
353by this context (masked).
354
355For logging, the context stores a formatting callback (which takes the
356timestamp, context, level and string message and formats it in the way
357it should be logged) and a logging callback (which is responsible for
358actually logging the formatted message and telling C<AnyEvent::Log>
359whether it has consumed the message, or whether it should be propagated).
360
361For propagation, a context can have any number of attached I<parent
362contexts>. Any message that is neither masked by the logging mask nor
363masked by the logging callback returning true will be passed to all parent
364contexts.
365
366Each call to a logging function will log the message at most once per
367context, so it does not matter (much) if there are cycles or if the
368message can arrive at the same context via multiple paths.
369
370=head2 DEFAULTS
371
372By default, all logging contexts have an full set of log levels ("all"), a
373disabled logging callback and the default formatting callback.
374
375Package contexts have the package name as logging title by default.
376
377They have exactly one parent - the context of the "parent" package. The
378parent package is simply defined to be the package name without the last
379component, i.e. C<AnyEvent::Debug::Wrapped> becomes C<AnyEvent::Debug>,
380and C<AnyEvent> becomes ... C<AnyEvent::Log::Top> which is the
381exception of the rule - just like the parent of any package name in
382Perl is C<main>, the default parent of any toplevel package context is
383C<AnyEvent::Log::Top>.
384
385Since perl packages form only an approximate hierarchy, this parent
386context can of course be removed.
387
388All other (anonymous) contexts have no parents and an empty title by
389default.
390
391When the module is loaded it creates the default context called
392C<AnyEvent::Log::Default>, which simply logs everything to STDERR and
393doesn't propagate anything anywhere by default. The purpose of the default
394context is to provide a convenient place to override the global logging
395target or to attach additional log targets. It's not meant for filtering.
396
397It then creates the root context called C<AnyEvent::Log::Root> and
398sets its log level set to all levels up to the one specified by
399C<$ENV{PERL_ANYEVENT_VERBOSE}>. It then attached the default logging
400context to it. The purpose of the root context is to simply provide
401filtering according to some global log level.
402
403Finally it creates the toplevel package context called
404C<AnyEvent::Log::Top> and attached the root context but otherwise leaves
405it at default config. It's purpose is simply to collect all log messages
406system-wide.
407
408These three special contexts can also be referred to by the names
409C<AE::Log::Default>, C<AE::Log::Root> and C<AE::Log::Top>.
410
411The effect of all this is that log messages, by default, wander up
412to the root context where log messages with lower priority then
413C<$ENV{PERL_ANYEVENT_VERBOSE}> will be filtered away and then to the
414AnyEvent::Log::Default context to be logged to STDERR.
415
416Splitting the top level context into three contexts makes it easy to set
417a global logging level (by modifying the root context), but still allow
418other contexts to log, for example, their debug and trace messages to the
419default target despite the global logging level, or to attach additional
420log targets that log messages, regardless of the global logging level.
421
422It also makes it easy to replace the default STDERR-logger by something
423that logs to a file, or to attach additional logging targets.
424
425=head2 CREATING/FINDING/DESTROYING CONTEXTS
257 426
258=over 4 427=over 4
259 428
260=item $ctx = AnyEvent::Log::cfg [$pkg] 429=item $ctx = AnyEvent::Log::ctx [$pkg]
261 430
262Returns a I<config> object for the given package name (or previously 431This function creates or returns a logging context (which is an object).
263created package-less configuration). If no package name, or C<undef>, is 432
433If a package name is given, then the context for that packlage is
434returned. If it is called without any arguments, then the context for the
435callers package is returned (i.e. the same context as a C<AE::log> call
436would use).
437
264given, then it creates a new anonymous context that is not tied to any 438If C<undef> is given, then it creates a new anonymous context that is not
265package. 439tied to any package and is destroyed when no longer referenced.
266 440
267=cut 441=cut
268 442
269sub cfg(;$) { 443sub ctx(;$) {
270 my $name = shift; 444 my $pkg = @_ ? shift : (caller)[0];
271 445
272 my $ctx = defined $name ? $CTX{$name} : undef; 446 ref $pkg
447 ? $pkg
448 : defined $pkg
449 ? $CTX{$pkg} ||= AnyEvent::Log::_pkg_ctx $pkg
450 : bless [undef, (1 << 10) - 1 - 1], "AnyEvent::Log::Ctx"
451}
273 452
274 unless ($ctx) { 453=item AnyEvent::Log::reset
275 $ctx = bless {}, "AnyEvent::Log::Ctx"; 454
276 $name = -$ctx unless defined $name; 455Deletes all contexts and recreates the default hierarchy, i.e. resets the
277 $ctx->{name} = $name; 456logging subsystem to defaults.
278 $CTX{$name} = $ctx; 457
458This can be used to implement config-file (re-)loading: before loading a
459configuration, reset all contexts.
460
461=cut
462
463sub reset {
464 @$_ = () for values %CTX; # just to be sure - to kill circular logging dependencies
465 %CTX = ();
466
467 my $default = ctx undef;
468 $default->title ("AnyEvent::Log::Default");
469 $default->log_cb (sub {
470 print STDERR shift;
471 0
279 } 472 });
473 $CTX{"AnyEvent::Log::Default"} = $CTX{"AE::Log::Default"} = $default;
280 474
281 $ctx 475 my $root = ctx undef;
476 $root->title ("AnyEvent::Log::Root");
477 $root->level ($AnyEvent::VERBOSE);
478 $root->attach ($default);
479 $CTX{"AnyEvent::Log::Root"} = $CTX{"AE::Log::Root"} = $root;
480
481 my $top = ctx undef;
482 $top->title ("AnyEvent::Log::Top");
483 $top->attach ($root);
484 $CTX{"AnyEvent::Log::Top"} = $CTX{"AE::Log::Top"} = $top;
282} 485}
486
487AnyEvent::Log::reset;
488
489package AnyEvent::Log::Default;
490package AE::Log::Default;
491package AnyEvent::Log::Root;
492package AE::Log::Root;
493package AnyEvent::Log::Top;
494package AE::Log::Top;
495
496=back
497
498=cut
283 499
284package AnyEvent::Log::Ctx; 500package AnyEvent::Log::Ctx;
285 501
286sub DESTROY { 502# 0 1 2 3 4
287 # if only one member is remaining (name!) then delete this context 503# [$title, $level, %$parents, &$logcb, &$fmtcb]
288 delete $CTX{$_[0]{name}} 504
289 if 1 == scalar keys %{ $_[0] }; 505=head2 CONFIGURING A LOG CONTEXT
506
507The following methods can be used to configure the logging context.
508
509=over 4
510
511=item $ctx->title ([$new_title])
512
513Returns the title of the logging context - this is the package name, for
514package contexts, and a user defined string for all others.
515
516If C<$new_title> is given, then it replaces the package name or title.
517
518=cut
519
520sub title {
521 $_[0][0] = $_[1] if @_ > 1;
522 $_[0][0]
290} 523}
524
525=back
526
527=head3 LOGGING LEVELS
528
529The following methods deal with the logging level set associated with the
530log context.
531
532The most common method to use is probably C<< $ctx->level ($level) >>,
533which configures the specified and any higher priority levels.
534
535All functions which accept a list of levels also accept the special string
536C<all> which expands to all logging levels.
537
538=over 4
539
540=item $ctx->levels ($level[, $level...)
541
542Enables logging for the given levels and disables it for all others.
543
544=item $ctx->level ($level)
545
546Enables logging for the given level and all lower level (higher priority)
547ones. In addition to normal logging levels, specifying a level of C<0> or
548C<off> disables all logging for this level.
549
550Example: log warnings, errors and higher priority messages.
551
552 $ctx->level ("warn");
553 $ctx->level (5); # same thing, just numeric
554
555=item $ctx->enable ($level[, $level...])
556
557Enables logging for the given levels, leaving all others unchanged.
558
559=item $ctx->disable ($level[, $level...])
560
561Disables logging for the given levels, leaving all others unchanged.
562
563=cut
564
565sub _lvl_lst {
566 map {
567 $_ > 0 && $_ <= 9 ? $_+0
568 : $_ eq "all" ? (1 .. 9)
569 : $STR2LEVEL{$_} || Carp::croak "$_: not a valid logging level, caught"
570 } @_
571}
572
573our $NOP_CB = sub { 0 };
574
575sub levels {
576 my $ctx = shift;
577 $ctx->[1] = 0;
578 $ctx->[1] |= 1 << $_
579 for &_lvl_lst;
580 AnyEvent::Log::_reassess;
581}
582
583sub level {
584 my $ctx = shift;
585 my $lvl = $_[0] =~ /^(?:0|off|none)$/ ? 0 : (_lvl_lst $_[0])[-1];
586
587 $ctx->[1] = ((1 << $lvl) - 1) << 1;
588 AnyEvent::Log::_reassess;
589}
590
591sub enable {
592 my $ctx = shift;
593 $ctx->[1] |= 1 << $_
594 for &_lvl_lst;
595 AnyEvent::Log::_reassess;
596}
597
598sub disable {
599 my $ctx = shift;
600 $ctx->[1] &= ~(1 << $_)
601 for &_lvl_lst;
602 AnyEvent::Log::_reassess;
603}
604
605=back
606
607=head3 PARENT CONTEXTS
608
609The following methods attach and detach another logging context to a
610logging context.
611
612Log messages are propagated to all parent contexts, unless the logging
613callback consumes the message.
614
615=over 4
616
617=item $ctx->attach ($ctx2[, $ctx3...])
618
619Attaches the given contexts as parents to this context. It is not an error
620to add a context twice (the second add will be ignored).
621
622A context can be specified either as package name or as a context object.
623
624=item $ctx->detach ($ctx2[, $ctx3...])
625
626Removes the given parents from this context - it's not an error to attempt
627to remove a context that hasn't been added.
628
629A context can be specified either as package name or as a context object.
630
631=item $ctx->parents ($ctx2[, $ctx3...])
632
633Replaces all parents attached to this context by the ones given.
634
635=cut
636
637sub attach {
638 my $ctx = shift;
639
640 $ctx->[2]{$_+0} = $_
641 for map { AnyEvent::Log::ctx $_ } @_;
642}
643
644sub detach {
645 my $ctx = shift;
646
647 delete $ctx->[2]{$_+0}
648 for map { AnyEvent::Log::ctx $_ } @_;
649}
650
651sub parents {
652 undef $_[0][2];
653 &attach;
654}
655
656=back
657
658=head3 MESSAGE LOGGING
659
660The following methods configure how the logging context actually does
661the logging (which consists of formatting the message and printing it or
662whatever it wants to do with it) and also allows you to log messages
663directly to a context, without going via your package context.
664
665=over 4
666
667=item $ctx->log_cb ($cb->($str))
668
669Replaces the logging callback on the context (C<undef> disables the
670logging callback).
671
672The logging callback is responsible for handling formatted log messages
673(see C<fmt_cb> below) - normally simple text strings that end with a
674newline (and are possibly multiline themselves).
675
676It also has to return true iff it has consumed the log message, and false
677if it hasn't. Consuming a message means that it will not be sent to any
678parent context. When in doubt, return C<0> from your logging callback.
679
680Example: a very simple logging callback, simply dump the message to STDOUT
681and do not consume it.
682
683 $ctx->log_cb (sub { print STDERR shift; 0 });
684
685You can filter messages by having a log callback that simply returns C<1>
686and does not do anything with the message, but this counts as "message
687being logged" and might not be very efficient.
688
689Example: propagate all messages except for log levels "debug" and
690"trace". The messages will still be generated, though, which can slow down
691your program.
692
693 $ctx->levels ("debug", "trace");
694 $ctx->log_cb (sub { 1 }); # do not log, but eat debug and trace messages
695
696=item $ctx->fmt_cb ($fmt_cb->($timestamp, $ctx, $level, $message))
697
698Replaces the formatting callback on the context (C<undef> restores the
699default formatter).
700
701The callback is passed the (possibly fractional) timestamp, the original
702logging context, the (numeric) logging level and the raw message string and needs to
703return a formatted log message. In most cases this will be a string, but
704it could just as well be an array reference that just stores the values.
705
706Example: format just the raw message, with numeric log level in angle
707brackets.
708
709 $ctx->fmt_cb (sub {
710 my ($time, $ctx, $lvl, $msg) = @_;
711
712 "<$lvl>$msg\n"
713 });
714
715Example: return an array reference with just the log values, and use
716C<PApp::SQL::sql_exec> to store the emssage in a database.
717
718 $ctx->fmt_cb (sub { \@_ });
719 $ctx->log_cb (sub {
720 my ($msg) = @_;
721
722 sql_exec "insert into log (when, subsys, prio, msg) values (?, ?, ?, ?)",
723 $msg->[0] + 0,
724 "$msg->[1]",
725 $msg->[2] + 0,
726 "$msg->[3]";
727
728 0
729 });
730
731=cut
732
733sub log_cb {
734 my ($ctx, $cb) = @_;
735
736 $ctx->[3] = $cb;
737}
738
739sub fmt_cb {
740 my ($ctx, $cb) = @_;
741
742 $ctx->[4] = $cb;
743}
744
745=item $ctx->log ($level, $msg[, @params])
746
747Same as C<AnyEvent::Log::log>, but uses the given context as log context.
748
749=item $logger = $ctx->logger ($level[, \$enabled])
750
751Same as C<AnyEvent::Log::logger>, but uses the given context as log
752context.
753
754=cut
755
756*log = \&AnyEvent::Log::_log;
757*logger = \&AnyEvent::Log::_logger;
291 758
2921; 7591;
293 760
294=back 761=back
295 762

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines