On Wed, Sep 17, 2014 at 9:22 AM, Jeff Trawick <traw...@gmail.com> wrote:

> On Mon, Sep 15, 2014 at 2:00 AM, Jan Kaluža <jkal...@redhat.com> wrote:
>
>> On 09/14/2014 01:21 PM, Martynas Bendorius wrote:
>>
>>> Hello,
>>>
>>> Is there any special reason why mod_systemd and mod_journald (available
>>> in trunk) are not backported to 2.4 yet?
>>>
>>
>> Hi,
>>
>> I think mod_systemd could be proposed for 2.4 branch (maybe even with the
>> changes adding socket activation), but for mod_journald, we would have to
>> backport "modular logging", which breaks the API/ABI and therefore I'm
>> afraid that won't happen in 2.4 branch :(.
>>
>>
> I have an old patch somewhere that doesn't break the API/ABI, and
> accommodates such differences as syslog being built-in in 2.4.x.  I didn't
> realize that anybody besides me actually cared.
>
> I'll try to find time to see how it fits in 2.4.x-HEAD.
>

I've simply attached it from its state one year ago, not having time to
play with it.  I don't think it is necessary to break the ABI.  syslog
support remains part of core logging instead of in a module.


>
>
>
>> Jan Kaluza
>>
>>
>>  As we have a lot of distributions already using systemd by default
>>> (CentOS/RHEL 7, Fedora, Arch Linux, CoreOS, openSUSE), and more of them
>>> are going to use systemd by default (Debian 8 (Jessie), Ubuntu), it
>>> requires manual patching of apache for the support of systemd/journald.
>>>
>>> Thank you!
>>>
>>>
>>
>
>
> --
Born in Roswell... married an alien...
http://emptyhammock.com/
Index: docs/manual/mod/core.xml
===================================================================
--- docs/manual/mod/core.xml    (revision 1545470)
+++ docs/manual/mod/core.xml    (working copy)
@@ -1293,10 +1293,10 @@
     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>
@@ -1303,6 +1303,9 @@
 
     <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: docs/manual/mod
===================================================================
--- docs/manual/mod     (revision 1545470)
+++ docs/manual/mod     (working copy)

Property changes on: docs/manual/mod
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /httpd/httpd/trunk/docs/manual/mod:r1525597
Index: docs/manual
===================================================================
--- docs/manual (revision 1545470)
+++ docs/manual (working copy)

Property changes on: docs/manual
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /httpd/httpd/trunk/docs/manual:r1525597
Index: include/http_core.h
===================================================================
--- include/http_core.h (revision 1545470)
+++ include/http_core.h (working copy)
@@ -826,8 +826,55 @@
 
     /** message format */
     const char *format;
+
+    /** 1 if logging using provider, 0 otherwise */
+    int using_provider;
 } ap_errorlog_info;
 
+#define AP_ERRORLOG_PROVIDER_GROUP "error_log_writer"
+#define AP_ERRORLOG_PROVIDER_VERSION "0"
+#define AP_ERRORLOG_DEFAULT_PROVIDER "file"
+
+/** add APR_EOL_STR to the end of log message */
+#define AP_ERRORLOG_PROVIDER_ADD_EOL_STR       1
+
+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
+     * @note On success, the provider must return non-NULL, even if
+     * the handle is not necessary when the writer() function is
+     * called.  On failure, the provider should log a startup error
+     * message and return NULL to abort httpd startup.
+     */
+    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, apr_size_t len);
+
+    /** Checks syntax of ErrorLog directive argument.
+     * @param cmd The config directive
+     * @param arg ErrorLog directive argument (or the empty string if
+     * no argument was provided)
+     * @return Error message or NULL on success
+     * @remark The argument will be stored in the error_fname field
+     * of server_rec for access later.
+     */
+    const char * (*parse_errorlog_arg)(cmd_parms *cmd, const char *arg);
+
+    /** a combination of the AP_ERRORLOG_PROVIDER_* flags */
+    unsigned int flags;
+};
+
 /**
  * callback function prototype for a external errorlog handler
  * @note To avoid unbounded memory usage, these functions must not allocate
Index: include/httpd.h
===================================================================
--- include/httpd.h     (revision 1545470)
+++ include/httpd.h     (working copy)
@@ -1304,6 +1304,11 @@
 
     /** Opaque storage location */
     void *context;
+
+    /** 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;
 };
 
 /**
Index: server/core.c
===================================================================
--- server/core.c       (revision 1545470)
+++ server/core.c       (working copy)
@@ -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 */
 
@@ -3812,6 +3813,55 @@
     return a;
 }
 
+static const char *set_errorlog(cmd_parms *cmd, void *dummy, const char *arg1,
+                                const char *arg2)
+{
+    ap_errorlog_provider *provider;
+    const char *err;
+    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);
+    }
+
+    err = provider->parse_errorlog_arg(cmd, arg2);
+    if (err) {
+        return err;
+    }
+
+    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)
 {
@@ -3973,7 +4023,7 @@
   "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,
@@ -4408,7 +4458,8 @@
 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) {
+        || strcmp(s->error_fname, "syslog") == 0
+        || s->errorlog_provider != NULL) {
         return APR_SUCCESS;
     }
     else {
@@ -4815,7 +4866,8 @@
     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] != '|' && strcmp(s->error_fname, "syslog") != 0
+        && s->errorlog_provider == NULL)
         tmp = ap_server_root_relative(p, s->error_fname);
     else
         tmp = s->error_fname;
Index: server/log.c
===================================================================
--- server/log.c        (revision 1545470)
+++ server/log.c        (working copy)
@@ -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>
@@ -414,10 +415,18 @@
         else {
             openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
         }
+        s->error_log = NULL;
+    }
+#endif
 
+    else if (s->errorlog_provider) {
+        s->errorlog_provider_handle = s->errorlog_provider->init(p, s);
         s->error_log = NULL;
+        if (!s->errorlog_provider_handle) {
+            /* provider must log something to the console */
+            return DONE;
+        }
     }
-#endif
     else {
         fname = ap_server_root_relative(p, s->error_fname);
         if (!fname) {
@@ -516,9 +525,12 @@
 #define NULL_DEVICE "/dev/null"
 #endif
 
-    if (replace_stderr && freopen(NULL_DEVICE, "w", stderr) == NULL) {
-        ap_log_error(APLOG_MARK, APLOG_CRIT, errno, s_main, APLOGNO(00093)
-                     "unable to replace stderr with %s", NULL_DEVICE);
+    if (replace_stderr) {
+        if (freopen(NULL_DEVICE, "w", stderr) == NULL) {
+            ap_log_error(APLOG_MARK, APLOG_CRIT, errno, s_main, APLOGNO(00093)
+                        "unable to replace stderr with %s", NULL_DEVICE);
+        }
+        stderr_log = NULL;
     }
 
     for (virt = s_main->next; virt; virt = virt->next) {
@@ -539,6 +551,18 @@
                 virt->error_log = q->error_log;
             }
         }
+        else if (virt->errorlog_provider) {
+            /* separately-configured vhost-specific provider */
+            if (open_error_log(virt, 0, p) != OK) {
+                return DONE;
+            }
+        }
+        else if (s_main->errorlog_provider) {
+            /* inherit provider from s_main */
+            virt->errorlog_provider = s_main->errorlog_provider;
+            virt->errorlog_provider_handle = s_main->errorlog_provider_handle;
+            virt->error_log = NULL;
+        }
         else {
             virt->error_log = s_main->error_log;
         }
@@ -911,7 +935,8 @@
 
 /*
  * 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 to syslog or
+ * using provider.
  */
 static int do_errorlog_default(const ap_errorlog_info *info, char *buf,
                                int buflen, int *errstr_start, int *errstr_end,
@@ -924,7 +949,7 @@
     char scratch[MAX_STRING_LEN];
 #endif
 
-    if (!info->using_syslog && !info->startup) {
+    if (!info->using_syslog && !info->using_provider && !info->startup) {
         buf[len++] = '[';
         len += log_ctime(info, "u", buf + len, buflen - len);
         buf[len++] = ']';
@@ -1083,13 +1108,8 @@
 static void write_logline(char *errstr, apr_size_t len, apr_file_t *logf,
                           int level)
 {
-    /* NULL if we are logging to syslog */
+    /* NULL if we are writing 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);
     }
@@ -1114,6 +1134,8 @@
     const request_rec *rmain = NULL;
     core_server_config *sconf = NULL;
     ap_errorlog_info info;
+    ap_errorlog_provider *errorlog_provider = NULL;
+    void *errorlog_provider_handle = NULL;
 
     /* do we need to log once-per-req or once-per-conn info? */
     int log_conn_info = 0, log_req_info = 0;
@@ -1140,33 +1162,31 @@
 #endif
 
         logf = stderr_log;
+        if (!logf && ap_server_conf && ap_server_conf->errorlog_provider) {
+            errorlog_provider = ap_server_conf->errorlog_provider;
+            errorlog_provider_handle = 
ap_server_conf->errorlog_provider_handle;
+        }
     }
     else {
         int configured_level = r ? ap_get_request_module_loglevel(r, 
module_index)        :
                                c ? ap_get_conn_server_module_loglevel(c, s, 
module_index) :
                                    ap_get_server_module_loglevel(s, 
module_index);
+        /*
+         * If we are doing normal logging, don't log messages that are
+         * above the module's log level unless it is a startup/shutdown notice
+         */
+        if ((level_and_mask != APLOG_NOTICE)
+            && (level_and_mask > configured_level)) {
+            return;
+        }
+
         if (s->error_log) {
-            /*
-             * If we are doing normal logging, don't log messages that are
-             * above the module's log level unless it is a startup/shutdown 
notice
-             */
-            if ((level_and_mask != APLOG_NOTICE)
-                && (level_and_mask > configured_level)) {
-                return;
-            }
-
             logf = s->error_log;
         }
-        else {
-            /*
-             * If we are doing syslog logging, don't log messages that are
-             * above the module's log level (including a startup/shutdown 
notice)
-             */
-            if (level_and_mask > configured_level) {
-                return;
-            }
-        }
 
+        errorlog_provider = s->errorlog_provider;
+        errorlog_provider_handle = s->errorlog_provider_handle;
+
         /* the faked server_rec from mod_cgid does not have s->module_config */
         if (s->module_config) {
             sconf = ap_get_core_module_config(s->module_config);
@@ -1195,6 +1215,15 @@
         }
     }
 
+    if (!logf && !(errorlog_provider && errorlog_provider_handle)) {
+        /* There is no file to send the log message to (or it is
+         * redirected to /dev/null and therefore any formating done below
+         * would be lost anyway) and there is no initialized log provider
+         * available, so we just return here.
+         */
+        return;
+    }
+
     info.s             = s;
     info.c             = c;
     info.pool          = pool;
@@ -1201,7 +1230,8 @@
     info.file          = NULL;
     info.line          = 0;
     info.status        = 0;
-    info.using_syslog  = (logf == NULL);
+    info.using_provider= s && errorlog_provider != NULL;
+    info.using_syslog  = logf == NULL && !info.using_provider;
     info.startup       = ((level & APLOG_STARTUP) == APLOG_STARTUP);
     info.format        = fmt;
 
@@ -1279,8 +1309,27 @@
              */
             continue;
         }
-        write_logline(errstr, len, logf, level_and_mask);
 
+        if (logf
+            || (info.using_provider
+                && (errorlog_provider->flags
+                    & AP_ERRORLOG_PROVIDER_ADD_EOL_STR))) {
+            /* 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);
+            len += strlen(APR_EOL_STR);
+        }
+
+        if (!info.using_provider) {
+            write_logline(errstr, len, logf, level_and_mask);
+        }
+        else {
+            errorlog_provider->writer(&info, errorlog_provider_handle,
+                                      errstr, len);
+        }
+
         if (done) {
             /*
              * We don't call the error_log hook for per-request/per-conn
Index: .
===================================================================
--- .   (revision 1545470)
+++ .   (working copy)

Property changes on: .
___________________________________________________________________
Modified: svn:mergeinfo
   Merged 
/httpd/httpd/trunk:r1525597,1525664,1525845,1527003,1527005,1532344,1539988,1541029,1543979,1544156

Reply via email to