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.8 by root, Fri Aug 19 19:20:36 2011 UTC vs.
Revision 1.11 by root, Sat Aug 20 01:03:09 2011 UTC

10 AE::log debug => "hit my knee"; 10 AE::log debug => "hit my knee";
11 AE::log warn => "it's a bit too hot"; 11 AE::log warn => "it's a bit too hot";
12 AE::log error => "the flag was false!"; 12 AE::log error => "the flag was false!";
13 AE::log fatal => "the bit toggled! run!"; 13 AE::log fatal => "the bit toggled! run!";
14 14
15 # complex use 15 # "complex" use
16 use AnyEvent::Log; 16 use AnyEvent::Log;
17 17
18 my $tracer = AnyEvent::Log::logger trace => \$my $trace; 18 my $tracer = AnyEvent::Log::logger trace => \$my $trace;
19 19
20 $tracer->("i am here") if $trace; 20 $tracer->("i am here") if $trace;
21 $tracer->(sub { "lots of data: " . Dumper $self }) if $trace; 21 $tracer->(sub { "lots of data: " . Dumper $self }) if $trace;
22 22
23 #TODO: config 23 # configuration
24 #TODO: ctx () becomes caller[0]... 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);
25 40
26=head1 DESCRIPTION 41=head1 DESCRIPTION
27 42
28This module implements a relatively simple "logging framework". It doesn't 43This module implements a relatively simple "logging framework". It doesn't
29attempt to be "the" logging solution or even "a" logging solution for 44attempt to be "the" logging solution or even "a" logging solution for
30AnyEvent - AnyEvent simply creates logging messages internally, and this 45AnyEvent - AnyEvent simply creates logging messages internally, and this
31module 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
32using it from other modules as well. 47using it from other modules as well.
33 48
34Remember 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
35logged, 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
36before starting your program.#TODO 51starting your program, or change the logging level at runtime with
52something like:
37 53
38Possible future extensions are to allow custom log targets (where the 54 use AnyEvent;
39level is an object), log filtering based on package, formatting, aliasing 55 (AnyEvent::Log::ctx "")->level ("info");
40or package groups.
41 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
42=head1 LOG FUNCTIONS 62=head1 LOGGING FUNCTIONS
43 63
44These 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
45package as a "logging module/source". Also, the main logging function is 65package as a "logging module/source". Also, the main logging function is
46callable 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
47loaded. 67loaded.
71 "$now_str1$f$now_str2" 91 "$now_str1$f$now_str2"
72} 92}
73 93
74our %CTX; # all logging contexts 94our %CTX; # all logging contexts
75 95
76my $default_log_cb = sub { 0 };
77
78# creates a default package context object for the given package 96# creates a default package context object for the given package
79sub _pkg_ctx($) { 97sub _pkg_ctx($) {
80 my $ctx = bless [$_[0], 0, {}, $default_log_cb], "AnyEvent::Log::Ctx"; 98 my $ctx = bless [$_[0], (1 << 10) - 1 - 1, {}], "AnyEvent::Log::Ctx";
81 99
82 # link "parent" package 100 # link "parent" package
83 my $pkg = $_[0] =~ /^(.+)::/ ? $1 : ""; 101 my $pkg = $_[0] =~ /^(.+)::/ ? $1 : "AE::Log::Top";
84 102
85 $pkg = $CTX{$pkg} ||= &_pkg_ctx ($pkg); 103 $pkg = $CTX{$pkg} ||= &_pkg_ctx ($pkg);
86 $ctx->[2]{$pkg+0} = $pkg; 104 $ctx->[2]{$pkg+0} = $pkg;
87 105
88 $ctx 106 $ctx
114Note 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
115C<AE::log>, without C<use>-ing this module if possible (i.e. you don't 133C<AE::log>, without C<use>-ing this module if possible (i.e. you don't
116need any additional functionality), as those functions will load the 134need any additional functionality), as those functions will load the
117logging module on demand only. They are also much shorter to write. 135logging module on demand only. They are also much shorter to write.
118 136
119Also, if you otpionally generate a lot of debug messages (such as when 137Also, if you optionally generate a lot of debug messages (such as when
120tracing some code), you should look into using a logger callback and a 138tracing some code), you should look into using a logger callback and a
121boolean enabler (see C<logger>, below). 139boolean enabler (see C<logger>, below).
122 140
123Example: log something at error level. 141Example: log something at error level.
124 142
146 debug => 8, 164 debug => 8,
147 trace => 9, 165 trace => 9,
148); 166);
149 167
150sub now () { time } 168sub now () { time }
169
151AnyEvent::post_detect { 170AnyEvent::post_detect {
152 *now = \&AE::now; 171 *now = \&AE::now;
153}; 172};
154 173
155our @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);
156 175
157# time, ctx, level, msg 176# time, ctx, level, msg
158sub _format($$$$) { 177sub _format($$$$) {
159 my $pfx = ft $_[0]; 178 my $ts = ft $_[0];
179 my $ct = " ";
160 180
161 join "", 181 my @res;
162 map "$pfx $_\n", 182
163 split /\n/,
164 sprintf "%-5s %s: %s", $LEVEL2STR[$_[2]], $_[1][0], $_[3] 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
165} 189}
166 190
167sub _log { 191sub _log {
168 my ($ctx, $level, $format, @args) = @_; 192 my ($ctx, $level, $format, @args) = @_;
169 193
194 $level = $level > 0 && $level <= 9
195 ? $level+0
170 $level = $level > 0 && $level <= 9 ? $level+0 : $STR2LEVEL{$level} || Carp::croak "$level: not a valid logging level, caught"; 196 : $STR2LEVEL{$level} || Carp::croak "$level: not a valid logging level, caught";
171 197
172 my $mask = 1 << $level; 198 my $mask = 1 << $level;
173 my $now = AE::now;
174 199
175 my (@ctx, $did_format, $fmt); 200 my (%seen, @ctx, $now, $fmt);
176 201
177 do { 202 do
178 if ($ctx->[1] & $mask) { 203 {
204 # skip if masked
205 if ($ctx->[1] & $mask && !$seen{$ctx+0}++) {
206 if ($ctx->[3]) {
179 # logging target found 207 # logging target found
180 208
181 # get raw message 209 # now get raw message, unless we have it already
182 unless ($did_format) { 210 unless ($now) {
183 $format = $format->() if ref $format; 211 $format = $format->() if ref $format;
184 $format = sprintf $format, @args if @args; 212 $format = sprintf $format, @args if @args;
185 $format =~ s/\n$//; 213 $format =~ s/\n$//;
186 $did_format = 1; 214 $now = AE::now;
187 }; 215 };
188 216
189 # format msg 217 # format msg
190 my $str = $ctx->[4] 218 my $str = $ctx->[4]
191 ? $ctx->[4]($now, $_[0], $level, $format) 219 ? $ctx->[4]($now, $_[0], $level, $format)
192 : $fmt ||= _format $now, $_[0], $level, $format; 220 : $fmt ||= _format $now, $_[0], $level, $format;
193 221
194 $ctx->[3]($str) 222 $ctx->[3]($str);
195 and next; 223 }
224
225 # not masked, not consumed - propagate to parent contexts
226 push @ctx, values %{ $ctx->[2] };
227 }
196 } 228 }
197
198 # not consume - push parent contexts
199 push @ctx, values %{ $ctx->[2] };
200 } while $ctx = pop @ctx; 229 while $ctx = pop @ctx;
201 230
202 exit 1 if $level <= 1; 231 exit 1 if $level <= 1;
203} 232}
204 233
205sub log($$;@) { 234sub log($$;@) {
258# re-assess logging status for all loggers 287# re-assess logging status for all loggers
259sub _reassess { 288sub _reassess {
260 for (@_ ? $LOGGER{$_[0]} : values %LOGGER) { 289 for (@_ ? $LOGGER{$_[0]} : values %LOGGER) {
261 my ($ctx, $level, $renabled) = @$_; 290 my ($ctx, $level, $renabled) = @$_;
262 291
263 # to detetc whether a message would be logged, we # actually 292 # to detect whether a message would be logged, we # actually
264 # 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
265 # sure that the logging decision is correct :) 294 # sure that the logging decision is correct :)
266 295
267 $$renabled = !eval { 296 $$renabled = !eval {
268 local $SIG{__DIE__}; 297 local $SIG{__DIE__};
269 298
306 _logger 335 _logger
307 $CTX{ (caller)[0] } ||= _pkg_ctx +(caller)[0], 336 $CTX{ (caller)[0] } ||= _pkg_ctx +(caller)[0],
308 @_ 337 @_
309} 338}
310 339
311#TODO
312
313=back 340=back
314 341
315=head1 CONFIGURATION FUNCTIONALITY 342=head1 LOGGING CONTEXTS
316 343
317None, 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
345context>, based on the package of the caller. Every perl package has its
346own logging context.
318 347
319#TODO: wahst a context 348A logging context has three major responsibilities: filtering, logging and
320#TODO 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
321 426
322=over 4 427=over 4
323 428
324=item $ctx = AnyEvent::Log::ctx [$pkg] 429=item $ctx = AnyEvent::Log::ctx [$pkg]
325 430
326Returns a I<config> object for the given package name. 431This function creates or returns a logging context (which is an object).
327 432
328If no package name is given, returns the context for the current perl 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
329package (i.e. the same context as a C<AE::log> call would use). 435callers package is returned (i.e. the same context as a C<AE::log> call
436would use).
330 437
331If C<undef> is given, then it creates a new anonymous context that is not 438If C<undef> is given, then it creates a new anonymous context that is not
332tied to any package and is destroyed when no longer referenced. 439tied to any package and is destroyed when no longer referenced.
333 440
334=cut 441=cut
338 445
339 ref $pkg 446 ref $pkg
340 ? $pkg 447 ? $pkg
341 : defined $pkg 448 : defined $pkg
342 ? $CTX{$pkg} ||= AnyEvent::Log::_pkg_ctx $pkg 449 ? $CTX{$pkg} ||= AnyEvent::Log::_pkg_ctx $pkg
343 : bless [undef, 0, undef, $default_log_cb], "AnyEvent::Log::Ctx" 450 : bless [undef, (1 << 10) - 1 - 1], "AnyEvent::Log::Ctx"
344} 451}
345 452
346# create default root context 453=item AnyEvent::Log::reset
347{ 454
455Deletes all contexts and recreates the default hierarchy, i.e. resets the
456logging subsystem to defaults.
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
348 my $root = ctx undef; 467 my $default = ctx undef;
349 $root->[0] = ""; 468 $default->title ("AnyEvent::Log::Default");
350 $root->title ("default");
351 $root->level ($AnyEvent::VERBOSE);
352 $root->log_cb (sub { 469 $default->log_cb (sub {
353 print STDERR shift; 470 print STDERR shift;
354 0 471 0
355 }); 472 });
356 $CTX{""} = $root; 473 $CTX{"AnyEvent::Log::Default"} = $CTX{"AE::Log::Default"} = $default;
474
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;
357} 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
358 499
359package AnyEvent::Log::Ctx; 500package AnyEvent::Log::Ctx;
360 501
361# 0 1 2 3 4 502# 0 1 2 3 4
362# [$title, $level, %$parents, &$logcb, &$fmtcb] 503# [$title, $level, %$parents, &$logcb, &$fmtcb]
504
505=head2 CONFIGURING A LOG CONTEXT
506
507The following methods can be used to configure the logging context.
508
509=over 4
363 510
364=item $ctx->title ([$new_title]) 511=item $ctx->title ([$new_title])
365 512
366Returns the title of the logging context - this is the package name, for 513Returns the title of the logging context - this is the package name, for
367package contexts, and a user defined string for all others. 514package contexts, and a user defined string for all others.
373sub title { 520sub title {
374 $_[0][0] = $_[1] if @_ > 1; 521 $_[0][0] = $_[1] if @_ > 1;
375 $_[0][0] 522 $_[0][0]
376} 523}
377 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
378=item $ctx->levels ($level[, $level...) 540=item $ctx->levels ($level[, $level...)
379 541
380Enables logging fot the given levels and disables it for all others. 542Enables logging for the given levels and disables it for all others.
381 543
382=item $ctx->level ($level) 544=item $ctx->level ($level)
383 545
384Enables logging for the given level and all lower level (higher priority) 546Enables logging for the given level and all lower level (higher priority)
385ones. Specifying a level of C<0> or C<off> disables all logging for this 547ones. In addition to normal logging levels, specifying a level of C<0> or
386level. 548C<off> disables all logging for this level.
387 549
388Example: log warnings, errors and higher priority messages. 550Example: log warnings, errors and higher priority messages.
389 551
390 $ctx->level ("warn"); 552 $ctx->level ("warn");
391 $ctx->level (5); # same thing, just numeric 553 $ctx->level (5); # same thing, just numeric
399Disables logging for the given levels, leaving all others unchanged. 561Disables logging for the given levels, leaving all others unchanged.
400 562
401=cut 563=cut
402 564
403sub _lvl_lst { 565sub _lvl_lst {
566 map {
567 $_ > 0 && $_ <= 9 ? $_+0
568 : $_ eq "all" ? (1 .. 9)
404 map { $_ > 0 && $_ <= 9 ? $_+0 : $STR2LEVEL{$_} || Carp::croak "$_: not a valid logging level, caught" } 569 : $STR2LEVEL{$_} || Carp::croak "$_: not a valid logging level, caught"
405 @_ 570 } @_
406} 571}
407 572
408our $NOP_CB = sub { 0 }; 573our $NOP_CB = sub { 0 };
409 574
410sub levels { 575sub levels {
415 AnyEvent::Log::_reassess; 580 AnyEvent::Log::_reassess;
416} 581}
417 582
418sub level { 583sub level {
419 my $ctx = shift; 584 my $ctx = shift;
420 my $lvl = $_[0] =~ /^(?:0|off|none)$/ ? 0 : (_lvl_lst $_[0])[0]; 585 my $lvl = $_[0] =~ /^(?:0|off|none)$/ ? 0 : (_lvl_lst $_[0])[-1];
586
421 $ctx->[1] = ((1 << $lvl) - 1) << 1; 587 $ctx->[1] = ((1 << $lvl) - 1) << 1;
422 AnyEvent::Log::_reassess; 588 AnyEvent::Log::_reassess;
423} 589}
424 590
425sub enable { 591sub enable {
434 $ctx->[1] &= ~(1 << $_) 600 $ctx->[1] &= ~(1 << $_)
435 for &_lvl_lst; 601 for &_lvl_lst;
436 AnyEvent::Log::_reassess; 602 AnyEvent::Log::_reassess;
437} 603}
438 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
439=item $ctx->attach ($ctx2[, $ctx3...]) 617=item $ctx->attach ($ctx2[, $ctx3...])
440 618
441Attaches the given contexts as parents to this context. It is not an error 619Attaches the given contexts as parents to this context. It is not an error
442to add a context twice (the second add will be ignored). 620to add a context twice (the second add will be ignored).
443 621
448Removes the given parents from this context - it's not an error to attempt 626Removes the given parents from this context - it's not an error to attempt
449to remove a context that hasn't been added. 627to remove a context that hasn't been added.
450 628
451A context can be specified either as package name or as a context object. 629A context can be specified either as package name or as a context object.
452 630
631=item $ctx->parents ($ctx2[, $ctx3...])
632
633Replaces all parents attached to this context by the ones given.
634
453=cut 635=cut
454 636
455sub attach { 637sub attach {
456 my $ctx = shift; 638 my $ctx = shift;
457 639
463 my $ctx = shift; 645 my $ctx = shift;
464 646
465 delete $ctx->[2]{$_+0} 647 delete $ctx->[2]{$_+0}
466 for map { AnyEvent::Log::ctx $_ } @_; 648 for map { AnyEvent::Log::ctx $_ } @_;
467} 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
468 666
469=item $ctx->log_cb ($cb->($str)) 667=item $ctx->log_cb ($cb->($str))
470 668
471Replaces the logging callback on the context (C<undef> disables the 669Replaces the logging callback on the context (C<undef> disables the
472logging callback). 670logging callback).
482Example: a very simple logging callback, simply dump the message to STDOUT 680Example: a very simple logging callback, simply dump the message to STDOUT
483and do not consume it. 681and do not consume it.
484 682
485 $ctx->log_cb (sub { print STDERR shift; 0 }); 683 $ctx->log_cb (sub { print STDERR shift; 0 });
486 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
487=item $ctx->fmt_cb ($fmt_cb->($timestamp, $ctx, $level, $message)) 696=item $ctx->fmt_cb ($fmt_cb->($timestamp, $ctx, $level, $message))
488 697
489Replaces the fornatting callback on the cobntext (C<undef> restores the 698Replaces the formatting callback on the context (C<undef> restores the
490default formatter). 699default formatter).
491 700
492The callback is passed the (possibly fractional) timestamp, the original 701The callback is passed the (possibly fractional) timestamp, the original
493logging context, the (numeric) logging level and the raw message string and needs to 702logging context, the (numeric) logging level and the raw message string and needs to
494return a formatted log message. In most cases this will be a string, but 703return a formatted log message. In most cases this will be a string, but
522=cut 731=cut
523 732
524sub log_cb { 733sub log_cb {
525 my ($ctx, $cb) = @_; 734 my ($ctx, $cb) = @_;
526 735
527 $ctx->[3] = $cb || $default_log_cb; 736 $ctx->[3] = $cb;
528} 737}
529 738
530sub fmt_cb { 739sub fmt_cb {
531 my ($ctx, $cb) = @_; 740 my ($ctx, $cb) = @_;
532 741

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines