LogCarp - Error, log and debug streams, httpd style format
LogCarp redefines the STDERR stream and the defines the STDBUG and STDLOG streams in such a way that all messages are formatted similar to an HTTPD error log. Methods are defined for directing messages to the STDBUG and STDLOG streams. Each stream can be directed to its own location independent of the others.
use LogCarp; print "LogCarp version: ", LogCarp::VERSION; DEBUGLEVEL 2; croak "We're outta here!"; confess "It was my fault: $!"; carp "It was your fault!"; warn "I'm confused"; die "I'm dying.\n"; debug "Just for debugging: somevar=", $somevar, "\n"; logmsg "Just for logging: We're here.\n"; trace "detail=", $detail, "\n"; carpout \*ERRFILE; debugout \*DEBUGFILE; logmsgout \*LOGFILE; is_STDOUT \*ERRFILE is_STDERR \*LOGFILE is_STDBUG \*LOGFILE is_STDLOG \*ERRFILE
LogCarp.pm is a Perl5 package defining methods for directing the existing STDERR stream as well as creating and directing two new messaging streams, STDBUG and STDLOG.
Their use was intended mainly for a CGI development environment, or where separate facilities for errors, logging, and debugging output are needed.
This is because CGI scripts have a nasty habit of leaving warning messages in the error logs that are neither time stamped nor fully identified. Tracking down the script that caused the error is a pain. This fixes that. Replace the usual
use Carp;
with
use LogCarp;
And the standard warn(), die(), croak(), confess() and carp() calls will automagically be replaced with methods that write out nicely time-, process-, program-, and stream-stamped messages to the STDERR, STDLOG, and STDBUG streams.
warn()
die()
croak()
confess()
carp()
A new method to generate messages on the new STDLOG stream is logmsg(). Calls to logmsg() will write out the same nicely time-, process-, program-, and stream-stamped messages described above to both the STDLOG and the STDBUG streams.
logmsg()
Messages on multiple streams directed to the same location do not receive multiple copies.
New methods to generate messages on the new STDBUG stream are debug() and trace().
debug()
trace()
In addition, the process number (represented below as $$) and the stream on which the message appears is displayed to disambiguate multiple simultaneous executions as well as multiple streams directed to the same location.
For example:
[Mon Sep 15 09:04:55 1997] $$ test.pl ERR: I'm confused at test.pl line 3. [Mon Sep 15 09:04:55 1997] $$ test.pl BUG: answer=42. [Mon Sep 15 09:04:55 1997] $$ test.pl LOG: I did something. [Mon Sep 15 09:04:55 1997] $$ test.pl ERR: Got a warning: Permission denied. [Mon Sep 15 09:04:55 1997] $$ test.pl ERR: I'm dying.
By default, error messages are sent to STDERR. Most HTTPD servers direct STDERR to the server's error log. Some applications may wish to keep private error logs, distinct from the server's error log, or they may wish to direct error messages to STDOUT so that the browser will receive them (for debugging, not for public consumption).
The carpout() method is provided for this purpose.
carpout()
For CGI programs that need to send something to the HTTPD server's real error log, the original STDERR stream has not been closed, it has been saved as _STDERR. The reason for this is twofold.
The first is that your CGI application might really need to write something to the server's error log, unrelated to your own error log. To do so, simply write directly to the _STDERR stream.
The second is that some servers, when dealing with CGI scripts, close their connection to the browser when the script closes either STDOUT or STDERR.
Saving the program's initial STDERR in _STDERR is used to prevent this from happening prematurely.
Do not manipulate the _STDERR filehandle in any other way other than writing to it. For CGI applications, the serverwarn() method formats and sends your message to the HTTPD error log (on the _STDERR stream).
serverwarn()
A new stream, STDLOG, has been defined for log messages. By default, STDLOG is routed to STDERR. Most HTTPD servers direct STDERR (and thus the default STDLOG also) to the server's error log. Some applications may wish to keep private activity logs, distinct from the server's log, or they may wish to direct log messages to STDOUT so that the browser will receive them (for debugging, not for public consumption).
The logmsgout() method is provided for this purpose.
logmsgout()
A new stream, STDBUG, has been defined for debugging messages. Since this stream is for producing debugging output, the default STDBUG is routed to STDOUT. Some applications may wish to keep private debug logs, distinct from the application output, or CGI applications may wish to leave debug messages directed to STDOUT so that the browser will receive them (only when debugging). Your program may also control the output by manipulating DEBUGLEVEL in the application.
The debugout() method is provided for this purpose.
debugout()
Each of these methods, carpout(), logmsgout(), and debugout(), requires one argument, which should be a reference to an open filehandle for writing. It should be called in a BEGIN block at the top of the application so that compiler errors will be caught. Example:
BEGIN
BEGIN { use LogCarp; open \*LOG, ">>/usr/local/cgi-logs/mycgi-log" or die "Unable to open mycgi-log: $!\n"; carpout \*LOG; }
NOTE: carpout() does handle file locking on systems that support flock so multiple simultaneous CGIs are not an issue.
If you want to send errors to the browser, give carpout() a reference to STDOUT:
BEGIN { use LogCarp; carpout \*STDOUT; }
If you do this, be sure to send a Content-Type header immediately -- perhaps even within the BEGIN block -- to prevent server errors.
You can pass filehandles to carpout() in a variety of ways. The "correct" way according to Tom Christiansen is to pass a reference to a filehandle GLOB:
carpout \*LOG;
This looks weird to mere mortals however, so the following syntaxes are accepted as well:
carpout(LOG); carpout(\LOG); carpout('LOG'); carpout(\'LOG'); carpout(main::LOG); carpout('main::LOG'); carpout(\'main::LOG'); ... and so on
Use of carpout() is not great for performance, so it is recommended for debugging purposes or for moderate-use applications. A future version of this module may delay redirecting STDERR until one of the LogCarp methods is called to prevent the performance hit.
The following methods are for generating a message on the respective stream:
The STDERR stream: warn() and die() The STDLOG stream: logmsg() The STDBUG stream: debug() and trace()
The following methods are for generating a message on the respective stream, but will indicate the message location from the caller's perspective. See the standard Carp.pm module for details.
The STDERR stream: carp(), croak() and confess()
The following methods are for manipulating the respective stream:
The STDERR stream: carpout() The STDLOG stream: logmsgout() The STDBUG stream: debugout()
The following methods are for manipulating the amount (or level) of output filtering on the respective stream:
The STDBUG stream: DEBUGLEVEL() The STDLOG stream: LOGLEVEL()
The following methods are for comparing a filehandle to the respective stream:
is_STDOUT() is_STDERR() is_STDBUG() is_STDLOG()
Each is explained in its own section below.
No variables are exported into the caller's namespace.
A number indicating the level of debugging output that is to occur. At each increase in level, additional debugging output is allowed.
Currently three levels are defined: 0 - No messages are output on the STDBUG stream. 1 - debug() messages are output on the STDBUG stream. 2 - debug() and trace() messages are output on the STDBUG stream.
It is recommended to use the DEBUGLEVEL method to get/set this value.
A number indicating the level of logging output that is to occur. At each increase in level, additional logging output is allowed.
Currently two levels are defined: 0 - No messages are output on the STDLOG stream. 1 - logmsg() messages are output on the STDLOG stream.
It is recommended to use the LOGLEVEL method to get/set this value.
The value returned by executing the package is 1 (or true).
carpout(), debugout(), and logmsgout() do not handle file locking for you at this point.
Check out what's left in the TODO file.
Carp, CGI::Carp
Based heavily on CGI::Carp by Lincoln D. Stein (lstein@genome.wi.mit.edu).
mak - Michael King (mike808@mo.net)
LogCarp.pm v1.01 09/15/97 09:04:00 mak v1.02 01/04/98 19:03:25 mak v1.03 01/04/98 19:03:25 mak v1.04 01/06/98 20:52:19 mak
Copyright (C) 1997,1998 Michael King (mike808@mo.net) Fenton, MO USA. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
This module is copyright (c) 1997,1998 by Michael King (mike808@mo.net) and is made available to the Perl public under terms of the Artistic License used to cover Perl itself. See the file Artistic in the distribution of Perl 5.002 or later for details of copy and distribution terms.
The latest version of this module is likely to be available from:
http://walden.mo.net/~mike808/LogCarp
The best place to discuss this code is via email with the author.
DEBUGLEVEL is a normal get/set method.
When the scalar argument LEVEL is present, the DEBUGLEVEL will be set to LEVEL. LEVEL is expected to be numeric, with the following case-insensitive character-valued translations:
NO, FALSE, and OFF all equate to a value of 0 (ZERO). YES, TRUE, and ON all equate to a value of 1 (ONE). TRACE or TRACING equate to a value of 2 (TWO). Values in scientific notation equate to their numeric equivalent.
NOTE:
All other character values of LEVEL equate to 0 (ZERO). This will have the effect of turning off debug output.
After this translation to a numeric value is performed, the DEBUGLEVEL is set to LEVEL.
Whenever the DEBUGLEVEL is set to a non-zero value (i.e. ON or TRACE), the LOGLEVEL will be also set to 1 (ONE).
The value of DEBUGLEVEL is then returned to the caller, whether or not LEVEL is present.
LOGLEVEL is a normal get/set method.
When the scalar argument LEVEL is present, the LOGLEVEL will be set to LEVEL. LEVEL is expected to be numeric, with the following case-insensitive character-valued translations:
NO, FALSE, and OFF all equate to a value of 0 (ZERO). YES, TRUE, and ON all equate to a value of 1 (ONE). Values in scientific notation equate to their numeric equivalent.
All other character values of LEVEL equate to 0 (ZERO). This will have the effect of turning off log output.
After this translation to a numeric value is performed, the LOGLEVEL is set to LEVEL.
The value of LOGLEVEL is then returned to the caller, whether or not LEVEL is present.
This method is a replacement for Perl's builtin warn(). The message is sent to the STDERR, STDLOG, and STDBUG streams.
This method is a replacement for Perl's builtin die(). The message is sent to the STDERR, STDLOG, and STDBUG streams.
This method is a replacement for Carp::carp(). The message is sent to the STDERR, STDLOG, and STDBUG streams.
Carp::carp()
This method is a replacement for Carp::croak(). The message is sent to the STDERR, STDLOG, and STDBUG streams.
Carp::croak()
This method is a replacement for Carp::confess(). The message is sent to the STDERR, STDLOG, and STDBUG streams.
Carp::confess()
This method operates similarly to the warn() method. The message is sent to the STDLOG and STDBUG streams.
This method operates similarly to the warn() method. The message is sent to the STDBUG stream when DEBUGLEVEL > 0.
This method operates similarly to the warn() method. The message is sent to the STDBUG stream when DEBUGLEVEL is greater than one.
A method to redirect the STDERR stream to the given FILEHANDLE. It accepts FILEHANDLE as a reference or a string.
See the section on REDIRECTING ERROR MESSAGES and the section on REDIRECTING MESSAGES IN GENERAL.
A method to redirect the STDLOG stream to the given FILEHANDLE. It accepts FILEHANDLE as a reference or a string.
A method to redirect the STDBUG stream to the given FILEHANDLE. It accepts FILEHANDLE as a reference or a string.
This method compares FILEHANDLE with the STDOUT stream and returns the boolean result.
This method is not exported by default.
This method compares FILEHANDLE with the STDERR stream and returns the boolean result.
This method compares FILEHANDLE with the STDBUG stream and returns the boolean result.
This method compares FILEHANDLE with the STDLOG stream and returns the boolean result.
This private method encapsulates Perl's underlying warn() method, actually producing the message on the STDERR stream. Locking is performed to ensure exclusive access while appending.
This method is not exportable.
This private method encapsulates Perl's underlying die() method, actually producing the message on the STDERR stream and then terminating execution. Locking is performed to ensure exclusive access while appending.
This private method synthesizes an underlying logmsg() method, actually producing the message on the STDLOG stream. Locking is performed to ensure exclusive access while appending. The message will only be sent when LOGLEVEL is greater than zero.
This private method synthesizes an underlying debug() method, actually producing the message on the STDBUG stream. Locking is performed to ensure exclusive access while appending. The message will only be sent when DEBUGLEVEL is greater than zero.
This private method returns the file, line, and basename of the currently executing function.
A private method to construct a normalized timestamp prefix for a message.
This private method compares two FILEHANDLE streams to each other and returns the boolean result.
Note: This function is probably not portable to non-Unix-based operating systems (i.e. NT, VMS, etc.).
Some private methods encapsulating the implementation-defined values for the OPERATION parameter of the Perl builtin flock(), based upon the operating system flock(2) function. See the manual page for flock(2) for your system-specific values.
flock()
flock(2)
The as-defined-here values for the flock() OPERATION parameter are:
LOCK_SH = 1 - Shared lock LOCK_EX = 2 - Exclusive lock LOCK_NB = 4 - Non-blocking lock LOCK_UN = 8 - Unlock
NOTE: YMMV.
Some private methods encapsulating the implementation-defined values for the WHENCE parameter of the Perl builtin seek(), based upon the operating system flock(2) function. See the manual page for flock(2) for your system-specific values.
seek()
The as-defined-here values for the seek() WHENCE parameter are:
SEEK_BOF = 0 - Beginning of the file SEEK_CUR = 1 - Current location in the file SEEK_BOF = 2 - End of the file
A private method that uses Perl's builtin flock() and seek() to obtain an exclusive lock on the stream specified by FILEHANDLE. A lock is only attempted on actual files that are writeable.
A private method that uses Perl's builtin flock() to release any exclusive lock on the stream specified by FILEHANDLE. An unlock is only attempted on actual files that are writeable.
To install LogCarp, copy and paste the appropriate command in to your terminal.
cpanm
cpanm LogCarp
CPAN shell
perl -MCPAN -e shell install LogCarp
For more information on module installation, please visit the detailed CPAN module installation guide.