NAME
Apache2::ModLogConfig - a Perl interface to mod_log_config
SYNOPSIS
Call a Perl handler from a "CustomLog" format specification:
use Apache2::ModLogConfig ();
sub My::Format {
my ($r)=@_;
return $a_string;
}
CustomLog LOGFILE "... %{My::Format}^..."
Use a Perl handler as logfile:
PerlModule Apache2::ModLogConfig
PerlModule My::LogReceiver
CustomLog "@perl: My::LogReceiver" "format spec"
Print to a logfile:
use Apache2::ModLogConfig ();
sub handler {
my ($r)=@_;
...
my $log=$r->server->custom_log_by_name('logs/access_log');
my $success=$log->print($r, qw/тут был вася/, "\n");
...
}
INSTALLATION
perl Makefile.PL
make
make test
make install
DESCRIPTION
The reason to start this module was to monitor the number of incoming
and outgoing bytes for each request. "mod_log_config" in combination
with "mod_logio" can log these numbers. But in Perl they are really hard
to get.
"mod_logio" uses a network-level input filter as byte counter. The
outgoing bytes are counted by the core output filter and reported back
to "mod_logio" if loaded.
Now, with the help of this module you can do 3 things:
* call a Perl handler from a "CustomLog" format specification
* use a Perl handler in place of a logfile
* write out-of-bound messages to logfiles managed by "mod_log_config"
For this to work, the module must be loaded before the
"PerlOpenLogsHandler" phase. Calling a Perl handler from a format
specification requires an early start of the interpreter and the module
must be loaded at that stage. That means you need either a
"..." section in your httpd.conf or the module must be
loaded by "PerlLoadModule".
Note, while developing this module I have found a bug in httpd that can
lead to segfaults. It is present at least up to httpd 2.2.17. It occurs
if "mod_log_config" is statically compiled into httpd and "BufferedLogs"
are used. In this case avoid changing the "BufferedLogs" setting while
restarting httpd via "SIGHUP" or "SIGUSR1".
See
Call a Perl handler from a "CustomLog" format specification
To be used this way "Apache2::ModLogConfig" registers the "^" format
with "mod_log_config".
"^" was chosen because it resembles the "^" in a number of Perl
variables like $^V for example.
Now, a format specifier can receive an argument. The argument is given
in braces between the "%" sign and the specifier. The "^" specifier's
argument specifies the Perl handler to call. A fully qualified name is
expected.
Example:
LogFormat "%{My::Handler::function}^" perllog
The handler is called with an Apache2::RequestRec object as the only
parameter. In a chain of internal redirects this is by default the final
request. It can be modified according to the "mod_log_config"
documentation:
LogFormat "%<{My::Handler::function}^" perllog
This way the initial request is passed to the handler.
Other modifiers are also applicable as described by "mod_log_config".
Use a Perl handler in place of a logfile
Now Perl handler works as log drain. That means it will receive a log
file.
CustomLog "@perl: My::LogReceiver" FORMATSPEC
The prefix @perl: is used to distinguish between a normal file name or
pipe specification and the Perl handler.
The actual handler name is resolved the usual modperl way. That means if
there is no function named "My::LogReceiver", "My::LogReceiver::handler"
is looked up. Auto-loading should work as well (although untested).
Further, an anonymous function can be specified as:
CustomLog "@perl: sub { my ($r, @strings)=@_; ... }" FORMATSPEC
The handler is called with the final request of a chain of internal
redirects as the first parameters. The other parameters are all strings
where each one corresponds to either a the result of a format specifier
or a constant string.
Assuming the following format specification
"input bytes=%I, output bytes=%O"
the handler is called with 6 parameters:
* the request object
* the string "input bytes="
* a number according to %I
* the string ", output bytes="
* a number according to %O
* and a trailing "\n" to close the line
Note, a possible "PerlLogHandler" runs before the "mod_log_config"
handler. So, it's not possible to record a few values here and use them
in a "PerlLogHandler". A "PerlCleanupHandler" or a request pool cleanup
handler however should be fine.
My original problem now can be solved as:
package My::IO;
sub handler {
my ($r, $in, $out)=@_;
$r->notes->{InBytes}=$in;
$r->notes->{OutBytes}=$out;
}
sub cleanup {
my ($r)=@_;
my ($in, $out)=@{$r->notes}{qw/InBytes OutBytes/};
...
}
in httpd.conf:
CustomLog "@perl: My::IO" "%I%O"
PerlCleanupHandler My::IO::cleanup
Writing to a "CustomLog" logfile and introspection
Have you ever wanted to write to the access_log directly? I haven't. But
now it's feasible and perhaps someone finds a weird usage case.
"Apache2::ModLogConfig" implements the following methods.
@names=$s->custom_logs
Assuming $s is a Apache2::ServerRec object this method returns the
logfile names defined for this VHost. The elements of @names are
literally the strings specified as first parameter to "CustomLog".
$log=$s->custom_log_by_name($name)
Assuming $s is a Apache2::ServerRec object this method returns an
"Apache2::ModLogConfig" object for the given name.
$status=$log->print($r, @strings)
Assuming $log is an "Apache2::ModLogConfig" object and $r is an
Apache2::RequestRec this method prints the strings in @strings to the
file. No escaping is done.
$status is an APR status code ("APR::Const::SUCCESS" if all is well).
EXPORT
None.
SEE ALSO
modperl, mod_log_config, apache httpd
AUTHOR
Torsten Förtsch,
COPYRIGHT AND LICENSE
Copyright (C) 2011 by Torsten Förtsch
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, either Perl version 5.12.3 or, at
your option, any later version of Perl 5 you may have available.