File Coverage

blib/lib/Catalyst/Plugin/AccessLog.pm
Criterion Covered Total %
statement 12 21 57.1
branch 0 8 0.0
condition 0 6 0.0
subroutine 4 5 80.0
pod 0 1 0.0
total 16 41 39.0


line stmt bran cond sub pod time code
1             package Catalyst::Plugin::AccessLog;
2             # ABSTRACT: Request logging from within Catalyst
3             our $VERSION = '1.10'; # VERSION
4             our $AUTHORITY = 'cpan:ARODLAND'; # AUTHORITY
5              
6 1     1   900 use namespace::autoclean;
  1         13096  
  1         5  
7 1     1   502 use Moose::Role;
  1         310819  
  1         7  
8 1     1   4158 use Scalar::Util qw(reftype blessed);
  1         3  
  1         92  
9 1     1   818 use Catalyst::Utils;
  1         67680  
  1         585  
10              
11             after 'setup_finalize' => sub { # Init ourselves
12             my $c = shift;
13             my $default_config = {
14             formatter => {
15             class => 'Catalyst::Plugin::AccessLog::Formatter',
16             },
17             hostname_lookups => 0,
18             enable_stats => 1,
19             target => \*STDERR,
20             };
21              
22             my $config = $c->config->{'Plugin::AccessLog'} = Catalyst::Utils::merge_hashes(
23             $default_config,
24             $c->config->{'Plugin::AccessLog'}
25             );
26              
27             if (!ref $config->{target}) {
28             open my $output, '>>', $config->{target} or die qq[Error opening "$config->{target}" for log output];
29             select((select($output), $|=1)[0]);
30             $config->{target} = $output;
31             }
32              
33             Catalyst::Utils::ensure_class_loaded( $config->{formatter}{class} );
34              
35             };
36              
37             override 'use_stats' => sub {
38             my ($c) = @_;
39             if ($c->config->{'Plugin::AccessLog'}{enable_stats}) {
40             return 1;
41             } else {
42             return super;
43             }
44             };
45              
46             sub access_log_write {
47 0     0 0   my $c = shift;
48 0           my $output = join "", @_;
49 0 0         $output .= "\n" unless $output =~ /\n\Z/;
50              
51 0           my $target = $c->config->{'Plugin::AccessLog'}{target};
52 0 0 0       if (reftype($target) eq 'GLOB' or blessed($target) && $target->isa('IO::Handle')) {
    0 0        
    0          
53 0           print $target $output;
54             } elsif (reftype($target) eq 'CODE') {
55 0           $target->($output, $c);
56             } elsif ($target->can('info')) { # Logger object
57 0           $target->info($output);
58             } else {
59 0           warn "Don't know how to log to config->{'Plugin::AccessLog'}{target}";
60             }
61             }
62              
63             after 'finalize' => sub {
64             my $c = shift;
65             my $config = $c->config->{'Plugin::AccessLog'};
66              
67             my %formatter_opts = %{ $config->{formatter} };
68             my $formatter_class = delete $formatter_opts{class};
69             my $formatter = $formatter_class->new( %formatter_opts );
70              
71             my $line = $formatter->format_line($c);
72             $c->access_log_write($line);
73             };
74              
75             1;
76              
77             =head1 DEPRECATION NOTICE
78              
79             This module doesn't work well on Catalyst 5.9 or above, and no longer
80             passes its tests. Repairing it isn't possible. Using this module for
81             anything new isn't recommended; use L<Plack::Middleware::AccessLog> or log
82             at the proxy layer. It remains online in support of existing users.
83              
84             =head1 SYNOPSIS
85              
86             Requires Catalyst 5.8 or above.
87              
88             # In lib/MyApp.pm context
89             use Catalyst qw(
90             ConfigLoader
91             -Stats=1
92             AccessLog
93             ... other plugins here ...
94             );
95              
96             __PACKAGE__->config(
97             'Plugin::AccessLog' => {
98             formatter => {
99             format => '%[time] %[remote_address] %[path] %[status] %[size]',
100             time_format => '%c',
101             time_zone => 'America/Chicago',
102             },
103             }
104             );
105              
106             __PACKAGE__->setup();
107              
108             =head1 DESCRIPTION
109              
110             This plugin isn't for "debug" logging. Instead it enables you to create
111             "access logs" from within a Catalyst application instead of requiring a
112             webserver to do it for you. It will work even with Catalyst debug logging
113             turned off (but see C<enable_stats> below).
114              
115             =head1 CONFIGURATION
116              
117             All configuration is optional; by default the plugin will log to STDERR in a
118             format compatible with the "Common Log Format"
119             (L<http://en.wikipedia.org/wiki/Common_Log_Format>).
120              
121             =over 4
122              
123             =item target
124              
125             B<Default:> C<\*STDERR>
126              
127             Where to log to. If C<target> is a filehandle or something that
128             C<< isa("IO::Handle") >>, lines of logging information will be C<print>ed to
129             it. If C<target> is an object with an C<info> method it's assumed to be a
130             logging object (e.g. L<Log::Dispatch> or L<Log::Log4perl>) and lines will be
131             passed to the C<info> method. If it's a C<CODE> ref then it will be called
132             with each line of logging output. If it's an unblessed scalar it will be
133             interpreted as a filename and the plugin will try to open it for append
134             and write lines to it.
135              
136             =item formatter
137              
138             B<Default:> C<< { class => "Catalyst::Plugin::AccessLog::Formatter" } >>
139              
140             The formatter to use. Defaults to the Formatter class included in this
141             distribution. This option must be a hashref. The C<class> option is taken as
142             the name of the class to use as the formatter; all other keys are passed to
143             that class's constructor. See L<Catalyst::Plugin::AccessLog::Formatter> for
144             the keys supported by that module.
145              
146             =item enable_stats
147              
148             B<Default:> B<true>
149              
150             C<Catalyst::Plugin::AccessLog> works without regard to Catalyst's debug
151             logging option. However, the time-related escapes are only available if the
152             C<Catalyst::Stats> statistics collection is enabled, and by default stats are
153             tied to the value of the debug flag. If this option is set, stats will be
154             enabled for the application regardless of the C<-Stats> or C<-Debug> flags, or
155             the C<MYAPP_STATS> or C<MYAPP_DEBUG> environment variables.
156              
157             =back
158              
159             =head1 NOTES
160              
161             =head2 Logging to C<< $c->log >>
162              
163             It is generally not recommended to write the access log to C<< $c->log >>,
164             especially if static file handling is enabled. However, there might be a
165             good reason to do it somewhere. If the logging target is a coderef, it will
166             receive C<$c> as its second argument. You can log to C<< $c->log >> with:
167              
168             target => sub { pop->log->info(shift) }
169              
170             Don't store C<$c> anywhere that persists after the lifetime of the coderef
171             or bad things will happen to you and everyone you know.
172              
173             =head1 SOURCE, BUGS, ETC.
174              
175             L<http://github.com/arodland/Catalyst-Plugin-AccessLog>
176              
177             =cut