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"; log "Just for logging: We're here.\n"; trace "detail=", $detail, "\n";
carpout \*ERRFILE; debugout \*DEBUGFILE; logout \*LOGFILE;
is_STDOUT \*ERRFILE is_STDERR \*LOGFILE is_STDBUG \*LOGFILE is_STDLOG \*ERRFILE
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.
A new method to generate messages on the new STDLOG stream is log()
. Calls to log()
will write out the same nicely time-, process-, program-, and
stream-stamped messages described above to both the STDLOG and the STDBUG
streams.
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()
.
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.
The carpout()
method is provided for this purpose.
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).
The logout()
method is provided for this purpose.
The debugout()
method is provided for this purpose.
carpout()
, logout()
, 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 { 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 STDERR stream: warn() and die() The STDLOG stream: log() 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: logout() 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()
is_STDOUT() is_STDERR() is_STDBUG() is_STDLOG()
Each is explained in its own section below.
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.
Currently two levels are defined: 0 - No messages are output on the STDLOG
stream. 1 - log()
messages are output on the STDLOG stream.
It is recommended to use the LOGLEVEL method to get/set this value.
carpout(),
debugout(),
and logout()
do not handle file locking for you at this point.
mak - Michael King (mike808@mo.net), Net Effects
Based heavily on CGI::Carp by Lincoln D. Stein (lstein@genome.wi.mit.edu).
LogCarp.pm v1.1 09/15/97 09:04:00 mak
Copyright (C) 1997 Michael King Ballwin, MO USA. All rights reserved.
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.
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.
NOTE:
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.
warn()
. The message is sent to the STDERR, STDLOG, and STDBUG streams.
die()
. The message is sent to the STDERR, STDLOG, and STDBUG streams.
Carp::carp()
. The message is sent to the STDERR, STDLOG, and STDBUG streams.
Carp::croak()
. The message is sent to the STDERR, STDLOG, and STDBUG streams.
Carp::confess()
. The message is sent to the STDERR, STDLOG, and STDBUG streams.
warn()
method. The message is sent to the STDLOG and STDBUG streams.
warn()
method. The message is sent to the STDBUG stream when DEBUGLEVEL > 0.
warn()
method. The message is sent to the STDBUG stream when DEBUGLEVEL is greater
than one.
See the section on REDIRECTING ERROR MESSAGES and the section on REDIRECTING MESSAGES IN GENERAL.
See the section on REDIRECTING ERROR MESSAGES and the section on REDIRECTING MESSAGES IN GENERAL.
See the section on REDIRECTING ERROR MESSAGES and the section on REDIRECTING MESSAGES IN GENERAL.
This method is not exported by default.
This method is not exported by default.
This method is not exported by default.
This method is not exported by default.
warn()
method, actually producing the message on the STDERR stream. Locking is
performed to ensure exclusive access while appending.
This method is not exportable.
die()
method, actually producing the message on the STDERR stream and then
terminating execution. Locking is performed to ensure exclusive access
while appending.
This method is not exportable.
log()
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 method is not exportable.
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 method is not exportable.
This method is not exportable.
This method is not exportable.
This method is not exportable.
flock()
, based upon the operating system flock(2)
function. See the manual page for flock(2)
for your system-specific values.
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.
seek()
, based upon the operating system flock(2)
function. See the manual page for flock(2)
for your system-specific values.
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
NOTE: YMMV.
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.
This method is not exportable.
flock()
to release any exclusive lock on the stream specified by FILEHANDLE. An
unlock is only attempted on actual files that are writeable.
This method is not exportable.