Catalyst-Plugin-AccessLog
view release on metacpan or search on metacpan
lib/Catalyst/Plugin/AccessLog/Formatter.pm view on Meta::CPAN
package Catalyst::Plugin::AccessLog::Formatter;
# ABSTRACT: Log formatter for Catalyst::Plugin::AccessLog
our $VERSION = '1.10'; # VERSION
our $AUTHORITY = 'cpan:ARODLAND'; # AUTHORITY
use namespace::autoclean;
use Moose;
use DateTime;
my %items;
sub item {
my ($names, $code) = @_;
$names = [ $names ] unless ref $names;
$items{$_} = $code for @$names;
}
my %whitespace_escapes = (
"\r" => "\\r",
"\n" => "\\n",
"\t" => "\\t",
"\x0b" => "\\v",
);
# Approximate the rules for safely escaping headers/etc given in the apache docs
sub escape_string {
my $str = shift;
return "" unless defined $str and length $str;
$str =~ s/(["\\])/\\$1/g;
$str =~ s/([\r\n\t\x0b])/$whitespace_escapes{$1}/eg;
$str =~ s/([^[:print:]])/sprintf '\x%02x', ord $1/eg;
return $str;
}
sub get_item {
my ($self, $c, $key, $arg) = @_;
return "[unknown format key $key]" unless exists $items{$key};
return $items{$key}->($self, $c, $arg);
}
sub format_line {
my ($self, $c) = @_;
my $format = $self->format;
my $output = "";
while (1) {
my $argument = qr/\{ ( [^}]+ ) \}/x;
my $longopt = qr/\[ ( [^]]+ ) \]/x;
if ($format =~ /\G \Z/cgx) { # Found end of string.
last;
} elsif ($format =~ /\G ( [^%]+ )/cgx) { # Found non-percenty text.
$output .= $1;
} elsif ($format =~ /\G \%\% /cgx) { # Literal percent
$output .= "%";
} elsif ($format =~ /\G \% $argument $longopt/cgx) { # Long opt with argument
$output .= $self->get_item($c, $2, $1);
} elsif ($format =~ /\G \% $longopt/cgx) { # Long opt
$output .= $self->get_item($c, $1);
} elsif ($format =~ /\G \% $argument (.)/cgx) { # Short opt with argument
$output .= $self->get_item($c, $2, $1);
} elsif ($format =~ /\G \% (.)/cgx) { # Short opt
$output .= $self->get_item($c, $1);
} else {
warn "Can't happen!";
}
}
return $output;
}
=head1 DESCRIPTION
The log format argument is a string which will be used to generate each line
of the access log. The string consists of literal characters which will be
copied to the log output verbatim, and escapes, which will be replaced with
information about the request or the response. This format string is
intended to be compatible with the Apache C<LogFormat> directive, however it
contains some extensions and leaves a few features unimplemented.
Escapes can be either B<short escapes> or B<long escapes>. Both types begin
with the "C<%>" character. Short escapes consist of a C<%> followed by a
single character, for example C<%h> for the remote hostname. Long
escapes consist of a C<%> followed by a name inside B<square brackets>, for
example C<%[remote_hostname]> for the same option. Apache-compatible
options have both short escapes and long escapes, while incompatible options
have only long escapes.
Some escapes (currently C<%[time]>, C<%[apache_time]>, C<%[header]>, and
C<%[apache_header]>) may also take an argument, which can be optional or
required. The argument is placed inside B<curly braces> between the percent
sign and the name of the escape, for example C<%{User-agent}i> or
C<%{User-agent}[header]> to get the value of the C<User-agent> header.
A literal percent-sign can be produced in the output using the escape
sequence C<%%>.
=head2 Configuration
The following are optional arguments passed to
C<< Catalyst::Plugin::AccessLog::Formatter->new >>. Ordinarily these values
will be provided by L<Catalyst::Plugin::AccessLog> from its C<formatter>
config hash.
=over 4
=item format
B<Default:> C<'%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"'> (Apache
C<common> log format).
The format string for each line of output. You can use Apache C<LogFormat>
strings, with a reasonably good level of compatibility, or you can use a
slightly more readable format. The log format is documented in detail in
L<Catalyst::Plugin::AccessLog::Formatter>.
=cut
has 'format' => (
is => 'rw',
default => '%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"',
);
=item time_format
B<Default:> C<'%Y-%m-%dT%H:%M:%S'> (ISO 8601)
The default time format for the C<%t> / C<%[time]> escape. This is a
C<strftime> format string, which will be provided to L<DateTime>'s
C<strftime> method.
=cut
has 'time_format' => (
is => 'rw',
default => '%Y-%m-%dT%H:%M:%S',
);
=item time_zone
B<Default:> local
The timezone to use when printing times in access logs. This will be passed
to L<DateTime::TimeZone>'s constructor. Olson timezone names, POSIX TZ
values, and the keywords C<"local"> and C<"UTC"> are reasonable choices.
=cut
has 'time_zone' => (
is => 'rw',
default => 'local',
);
=item hostname_lookups
( run in 1.035 second using v1.01-cache-2.11-cpan-5837b0d9d2c )