ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Log.pm
Revision: 1.3
Committed: Wed Aug 17 02:02:38 2011 UTC (12 years, 10 months ago) by root
Branch: MAIN
Changes since 1.2: +120 -7 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 AnyEvent::Log - simple logging "framework"
4
5 =head1 SYNOPSIS
6
7 use AnyEvent::Log;
8
9 =head1 DESCRIPTION
10
11 This module implements a relatively simple "logging framework". It doesn't
12 attempt to be "the" logging solution or even "a" logging solution for
13 AnyEvent - AnyEvent simply creates logging messages internally, and this
14 module more or less exposes the mechanism, with some extra spiff to allow
15 using it from other modules as well.
16
17 Remember that the default verbosity level is C<0>, so nothing
18 will be logged, ever, unless you set C<$Anyvent::VERBOSE> or
19 C<PERL_ANYEVENT_VERBOSE> to a higher number.
20
21 Possible future extensions are to allow custom log targets (where the
22 level is an object), log filtering based on package, formatting, aliasing
23 or package groups.
24
25 =head1 LOG FUNCTIONS
26
27 These functions allow you to log messages. They always use the caller's
28 package as a "logging module/source". Also, The main logging function is
29 easily available as C<AnyEvent::log> or C<AE::log> when the C<AnyEvent>
30 module is loaded.
31
32 =over 4
33
34 =cut
35
36 package AnyEvent::Log;
37
38 use Carp ();
39 use POSIX ();
40
41 use AnyEvent (); BEGIN { AnyEvent::common_sense }
42 use AnyEvent::Util ();
43
44 our ($now_int, $now_str1, $now_str2);
45
46 # Format Time, not public - yet?
47 sub ft($) {
48 my $i = int $_[0];
49 my $f = sprintf "%06d", 1e6 * ($_[0] - $i);
50
51 ($now_int, $now_str1, $now_str2) = ($i, split /\x01/, POSIX::strftime "%Y-%m-%d %H:%M:%S.\x01 %z", localtime $i)
52 if $now_int != $i;
53
54 "$now_str1$f$now_str2"
55 }
56
57 our %CFG; #TODO
58
59 =item AnyEvent::Log::log $level, $msg[, @args]
60
61 Requests logging of the given C<$msg> with the given log level (1..9).
62 You can also use the following strings as log level: C<fatal> (1),
63 C<alert> (2), C<critical> (3), C<error> (4), C<warn> (5), C<note> (6),
64 C<info> (7), C<debug> (8), C<trace> (9).
65
66 For C<fatal> log levels, the program will abort.
67
68 If only a C<$msg> is given, it is logged as-is. With extra C<@args>, the
69 C<$msg> is interpreted as an sprintf format string.
70
71 The C<$msg> should not end with C<\n>, but may if that is convenient for
72 you. Also, multiline messages are handled properly.
73
74 Last not least, C<$msg> might be a code reference, in which case it is
75 supposed to return the message. It will be called only then the message
76 actually gets logged, which is useful if it is costly to create the
77 message in the first place.
78
79 Whether the given message will be logged depends on the maximum log level
80 and the caller's package.
81
82 Note that you can (and should) call this function as C<AnyEvent::log> or
83 C<AE::log>, without C<use>-ing this module if possible, as those functions
84 will laod the logging module on demand only.
85
86 Example: log something at error level.
87
88 AE::log error => "something";
89
90 Example: use printf-formatting.
91
92 AE::log info => "%5d %-10.10s %s", $index, $category, $msg;
93
94 Example: only generate a costly dump when the message is actually being logged.
95
96 AE::log debug => sub { require Data::Dump; Data::Dump::dump \%cache };
97
98 =cut
99
100 # also allow syslog equivalent names
101 our %STR2LEVEL = (
102 fatal => 1, emerg => 1,
103 alert => 2,
104 critical => 3, crit => 3,
105 error => 4, err => 4,
106 warn => 5, warning => 5,
107 note => 6, notice => 6,
108 info => 7,
109 debug => 8,
110 trace => 9,
111 );
112
113 our @LEVEL2STR = qw(0 fatal alert crit error warn note info debug trace);
114
115 sub _log {
116 my ($pkg, $targ, $msg, @args) = @_;
117
118 my $level = ref $targ ? die "Can't use reference as logging level (yet)"
119 : $targ > 0 && $targ <= 9 ? $targ+0
120 : $STR2LEVEL{$targ} || Carp::croak "$targ: not a valid logging level, caught";
121
122 return if $level > $AnyEvent::VERBOSE;
123
124 $msg = $msg->() if ref $msg;
125 $msg = sprintf $msg, @args if @args;
126 $msg =~ s/\n$//;
127
128 # now we have a message, log it
129 #TODO: could do LOTS of stuff here, and should, at least in some later version
130
131 $msg = sprintf "%5s %s: %s", $LEVEL2STR[$level], $pkg, $msg;
132 my $pfx = ft AE::now;
133
134 for (split /\n/, $msg) {
135 printf STDERR "$pfx $_\n";
136 $pfx = "\t";
137 }
138
139 exit 1 if $level <= 1;
140 }
141
142 sub log($$;@) {
143 _log +(caller)[0], @_;
144 }
145
146 *AnyEvent::log = *AE::log = \&log;
147
148 =item $logger = AnyEvent::Log::logger $level[, \$enabled]
149
150 Creates a code reference that, when called, acts as if the
151 C<AnyEvent::Log::log> function was called at this point with the givne
152 level. C<$logger> is passed a C<$msg> and optional C<@args>, just as with
153 the C<AnyEvent::Log::log> function:
154
155 my $debug_log = AnyEvent::Log::logger "debug";
156
157 $debug_log->("debug here");
158 $debug_log->("%06d emails processed", 12345);
159 $debug_log->(sub { $obj->as_string });
160
161 The idea behind this function is to decide whether to log before actually
162 logging - when the C<logger> function is called once, but the returned
163 logger callback often, then this can be a tremendous speed win.
164
165 Despite this speed advantage, changes in logging configuration will
166 still be reflected by the logger callback, even if configuration changes
167 I<after> it was created.
168
169 To further speed up logging, you can bind a scalar variable to the logger,
170 which contains true if the logger should be called or not - if it is
171 false, calling the logger can be safely skipped. This variable will be
172 updated as long as C<$logger> is alive.
173
174 Full example:
175
176 # near the init section
177 use AnyEvent::Log;
178
179 my $debug_log = AnyEvent:Log::logger debug => \my $debug;
180
181 # and later in your program
182 $debug_log->("yo, stuff here") if $debug;
183
184 $debug and $debug_log->("123");
185
186 Note: currently the enabled var is always true - that will be fixed in a
187 future version :)
188
189 =cut
190
191 our %LOGGER;
192
193 # re-assess logging status for all loggers
194 sub _reassess {
195 for (@_ ? $LOGGER{$_[0]} : values %LOGGER) {
196 my ($pkg, $level, $renabled) = @$_;
197
198 # to detetc whether a message would be logged, we # actually
199 # try to log one and die. this isn't # fast, but we can be
200 # sure that the logging decision is correct :)
201
202 $$renabled = !eval {
203 local $SIG{__DIE__};
204
205 _log $pkg, $level, sub { die };
206
207 1
208 };
209
210 $$renabled = 1; # TODO
211 }
212 }
213
214 sub logger($;$) {
215 my ($level, $renabled) = @_;
216
217 $renabled ||= \my $enabled;
218 my $pkg = (caller)[0];
219
220 $$renabled = 1;
221
222 my $logger = [$pkg, $level, $renabled];
223
224 $LOGGER{$logger+0} = $logger;
225
226 _reassess $logger+0;
227
228 my $guard = AnyEvent::Util::guard {
229 # "clean up"
230 delete $LOGGER{$logger+0};
231 };
232
233 sub {
234 $guard if 0; # keep guard alive, but don't cause runtime overhead
235
236 _log $pkg, $level, @_
237 if $$renabled;
238 }
239 }
240
241 #TODO
242
243 =back
244
245 =head1 CONFIGURATION FUNCTIONALITY
246
247 None, yet, except for C<PERL_ANYEVENT_VERBOSE>, described in the L<AnyEvent> manpage.
248
249 =over 4
250
251 =cut
252
253 1;
254
255 =back
256
257 =head1 AUTHOR
258
259 Marc Lehmann <schmorp@schmorp.de>
260 http://home.schmorp.de/
261
262 =cut