Update TODO with more verbose descriptions of known issues
[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;
e106a59f 7use Class::MOP ();
9b2bc37b 8
a6433a05 9our %LEVELS = ();
10
3cdcf968 11has level => (is => 'rw');
5fb12dbb 12has _body => (is => 'rw');
3cdcf968 13has abort => (is => 'rw');
14
2f9e6321 15{
a6433a05 16 my @levels = qw[ debug info warn error fatal ];
846772b7 17
e106a59f 18 my $meta = Class::MOP::get_metaclass_by_name(__PACKAGE__);
846772b7 19 for ( my $i = 0 ; $i < @levels ; $i++ ) {
20
21 my $name = $levels[$i];
22 my $level = 1 << $i;
23
a6433a05 24 $LEVELS{$name} = $level;
25
4090e3bb 26 $meta->add_method($name, sub {
846772b7 27 my $self = shift;
28
3cdcf968 29 if ( $self->level & $level ) {
846772b7 30 $self->_log( $name, @_ );
31 }
4090e3bb 32 });
846772b7 33
4090e3bb 34 $meta->add_method("is_$name", sub {
846772b7 35 my $self = shift;
3cdcf968 36 return $self->level & $level;
4090e3bb 37 });;
846772b7 38 }
a6433a05 39}
40
4090e3bb 41around new => sub {
42 my $orig = shift;
a6433a05 43 my $class = shift;
4090e3bb 44 my $self = $class->$orig;
e2422920 45
46 if (@_ == 1 && $_[0] eq 'debug') {
47 $self->levels( keys %LEVELS );
48 } else {
49 $self->levels( scalar(@_) ? @_ : keys %LEVELS );
50 }
51
a6433a05 52 return $self;
4090e3bb 53};
a6433a05 54
55sub levels {
56 my ( $self, @levels ) = @_;
57 $self->level(0);
58 $self->enable(@levels);
59}
60
61sub enable {
62 my ( $self, @levels ) = @_;
3cdcf968 63 my $level = $self->level;
64 for(map { $LEVELS{$_} } @levels){
65 $level |= $_;
66 }
67 $self->level($level);
a6433a05 68}
846772b7 69
a6433a05 70sub disable {
71 my ( $self, @levels ) = @_;
3cdcf968 72 my $level = $self->level;
73 for(map { $LEVELS{$_} } @levels){
74 $level &= ~$_;
75 }
76 $self->level($level);
846772b7 77}
78
a6433a05 79sub _dump {
846772b7 80 my $self = shift;
f63c03e4 81 $self->info( Data::Dump::dump(@_) );
846772b7 82}
83
84sub _log {
85 my $self = shift;
86 my $level = shift;
846772b7 87 my $message = join( "\n", @_ );
1cf0345b 88 $message .= "\n" unless $message =~ /\n$/;
3cdcf968 89 my $body = $self->_body;
90 $body .= sprintf( "[%s] %s", $level, $message );
91 $self->_body($body);
4be535b1 92}
93
94sub _flush {
b5ecfcf0 95 my $self = shift;
3cdcf968 96 if ( $self->abort || !$self->_body ) {
b5ecfcf0 97 $self->abort(undef);
98 }
99 else {
3cdcf968 100 $self->_send_to_log( $self->_body );
4be535b1 101 }
3cdcf968 102 $self->_body(undef);
846772b7 103}
104
adee716c 105sub _send_to_log {
106 my $self = shift;
107 print STDERR @_;
108}
109
71415389 110# 5.7 compat code.
111# Alias _body to body, add a before modifier to warn..
112my $meta = __PACKAGE__->meta; # Calling meta method here fine as we happen at compile time.
113$meta->add_method('body', $meta->get_method('_body'));
114my %package_hash; # Only warn once per method, per package.
115 # I haven't provided a way to disable them, patches welcome.
116$meta->add_before_method_modifier('body', sub {
117 my $class = blessed(shift);
118 $package_hash{$class}++ || do {
119 warn("Class $class is calling the deprecated method Catalyst::Log->body method,\n"
120 . "this will be removed in Catalyst 5.81");
121 };
122});
123# End 5.70 backwards compatibility hacks.
124
6680c772 125no Moose;
d14f9123 126__PACKAGE__->meta->make_immutable(inline_constructor => 0);
6680c772 127
846772b7 1281;
129
130__END__
fc7ec1d9 131
132=head1 NAME
133
134Catalyst::Log - Catalyst Log Class
135
136=head1 SYNOPSIS
137
82d2fcbe 138 $log = $c->log;
846772b7 139 $log->debug($message);
140 $log->info($message);
141 $log->warn($message);
142 $log->error($message);
143 $log->fatal($message);
846772b7 144
f4dbb0d9 145 if ( $log->is_debug ) {
846772b7 146 # expensive debugging
147 }
82d2fcbe 148
a6433a05 149
fc7ec1d9 150See L<Catalyst>.
151
152=head1 DESCRIPTION
153
adee716c 154This module provides the default, simple logging functionality for Catalyst.
155If you want something different set C<< $c->log >> in your application module,
156e.g.:
82d2fcbe 157
158 $c->log( MyLogger->new );
159
160Your logging object is expected to provide the interface described here.
397be447 161Good alternatives to consider are Log::Log4Perl and Log::Dispatch.
162
163If you want to be able to log arbitrary warnings, you can do something along
164the lines of
165
166 $SIG{__WARN__} = sub { MyApp->log->warn(@_); };
167
168however this is (a) global, (b) hairy and (c) may have unexpected side effects.
169Don't say we didn't warn you.
82d2fcbe 170
a6433a05 171=head1 LOG LEVELS
172
b5ecfcf0 173=head2 debug
a6433a05 174
175 $log->is_debug;
176 $log->debug($message);
177
b5ecfcf0 178=head2 info
a6433a05 179
180 $log->is_info;
181 $log->info($message);
182
b5ecfcf0 183=head2 warn
a6433a05 184
185 $log->is_warn;
186 $log->warn($message);
187
b5ecfcf0 188=head2 error
a6433a05 189
190 $log->is_error;
191 $log->error($message);
192
b5ecfcf0 193=head2 fatal
a6433a05 194
195 $log->is_fatal;
196 $log->fatal($message);
197
b22c6668 198=head1 METHODS
fc7ec1d9 199
b5ecfcf0 200=head2 new
a6433a05 201
26e73131 202Constructor. Defaults to enable all levels unless levels are provided in
a6433a05 203arguments.
204
205 $log = Catalyst::Log->new;
26e73131 206 $log = Catalyst::Log->new( 'warn', 'error' );
a6433a05 207
3cdcf968 208=head2 level
209
210Contains a bitmask of the currently set log levels.
211
b5ecfcf0 212=head2 levels
a6433a05 213
214Set log levels
b22c6668 215
a6433a05 216 $log->levels( 'warn', 'error', 'fatal' );
fc7ec1d9 217
b5ecfcf0 218=head2 enable
fc7ec1d9 219
a6433a05 220Enable log levels
fc7ec1d9 221
a6433a05 222 $log->enable( 'warn', 'error' );
fc7ec1d9 223
b5ecfcf0 224=head2 disable
fc7ec1d9 225
a6433a05 226Disable log levels
fc7ec1d9 227
a6433a05 228 $log->disable( 'warn', 'error' );
fc7ec1d9 229
b5ecfcf0 230=head2 is_debug
a2f2cde9 231
b5ecfcf0 232=head2 is_error
a2f2cde9 233
b5ecfcf0 234=head2 is_fatal
a2f2cde9 235
b5ecfcf0 236=head2 is_info
a2f2cde9 237
b5ecfcf0 238=head2 is_warn
49ba64d7 239
240Is the log level active?
241
b5ecfcf0 242=head2 abort
4be535b1 243
ac5c933b 244Should Catalyst emit logs for this request? Will be reset at the end of
245each request.
4be535b1 246
247*NOTE* This method is not compatible with other log apis, so if you plan
248to use Log4Perl or another logger, you should call it like this:
249
250 $c->log->abort(1) if $c->log->can('abort');
251
adee716c 252=head2 _send_to_log
253
254 $log->_send_to_log( @messages );
255
256This protected method is what actually sends the log information to STDERR.
257You may subclass this module and override this method to get finer control
258over the log output.
259
3cdcf968 260=head2 meta
261
fc7ec1d9 262=head1 SEE ALSO
263
264L<Catalyst>.
265
2f381252 266=head1 AUTHORS
fc7ec1d9 267
2f381252 268Catalyst Contributors, see Catalyst.pm
fc7ec1d9 269
270=head1 COPYRIGHT
271
a6433a05 272This program is free software, you can redistribute it and/or modify
61b1e958 273it under the same terms as Perl itself.
fc7ec1d9 274
275=cut
276
e5ecd5bc 277__PACKAGE__->meta->make_immutable;
278
fc7ec1d9 2791;