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 */