]> granicus.if.org Git - apache/commitdiff
Add ap_errorlog_provider to make ErrorLog logging modular. Move
authorJan Kaluža <jkaluza@apache.org>
Mon, 23 Sep 2013 14:02:27 +0000 (14:02 +0000)
committerJan Kaluža <jkaluza@apache.org>
Mon, 23 Sep 2013 14:02:27 +0000 (14:02 +0000)
syslog support from core to new mod_syslog.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1525597 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/manual/mod/core.xml
include/http_core.h
include/httpd.h
server/core.c
server/log.c

diff --git a/CHANGES b/CHANGES
index b91572e45cd29367a549f51287e9135fef296c3d..f27e513044b563643d04e679fee4aa2f9f289379 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) core: Add ap_errorlog_provider to make ErrorLog logging modular. Move
+     syslog support from core to new mod_syslog. [Jan Kaluza]
+
   *) mod_proxy_fcgi: Handle reading protocol data that is split between
      packets.  [Jeff Trawick]
 
index 06e6a4ec1a277f4a9ec6018e86d8b45e73b150be..ecd588653dad71226266b5325c43ee14849ac17c 100644 (file)
@@ -1298,16 +1298,19 @@ ErrorDocument 404 /cgi-bin/bad_urls.pl
     more information.</p>
 
     <p>Using <code>syslog</code> instead of a filename enables logging
-    via syslogd(8) if the system supports it. The default is to use
-    syslog facility <code>local7</code>, but you can override this by
-    using the <code>syslog:<var>facility</var></code> syntax where
-    <var>facility</var> can be one of the names usually documented in
+    via syslogd(8) if the system supports it and if <module>mod_syslog</module>
+    is loaded. The default is to use syslog facility <code>local7</code>,
+    but you can override this by using the <code>syslog:<var>facility</var></code>
+    syntax where <var>facility</var> can be one of the names usually documented in
     syslog(1).  The facility is effectively global, and if it is changed
     in individual virtual hosts, the final facility specified affects the
     entire server.</p>
 
     <highlight language="config">ErrorLog syslog:user</highlight>
 
+    <p>Additional modules can provide their own ErrorLog providers. The syntax
+    is similar to <code>syslog</code> example above.</p>
+
     <p>SECURITY: See the <a
     href="../misc/security_tips.html#serverroot">security tips</a>
     document for details on why your security could be compromised
index 80ce6cdd96196c97c8b8322fba931959bfcd5ba3..a31aa054a179f379047fe958c85f607544b92eea 100644 (file)
@@ -833,8 +833,8 @@ typedef struct ap_errorlog_info {
     /** apr error status related to the log message, 0 if no error */
     apr_status_t status;
 
-    /** 1 if logging to syslog, 0 otherwise */
-    int using_syslog;
+    /** 1 if logging using provider, 0 otherwise */
+    int using_provider;
     /** 1 if APLOG_STARTUP was set for the log message, 0 otherwise */
     int startup;
 
@@ -842,6 +842,30 @@ typedef struct ap_errorlog_info {
     const char *format;
 } ap_errorlog_info;
 
+#define AP_ERRORLOG_PROVIDER_GROUP "error_log_writer"
+#define AP_ERRORLOG_PROVIDER_VERSION "0"
+#define AP_ERRORLOG_DEFAULT_PROVIDER "file"
+
+typedef struct ap_errorlog_provider ap_errorlog_provider;
+
+struct ap_errorlog_provider {
+    /** Initializes the error log writer.
+     * @param p The pool to create any storage from
+     * @param s Server for which the logger is initialized
+     * @return Pointer to handle passed later to writer() function
+     */
+    void * (*init)(apr_pool_t *p, server_rec *s);
+
+    /** Logs the error message to external error log.
+     * @param info Context of the error message
+     * @param handle Handle created by init() function
+     * @param errstr Error message
+     * @param len Length of the error message
+     */
+    apr_status_t (*writer)(const ap_errorlog_info *info, void *handle,
+                           const char *errstr, int len);
+};
+
 /**
  * callback function prototype for a external errorlog handler
  * @note To avoid unbounded memory usage, these functions must not allocate
index 175c7d867f603fe47c3144d15fab5bacacb86458..0439e97e27b707c33a1674df9e5c781550b1e1cf 100644 (file)
@@ -1245,6 +1245,10 @@ struct server_rec {
     apr_file_t *error_log;
     /** The log level configuration */
     struct ap_logconf log;
+    /** External error log writer provider */
+    struct ap_errorlog_provider *errorlog_provider;
+    /** Handle to be passed to external log provider's logging method */
+    void *errorlog_provider_handle;
 
     /* Module-specific configuration for server, and defaults... */
 
index 9e01154dc32e3b056807dd184d4e998997ca2043..de7997952c8fe64d0b212b723c8e4e6e746c2b84 100644 (file)
@@ -48,6 +48,7 @@
 #include "mod_core.h"
 #include "mod_proxy.h"
 #include "ap_listen.h"
+#include "ap_provider.h"
 
 #include "mod_so.h" /* for ap_find_loaded_module_symbol */
 
@@ -3955,6 +3956,49 @@ static apr_array_header_t *parse_errorlog_string(apr_pool_t *p,
     return a;
 }
 
+static const char *set_errorlog(cmd_parms *cmd, void *dummy, const char *arg1,
+                                const char *arg2)
+{
+    ap_errorlog_provider *provider;
+    cmd->server->errorlog_provider = NULL;
+
+    if (!arg2) {
+        /* Stay backward compatible and check for "syslog" */
+        if (strncmp("syslog", arg1, 6) == 0) {
+            arg2 = arg1 + 7; /* skip the ':' if any */
+            arg1 = "syslog";
+        }
+        else {
+            /* Admin can define only "ErrorLog provider" and we should 
+             * still handle that using the defined provider, but with empty
+             * error_fname. */
+            provider = ap_lookup_provider(AP_ERRORLOG_PROVIDER_GROUP, arg1,
+                                          AP_ERRORLOG_PROVIDER_VERSION);
+            if (provider) {
+                arg2 = "";
+            }
+            else {
+                return set_server_string_slot(cmd, dummy, arg1);
+            }
+        }
+    }
+
+    if (strcmp("file", arg1) == 0) {
+        return set_server_string_slot(cmd, dummy, arg2);
+    }
+
+    provider = ap_lookup_provider(AP_ERRORLOG_PROVIDER_GROUP, arg1,
+                                    AP_ERRORLOG_PROVIDER_VERSION);
+    if (!provider) {
+        return apr_psprintf(cmd->pool,
+                            "Unknown ErrorLog provider: %s",
+                            arg1);
+    }
+
+    cmd->server->errorlog_provider = provider;
+    return set_server_string_slot(cmd, dummy, arg2);
+}
+
 static const char *set_errorlog_format(cmd_parms *cmd, void *dummy,
                                        const char *arg1, const char *arg2)
 {
@@ -4118,7 +4162,7 @@ AP_INIT_TAKE1("ServerRoot", set_server_root, NULL, RSRC_CONF | EXEC_ON_READ,
   "Common directory of server-related files (logs, confs, etc.)"),
 AP_INIT_TAKE1("DefaultRuntimeDir", set_runtime_dir, NULL, RSRC_CONF | EXEC_ON_READ,
   "Common directory for run-time files (shared memory, locks, etc.)"),
-AP_INIT_TAKE1("ErrorLog", set_server_string_slot,
+AP_INIT_TAKE12("ErrorLog", set_errorlog,
   (void *)APR_OFFSETOF(server_rec, error_fname), RSRC_CONF,
   "The filename of the error log"),
 AP_INIT_TAKE12("ErrorLogFormat", set_errorlog_format, NULL, RSRC_CONF,
@@ -4560,7 +4604,7 @@ AP_DECLARE(int) ap_sys_privileges_handlers(int inc)
 static int check_errorlog_dir(apr_pool_t *p, server_rec *s)
 {
     if (!s->error_fname || s->error_fname[0] == '|'
-        || strcmp(s->error_fname, "syslog") == 0) {
+        || s->errorlog_provider != NULL) {
         return APR_SUCCESS;
     }
     else {
@@ -4986,7 +5030,7 @@ static void core_dump_config(apr_pool_t *p, server_rec *s)
     apr_file_printf(out, "ServerRoot: \"%s\"\n", ap_server_root);
     tmp = ap_server_root_relative(p, sconf->ap_document_root);
     apr_file_printf(out, "Main DocumentRoot: \"%s\"\n", tmp);
-    if (s->error_fname[0] != '|' && strcmp(s->error_fname, "syslog") != 0)
+    if (s->error_fname[0] != '|' && s->errorlog_provider == NULL)
         tmp = ap_server_root_relative(p, s->error_fname);
     else
         tmp = s->error_fname;
index 161cc9d3343e31b05e8ed4a1e8611b7adcb4af0e..01851241690884c657cd30a4ed2314b395c8c4f3 100644 (file)
@@ -53,6 +53,7 @@
 #include "http_main.h"
 #include "util_time.h"
 #include "ap_mpm.h"
+#include "ap_provider.h"
 
 #if HAVE_GETTID
 #include <sys/syscall.h>
@@ -75,71 +76,6 @@ APR_HOOK_STRUCT(
 
 int AP_DECLARE_DATA ap_default_loglevel = DEFAULT_LOGLEVEL;
 
-#ifdef HAVE_SYSLOG
-
-static const TRANS facilities[] = {
-    {"auth",    LOG_AUTH},
-#ifdef LOG_AUTHPRIV
-    {"authpriv",LOG_AUTHPRIV},
-#endif
-#ifdef LOG_CRON
-    {"cron",    LOG_CRON},
-#endif
-#ifdef LOG_DAEMON
-    {"daemon",  LOG_DAEMON},
-#endif
-#ifdef LOG_FTP
-    {"ftp", LOG_FTP},
-#endif
-#ifdef LOG_KERN
-    {"kern",    LOG_KERN},
-#endif
-#ifdef LOG_LPR
-    {"lpr", LOG_LPR},
-#endif
-#ifdef LOG_MAIL
-    {"mail",    LOG_MAIL},
-#endif
-#ifdef LOG_NEWS
-    {"news",    LOG_NEWS},
-#endif
-#ifdef LOG_SYSLOG
-    {"syslog",  LOG_SYSLOG},
-#endif
-#ifdef LOG_USER
-    {"user",    LOG_USER},
-#endif
-#ifdef LOG_UUCP
-    {"uucp",    LOG_UUCP},
-#endif
-#ifdef LOG_LOCAL0
-    {"local0",  LOG_LOCAL0},
-#endif
-#ifdef LOG_LOCAL1
-    {"local1",  LOG_LOCAL1},
-#endif
-#ifdef LOG_LOCAL2
-    {"local2",  LOG_LOCAL2},
-#endif
-#ifdef LOG_LOCAL3
-    {"local3",  LOG_LOCAL3},
-#endif
-#ifdef LOG_LOCAL4
-    {"local4",  LOG_LOCAL4},
-#endif
-#ifdef LOG_LOCAL5
-    {"local5",  LOG_LOCAL5},
-#endif
-#ifdef LOG_LOCAL6
-    {"local6",  LOG_LOCAL6},
-#endif
-#ifdef LOG_LOCAL7
-    {"local7",  LOG_LOCAL7},
-#endif
-    {NULL,      -1},
-};
-#endif
-
 static const TRANS priorities[] = {
     {"emerg",   APLOG_EMERG},
     {"alert",   APLOG_ALERT},
@@ -395,29 +331,10 @@ static int open_error_log(server_rec *s, int is_main, apr_pool_t *p)
 
         s->error_log = dummy;
     }
-
-#ifdef HAVE_SYSLOG
-    else if (!strncasecmp(s->error_fname, "syslog", 6)) {
-        if ((fname = strchr(s->error_fname, ':'))) {
-            const TRANS *fac;
-
-            fname++;
-            for (fac = facilities; fac->t_name; fac++) {
-                if (!strcasecmp(fname, fac->t_name)) {
-                    openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID,
-                            fac->t_val);
-                    s->error_log = NULL;
-                    return OK;
-                }
-            }
-        }
-        else {
-            openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
-        }
-
+    else if (s->errorlog_provider) {
+        s->errorlog_provider_handle = s->errorlog_provider->init(p, s);
         s->error_log = NULL;
     }
-#endif
     else {
         fname = ap_server_root_relative(p, s->error_fname);
         if (!fname) {
@@ -904,7 +821,7 @@ AP_DECLARE(void) ap_register_log_hooks(apr_pool_t *p)
 
 /*
  * This is used if no error log format is defined and during startup.
- * It automatically omits the timestamp if logging to syslog.
+ * It automatically omits the timestamp if logging using provider.
  */
 static int do_errorlog_default(const ap_errorlog_info *info, char *buf,
                                int buflen, int *errstr_start, int *errstr_end,
@@ -917,7 +834,7 @@ static int do_errorlog_default(const ap_errorlog_info *info, char *buf,
     char scratch[MAX_STRING_LEN];
 #endif
 
-    if (!info->using_syslog && !info->startup) {
+    if (!info->using_provider && !info->startup) {
         buf[len++] = '[';
         len += log_ctime(info, "u", buf + len, buflen - len);
         buf[len++] = ']';
@@ -1076,22 +993,14 @@ static int do_errorlog_format(apr_array_header_t *fmt, ap_errorlog_info *info,
 static void write_logline(char *errstr, apr_size_t len, apr_file_t *logf,
                           int level)
 {
-    /* NULL if we are logging to syslog */
-    if (logf) {
-        /* Truncate for the terminator (as apr_snprintf does) */
-        if (len > MAX_STRING_LEN - sizeof(APR_EOL_STR)) {
-            len = MAX_STRING_LEN - sizeof(APR_EOL_STR);
-        }
-        strcpy(errstr + len, APR_EOL_STR);
-        apr_file_puts(errstr, logf);
-        apr_file_flush(logf);
-    }
-#ifdef HAVE_SYSLOG
-    else {
-        syslog(level < LOG_PRIMASK ? level : APLOG_DEBUG, "%.*s",
-               (int)len, errstr);
+
+    /* Truncate for the terminator (as apr_snprintf does) */
+    if (len > MAX_STRING_LEN - sizeof(APR_EOL_STR)) {
+        len = MAX_STRING_LEN - sizeof(APR_EOL_STR);
     }
-#endif
+    strcpy(errstr + len, APR_EOL_STR);
+    apr_file_puts(errstr, logf);
+    apr_file_flush(logf);
 }
 
 static void log_error_core(const char *file, int line, int module_index,
@@ -1152,7 +1061,7 @@ static void log_error_core(const char *file, int line, int module_index,
         }
         else {
             /*
-             * If we are doing syslog logging, don't log messages that are
+             * If we are doing logging using provider, don't log messages that are
              * above the module's log level (including a startup/shutdown notice)
              */
             if (level_and_mask > configured_level) {
@@ -1194,7 +1103,7 @@ static void log_error_core(const char *file, int line, int module_index,
     info.file          = NULL;
     info.line          = 0;
     info.status        = 0;
-    info.using_syslog  = (logf == NULL);
+    info.using_provider= (logf == NULL);
     info.startup       = ((level & APLOG_STARTUP) == APLOG_STARTUP);
     info.format        = fmt;
 
@@ -1272,7 +1181,14 @@ static void log_error_core(const char *file, int line, int module_index,
              */
             continue;
         }
-        write_logline(errstr, len, logf, level_and_mask);
+
+        if (logf) {
+            write_logline(errstr, len, logf, level_and_mask);
+        }
+        else {
+            s->errorlog_provider->writer(&info, s->errorlog_provider_handle,
+                                         errstr, len);
+        }
 
         if (done) {
             /*