tadman has asked for the wisdom of the Perl Monks concerning the following question:

With Apache, there is a lot of flexibility in how your TransferLog is constructed, such as with the CustomLog directive, but the ErrorLog seems to be a whole different beast. It's a free-form file, with a simple prefix that occurs before each message block.

What I'm trying to do is capture and re-format errors that are being written to the ErrorLog under mod_perl, such that they can be cross-referenced with the corresponding request in the TransferLog. Right now when errors are generated, you have to make an educated guess as to which request caused it, for example, by looking for an HTTP 500 response at around the same time. This is fairly imprecise, as under heavier loads, you're going to be trying to match up two or more errors to two or more defective requests.

Things like Apache::Log allow you to write error messages, of course. Apache::DBILogger only captures TransferLog-type entries. Is there a way to do the same thing for ErrorLog? Maybe I'm missing something, but I've been unable to find any documentation on how this format can be changed.

Replies are listed 'Best First'.
Re: Custom Apache ErrorLog Using mod_perl
by Aristotle (Chancellor) on Aug 28, 2002 at 21:42 UTC
    CGI::Carp does something like this; I don't know how well it translates to mod_perl. But it might just work as is, and if not you can read the source for a starting point. (It's done using @SIG{qw(__DIE__ __WARN__)} handlers.)

    Makeshifts last the longest.

      I'm thinking I can just spam the ErrorLog at the beginning of each request, and that with a piped error-log handler, I can re-format it back in to something sensible, stripping out "empty" errors.

      I'm using CGI::Carp of course, but the errors it cranks out are free-form, just like you'd expect.
        I don't quite follow.. does CGI::Carp prefix your errors with a nice identifier and timestamp, or not? If yes, what exactly is the problem?

        Makeshifts last the longest.

Re: Custom Apache ErrorLog Using mod_perl (use an application errlog)
by Flexx (Pilgrim) on Aug 29, 2002 at 11:06 UTC

    Hi!

    I know the problem... Indeed: http://httpd.apache.org/docs/logs.html#errorlogsays:

    " It is not possible to customize the error log by adding or removing information."

    For my part, I wrote an error handler module, that processes all errors my application produces. That means I don't warn or die, I call my $err->raise(666, 'devil!'), $err->warn(665, 'almost devil!'), etc. methods, who will put messages in my application logfile (where I can put the request, and additional debugging information alongside the actual error message.), and then die, warn or even take corrective measures. Also, these handlers will print error messages in whatever content type (text/plain, text/html, or text/xml) the client requested automatically.

    So the apache log will present only true low level erros (404, 403, server start/stop etc.) and occasionally internal server errors (500), which almost always are what I call production only runtime errors -- bugs that didn't strike during testing, due to smaller load or user interaction not anticipated in test runs... (yep, these things happen to me... ;), or simple syntax errors when testing new code.

    In those cases I normally don't need to know the exact request that caused the error -- since the erronous file and line number are logged, I normally find the error by looking at my code... ;)

    Any true application level errors are logged in my application's log, where they belong, IMHO.

    Spamming the log might help on a low-volume or single child server, but won't do during rapid fire "attacks" by your clients.

    I am not an expert in this, but it might be possible to write a mod_perl handler that intercepts error logging.

    I also think it's a good wishlist item for the apache project to have a request id/PID in all logfiles, and/or means of customizing the error log format. A combined access/error log would be fine too.

Re: Custom Apache ErrorLog Using mod_perl
by valdez (Monsignor) on Aug 29, 2002 at 10:32 UTC

    This is a known problem with mod_perl, and the only solution I've found around is in chapter 16 of mod_perl Developer's Cookbook that can be found online here.

    It is not exactly what you are looking for, but I hope it can be a good starting point.

    Ciao, Valerio
Re: Custom Apache ErrorLog Using mod_perl
by hagus (Monk) on Aug 29, 2002 at 03:56 UTC
    Is there any reason you couldn't contact the Apache group and see what the story is? I would either patch the ErrorLog behavior to match what I required, or see if someone has done / will do the same thing.

    Thinking right off the top of my head, I would envisage some key that is generated on each request. So if a 200 came in for page blah, and that generated a 500 error, both those messages would contain the same key, because conceptually they belong to the same HTTP 'session' for that particular page.

    Just thinking out loud ...

    --
    Ash OS durbatulk, ash OS gimbatul,
    Ash OS thrakatulk, agh burzum-ishi krimpatul!
    Uzg-Microsoft-ishi amal fauthut burguuli.

Re: Custom Apache ErrorLog Using mod_perl
by PodMaster (Abbot) on Aug 29, 2002 at 11:00 UTC
Re: Custom Apache ErrorLog Using mod_perl
by mp (Deacon) on Aug 29, 2002 at 20:24 UTC
    This idea is untested, but may meet your requirements:

    CGI::Carp overrides warn and die to get its messages into the error log. Try perldoc -m CGI::Carp for more details.

    $main::SIG{__WARN__}=\&CGI::Carp::warn; $main::SIG{__DIE__}=\&CGI::Carp::die; sub warn { #... } sub die { #... }

    You could customize your access logging as described in chapter 16 of the mod_perl cookbook, so that a unique key gets recorded in the access log for each request (a timestamp using Time::HiRes might be sufficient, if not, you can find some discussion about generating unique ids by going to the mod_perl mailing list archives and searching for the phrase"unique id").

    You can store this key into $r->pnotes, then override warn and die like CGI::Carp does and have those subroutines warn/die with the key added to the message. It looks like you could use CGI::Carp almost as-is, if you just rewrite the 'stamp' subroutine to pull the key out of $r->pnotes and possibly the IP address out of $r as well, then use all the rest of the CGI::Carp code.

    Then you would have a key in both the error log and the access log that you could match by.