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/28 02:37:45 UTC

Re: [PATCH] loglevels final: take2

Below is the latest version incorporating some of the suggested 
changes, and my preferred log format. The changes below do not 
preserve existing logging format, but do make the output somewhat 
more consistant. System info is logged on the first line, supplied 
error string on the second. These examples are from syslog, thus 
the host, process id, etc. Output levels are tunable by configured  
LogLevel.


Example at 'debug' level:

Jul 27 19:12:41 sierra httpd[16183]: [error] 2: No such file or directory: http_core.c: 1421: 
Jul 27 19:12:41 sierra httpd[16183]: file does not exist: /usr/local/etc/httpd/docs/foo

At middle levels:
Jul 27 19:12:41 sierra httpd[16183]: [error] 2: No such file or directory
Jul 27 19:12:41 sierra httpd[16183]: file does not exist: /usr/local/etc/httpd/docs/foo

And at lowest levels:
Jul 27 19:12:41 sierra httpd[16183]: [error]
Jul 27 19:12:41 sierra httpd[16183]: file does not exist: /usr/local/etc/httpd/docs/foo


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/28 00:24:38
@@ -58,12 +58,51 @@
  */
 
 
+
+#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 TRANS facilities[] = {
+    {"auth",	LOG_AUTH},
+    {"authpriv",LOG_AUTHPRIV},
+    {"cron", 	LOG_CRON},
+    {"daemon",	LOG_DAEMON},
+    {"ftp",	LOG_FTP},
+    {"kern",	LOG_KERN},
+    {"lpr",	LOG_LPR},
+    {"mail",	LOG_MAIL},
+    {"news",	LOG_NEWS},
+    {"syslog",	LOG_SYSLOG},
+    {"user",	LOG_USER},
+    {"uucp",	LOG_UUCP},
+    {"local0",	LOG_LOCAL0},
+    {"local1",	LOG_LOCAL1},
+    {"local2",	LOG_LOCAL2},
+    {"local3",	LOG_LOCAL3},
+    {"local4",	LOG_LOCAL4},
+    {"local5",	LOG_LOCAL5},
+    {"local6",	LOG_LOCAL6},
+    {"local7",	LOG_LOCAL7},
+    {NULL,		-1},
+};
+
+static TRANS priorities[] = {
+    {"emerg",	APLOG_EMERG},
+    {"alert",	APLOG_ALERT},
+    {"crit",	APLOG_CRIT},
+    {"error",	APLOG_ERR},
+    {"warn",	APLOG_WARNING},
+    {"notice",	APLOG_NOTICE},
+    {"info",	APLOG_INFO},
+    {"debug",	APLOG_DEBUG},
+    {NULL,	-1},
+};
 
 static int
 error_log_child (void *cmd)
@@ -92,29 +131,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 TRANS *fac;
+    
 
     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 (fac = facilities; fac->t_name; fac++) {
+		if (!strcasecmp(fname, fac->t_name)) {
+		    openlog("httpd", LOG_NDELAY|LOG_CONS|LOG_PID, fac->t_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 +196,71 @@
     }
 }
 
-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_verror (int level, const request_rec *r, va_list args)
+{
+}
+
+API_EXPORT(void) aplog_error (const char *file, int line, int level,
+			      const request_rec *r, const char *fmt, ...)
+{
+    core_dir_config *conf;
+    va_list args;
+    char errstr[MAX_STRING_LEN];
+    static TRANS *pname = priorities;
+    
+
+    if (r != NULL) { /* backward compatibilty for historic logging functions */
+	conf = get_module_config(r->per_dir_config, &core_module);
+
+	if (level > conf->loglevel)
+	    return;
+
+	switch (conf->loglevel) {
+	case APLOG_DEBUG:
+	    ap_snprintf(errstr, sizeof(errstr), "[%s] %d: %s: %s: %d: ",
+			pname[level].t_name, errno, strerror(errno), file, line);
+	    break;
+	case APLOG_EMERG:
+	case APLOG_CRIT:
+	case APLOG_ALERT:
+	    ap_snprintf(errstr, sizeof(errstr), "[%s] %d: %s: ",
+			pname[level].t_name, errno, strerror(errno));
+	    break;
+	case APLOG_INFO:
+	case APLOG_ERR:
+	case APLOG_WARNING:
+	case APLOG_NOTICE:
+	    ap_snprintf(errstr, sizeof(errstr), "[%s]", pname[level].t_name);
+	    break;
+	}
+    }
+    else
+	ap_snprintf(errstr, sizeof(errstr), "[%s]", pname[level].t_name);
+	
+    va_start(args, fmt);
+
+    /* NULL if we are logging to syslog */
+    if (r->server->error_log) {
+	fprintf(r->server->error_log, "[%s] %s", get_time(), 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 +274,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_MARK, APLOG_ERR, 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(file, 0, APLOG_CRIT, NULL, 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_MARK, APLOG_ERR, 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(file, 0, APLOG_INFO, r, 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/28 00:24:54
@@ -50,7 +50,26 @@
  *
  */
 
+#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
+#define APLOG_MARK	__FILE__,__LINE__
+
+typedef struct _trans {
+	char	*t_name;
+	int	t_val;
+} TRANS;
+
+
 void open_logs (server_rec *, pool *p);
+API_EXPORT(void) aplog_error(const char *file, int line, int level,
+			     const request_rec *r, const char *fmt, ...);
 API_EXPORT(void) error_log2stderr (server_rec *);     
 
 void log_pid (pool *p, char *fname);
@@ -60,4 +79,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);
+
 
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/28 00:25:21
@@ -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_MARK, APLOG_ERR, r, "file does not exist: %s",
+		    r->path_info ?
+		    pstrcat(r->pool, r->filename, r->path_info, NULL) : r->filename);
 	return NOT_FOUND;
     }
     if (r->method_number != M_GET) return METHOD_NOT_ALLOWED;



Re: [PATCH] loglevels final: take2

Posted by Dean Gaudet <dg...@arctic.org>.
Multiline logging is not easily greppable... which is a really bad idea.
Not to mention that lines from two httpds are easily mixed together.

errno has no meaning in the context of some errors.  It doesn't
make sense to include it directly at the lowest level of logging.
A wrapper that deals only with "in routine blat, such and such unix
call failed: %s" should invoke the lowest level logging function.

End users aren't going to care about the file and line number.  Our
errors should be verbose enough that we can easily derrive it ourselves.
The line number is meaningless in any event, we almost never work from
the same code that the users report errors on.

Consider this warning in perform_idle_server_maintenance:

	log_printf (server_conf,
		    "server reached MaxClients setting, consider"
		    " raising the MaxClients setting");

No useful errno, no need for a filename or a line number.  It directly
tells the user what they should do.  It would be logged at warn level.

Dean

On Sun, 27 Jul 1997, Randy Terbush wrote:

> Below is the latest version incorporating some of the suggested 
> changes, and my preferred log format. The changes below do not 
> preserve existing logging format, but do make the output somewhat 
> more consistant. System info is logged on the first line, supplied 
> error string on the second. These examples are from syslog, thus 
> the host, process id, etc. Output levels are tunable by configured  
> LogLevel.