Show Contents Previous Page Next Page
Chapter 10 - C API Reference Guide, Part I / Server Core Routines Error Logging At server startup time, Apache reopens the standard error file descriptor
to the ErrorLog file.4 If configured,
each virtual server can also have its own error log. Modules can write messages
to the error log in a simple way just by writing directly to standard error.
However, the simple way is less than desirable because it
leaves a bare string in the error log, with no indication
of the time or date that the error occurred or which module
left the message. Apache's error-logging API avoids these
problems by providing module writers with two functions, ap_log_rerror()
and ap_log_error(), both of which write nicely formatted
error messages to the error log. In addition to a timestamp
and a message, optional flags allow modules to include the
name and line number of the C source code file where the error
occurred as well as the contents of the system errno
variable. As of Version 1.3, Apache supports the notion of a message severity level.
In this scheme, which should be familiar to users of the Unix syslog
system,5 each message is assigned one of eight
severities that range from high (APLOG_EMERG ) to low (APLOG_DEBUG ).
A log level setting, set by the webmaster with the configuration directive LogLevel,
controls which messages actually get sent to the log file. For example, if LogLevel
is set to warn, only messages with severity APLOG_WARN
or higher will be written to the log file. Messages at a lower priority will
be ignored. This facility allows your module to write lots and lots of debugging
messages at a low severity level. During module development, you can set LogLevel
to a low level in order to see the debugging messages. Later you can raise the
log level so that the debugging messages are suppressed on the production server.
All logging constants and routines are declared in http_log.h:
void ap_log_error (const char *file, int line, int level, const server_rec
*s, const char *fmt, ...) void ap_log_rerror (const char *file, int line, int level, const request_rec
*r, const char *fmt, ...)
ap_log_rerror() and ap_log_error()
are the two main entry points for the Apache error log
API. These calls have many arguments, and C programmers
might want to define some macros in order to save keystrokes.
A couple of examples of this technique are given at the
end of this section. The first two arguments are the filename and line number
where the error occurred. Most modules will want to use
the APLOG_MARK macro here. It uses the C compiler
__FILE__ and __LINE__ tokens to
automatically pass this information. The third argument,
level, is the severity level at which to record
the message. level should be selected from the
list of symbolic constants given later. The severity level
is actually a bit mask; by setting other bits in the mask,
you can adjust other logging options, as we describe later.
The fourth argument is different for the two calls. For
ap_log_error(), it is the server_rec ,
ordinarily obtained from r->server . For
ap_log_rerror(), it is the request record
itself, r . Internally, the logging API uses
the server record to find the error log's FILE*
for writing, or it passes messages to the syslog()
function if native syslog support is enabled. The
fifth argument, fmt, is a sprintf()-style
format string. It, and the variable number of arguments
that follow it, are passed to sprintf() to generate
the message written to the log file.
if (!(fh = ap_pfopen(r->pool, cfg->config_file, "r"))) {
ap_log_error(APLOG_MARK, APLOG_EMERG, r->server,
"Cannot open configuration file %s.", cfg->config_file);
return HTTP_INTERNAL_SERVER_ERROR;
}
One difference between ap_log_error() and ap_log_rerror()
is that the latter function can optionally write the error
message to the notes table under a key named error-notes .
This message can then be retrieved and displayed by ErrorDocument
handlers and other error processors. The message is only written
to the notes table if the message severity level is warn
or higher, and there is not already an error-notes
entry in the notes table. Another difference is that ap_log_error()
includes the client's dotted IP address in the formatted error
message.
void ap_log_reason (const char *reason, const char *fname, request_rec
*r)
It is so common to encounter a system error while opening
a file or performing I/O on the system that a special routine
is provided in the API. ap_log_reason() takes a
character string describing the problem, the name of the
file that was involved in the error, and the current request
record. It is also common to use this function to log unsuccessful
attempts to access protected documents, since the remote
hos t's name is incorporated into the error message as well.
Here's a typical example of using ap_log_reason()
and the line that it writes to the log file.
ap_log_reason("Can't open index.html", r->uri, r);
[Tue Jul 21 16:30:47 1998] [error] access to /
failed for w15.yahoo.com, reason: Can't open index.html No such file
or directory
Internally, ap_log_reason() is just a frontend to
the following call:
ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
"access to %s failed for %s, reason: %s",
file,
ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME),
reason);
The level flag passed to ap_log_error()
and ap_log_rerror() should be one of the severity level
constants listed below, possibly logically ORed with either
of the constants APLOG_NOERRNO or APLOG_WIN32ERROR .
APLOG_NOERRNO
By default, the logging API will include the contents of
the system errno variable in the message. This
feature is sometimes useful, as when you log an error that
results from a failed system call, and sometimes not useful
at all (and may in fact lead to misleading messages since
errno is not reset by successful calls). Combine
the severity level with APLOG_NOERRNO to suppress
the automatic inclusion of errno .
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r,
"The requested URI was %s", r->uri);
APLOG_WIN32ERROR
This constant, available on Win32 platforms only, will
make Apache log the value returned by the GetLastError()
system call in addition to the value of errno
from the standard C library.
APLOG_EMERG
This severity level indicates that an emergency condition
has occurred. It should be reserved for problems that render
the server unusable.
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, r->server,
"Cannot find lock file. Aborting.");
APLOG_ALERT
This level is intended for problems that require immediate
attention.
APLOG_CRIT
This logs messages at a level intended for severe problems
that require immediate attention.
APLOG_ERR
This logs the message at the error severity level,
intended for use with noncritical errors that nevertheless
require someone's attention.
ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
"Could not open file", r->filename);
APLOG_WARN
The warn level is one step less severe than error
and is intended for warnings that may or may not require attention.
APLOG_NOTICE
notice messages are used for normal but significant
conditions.
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r->server,
"Cannot connect to master database, using backup.");
APLOG_INFO
The info severity level is used for informational
messages issued for nonerror conditions.
APLOG_DEBUG
The lowest severity of all is debug, used for
issuing messages during the development and debugging of a
module.
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
"Filename=%s,uri=%s,mtime=%d,",
r->filename, r->uri, r->finfo.mtime);
If the ap_log_rerror() and ap_log_error()
calls are too verbose for your tastes, we recommend that you
create a few preprocessor macros for frequently used combinations.
For example:
#define my_error(mess) ap_log_error(APLOG_MARK,\
APLOG_NOERRNO|APLOG_ERROR,\
r->server, mess)
#define my_debug(mess) ap_log_error(APLOG_MARK,\
APLOG_NOERRNO|APLOG_DEBUG,\
r->server, mess)
Now you can log simple error messages this way: my_error("Can't find lock file. Aborting.");
Show Contents Previous Page Next Page Copyright © 1999 by O'Reilly & Associates, Inc. |