Akins, Brian wrote:

CustomLog mysql://something common env=images
CustomLog file:///logs/my.log combined
CustomLog spread://somegroup refere
CustomLog buffer:///logs/other.log common


This patch implements the above.  Within mod_log_config two providers
are provided: file and buffer.  If no "scheme" is given, file is assumed.

I have tested and preliminarily it works for both file and buffer.  I
had to rearrange some of the buffer code to get it to work "non-globally."

It should be just as easy to write custom log handles. With this patch,
different custom loggers could handle different log "files."

Comments?


--
Brian Akins
Lead Systems Engineer
CNN Internet Technologies

diff -ur httpd-2.1.8-beta/modules/loggers/mod_log_config.c 
httpd-2.1.8-beta.new/modules/loggers/mod_log_config.c
--- httpd-2.1.8-beta/modules/loggers/mod_log_config.c   2005-09-18 
16:39:34.000000000 -0400
+++ httpd-2.1.8-beta.new/modules/loggers/mod_log_config.c       2005-10-03 
11:10:48.677989129 -0400
@@ -159,6 +159,7 @@
 #include "http_protocol.h"
 #include "util_time.h"
 #include "ap_mpm.h"
+#include "ap_provider.h"
 
 #if APR_HAVE_UNISTD_H
 #include <unistd.h>
@@ -167,6 +168,8 @@
 #include <limits.h>
 #endif
 
+#define DEFAULT_LOG_PROVIDER "file"
+
 #define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"
 
 module AP_MODULE_DECLARE_DATA log_config_module;
@@ -188,15 +191,9 @@
                            int nelts,
                            apr_size_t len);
 static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s, 
-                                        const char* name);
+                                        const apr_uri_t *uri);
 static void *ap_buffered_log_writer_init(apr_pool_t *p, server_rec *s, 
-                                        const char* name);
-
-static ap_log_writer_init* ap_log_set_writer_init(ap_log_writer_init *handle);
-static ap_log_writer* ap_log_set_writer(ap_log_writer *handle);
-static ap_log_writer *log_writer = ap_default_log_writer;
-static ap_log_writer_init *log_writer_init = ap_default_log_writer_init;
-static int buffered_logs = 0; /* default unbuffered */
+                                         const apr_uri_t *uri);
 static apr_array_header_t *all_buffered_logs = NULL;
 
 /* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
@@ -255,10 +252,12 @@
 } buffered_log;
 
 typedef struct {
-    const char *fname;
+    apr_uri_t uri;
+    const char *fname; /*raw file name*/
     const char *format_string;
     apr_array_header_t *format;
-    void *log_writer;
+    void *handle;
+    log_provider_t *provider;
     char *condition_var;
 } config_log_state;
 
@@ -954,12 +953,7 @@
     for (i = 0; i < format->nelts; ++i) {
         len += strl[i] = strlen(strs[i]);
     }
-    if (!log_writer) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r,
-                "log writer isn't correctly setup");
-         return HTTP_INTERNAL_SERVER_ERROR;
-    }
-    rv = log_writer(r, cls->log_writer, strs, strl, format->nelts, len);
+    rv = cls->provider->writer(r, cls->handle, strs, strl, format->nelts, len);
     /* xxx: do we return an error on log_writer? */
     return OK;
 }
@@ -1093,8 +1087,22 @@
     else {
         cls->format = parse_log_string(cmd->pool, fmt, &err_string);
     }
-    cls->log_writer = NULL;
+    
+    if(apr_uri_parse(cmd->pool, cls->fname, &cls->uri) != APR_SUCCESS) {
+        return "failed to parse uri";
+    }
 
+    if(!cls->uri.scheme) {
+        cls->uri.scheme = DEFAULT_LOG_PROVIDER;
+    }
+
+    if((cls->provider = ap_lookup_provider(LOG_PROVIDER_GROUP,
+                                           cls->uri.scheme, 
LOG_PROVIDER_VERSION))
+       == NULL) {
+        return apr_psprintf(cmd->pool, "unable to file handler for: \"%s\" in 
%s",
+                            cls->uri.scheme, cls->fname);
+    }
+    
     return err_string;
 }
 
@@ -1109,15 +1117,6 @@
     return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t", NULL);
 }
 
-static const char *set_buffered_logs_on(cmd_parms *parms, void *dummy, int 
flag)
-{
-    buffered_logs = flag;
-    if (buffered_logs) {
-        ap_log_set_writer_init(ap_buffered_log_writer_init);
-        ap_log_set_writer(ap_buffered_log_writer);
-    }
-    return NULL;
-}
 static const command_rec config_log_cmds[] =
 {
 AP_INIT_TAKE23("CustomLog", add_custom_log, NULL, RSRC_CONF,
@@ -1129,8 +1128,6 @@
      "a log format string (see docs) and an optional format name"),
 AP_INIT_TAKE1("CookieLog", set_cookie_log, NULL, RSRC_CONF,
      "the filename of the cookie log"),
-AP_INIT_FLAG("BufferedLogs", set_buffered_logs_on, NULL, RSRC_CONF,
-                 "Enable Buffered Logging (experimental)"),
     {NULL}
 };
 
@@ -1138,7 +1135,7 @@
                                          config_log_state *cls,
                                          apr_array_header_t *default_format)
 {
-    if (cls->log_writer != NULL) {
+    if (cls->handle != NULL) {
         return cls;             /* virtual config shared w/main server */
     }
 
@@ -1146,8 +1143,8 @@
         return cls;             /* Leave it NULL to decline.  */
     }
     
-    cls->log_writer = log_writer_init(p, s, cls->fname);
-    if (cls->log_writer == NULL)
+    cls->handle = cls->provider->init(p, s, &cls->uri);
+    if (cls->handle == NULL)
         return NULL; 
 
     return cls;
@@ -1216,33 +1213,20 @@
 
 static apr_status_t flush_all_logs(void *data)
 {
-    server_rec *s = data;
-    multi_log_state *mls;
-    apr_array_header_t *log_list;
-    config_log_state *clsarray;
     buffered_log *buf;
     int i;
-
-    if (!buffered_logs)
+    buffered_log **array;
+    
+    if (!all_buffered_logs)
         return APR_SUCCESS;
     
-    for (; s; s = s->next) {
-        mls = ap_get_module_config(s->module_config, &log_config_module);
-        log_list = NULL;
-        if (mls->config_logs->nelts) {
-            log_list = mls->config_logs;
-        }
-        else if (mls->server_config_logs) {
-            log_list = mls->server_config_logs;
-        }
-        if (log_list) {
-            clsarray = (config_log_state *) log_list->elts;
-            for (i = 0; i < log_list->nelts; ++i) {
-                buf = clsarray[i].log_writer;
-                flush_log(buf);
-            }
-        }
+    array = (buffered_log **)all_buffered_logs->elts;
+        
+    for (i = 0; i < all_buffered_logs->nelts; i++) {
+        buf = array[i];
+        flush_log(buf);
     }
+    
     return APR_SUCCESS;
 }
 
@@ -1251,11 +1235,6 @@
 {
     int res;
 
-    /* First init the buffered logs array, which is needed when opening the 
logs. */
-    if (buffered_logs) {
-        all_buffered_logs = apr_array_make(p, 5, sizeof(buffered_log *));
-    }
-
     /* Next, do "physical" server, which gets default log fd and format
      * for the virtual servers, if they don't override...
      */
@@ -1277,12 +1256,12 @@
     ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads);
 
     /* Now register the last buffer flush with the cleanup engine */
-    if (buffered_logs) {
+    if (all_buffered_logs) {
         int i;
         buffered_log **array = (buffered_log **)all_buffered_logs->elts;
         
         apr_pool_cleanup_register(p, s, flush_all_logs, flush_all_logs);
-
+        
         for (i = 0; i < all_buffered_logs->nelts; i++) {
             buffered_log *this = array[i];
             
@@ -1319,21 +1298,6 @@
 
     apr_hash_set(log_hash, tag, 1, (const void *)log_struct);
 }
-static ap_log_writer_init* ap_log_set_writer_init(ap_log_writer_init *handle)
-{
-    ap_log_writer_init *old = log_writer_init; 
-    log_writer_init = handle;
-
-    return old;
-
-}
-static ap_log_writer *ap_log_set_writer(ap_log_writer *handle)
-{
-    ap_log_writer *old = log_writer; 
-    log_writer = handle;
-
-    return old;
-}
 
 static apr_status_t ap_default_log_writer( request_rec *r,
                            void *handle, 
@@ -1360,8 +1324,10 @@
     return rv;
 }
 static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s, 
-                                        const char* name)
+                                        const apr_uri_t *uri)
 {
+    const char *name = uri->path;
+    
     if (*name == '|') {
         piped_log *pl;
 
@@ -1391,11 +1357,16 @@
     }
 }
 static void *ap_buffered_log_writer_init(apr_pool_t *p, server_rec *s, 
-                                        const char* name)
+                                        const apr_uri_t *uri)
 {
+    
     buffered_log *b;
     b = apr_pcalloc(p, sizeof(buffered_log));
-    b->handle = ap_default_log_writer_init(p, s, name);
+    b->handle = ap_default_log_writer_init(p, s, uri);
+    
+    if(!all_buffered_logs) {
+        all_buffered_logs = apr_array_make(p, 5, sizeof(buffered_log *));
+    }
     
     if (b->handle) {
         *(buffered_log **)apr_array_push(all_buffered_logs) = b;
@@ -1489,6 +1460,16 @@
     return OK;
 }
 
+static const log_provider_t default_logger = {
+    &ap_default_log_writer_init,
+    ap_default_log_writer
+};
+
+static const log_provider_t buffer_logger = {
+    &ap_buffered_log_writer_init,
+    ap_buffered_log_writer
+};
+
 static void register_hooks(apr_pool_t *p)
 {
     ap_hook_pre_config(log_pre_config,NULL,NULL,APR_HOOK_REALLY_FIRST);
@@ -1504,8 +1485,10 @@
      */ 
     log_hash = apr_hash_make(p);
     APR_REGISTER_OPTIONAL_FN(ap_register_log_handler);
-    APR_REGISTER_OPTIONAL_FN(ap_log_set_writer_init);
-    APR_REGISTER_OPTIONAL_FN(ap_log_set_writer);
+    ap_register_provider(p, LOG_PROVIDER_GROUP, "file", 
+                         LOG_PROVIDER_VERSION, &default_logger);
+    ap_register_provider(p, LOG_PROVIDER_GROUP, "buffer", 
+                         LOG_PROVIDER_VERSION, &buffer_logger);
 }
 
 module AP_MODULE_DECLARE_DATA log_config_module =
diff -ur httpd-2.1.8-beta/modules/loggers/mod_log_config.h 
httpd-2.1.8-beta.new/modules/loggers/mod_log_config.h
--- httpd-2.1.8-beta/modules/loggers/mod_log_config.h   2005-05-19 
07:53:48.000000000 -0400
+++ httpd-2.1.8-beta.new/modules/loggers/mod_log_config.h       2005-10-03 
11:08:21.800235579 -0400
@@ -30,7 +30,7 @@
  * callback function prototype for external writer initialization.
  */
 typedef void *ap_log_writer_init(apr_pool_t *p, server_rec *s, 
-                                 const char *name);
+                                 const apr_uri_t *uri);
 /**
  * callback which gets called where there is a log line to write.
  */
@@ -50,14 +50,13 @@
 APR_DECLARE_OPTIONAL_FN(void, ap_register_log_handler, 
                         (apr_pool_t *p, char *tag, ap_log_handler_fn_t *func,
                          int def));
-/**
- * you will need to set your init handler *BEFORE* the open_logs 
- * in mod_log_config gets executed
- */
-APR_DECLARE_OPTIONAL_FN(ap_log_writer_init*, 
ap_log_set_writer_init,(ap_log_writer_init *func));
-/** 
- * you should probably set the writer at the same time (ie..before open_logs)
- */
-APR_DECLARE_OPTIONAL_FN(ap_log_writer*, ap_log_set_writer, (ap_log_writer* 
func));
 
+
+typedef struct {
+    ap_log_writer_init *init;
+    ap_log_writer *writer;
+} log_provider_t;
+
+#define LOG_PROVIDER_GROUP "log_config"
+#define LOG_PROVIDER_VERSION "1"
 #endif /* MOD_LOG_CONFIG */

Reply via email to