pretty much complete core doc
[p5sagit/Log-Contextual.git] / lib / Log / Contextual.pm
CommitLineData
0daa11f3 1package Log::Contextual;
2
a2777569 3use strict;
4use warnings;
2033c911 5
a2777569 6our $VERSION = '1.000';
2033c911 7
8require Exporter;
f11f9542 9use Data::Dumper::Concise;
2033c911 10
a2777569 11BEGIN { our @ISA = qw(Exporter) }
2033c911 12
f11f9542 13my @dlog = (qw{
14 Dlog_debug DlogS_debug
15 Dlog_trace DlogS_trace
16 Dlog_warn DlogS_warn
17 Dlog_info DlogS_info
18 Dlog_error DlogS_error
19 Dlog_fatal DlogS_fatal
20});
21
22my @log = (qw{
23 log_debug
24 log_trace
25 log_warn
26 log_info
27 log_error
28 log_fatal
29});
30
a2777569 31our @EXPORT_OK = (
f11f9542 32 @dlog, @log,
33 qw{set_logger with_logger}
34);
35
a2777569 36our %EXPORT_TAGS = (
f11f9542 37 dlog => \@dlog,
38 log => \@log,
3dc9bd3c 39 all => [@dlog, @log],
f11f9542 40);
41
42sub import {
a2777569 43 my $package = shift;
f11f9542 44 die 'Log::Contextual does not have a default import list'
a2777569 45 unless @_;
46
47 for my $idx ( 0 .. $#_ ) {
48 if ( $_[$idx] eq '-logger' ) {
49 set_logger($_[$idx + 1]);
50 splice @_, $idx, 2;
51 last;
52 }
53 }
54 $package->export_to_level(1, $package, @_);
f11f9542 55}
2033c911 56
7cec609c 57our $Get_Logger;
58
8dc5a747 59sub set_logger {
60 my $logger = $_[0];
61 $logger = do { my $l = $logger; sub { $l } }
62 if ref $logger ne 'CODE';
63 $Get_Logger = $logger;
7cec609c 64}
65
98833ffb 66sub with_logger {
67 my $logger = $_[0];
68 $logger = do { my $l = $logger; sub { $l } }
69 if ref $logger ne 'CODE';
70 local $Get_Logger = $logger;
80c3e48b 71 $_[1]->();
2daff231 72}
73
6dc6632a 74sub log_trace (&) {
75 my $log = $Get_Logger->();
76 $log->trace($_[0]->())
77 if $log->is_trace;
78}
79
7cec609c 80sub log_debug (&) {
81 my $log = $Get_Logger->();
82 $log->debug($_[0]->())
83 if $log->is_debug;
84}
85
6dc6632a 86sub log_info (&) {
87 my $log = $Get_Logger->();
88 $log->info($_[0]->())
89 if $log->is_info;
90}
91
92sub log_warn (&) {
93 my $log = $Get_Logger->();
94 $log->warn($_[0]->())
95 if $log->is_warn;
96}
97
98sub log_error (&) {
99 my $log = $Get_Logger->();
100 $log->error($_[0]->())
101 if $log->is_error;
102}
103
104sub log_fatal (&) {
105 my $log = $Get_Logger->();
106 $log->fatal($_[0]->())
107 if $log->is_fatal;
108}
109
f11f9542 110
111
112sub Dlog_trace (&@) {
113 my $code = shift;
114 my @values = @_;
115 log_trace {
116 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
117 };
118 @values
119}
120
121sub DlogS_trace (&$) {
122 my $code = $_[0];
123 my $value = $_[1];
124 log_trace {
125 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
126 };
127 $value
128}
129
130sub Dlog_debug (&@) {
131 my $code = shift;
132 my @values = @_;
133 log_debug {
134 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
135 };
136 @values
137}
138
139sub DlogS_debug (&$) {
140 my $code = $_[0];
141 my $value = $_[1];
142 log_debug {
143 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
144 };
145 $value
146}
147
148sub Dlog_info (&@) {
149 my $code = shift;
150 my @values = @_;
151 log_info {
152 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
153 };
154 @values
155}
156
157sub DlogS_info (&$) {
158 my $code = $_[0];
159 my $value = $_[1];
160 log_info {
161 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
162 };
163 $value
164}
165
166sub Dlog_warn (&@) {
167 my $code = shift;
168 my @values = @_;
169 log_warn {
170 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
171 };
172 @values
173}
174
175sub DlogS_warn (&$) {
176 my $code = $_[0];
177 my $value = $_[1];
178 log_warn {
179 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
180 };
181 $value
182}
183
184sub Dlog_error (&@) {
185 my $code = shift;
186 my @values = @_;
187 log_error {
188 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
189 };
190 @values
191}
192
193sub DlogS_error (&$) {
194 my $code = $_[0];
195 my $value = $_[1];
196 log_error {
197 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
198 };
199 $value
200}
201
202sub Dlog_fatal (&@) {
203 my $code = shift;
204 my @values = @_;
205 log_fatal {
206 do { local $_ = Data::Dumper::Concise::Dumper @values; $code->() };
207 };
208 @values
209}
210
211sub DlogS_fatal (&$) {
212 my $code = $_[0];
213 my $value = $_[1];
214 log_fatal {
215 do { local $_ = Data::Dumper::Concise::Dumper $value; $code->() };
216 };
217 $value
218}
219
0daa11f3 2201;
0a3750e2 221
222__END__
223
2daff231 224=head1 NAME
225
226Log::Contextual - Super simple logging interface
227
228=head1 SYNOPSIS
229
21431192 230 use Log::Contextual qw{:log set_logger with_logger};
2daff231 231
21431192 232 my $logger = Log::Contextual::SimpleLogger->new({ levels => [qw{debug}]});
2daff231 233
234 set_logger { $logger };
235
236 log_debug { "program started" };
237
238 sub foo {
21431192 239 with_logger Log::Contextual::SimpleLogger->new({
240 levels => [qw{trace debug}]
241 }) => sub {
242 log_trace { 'foo entered' };
2daff231 243 # ...
21431192 244 log_trace { 'foo left' };
245 };
2daff231 246 }
247
248=head1 DESCRIPTION
249
3dc9bd3c 250This module is a simple interface to extensible logging. It is bundled with a
251really basic logger, L<Log::Contextual::SimpleLogger>, but in general you
252should use a real logger instead of that. For something more serious but not
253overly complicated, take a look at L<Log::Dispatchouli>.
254
255=head1 OPTIONS
256
257When you import this module you may use C<-logger> as a shortcut for
258L<set_logger>, for example:
259
260 use Log::Contextual::SimpleLogger;
261 use Log::Contextual qw{:dlog},
262 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw{ debug }] });
263
264sometimes you might want to have the logger handy for other stuff, in which
265case you might try something like the following:
266
267 my $var_log;
268 BEGIN { $var_log = VarLogger->new }
269 use Log::Contextual qw{:dlog}, -logger => $var_log;
270
271=head1 A WORK IN PROGRESS
272
273This module is certainly not complete, but we will not break the interface
274lightly, so I would say it's safe to use in production code. The main result
275from that at this point is that doing:
276
277 use Log::Contextual;
278
279will die as we do not yet know what the defaults should be. If it turns out
280that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
281probably make C<:log> the default. But only time, and usage, will tell.
2daff231 282
283=head1 FUNCTIONS
284
285=head2 set_logger
286
287 my $logger = WarnLogger->new;
21431192 288 set_logger $logger;
289
290Arguments: Ref|CodeRef $returning_logger
2daff231 291
21431192 292C<set_logger> will just set the current logger to whatever you pass it. It
293expects a C<CodeRef>, but if you pass it something else it will wrap it in a
294C<CodeRef> for you.
2daff231 295
296=head2 with_logger
297
298 my $logger = WarnLogger->new;
21431192 299 with_logger $logger => sub {
2daff231 300 if (1 == 0) {
301 log_fatal { 'Non Logical Universe Detected' };
302 } else {
303 log_info { 'All is good' };
304 }
80c3e48b 305 };
2daff231 306
21431192 307Arguments: Ref|CodeRef $returning_logger, CodeRef $to_execute
2daff231 308
21431192 309C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
310as with L<set_logger>, C<with_logger> will wrap C<$returning_logger> with a
311C<CodeRef> if needed.
2daff231 312
21431192 313=head2 log_$level
2daff231 314
3dc9bd3c 315Import Tag: ":log"
316
2daff231 317Arguments: CodeRef $returning_message
318
21431192 319All of the following six functions work the same except that a different method
320is called on the underlying C<$logger> object. The basic pattern is:
2daff231 321
21431192 322 sub log_$level (&) {
323 if ($logger->is_$level) {
324 $logger->$level(shift->());
325 }
326 }
2daff231 327
21431192 328=head3 log_trace
2daff231 329
21431192 330 log_trace { 'entered method foo with args ' join q{,}, @args };
2daff231 331
21431192 332=head3 log_debug
2daff231 333
21431192 334 log_debug { 'entered method foo' };
2daff231 335
21431192 336=head3 log_info
2daff231 337
21431192 338 log_info { 'started process foo' };
2daff231 339
21431192 340=head3 log_warn
2daff231 341
21431192 342 log_warn { 'possible misconfiguration at line 10' };
2daff231 343
21431192 344=head3 log_error
2daff231 345
21431192 346 log_error { 'non-numeric user input!' };
2daff231 347
21431192 348=head3 log_fatal
2daff231 349
350 log_fatal { '1 is never equal to 0!' };
351
21431192 352=head2 Dlog_$level
353
3dc9bd3c 354Import Tag: ":dlog"
355
83b33eb5 356Arguments: CodeRef $returning_message, @args
2daff231 357
83b33eb5 358All of the following six functions work the same as their L<log_$level> brethren,
21431192 359except they return what is passed into them and as a bonus put the stringified
360(with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
361you can do cool things like the following:
362
363 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
364
365and the output might look something like:
366
367 names: "fREW"
368 "fRIOUX"
369 "fROOH"
370 "fRUE"
371 "fiSMBoC"
372
373=head3 Dlog_trace
374
375 my ($foo, $bar) = Dlog_trace { "entered method foo with args $_" } @_;
376
377=head3 Dlog_debug
378
379 Dlog_debug { "random data structure: $_" } { foo => $bar };
380
381=head3 Dlog_info
382
383 return Dlog_info { "html from method returned: $_" } "<html>...</html>";
384
385=head3 Dlog_warn
386
387 Dlog_warn { "probably invalid value: $_" } $foo;
388
389=head3 Dlog_error
390
391 Dlog_error { "non-numeric user input! ($_)" } $port;
2daff231 392
21431192 393=head3 Dlog_fatal
2daff231 394
21431192 395 Dlog_fatal { '1 is never equal to 0!' } 'ZOMG ZOMG' if 1 == 0;
2daff231 396
83b33eb5 397=head2 DlogS_$level
398
3dc9bd3c 399Import Tag: ":dlog"
400
83b33eb5 401Arguments: CodeRef $returning_message, Item $arg
402
403All of the following six functions work the same as the related L<Dlog_$level>
404functions, except they only take a single scalar after the
405C<$returning_message> instead of slurping up (and also setting C<wantarray>)
406all the C<@args>
407
408 my $pals_rs = DlogS_debug { "pals resultset: $_" }
409 $schema->resultset('Pals')->search({ perlers => 1 });
410
411=head3 DlogS_trace
412
3dc9bd3c 413 my ($foo, $bar) = DlogS_trace { "entered method foo with first arg $_" } $_[0], $_[1];
83b33eb5 414
415=head3 DlogS_debug
416
417 DlogS_debug { "random data structure: $_" } { foo => $bar };
418
419=head3 DlogS_info
420
421 return DlogS_info { "html from method returned: $_" } "<html>...</html>";
422
423=head3 DlogS_warn
424
425 DlogS_warn { "probably invalid value: $_" } $foo;
426
427=head3 DlogS_error
428
429 DlogS_error { "non-numeric user input! ($_)" } $port;
430
431=head3 DlogS_fatal
432
433 DlogS_fatal { '1 is never equal to 0!' } 'ZOMG ZOMG' if 1 == 0;
434
3dc9bd3c 435=head1 LOGGER INTERFACE
436
437Because this module is ultimately pretty looking glue (glittery?) with the
438awesome benefit of the Contextual part, users will often want to make their
439favorite logger work with it. The following are the methods that should be
440implemented in the logger:
441
442 is_trace
443 is_debug
444 is_info
445 is_warn
446 is_error
447 is_fatal
448 trace
449 debug
450 info
451 warn
452 error
453 fatal
454
455The first six merely need to return true if that level is enabled. The latter
456six take the results of whatever the user returned from their coderef and log
457them. For a basic example see L<Log::Contextual::SimpleLogger>.
458
2daff231 459=head1 AUTHOR
460
461frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
462
463=head1 DESIGNER
464
465mst - Matt S. Trout <mst@shadowcat.co.uk>
466
467=head1 COPYRIGHT
468
469Copyright (c) 2010 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
470above.
471
472=head1 LICENSE
473
474This library is free software and may be distributed under the same terms as
475Perl 5 itself.
476
477=cut
478