]> granicus.if.org Git - apache/commitdiff
* mod_log_config: Allow using ErrorLog providers for CustomLog.
authorJan Kaluža <jkaluza@apache.org>
Fri, 17 Apr 2015 10:14:15 +0000 (10:14 +0000)
committerJan Kaluža <jkaluza@apache.org>
Fri, 17 Apr 2015 10:14:15 +0000 (10:14 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1674261 13f79535-47bb-0310-9956-ffa450edef68

docs/manual/mod/mod_log_config.xml
modules/loggers/mod_log_config.c

index f40fb0b68cdd80085d4dbf6656ffd00f8c68ddcc..7a6d4c2cb38a6ec96b6d829f5f20cb83b07a942e 100644 (file)
 <directivesynopsis>
 <name>CustomLog</name>
 <description>Sets filename and format of log file</description>
-<syntax>CustomLog  <var>file</var>|<var>pipe</var>
+<syntax>CustomLog  <var>file</var>|<var>pipe</var>|<var>provider</var>
 <var>format</var>|<var>nickname</var>
 [env=[!]<var>environment-variable</var>|
 expr=<var>expression</var>]</syntax>
@@ -457,6 +457,20 @@ expr=<var>expression</var>]</syntax>
         may allow the use of back slashes. In general it is a good idea to always
         use forward slashes throughout the configuration files.</p>
       </note></dd>
+      <dt><var>provider</var></dt>
+      <dd>Modules implementing ErrorLog providers can also be used as a target
+      for CustomLog messages. To use ErrorLog provider as a target,
+      "provider:argument" syntax must be used. You can for example use
+      <module>mod_journald</module> or <module>mod_syslog</module>
+      as a provider:
+    <highlight language="config">
+# CustomLog logging to journald
+CustomLog "journald" "%h %l %u %t \"%r\" %&gt;s %b"
+
+# CustomLog logging to syslog with "user" facility
+CustomLog "syslog:user" "%h %l %u %t \"%r\" %&gt;s %b"
+    </highlight>
+      </dd>
     </dl>
 
     <p>The second argument specifies what will be written to the
index 75e131eeba9b5b0c4149e4857c27a39a643ef5ed..6bc7cd418198febd71e13a000ef9b736f163ad74 100644 (file)
 #include "http_protocol.h"
 #include "util_time.h"
 #include "ap_mpm.h"
+#include "ap_provider.h"
 
 #if APR_HAVE_UNISTD_H
 #include <unistd.h>
@@ -289,6 +290,35 @@ typedef struct {
     apr_array_header_t *conditions;
 } log_format_item;
 
+/*
+ * errorlog_provider_data holds pointer to provider and its handle
+ * generated by provider initialization. It is used when logging using
+ * ap_errorlog_provider.
+ */
+typedef struct {
+    struct ap_errorlog_provider *provider;
+    void *handle;
+} errorlog_provider_data;
+
+/*
+ * Type of the log_writer created by ap_default_log_writer_init.
+ * It is used by ap_default_log_writer to determine the type of
+ * the log_writer.
+ */
+enum default_log_writer_type {
+    LOG_WRITER_FD,
+    LOG_WRITER_PROVIDER
+};
+
+/*
+ * Abstract struct to allow multiple types of log writers to be created
+ * by ap_default_log_writer_init function.
+ */
+typedef struct {
+    enum default_log_writer_type type;
+    void *log_writer;
+} default_log_writer;
+
 static char *pfmt(apr_pool_t *p, int i)
 {
     if (i <= 0) {
@@ -1596,6 +1626,7 @@ static apr_status_t ap_default_log_writer( request_rec *r,
                            apr_size_t len)
 
 {
+    default_log_writer *log_writer = handle;
     char *str;
     char *s;
     int i;
@@ -1612,13 +1643,44 @@ static apr_status_t ap_default_log_writer( request_rec *r,
         s += strl[i];
     }
 
-    rv = apr_file_write_full((apr_file_t*)handle, str, len, NULL);
+    if (log_writer->type == LOG_WRITER_FD) {
+        rv = apr_file_write_full((apr_file_t*)log_writer->log_writer, str,
+                                 len, NULL);
+    }
+    else {
+        errorlog_provider_data *data = log_writer->log_writer;
+        ap_errorlog_info info;
+        info.r             = r;
+        info.s             = r->server;
+        info.c             = r->connection;
+        info.pool          = r->pool;
+        info.file          = NULL;
+        info.line          = 0;
+        info.status        = 0;
+        info.using_provider = 1;
+        info.startup       = 0;
+        info.format        = "";
+        data->provider->writer(&info, data->handle,
+                                str, len);
+    }
 
     return rv;
 }
 static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s,
                                         const char* name)
 {
+    default_log_writer *log_writer;
+    const char *provider_name = name;
+    ap_errorlog_provider *provider = NULL;
+    char *sep;
+
+    /* We support *Log "errorlog_provider:arg" syntax now, so get the provider
+     * name from the name. */
+    if ((sep = ap_strchr_c(name, ':')) != NULL) {
+        provider_name = apr_pstrmemdup(p, name, sep - name);
+        sep++;
+    }
+
     if (*name == '|') {
         piped_log *pl;
 
@@ -1626,7 +1688,34 @@ static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s,
         if (pl == NULL) {
            return NULL;
         }
-        return ap_piped_log_write_fd(pl);
+
+        log_writer = apr_pcalloc(p, sizeof(default_log_writer));
+        log_writer->type = LOG_WRITER_FD;
+        log_writer->log_writer = ap_piped_log_write_fd(pl);
+        if (!log_writer->log_writer) {
+            return NULL;
+        }
+        return log_writer;
+    }
+    else if ((provider = ap_lookup_provider(AP_ERRORLOG_PROVIDER_GROUP,
+        provider_name, AP_ERRORLOG_PROVIDER_VERSION)) != NULL) {
+        void *provider_handle;
+        errorlog_provider_data *provider_data;
+    
+        provider_handle = provider->init(p, s);
+        if (!provider_handle) {
+            /* provider must log something to the console */
+            return NULL;
+        }
+
+        provider_data = apr_pcalloc(p, sizeof(errorlog_provider_data));
+        provider_data->provider = provider;
+        provider_data->handle = provider_handle;
+
+        log_writer = apr_pcalloc(p, sizeof(default_log_writer));
+        log_writer->type = LOG_WRITER_PROVIDER;
+        log_writer->log_writer = provider_data;
+        return log_writer;
     }
     else {
         const char *fname = ap_server_root_relative(p, name);
@@ -1644,7 +1733,11 @@ static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s,
                             "could not open transfer log file %s.", fname);
             return NULL;
         }
-        return fd;
+
+        log_writer = apr_pcalloc(p, sizeof(default_log_writer));
+        log_writer->type = LOG_WRITER_FD;
+        log_writer->log_writer = fd;
+        return log_writer;
     }
 }
 static void *ap_buffered_log_writer_init(apr_pool_t *p, server_rec *s,