change default log level to info
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Log.pm
CommitLineData
fc7ec1d9 1package Catalyst::Log;
2
e5ecd5bc 3use Moose;
531f1ab6 4with 'MooseX::Emulate::Class::Accessor::Fast';
5
f63c03e4 6use Data::Dump;
dd5b1dc4 7use Moose::Util 'find_meta';
0816209f 8use Carp qw/ cluck /;
9b2bc37b 9
c72d2e24 10our %LEVELS = (); # Levels stored as bit field, ergo debug = 1, warn = 2 etc
11our %LEVEL_MATCH = (); # Stored as additive, thus debug = 31, warn = 30 etc
a6433a05 12
3cdcf968 13has level => (is => 'rw');
5fb12dbb 14has _body => (is => 'rw');
3cdcf968 15has abort => (is => 'rw');
1b526dcc 16has autoflush => (is => 'rw', default => sub {1});
21da7377 17has _psgi_logger => (is => 'rw', predicate => '_has_psgi_logger', clearer => '_clear_psgi_logger');
18has _psgi_errors => (is => 'rw', predicate => '_has_psgi_errors', clearer => '_clear_psgi_errors');
50f53fd7 19
20sub clear_psgi {
21 my $self = shift;
22 $self->_clear_psgi_logger;
23 $self->_clear_psgi_errors;
24}
25
26sub psgienv {
27 my ($self, $env) = @_;
28
21da7377 29 $self->_psgi_logger($env->{'psgix.logger'}) if $env->{'psgix.logger'};
30 $self->_psgi_errors($env->{'psgi.errors'}) if $env->{'psgi.errors'};
50f53fd7 31}
32
3cdcf968 33
2f9e6321 34{
a6433a05 35 my @levels = qw[ debug info warn error fatal ];
846772b7 36
dd5b1dc4 37 my $meta = find_meta(__PACKAGE__);
c72d2e24 38 my $summed_level = 0;
39 for ( my $i = $#levels ; $i >= 0 ; $i-- ) {
846772b7 40
41 my $name = $levels[$i];
eaae9a92 42
846772b7 43 my $level = 1 << $i;
c72d2e24 44 $summed_level |= $level;
eaae9a92 45
a6433a05 46 $LEVELS{$name} = $level;
c72d2e24 47 $LEVEL_MATCH{$name} = $summed_level;
a6433a05 48
4090e3bb 49 $meta->add_method($name, sub {
846772b7 50 my $self = shift;
51
3cdcf968 52 if ( $self->level & $level ) {
846772b7 53 $self->_log( $name, @_ );
54 }
4090e3bb 55 });
846772b7 56
4090e3bb 57 $meta->add_method("is_$name", sub {
846772b7 58 my $self = shift;
3cdcf968 59 return $self->level & $level;
4090e3bb 60 });;
846772b7 61 }
a6433a05 62}
63
4090e3bb 64around new => sub {
65 my $orig = shift;
a6433a05 66 my $class = shift;
4090e3bb 67 my $self = $class->$orig;
e2422920 68
310c2a39 69 $self->levels( scalar(@_) ? @_ : (qw/info warn error fatal/) );
a6433a05 70 return $self;
4090e3bb 71};
a6433a05 72
73sub levels {
74 my ( $self, @levels ) = @_;
75 $self->level(0);
76 $self->enable(@levels);
77}
78
79sub enable {
80 my ( $self, @levels ) = @_;
3cdcf968 81 my $level = $self->level;
c72d2e24 82 for(map { $LEVEL_MATCH{$_} } @levels){
3cdcf968 83 $level |= $_;
84 }
85 $self->level($level);
a6433a05 86}
846772b7 87
a6433a05 88sub disable {
89 my ( $self, @levels ) = @_;
3cdcf968 90 my $level = $self->level;
91 for(map { $LEVELS{$_} } @levels){
92 $level &= ~$_;
93 }
94 $self->level($level);
846772b7 95}
96
0816209f 97our $HAS_DUMPED;
a6433a05 98sub _dump {
846772b7 99 my $self = shift;
0816209f 100 unless ($HAS_DUMPED++) {
101 cluck("Catalyst::Log::_dump is deprecated and will be removed. Please change to using your own Dumper.\n");
102 }
f63c03e4 103 $self->info( Data::Dump::dump(@_) );
846772b7 104}
105
106sub _log {
107 my $self = shift;
108 my $level = shift;
846772b7 109 my $message = join( "\n", @_ );
21da7377 110 if ($self->can('_has_psgi_logger') and $self->_has_psgi_logger) {
111 $self->_psgi_logger->({
0eb98ebd 112 level => $level,
113 message => $message,
114 });
115 } else {
208732e6 116 $message .= "\n" unless $message =~ /\n$/;
0eb98ebd 117 my $body = $self->_body;
118 $body .= sprintf( "[%s] %s", $level, $message );
119 $self->_body($body);
120 }
1b526dcc 121 if( $self->autoflush && !$self->abort ) {
122 $self->_flush;
123 }
124 return 1;
4be535b1 125}
126
127sub _flush {
b5ecfcf0 128 my $self = shift;
3cdcf968 129 if ( $self->abort || !$self->_body ) {
b5ecfcf0 130 $self->abort(undef);
131 }
132 else {
3cdcf968 133 $self->_send_to_log( $self->_body );
4be535b1 134 }
3cdcf968 135 $self->_body(undef);
846772b7 136}
137
adee716c 138sub _send_to_log {
139 my $self = shift;
21da7377 140 if ($self->can('_has_psgi_errors') and $self->_has_psgi_errors) {
141 $self->_psgi_errors->print(@_);
0eb98ebd 142 } else {
143 print STDERR @_;
144 }
adee716c 145}
146
71415389 147# 5.7 compat code.
148# Alias _body to body, add a before modifier to warn..
149my $meta = __PACKAGE__->meta; # Calling meta method here fine as we happen at compile time.
150$meta->add_method('body', $meta->get_method('_body'));
eaae9a92 151my %package_hash; # Only warn once per method, per package.
71415389 152 # I haven't provided a way to disable them, patches welcome.
153$meta->add_before_method_modifier('body', sub {
154 my $class = blessed(shift);
155 $package_hash{$class}++ || do {
156 warn("Class $class is calling the deprecated method Catalyst::Log->body method,\n"
157 . "this will be removed in Catalyst 5.81");
158 };
159});
160# End 5.70 backwards compatibility hacks.
161
6680c772 162no Moose;
d14f9123 163__PACKAGE__->meta->make_immutable(inline_constructor => 0);
6680c772 164
846772b7 1651;
166
167__END__
fc7ec1d9 168
a273dd58 169=for stopwords psgienv
170
fc7ec1d9 171=head1 NAME
172
173Catalyst::Log - Catalyst Log Class
174
175=head1 SYNOPSIS
176
82d2fcbe 177 $log = $c->log;
846772b7 178 $log->debug($message);
179 $log->info($message);
180 $log->warn($message);
181 $log->error($message);
182 $log->fatal($message);
846772b7 183
f4dbb0d9 184 if ( $log->is_debug ) {
846772b7 185 # expensive debugging
186 }
82d2fcbe 187
a6433a05 188
fc7ec1d9 189See L<Catalyst>.
190
191=head1 DESCRIPTION
192
adee716c 193This module provides the default, simple logging functionality for Catalyst.
194If you want something different set C<< $c->log >> in your application module,
195e.g.:
82d2fcbe 196
197 $c->log( MyLogger->new );
198
199Your logging object is expected to provide the interface described here.
397be447 200Good alternatives to consider are Log::Log4Perl and Log::Dispatch.
201
202If you want to be able to log arbitrary warnings, you can do something along
203the lines of
204
205 $SIG{__WARN__} = sub { MyApp->log->warn(@_); };
206
207however this is (a) global, (b) hairy and (c) may have unexpected side effects.
208Don't say we didn't warn you.
82d2fcbe 209
a6433a05 210=head1 LOG LEVELS
211
b5ecfcf0 212=head2 debug
a6433a05 213
214 $log->is_debug;
215 $log->debug($message);
216
b5ecfcf0 217=head2 info
a6433a05 218
219 $log->is_info;
220 $log->info($message);
221
b5ecfcf0 222=head2 warn
a6433a05 223
224 $log->is_warn;
225 $log->warn($message);
226
b5ecfcf0 227=head2 error
a6433a05 228
229 $log->is_error;
230 $log->error($message);
231
b5ecfcf0 232=head2 fatal
a6433a05 233
234 $log->is_fatal;
235 $log->fatal($message);
236
b22c6668 237=head1 METHODS
fc7ec1d9 238
b5ecfcf0 239=head2 new
a6433a05 240
26e73131 241Constructor. Defaults to enable all levels unless levels are provided in
a6433a05 242arguments.
243
244 $log = Catalyst::Log->new;
26e73131 245 $log = Catalyst::Log->new( 'warn', 'error' );
a6433a05 246
3cdcf968 247=head2 level
248
249Contains a bitmask of the currently set log levels.
250
b5ecfcf0 251=head2 levels
a6433a05 252
253Set log levels
b22c6668 254
a6433a05 255 $log->levels( 'warn', 'error', 'fatal' );
fc7ec1d9 256
b5ecfcf0 257=head2 enable
fc7ec1d9 258
a6433a05 259Enable log levels
fc7ec1d9 260
a6433a05 261 $log->enable( 'warn', 'error' );
fc7ec1d9 262
b5ecfcf0 263=head2 disable
fc7ec1d9 264
a6433a05 265Disable log levels
fc7ec1d9 266
a6433a05 267 $log->disable( 'warn', 'error' );
fc7ec1d9 268
b5ecfcf0 269=head2 is_debug
a2f2cde9 270
b5ecfcf0 271=head2 is_error
a2f2cde9 272
b5ecfcf0 273=head2 is_fatal
a2f2cde9 274
b5ecfcf0 275=head2 is_info
a2f2cde9 276
b5ecfcf0 277=head2 is_warn
49ba64d7 278
279Is the log level active?
280
b5ecfcf0 281=head2 abort
4be535b1 282
eaae9a92 283Should Catalyst emit logs for this request? Will be reset at the end of
284each request.
4be535b1 285
286*NOTE* This method is not compatible with other log apis, so if you plan
287to use Log4Perl or another logger, you should call it like this:
288
289 $c->log->abort(1) if $c->log->can('abort');
290
1b526dcc 291=head2 autoflush
292
293When enabled (default), messages are written to the log immediately instead
294of queued until the end of the request.
295
296This option, as well as C<abort>, is provided for modules such as
297L<Catalyst::Plugin::Static::Simple> to be able to programmatically
298suppress the output of log messages. By turning off C<autoflush> (application-wide
299setting) and then setting the C<abort> flag within a given request, all log
300messages for the given request will be suppressed. C<abort> can still be set
301independently of turning off C<autoflush>, however. It just means any messages
302sent to the log up until that point in the request will obviously still be emitted,
303since C<autoflush> means they are written in real-time.
304
305If you need to turn off autoflush you should do it like this (in your main app
306class):
307
308 after setup_finalize => sub {
309 my $c = shift;
310 $c->log->autoflush(0) if $c->log->can('autoflush');
311 };
312
adee716c 313=head2 _send_to_log
314
315 $log->_send_to_log( @messages );
316
317This protected method is what actually sends the log information to STDERR.
318You may subclass this module and override this method to get finer control
319over the log output.
320
d298046a 321=head2 psgienv $env
322
323 $log->psgienv($env);
324
325NOTE: This is not meant for public consumption.
326
327Set the PSGI environment for this request. This ensures logs will be sent to
328the right place. If the environment has a C<psgix.logger>, it will be used. If
329not, we will send logs to C<psgi.errors> if that exists. As a last fallback, we
330will send to STDERR as before.
331
a273dd58 332=head2 clear_psgi
333
334Clears the PSGI environment attributes set by L</psgienv>.
335
3cdcf968 336=head2 meta
337
fc7ec1d9 338=head1 SEE ALSO
339
340L<Catalyst>.
341
2f381252 342=head1 AUTHORS
fc7ec1d9 343
2f381252 344Catalyst Contributors, see Catalyst.pm
fc7ec1d9 345
346=head1 COPYRIGHT
347
536bee89 348This library is free software. You can redistribute it and/or modify
61b1e958 349it under the same terms as Perl itself.
fc7ec1d9 350
351=cut
352
e5ecd5bc 353__PACKAGE__->meta->make_immutable;
354
fc7ec1d9 3551;