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,