You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Randy Terbush <ra...@zyzzyva.com> on 1997/07/27 20:20:21 UTC
[PATCH] loglevels final?
Below is what I feel makes the most sense toward implementing
logging verbosity control.
Reasoning:
Much of what gets logged as errors by Apache is information that
seems to generate more questions by users of a server hosting
service than enlightenment of problems. It would be nice to have
features such as these that allows tuning of the level of verbosity.
Features:
These changes enable syslog() logging of errors through another
parameter to the ErrorLog directive.
ErrorLog syslog # enables logging to syslog via LOCAL7 facility
ErrorLog syslog:daemon # allows setting of any other valid facility
Default logging level can be selected with the directive LogLevel.
LogLevel accepts a single parameter, one of:
emerg, alert, crit, error, warn, notice, info, debug.
These levels mirror the syslog counterparts.
After struggling to find a level/mask solution that would work, I
have reverted back to the single hierarchy that I originally
submitted. The reasons being that I think this part of the server
needs to stay relatively simple. It also becomes tricky to convert
to sane values for priority in syslog. My keeping levels in sync
with syslog standards, it makes it much easier to integrate Apache
error logging into existing system monitoring. As pointed out by
others, if you need to filter the log output, grep works just fine.
Lastly, I have tried to maintain the existing output format for
errors logged, but I would also like to lobby for a revamping of
error_log format to something that a) makes it easier to filter
certain levels of logging priority, and b) makes the errors logged
more consistent looking.
Perhaps something like:
[time] [level] errormessage
At higher verbosity levels:
[time] [level] errno: strerror(): routine: errormessage
And in request context:
[time] [level] host: request: errormessage
This patch only adds one example use of aplog_error() in
http_core.c and converts existing logging routines to wrappers for
aplog_error(). Converting existing use of log_* would be the next
phase of this change.
Index: http_core.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_core.c,v
retrieving revision 1.100
diff -u -3 -r1.100 http_core.c
--- http_core.c 1997/07/24 04:38:09 1.100
+++ http_core.c 1997/07/27 18:17:30
@@ -107,6 +107,8 @@
conf->limit_nproc = NULL;
#endif
+ conf->loglevel = DEFAULT_LOGLEVEL;
+
conf->sec = make_array (a, 2, sizeof(void *));
return (void *)conf;
@@ -1196,6 +1198,35 @@
return NULL;
}
+const char *set_loglevel (cmd_parms *cmd, core_dir_config *conf, const char *arg)
+{
+ char *str;
+
+ if ((str = getword_conf(cmd->pool, &arg))) {
+ if (!strcasecmp(str, "emerg"))
+ conf->loglevel = APLOG_EMERG;
+ else if (!strcasecmp(str, "alert"))
+ conf->loglevel = APLOG_ALERT;
+ else if (!strcasecmp(str, "crit"))
+ conf->loglevel = APLOG_CRIT;
+ else if (!strcasecmp(str, "error"))
+ conf->loglevel = APLOG_ERR;
+ else if (!strcasecmp(str, "warn"))
+ conf->loglevel = APLOG_WARNING;
+ else if (!strcasecmp(str, "notice"))
+ conf->loglevel = APLOG_NOTICE;
+ else if (!strcasecmp(str, "info"))
+ conf->loglevel = APLOG_INFO;
+ else if (!strcasecmp(str, "debug"))
+ conf->loglevel = APLOG_DEBUG;
+ }
+ else
+ return "LogLevel requires level keyword";
+
+ return NULL;
+}
+
+
/* Note --- ErrorDocument will now work from .htaccess files.
* The AllowOverride of Fileinfo allows webmasters to turn it off
*/
@@ -1320,6 +1351,7 @@
{ "ThreadsPerChild", set_threads, NULL, RSRC_CONF, TAKE1, "Number of threads a child creates" },
{ "ExcessRequestsPerChild", set_excess_requests, NULL, RSRC_CONF, TAKE1, "Maximum number of requests a particular child serves after it is ready to die." },
{ "ListenBacklog", set_listenbacklog, NULL, RSRC_CONF, TAKE1, "maximum length of the queue of pending connections, as used by listen(2)" },
+{ "LogLevel", set_loglevel, (void*)XtOffsetOf(core_dir_config, loglevel), OR_ALL, TAKE1, "set level of verbosity in error logging" },
{ NULL },
};
@@ -1386,9 +1418,9 @@
if (r->method_number == M_PUT) return METHOD_NOT_ALLOWED;
if (r->finfo.st_mode == 0 || (r->path_info && *r->path_info)) {
- log_reason("File does not exist",
- r->path_info ? pstrcat(r->pool, r->filename, r->path_info, NULL)
- : r->filename, r);
+ aplog_error(APLOG_INFO, r, NULL,
+ r->path_info ? pstrcat(r->pool, r->filename, r->path_info, NULL)
+ : r->filename, "File does not exist");
return NOT_FOUND;
}
if (r->method_number != M_GET) return METHOD_NOT_ALLOWED;
Index: http_core.h
===================================================================
RCS file: /export/home/cvs/apache/src/http_core.h,v
retrieving revision 1.24
diff -u -3 -r1.24 http_core.h
--- http_core.h 1997/07/16 00:41:21 1.24
+++ http_core.h 1997/07/27 18:17:32
@@ -179,6 +179,9 @@
struct rlimit *limit_nproc;
#endif
+ /* logging options */
+ int loglevel;
+
/* Access control */
array_header *sec;
regex_t *r;
Index: http_log.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_log.c,v
retrieving revision 1.21
diff -u -3 -r1.21 http_log.c
--- http_log.c 1997/07/21 05:53:43 1.21
+++ http_log.c 1997/07/27 18:17:34
@@ -58,12 +58,15 @@
*/
+
+#define CORE_PRIVATE
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include <stdarg.h>
+#include <syslog.h>
static int
error_log_child (void *cmd)
@@ -92,29 +95,47 @@
return(child_pid);
}
-void open_error_log(server_rec *s, pool *p)
+void open_error_log (server_rec *s, pool *p)
{
char *fname;
-
- fname = server_root_relative (p, s->error_fname);
+ register CODE *c;
+
if (*s->error_fname == '|') {
- FILE *dummy;
+ FILE *dummy;
- if (!spawn_child (p, error_log_child, (void *)(s->error_fname+1),
- kill_after_timeout, &dummy, NULL)) {
- perror ("spawn_child");
- fprintf (stderr, "Couldn't fork child for ErrorLog process\n");
- exit (1);
- }
+ if (!spawn_child (p, error_log_child, (void *)(s->error_fname+1),
+ kill_after_timeout, &dummy, NULL)) {
+ perror ("spawn_child");
+ fprintf (stderr, "Couldn't fork child for ErrorLog process\n");
+ exit (1);
+ }
- s->error_log = dummy;
- } else {
+ s->error_log = dummy;
+ }
+ else if (!strncasecmp(s->error_fname, "syslog", 6)) {
+ if ((fname = strchr(s->error_fname, ':'))) {
+ fname++;
+ for (c = facilitynames; c->c_name; c++) {
+ if (!strcasecmp(fname, c->c_name)) {
+ openlog("httpd", LOG_NDELAY|LOG_CONS|LOG_PID, c->c_val);
+ s->error_log = NULL;
+ return;
+ }
+ }
+ }
+ else
+ openlog("httpd", LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
+
+ s->error_log = NULL;
+ }
+ else {
+ fname = server_root_relative (p, s->error_fname);
if(!(s->error_log = pfopen(p, fname, "a"))) {
perror("fopen");
fprintf(stderr,"httpd: could not open error log file %s.\n", fname);
exit(1);
- }
+ }
}
}
@@ -139,12 +160,90 @@
}
}
-API_EXPORT(void) error_log2stderr(server_rec *s) {
+API_EXPORT(void) error_log2stderr (server_rec *s) {
if(fileno(s->error_log) != STDERR_FILENO)
dup2(fileno(s->error_log),STDERR_FILENO);
}
-void log_pid(pool *p, char *pid_fname) {
+API_EXPORT(void) aplog_error (int level, const request_rec *r, const char *routine,
+ const char *file, const char *fmt, ...)
+{
+ core_dir_config *conf;
+ va_list args;
+ const char *timestamp = NULL;
+ char errstr[MAX_STRING_LEN];
+
+
+ if (r != NULL) { /* backward compatibilty for historic loging functions */
+ conf = get_module_config(r->per_dir_config, &core_module);
+
+ if (level > conf->loglevel)
+ return;
+ }
+
+ /* NULL if we are logging to syslog */
+ if (r->server->error_log) timestamp = get_time();
+
+ switch (level) {
+ case APLOG_EMERG:
+ case APLOG_DEBUG:
+ case APLOG_CRIT:
+ case APLOG_ALERT:
+ /* these levels provide the same logging format as log_unixerr() did */
+ if (file != NULL)
+ if (timestamp)
+ ap_snprintf(errstr, sizeof(errstr), "[%s] %s: %s: %s",
+ timestamp, routine, file, strerror(errno));
+ else
+ ap_snprintf(errstr, sizeof(errstr), "%s: %s: %s",
+ routine, file, strerror(errno));
+
+ else
+ if (timestamp)
+ ap_snprintf(errstr, sizeof(errstr), "[%s] %s: %s",
+ timestamp, routine, strerror(errno));
+ else
+ ap_snprintf(errstr, sizeof(errstr), "%s: %s",
+ routine, strerror(errno));
+ break;
+ case APLOG_INFO:
+ /* this level provides same logging format as log_reason() did */
+ if (timestamp)
+ ap_snprintf(errstr, sizeof(errstr),
+ "[%s] access to %s failed for %s, reason: ", timestamp, file,
+ get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME));
+ else
+ ap_snprintf(errstr, sizeof(errstr),
+ "access to %s failed for %s, reason: ", file,
+ get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME));
+ break;
+ case APLOG_ERR:
+ case APLOG_WARNING:
+ case APLOG_NOTICE:
+ /* these levels provide same logging format as log_error() did */
+ if (timestamp)
+ ap_snprintf(errstr, sizeof(errstr), "[%s]", timestamp);
+ break;
+ }
+
+ va_start(args, fmt);
+
+ if (timestamp) { /* timestamp means we are logging to file */
+ fprintf(r->server->error_log, "%s", errstr);
+ vfprintf(r->server->error_log, fmt, args);
+ fflush(r->server->error_log);
+ }
+ else {
+ if (errstr)
+ syslog(level, "%s", errstr);
+
+ vsyslog(level, fmt, args);
+ }
+
+ va_end(args);
+}
+
+void log_pid (pool *p, char *pid_fname) {
FILE *pid_file;
if (!pid_fname) return;
@@ -158,50 +257,29 @@
fclose(pid_file);
}
-API_EXPORT(void) log_error(const char *err, server_rec *s) {
- fprintf(s->error_log, "[%s] %s\n",get_time(),err);
- fflush(s->error_log);
+API_EXPORT(void) log_error (const char *err, server_rec *s)
+{
+ aplog_error(APLOG_ERR, NULL, NULL, NULL, "%s\n", err);
}
-API_EXPORT(void) log_unixerr(const char *routine, const char *file,
- const char *msg, server_rec *s)
+API_EXPORT(void) log_unixerr (const char *routine, const char *file,
+ const char *msg, server_rec *s)
{
- const char *p, *q;
- FILE *err=s ? s->error_log : stderr;
-
- p = strerror(errno);
- q = get_time();
-
- if (file != NULL)
- fprintf(err, "[%s] %s: %s: %s\n", q, routine, file, p);
- else
- fprintf(err, "[%s] %s: %s\n", q, routine, p);
- if (msg != NULL) fprintf(s->error_log, "[%s] - %s\n", q, msg);
-
- fflush(err);
+ aplog_error(APLOG_CRIT, NULL, routine, file, msg);
}
-API_EXPORT(void) log_printf(const server_rec *s, const char *fmt, ...)
+API_EXPORT(void) log_printf (const server_rec *s, const char *fmt, ...)
{
va_list args;
- fprintf(s->error_log, "[%s] ", get_time());
va_start (args, fmt);
- vfprintf (s->error_log, fmt, args);
+ aplog_error(APLOG_ERR, NULL, NULL, NULL, fmt, args);
va_end (args);
-
- fputc('\n', s->error_log);
- fflush(s->error_log);
}
-API_EXPORT(void) log_reason(const char *reason, const char *file, request_rec *r)
+API_EXPORT(void) log_reason (const char *reason, const char *file, request_rec *r)
{
- fprintf (r->server->error_log,
- "[%s] access to %s failed for %s, reason: %s\n",
- get_time(), file,
- get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME),
- reason);
- fflush (r->server->error_log);
+ aplog_error(APLOG_INFO, r, NULL, file, reason);
}
API_EXPORT(void) log_assert(const char *szExp, const char *szFile, int nLine)
Index: http_log.h
===================================================================
RCS file: /export/home/cvs/apache/src/http_log.h,v
retrieving revision 1.10
diff -u -3 -r1.10 http_log.h
--- http_log.h 1997/07/21 05:53:43 1.10
+++ http_log.h 1997/07/27 18:17:34
@@ -50,7 +50,21 @@
*
*/
+#define SYSLOG_NAMES
+#define APLOG_EMERG 0 /* system is unusable */
+#define APLOG_ALERT 1 /* action must be taken immediately */
+#define APLOG_CRIT 2 /* critical conditions */
+#define APLOG_ERR 3 /* error conditions */
+#define APLOG_WARNING 4 /* warning conditions */
+#define APLOG_NOTICE 5 /* normal but significant condition */
+#define APLOG_INFO 6 /* informational */
+#define APLOG_DEBUG 7 /* debug-level messages */
+#define DEFAULT_LOGLEVEL APLOG_ERR
+
+
void open_logs (server_rec *, pool *p);
+API_EXPORT(void) aplog_error(int level, const request_rec *r, const char *routine,
+ const char *file, const char *fmt, ...);
API_EXPORT(void) error_log2stderr (server_rec *);
void log_pid (pool *p, char *fname);
@@ -60,4 +74,5 @@
API_EXPORT(void) log_printf(const server_rec *s, const char *fmt, ...);
API_EXPORT(void) log_reason(const char *reason, const char *fname,
request_rec *r);
+
Re: [PATCH] loglevels final?
Posted by Dean Gaudet <dg...@arctic.org>.
While I'm much happier with this approach (I too want it to be simple, and
syslog-style levels are just fine with me) you didn't address one of my
earlier complaints.
On Sun, 27 Jul 1997, Randy Terbush wrote:
> -void log_pid(pool *p, char *pid_fname) {
> +API_EXPORT(void) aplog_error (int level, const request_rec *r, const char *routine,
> + const char *file, const char *fmt, ...)
> +{
I think that the prototype should be:
API_EXPORT(void) aplog_error (int level, const request_rec *r,
const char *fmt, ...);
one of the reasons is this code:
> + if (timestamp) { /* timestamp means we are logging to file */
> + fprintf(r->server->error_log, "%s", errstr);
> + vfprintf(r->server->error_log, fmt, args);
> + fflush(r->server->error_log);
> + }
> + else {
> + if (errstr)
> + syslog(level, "%s", errstr);
> +
> + vsyslog(level, fmt, args);
> + }
Is not atomic for the syslog.
I also feel that "routine" and "file" are very vague, and don't apply to
all situations.
BTW you should probably also implement:
API_EXPORT(void) aplog_verror (int level, const request_rec *r,
va_list args);
Dean