From: Jan Kaluža Date: Fri, 17 Apr 2015 10:14:15 +0000 (+0000) Subject: * mod_log_config: Allow using ErrorLog providers for CustomLog. X-Git-Tag: 2.5.0-alpha~3261 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=438584b1065f40849b4cfb71bdda0734dc9402d3;p=apache * mod_log_config: Allow using ErrorLog providers for CustomLog. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1674261 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/docs/manual/mod/mod_log_config.xml b/docs/manual/mod/mod_log_config.xml index f40fb0b68c..7a6d4c2cb3 100644 --- a/docs/manual/mod/mod_log_config.xml +++ b/docs/manual/mod/mod_log_config.xml @@ -418,7 +418,7 @@ CustomLog Sets filename and format of log file -CustomLog file|pipe +CustomLog file|pipe|provider format|nickname [env=[!]environment-variable| expr=expression] @@ -457,6 +457,20 @@ expr=expression] may allow the use of back slashes. In general it is a good idea to always use forward slashes throughout the configuration files.

+
provider
+
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 + mod_journald or mod_syslog + as a provider: + +# CustomLog logging to journald +CustomLog "journald" "%h %l %u %t \"%r\" %>s %b" + +# CustomLog logging to syslog with "user" facility +CustomLog "syslog:user" "%h %l %u %t \"%r\" %>s %b" + +

The second argument specifies what will be written to the diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c index 75e131eeba..6bc7cd4181 100644 --- a/modules/loggers/mod_log_config.c +++ b/modules/loggers/mod_log_config.c @@ -161,6 +161,7 @@ #include "http_protocol.h" #include "util_time.h" #include "ap_mpm.h" +#include "ap_provider.h" #if APR_HAVE_UNISTD_H #include @@ -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,