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