fix pod error
[p5sagit/Log-Contextual.git] / lib / Log / Contextual / WarnLogger.pm
CommitLineData
ae59bbe3 1package Log::Contextual::WarnLogger;
2
3use strict;
4use warnings;
5
e7b18282 6use Carp 'croak';
7
8my @default_levels = qw( trace debug info warn error fatal );
9
e7b18282 10# generate subs to handle the default levels
11# anything else will have to be handled by AUTOLOAD at runtime
ae59bbe3 12{
6ae293d7 13 for my $level (@default_levels) {
ae59bbe3 14
6ae293d7 15 no strict 'refs';
ae59bbe3 16
6ae293d7 17 my $is_name = "is_$level";
18 *{$level} = sub {
19 my $self = shift;
ae59bbe3 20
6ae293d7 21 $self->_log($level, @_)
22 if $self->$is_name;
23 };
ae59bbe3 24
6ae293d7 25 *{$is_name} = sub {
26 my $self = shift;
27 return 1 if $ENV{$self->{env_prefix} . '_' . uc $level};
28 my $upto = $ENV{$self->{env_prefix} . '_UPTO'};
29 return unless $upto;
30 $upto = lc $upto;
31
32 return $self->{level_num}{$level} >= $self->{level_num}{$upto};
33 };
34 }
ae59bbe3 35}
36
e7b18282 37our $AUTOLOAD;
6ae293d7 38
e7b18282 39sub AUTOLOAD {
6ae293d7 40 my $self = $_[0];
e7b18282 41
6ae293d7 42 (my $name = our $AUTOLOAD) =~ s/.*:://;
43 return if $name eq 'DESTROY';
e7b18282 44
6ae293d7 45 # extract the log level from the sub name
46 my ($is, $level) = $name =~ m/^(is_)?(.+)$/;
47 my $is_name = "is_$level";
e7b18282 48
6ae293d7 49 no strict 'refs';
50 *{$level} = sub {
51 my $self = shift;
e7b18282 52
6ae293d7 53 $self->_log($level, @_)
54 if $self->$is_name;
55 };
e7b18282 56
6ae293d7 57 *{$is_name} = sub {
58 my $self = shift;
e7b18282 59
6ae293d7 60 my $prefix_field = $self->{env_prefix} . '_' . uc $level;
61 return 1 if $ENV{$prefix_field};
e7b18282 62
6ae293d7 63 # don't log if the variable specifically says not to
64 return 0 if defined $ENV{$prefix_field} and not $ENV{$prefix_field};
e7b18282 65
6ae293d7 66 my $upto_field = $self->{env_prefix} . '_UPTO';
67 my $upto = $ENV{$upto_field};
e7b18282 68
6ae293d7 69 if ($upto) {
70 $upto = lc $upto;
e7b18282 71
6ae293d7 72 croak "Unrecognized log level '$upto' in \$ENV{$upto_field}"
73 if not defined $self->{level_num}{$upto};
e7b18282 74
6ae293d7 75 return $self->{level_num}{$level} >= $self->{level_num}{$upto};
76 }
e7b18282 77
6ae293d7 78 # if we don't recognize this level and nothing says otherwise, log!
79 return 1 if not $self->{custom_levels};
80 };
81 goto &$AUTOLOAD;
e7b18282 82}
83
ae59bbe3 84sub new {
6ae293d7 85 my ($class, $args) = @_;
e7b18282 86
6ae293d7 87 my $levels = $args->{levels};
88 croak 'invalid levels specification: must be non-empty arrayref'
89 if defined $levels and (ref $levels ne 'ARRAY' or !@$levels);
e7b18282 90
6ae293d7 91 my $custom_levels = defined $levels;
92 $levels ||= [@default_levels];
e7b18282 93
6ae293d7 94 my %level_num;
95 @level_num{@$levels} = (0 .. $#{$levels});
e7b18282 96
6ae293d7 97 my $self = bless {
98 levels => $levels,
99 level_num => \%level_num,
100 custom_levels => $custom_levels,
101 }, $class;
ae59bbe3 102
6ae293d7 103 $self->{env_prefix} = $args->{env_prefix}
104 or die 'no env_prefix passed to Log::Contextual::WarnLogger->new';
105 return $self;
ae59bbe3 106}
107
108sub _log {
6ae293d7 109 my $self = shift;
110 my $level = shift;
111 my $message = join("\n", @_);
112 $message .= "\n" unless $message =~ /\n$/;
113 warn "[$level] $message";
ae59bbe3 114}
115
1161;
117
118__END__
119
120=head1 NAME
121
122Log::Contextual::WarnLogger - Simple logger for libraries using Log::Contextual
123
124=head1 SYNOPSIS
125
126 package My::Package;
127 use Log::Contextual::WarnLogger;
128 use Log::Contextual qw( :log ),
129 -default_logger => Log::Contextual::WarnLogger->new({
e7b18282 130 env_prefix => 'MY_PACKAGE',
131 levels => [ qw(debug info notice warning error critical alert emergency) ],
ae59bbe3 132 });
133
134 # warns '[info] program started' if $ENV{MY_PACKAGE_TRACE} is set
135 log_info { 'program started' }; # no-op because info is not in levels
136 sub foo {
137 # warns '[debug] entered foo' if $ENV{MY_PACKAGE_DEBUG} is set
138 log_debug { 'entered foo' };
139 ...
140 }
141
e7b18282 142
143
ae59bbe3 144=head1 DESCRIPTION
145
146This module is a simple logger made for libraries using L<Log::Contextual>. We
147recommend the use of this logger as your default logger as it is simple and
148useful for most users, yet users can use L<Log::Contextual/set_logger> to override
149your choice of logger in their own code thanks to the way L<Log::Contextual>
150works.
151
152=head1 METHODS
153
154=head2 new
155
e7b18282 156Arguments: C<< Dict[ env_prefix => Str, levels => List ] $conf >>
ae59bbe3 157
54714ae9 158 my $l = Log::Contextual::WarnLogger->new({ env_prefix => 'BAR' });
e7b18282 159
160or:
161
162 my $l = Log::Contextual::WarnLogger->new({
163 env_prefix => 'BAR',
54714ae9 164 levels => [ 'level1', 'level2' ],
ae59bbe3 165 });
166
167Creates a new logger object where C<env_prefix> defines what the prefix is for
e7b18282 168the environment variables that will be checked for the log levels.
169
170The log levels may be customized, but if not defined, these are used:
171
172=over 4
173
174=item trace
175
176=item debug
177
178=item info
179
180=item warn
181
182=item error
183
184=item fatal
185
186=back
187
188For example, if C<env_prefix> is set to C<FREWS_PACKAGE> the following environment
ae59bbe3 189variables will be used:
190
6d77ba42 191 FREWS_PACKAGE_UPTO
192
ae59bbe3 193 FREWS_PACKAGE_TRACE
194 FREWS_PACKAGE_DEBUG
195 FREWS_PACKAGE_INFO
196 FREWS_PACKAGE_WARN
197 FREWS_PACKAGE_ERROR
198 FREWS_PACKAGE_FATAL
199
6d77ba42 200Note that C<UPTO> is a convenience variable. If you set
201C<< FOO_UPTO=TRACE >> it will enable all log levels. Similarly, if you
202set it to C<FATAL> only fatal will be enabled.
203
ae59bbe3 204=head2 $level
205
206Arguments: C<@anything>
207
208All of the following six methods work the same. The basic pattern is:
209
210 sub $level {
211 my $self = shift;
212
213 warn "[$level] " . join qq{\n}, @_;
214 if $self->is_$level;
215 }
216
217=head3 trace
218
219 $l->trace( 'entered method foo with args ' join q{,}, @args );
220
221=head3 debug
222
223 $l->debug( 'entered method foo' );
224
225=head3 info
226
227 $l->info( 'started process foo' );
228
229=head3 warn
230
231 $l->warn( 'possible misconfiguration at line 10' );
232
233=head3 error
234
235 $l->error( 'non-numeric user input!' );
236
237=head3 fatal
238
239 $l->fatal( '1 is never equal to 0!' );
240
e7b18282 241If different levels are specified, appropriate functions named for your custom
242levels work as you expect.
243
ae59bbe3 244=head2 is_$level
245
246All of the following six functions just return true if their respective
247environment variable is enabled.
248
249=head3 is_trace
250
251 say 'tracing' if $l->is_trace;
252
253=head3 is_debug
254
255 say 'debuging' if $l->is_debug;
256
257=head3 is_info
258
259 say q{info'ing} if $l->is_info;
260
261=head3 is_warn
262
263 say 'warning' if $l->is_warn;
264
265=head3 is_error
266
267 say 'erroring' if $l->is_error;
268
269=head3 is_fatal
270
271 say q{fatal'ing} if $l->is_fatal;
272
e7b18282 273If different levels are specified, appropriate is_$level functions work as you
274would expect.
275
ae59bbe3 276=head1 AUTHOR
277
278See L<Log::Contextual/"AUTHOR">
279
280=head1 COPYRIGHT
281
282See L<Log::Contextual/"COPYRIGHT">
283
284=head1 LICENSE
285
286See L<Log::Contextual/"LICENSE">
287
288=cut
289