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.