mod_log_config.c revision 49dacedb6c387b786b7911082ff35121a45f414b
f743002678eb67b99bbc29fee116b65d9530fec0wrowe/* Licensed to the Apache Software Foundation (ASF) under one or more
80833bb9a1bf25dcf19e814438a4b311d2e1f4cffuankg * contributor license agreements. See the NOTICE file distributed with
5c43d2fb853f84497b5ece2d414ef9484aa87e5fsf * this work for additional information regarding copyright ownership.
5c43d2fb853f84497b5ece2d414ef9484aa87e5fsf * The ASF licenses this file to You under the Apache License, Version 2.0
5c43d2fb853f84497b5ece2d414ef9484aa87e5fsf * (the "License"); you may not use this file except in compliance with
5c43d2fb853f84497b5ece2d414ef9484aa87e5fsf * the License. You may obtain a copy of the License at
4f517d09c93a552f177f49ff97e93aa44eb127ebcovener * Unless required by applicable law or agreed to in writing, software
4f517d09c93a552f177f49ff97e93aa44eb127ebcovener * distributed under the License is distributed on an "AS IS" BASIS,
6736c640e65e06990ef33af71ee81fac4df4ff5fjim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20eead0b01d51fce0cc17d04b8f98ec38eac68aejim * See the License for the specific language governing permissions and
20eead0b01d51fce0cc17d04b8f98ec38eac68aejim * limitations under the License.
cc45ee60ddfb8380b3703455098475eb72625ca8jim * Modified by djm@va.pubnix.com:
cc45ee60ddfb8380b3703455098475eb72625ca8jim * If no TransferLog is given explicitly, decline to log.
46e5dfe0899face9346d6711e4f2ba873d526991sf * This is module implements the TransferLog directive (same as the
46e5dfe0899face9346d6711e4f2ba873d526991sf * common log module), and additional directives, LogFormat and CustomLog.
79ccc75d7de4e14e5add1fa73aaabda0f5d33fe6trawick * TransferLog fn Logs transfers to fn in standard log format, unless
79ccc75d7de4e14e5add1fa73aaabda0f5d33fe6trawick * a custom format is set with LogFormat
79ccc75d7de4e14e5add1fa73aaabda0f5d33fe6trawick * LogFormat format Set a log format from TransferLog files
fc1459657a1fde206a847f9028930725d715f8b4trawick * CustomLog fn format
fc1459657a1fde206a847f9028930725d715f8b4trawick * Log to file fn with format given by the format
e758971371df73b097609b2fd62bc14ad935e096trawick * There can be any number of TransferLog and CustomLog
e758971371df73b097609b2fd62bc14ad935e096trawick * commands. Each request will be logged to _ALL_ the
1dd5136d67e0164e4afd723a471b86a1b7eb1874sf * named files, in the appropriate format.
1dd5136d67e0164e4afd723a471b86a1b7eb1874sf * If no TransferLog or CustomLog directive appears in a VirtualHost,
1dd5136d67e0164e4afd723a471b86a1b7eb1874sf * the request will be logged to the log file(s) defined outside
e39eb98e3ad3fbf5c34b2fa1d16861f95143e22esf * the virtual host section. If a TransferLog or CustomLog directive
e39eb98e3ad3fbf5c34b2fa1d16861f95143e22esf * appears in the VirtualHost section, the log files defined outside
e39eb98e3ad3fbf5c34b2fa1d16861f95143e22esf * the VirtualHost will _not_ be used. This makes this module compatable
d6fc66efa723db8b3ee5e9fd32579bed884e4e58sf * with the CLF and config log modules, where the use of TransferLog
d6fc66efa723db8b3ee5e9fd32579bed884e4e58sf * inside the VirtualHost section overrides its use outside.
d6fc66efa723db8b3ee5e9fd32579bed884e4e58sf * Examples:
f00cb80197f824c3ff00dd4fdff3b2c267a519d1kbrand * TransferLog logs/access_log
f00cb80197f824c3ff00dd4fdff3b2c267a519d1kbrand * <VirtualHost>
f00cb80197f824c3ff00dd4fdff3b2c267a519d1kbrand * LogFormat "... custom format ..."
85eacfc96a04547ef25aabbc06440039715084c2jorton * TransferLog log/virtual_only
85eacfc96a04547ef25aabbc06440039715084c2jorton * CustomLog log/virtual_useragents "%t %{user-agent}i"
85eacfc96a04547ef25aabbc06440039715084c2jorton * </VirtualHost>
1d8d7e58e1d31d7b6fb7a518e09649a4dbb315e9trawick * This will log using CLF to access_log any requests handled by the
1d8d7e58e1d31d7b6fb7a518e09649a4dbb315e9trawick * main server, while any requests to the virtual host will be logged
f34da68471f256dca0ff770257c3e1f982f74cf1trawick * with the "... custom format..." to virtual_only _AND_ using
f34da68471f256dca0ff770257c3e1f982f74cf1trawick * the custom user-agent log to virtual_useragents.
8b645fd3c950da73513b546366c7cfa7476c5c06jim * Note that the NCSA referer and user-agent logs are easily added with
8b645fd3c950da73513b546366c7cfa7476c5c06jim * CustomLog:
8b645fd3c950da73513b546366c7cfa7476c5c06jim * CustomLog logs/referer "%{referer}i -> %U"
8b645fd3c950da73513b546366c7cfa7476c5c06jim * CustomLog logs/agent "%{user-agent}i"
193f0bb6057d67593ed652fbf58f043def51c642jim * RefererIgnore functionality can be obtained with conditional
193f0bb6057d67593ed652fbf58f043def51c642jim * logging (SetEnvIf and CustomLog ... env=!VAR).
68ba377fc3b124baa759662077c48077ebadb186minfrin * But using this method allows much easier modification of the
68ba377fc3b124baa759662077c48077ebadb186minfrin * log format, e.g. to log hosts along with UA:
68ba377fc3b124baa759662077c48077ebadb186minfrin * CustomLog logs/referer "%{referer}i %U %h"
00566fb187849626180724394a21ddcd28419fb2minfrin * The argument to LogFormat and CustomLog is a string, which can include
00566fb187849626180724394a21ddcd28419fb2minfrin * literal characters copied into the log files, and '%' directives as
d776b0a2d2889ce1d13494873368f34327a2e1bbtrawick * %...B: bytes sent, excluding HTTP headers.
f4ca9f6f002fece336168a16355434ca966f96a9trawick * %...b: bytes sent, excluding HTTP headers in CLF format, i.e. a '-'
57db302f0875a6c93a79333b8941cea4c1827272jim * when no bytes where sent (rather than a '0'.
57db302f0875a6c93a79333b8941cea4c1827272jim * %...{FOOBAR}C: The contents of the HTTP cookie FOOBAR
57db302f0875a6c93a79333b8941cea4c1827272jim * %...{FOOBAR}e: The contents of the environment variable FOOBAR
57db302f0875a6c93a79333b8941cea4c1827272jim * %...f: filename
92b1631880b0bf43fe8b2663a03c8571eb04e433jim * %...h: remote host
92b1631880b0bf43fe8b2663a03c8571eb04e433jim * %...a: remote IP-address
92b1631880b0bf43fe8b2663a03c8571eb04e433jim * %...A: local IP-address
89225e8e84d38b07a8335922497997e83d872e75jim * %...{Foobar}i: The contents of Foobar: header line(s) in the request
89225e8e84d38b07a8335922497997e83d872e75jim * sent to the client.
89225e8e84d38b07a8335922497997e83d872e75jim * %...k: number of keepalive requests served over this connection
78f94f1d06c4e6828ce04d618221e0fcecb57849humbedooh * %...l: remote logname (from identd, if supplied)
78f94f1d06c4e6828ce04d618221e0fcecb57849humbedooh * %...{Foobar}n: The contents of note "Foobar" from another module.
78f94f1d06c4e6828ce04d618221e0fcecb57849humbedooh * %...{Foobar}o: The contents of Foobar: header line(s) in the reply.
f5e28c78424d2f71c61ba457009f100bba38bc68chrisd * %...p: the canonical port for the server
f5e28c78424d2f71c61ba457009f100bba38bc68chrisd * %...{format}p: the canonical port for the server, or the actual local
f5e28c78424d2f71c61ba457009f100bba38bc68chrisd * or remote port
f4a715f904b014060ea6237fe29481ed21f5c7d0jorton * %...P: the process ID of the child that serviced the request.
f4a715f904b014060ea6237fe29481ed21f5c7d0jorton * %...{format}P: the process ID or thread ID of the child/thread that
f4a715f904b014060ea6237fe29481ed21f5c7d0jorton * serviced the request
536d2e7cd1fdec1255b8c3bdf41fdc714c506a54trawick * %...r: first line of request
536d2e7cd1fdec1255b8c3bdf41fdc714c506a54trawick * %...s: status. For requests that got internally redirected, this
536d2e7cd1fdec1255b8c3bdf41fdc714c506a54trawick * is status of the *original* request --- %...>s for the last.
536d2e7cd1fdec1255b8c3bdf41fdc714c506a54trawick * %...t: time, in common log format time format
70caa242e6b90e0d6f0fabb56b8c5c2fb51717b3jorton * %...{format}t: The time, in the form given by format, which should
985a4368b93c3e9171a57897ad9454c8dbf4cdf6jorton * be in strftime(3) format.
70caa242e6b90e0d6f0fabb56b8c5c2fb51717b3jorton * %...T: the time taken to serve the request, in seconds.
70caa242e6b90e0d6f0fabb56b8c5c2fb51717b3jorton * %...D: the time taken to serve the request, in micro seconds.
109e2a09790de3fb315d36d6232a14ab66c8eb0ahumbedooh * %...u: remote user (from auth; may be bogus if return status (%s) is 401)
109e2a09790de3fb315d36d6232a14ab66c8eb0ahumbedooh * %...U: the URL path requested.
109e2a09790de3fb315d36d6232a14ab66c8eb0ahumbedooh * %...v: the configured name of the server (i.e. which virtual host?)
4be250c774bdac977eef29a02183ca78de29fb41rjung * %...V: the server name according to the UseCanonicalName setting
4be250c774bdac977eef29a02183ca78de29fb41rjung * %...m: the request method
4be250c774bdac977eef29a02183ca78de29fb41rjung * %...H: the request protocol
12b5dc9afa1844df5ac8acab98fb538432a2fa1crjung * %...q: the query string prepended by "?", or empty if no query string
12b5dc9afa1844df5ac8acab98fb538432a2fa1crjung * %...X: Status of the connection.
12b5dc9afa1844df5ac8acab98fb538432a2fa1crjung * 'X' = connection aborted before the response completed.
12b5dc9afa1844df5ac8acab98fb538432a2fa1crjung * '+' = connection may be kept alive after the response is sent.
74e7a30182af5e68f14ccb8d57918b22b982db8bhumbedooh * '-' = connection will be closed after the response is sent.
74e7a30182af5e68f14ccb8d57918b22b982db8bhumbedooh * (This directive was %...c in late versions of Apache 1.3, but
74e7a30182af5e68f14ccb8d57918b22b982db8bhumbedooh * this conflicted with the historical ssl %...{var}c syntax.)
10961a2f60207cb873d889bb28b1f0ef707a4311humbedooh * %...L: Log-Id of the Request (or '-' if none)
10961a2f60207cb873d889bb28b1f0ef707a4311humbedooh * %...{c}L: Log-Id of the Connection (or '-' if none)
0448378b899e8df0c060360f17c0af692adf17bchumbedooh * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
0448378b899e8df0c060360f17c0af692adf17bchumbedooh * indicate conditions for inclusion of the item (which will cause it
0448378b899e8df0c060360f17c0af692adf17bchumbedooh * to be replaced with '-' if the condition is not met). Note that
60a765cccbd3f3b5997b65b0034220c79f78369etrawick * there is no escaping performed on the strings from %r, %...i and
60a765cccbd3f3b5997b65b0034220c79f78369etrawick * %...o; some with long memories may remember that I thought this was
60a765cccbd3f3b5997b65b0034220c79f78369etrawick * a bad idea, once upon a time, and I'm still not comfortable with
e7ca863b04ee2a7aea7738cadbf51ce5e6c5245dhumbedooh * it, but it is difficult to see how to "do the right thing" with all
e7ca863b04ee2a7aea7738cadbf51ce5e6c5245dhumbedooh * of '%..i', unless we URL-escape everything and break with CLF.
e7ca863b04ee2a7aea7738cadbf51ce5e6c5245dhumbedooh * The forms of condition are a list of HTTP status codes, which may
91654e263480f0fdc2a03d782ff23f8dad07cf79humbedooh * or may not be preceded by '!'. Thus, '%400,501{User-agent}i' logs
91814c869ca39ce45dfe147307d2a831cac6ecbehumbedooh * User-agent: on 400 errors and 501 errors (Bad Request, Not
91654e263480f0fdc2a03d782ff23f8dad07cf79humbedooh * Implemented) only; '%!200,304,302{Referer}i' logs Referer: on all
79c5787b92ac5f0e1cc82393816c77a006399316trawick * requests which did *not* return some sort of normal status.
79c5787b92ac5f0e1cc82393816c77a006399316trawick * The default LogFormat reproduces CLF; see below.
79c5787b92ac5f0e1cc82393816c77a006399316trawick * The way this is supposed to work with virtual hosts is as follows:
79c5787b92ac5f0e1cc82393816c77a006399316trawick * a virtual host can have its own LogFormat, or its own TransferLog.
79c5787b92ac5f0e1cc82393816c77a006399316trawick * If it doesn't have its own LogFormat, it inherits from the main
79c5787b92ac5f0e1cc82393816c77a006399316trawick * server. If it doesn't have its own TransferLog, it writes to the
79c5787b92ac5f0e1cc82393816c77a006399316trawick * same descriptor (meaning the same process for "| ...").
12b987b969f03ef98d9175a53d849ab62f5684fecovener * --- rst */
53e9b27aba029b18be814df40bcf6f0428771d1efuankg#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"
e6dd71992459d05a676b98b7963423dc5dc1e24aminfrinstatic int xfer_flags = (APR_WRITE | APR_APPEND | APR_CREATE | APR_LARGEFILE);
e6dd71992459d05a676b98b7963423dc5dc1e24aminfrinstatic apr_status_t ap_default_log_writer(request_rec *r,
23f1535d6a60817d2846bac0aea230ea475d7dccminfrin const char **strs,
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjungstatic apr_status_t ap_buffered_log_writer(request_rec *r,
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjung const char **strs,
ec7520b24cd80d34d82bbcaca153cbb23cc04bc0rjungstatic void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s,
6249dfa569d3b4f1f539665b979a80c6e335d93etrawick const char* name);
6249dfa569d3b4f1f539665b979a80c6e335d93etrawickstatic void *ap_buffered_log_writer_init(apr_pool_t *p, server_rec *s,
0827cb14e550f6f65018431c22c2c913631c8f25kbrand const char* name);
ae600ca541efc686b34f8b1f21bd3d0741d37674covenerstatic ap_log_writer_init *ap_log_set_writer_init(ap_log_writer_init *handle);
6249dfa569d3b4f1f539665b979a80c6e335d93etrawickstatic ap_log_writer *ap_log_set_writer(ap_log_writer *handle);
cfa64348224b66dd1c9979b809406c4d15b1c137fieldingstatic ap_log_writer *log_writer = ap_default_log_writer;
74499a117b3b2cd9666715a14f90c0e5d1a4ee8ajimstatic ap_log_writer_init *log_writer_init = ap_default_log_writer_init;
cfa64348224b66dd1c9979b809406c4d15b1c137fieldingstatic int buffered_logs = 0; /* default unbuffered */
74499a117b3b2cd9666715a14f90c0e5d1a4ee8ajim/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
cfa64348224b66dd1c9979b809406c4d15b1c137fielding * guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512
74499a117b3b2cd9666715a14f90c0e5d1a4ee8ajim * is guaranteed. So we'll just guess 512 in the event the system
cfa64348224b66dd1c9979b809406c4d15b1c137fielding * doesn't have this. Now, for file writes there is actually no limit,
#ifdef PIPE_BUF
const char *default_format_string;
} buffered_log;
const char *fname;
const char *format_string;
void *log_writer;
char *condition_var;
int inherit;
char *arg;
int condition_sense;
int want_orig;
return apr_itoa(p, i);
return stuff;
r->per_dir_config,
return r->useragent_ip;
return rvalue;
&r->parsed_uri, 0),
: r->the_request);
const char *key)
struct sle {
const char *value;
return NULL;
if (!result_list) {
++t_elt;
if (result_list) {
while (rp) {
return result;
return NULL;
const char *cookies_entry;
--last;
--last;
return NULL;
unsigned t_validate;
#define TIME_FMT_CUSTOM 0
if (!state) {
char *fmt = a;
if (!*fmt) {
fmt++;
a = fmt;
if (!*fmt) {
fmt++;
a = fmt;
if (!*fmt) {
if (!*fmt) {
else if (!*fmt) {
switch (fmt_type) {
case TIME_FMT_ABS_SEC:
case TIME_FMT_ABS_MSEC:
case TIME_FMT_ABS_USEC:
case TIME_FMT_ABS_MSEC_FRAC:
case TIME_FMT_ABS_USEC_FRAC:
return buf;
* See the comments in server/util_time.c for more information.
sizeof(*cached_time));
char sign;
int timz;
if (timz < 0) {
#if APR_HAS_THREADS
&tid);
const char **sa)
s = *sa;
s = *sa;
*sa = s;
return NULL;
const char *s = *sa;
*sa = ++s;
return NULL;
while (apr_isdigit(*++s)) {
if (!handler) {
*sa = s;
return NULL;
char *res;
return NULL;
s = APR_EOL_STR;
const char *cp;
int in_list = 0;
const char **strs;
int *strl;
char *envar;
return DECLINED;
return DECLINED;
return DECLINED;
const char *err;
if (rc < 0)
if (rc <= 0)
return DECLINED;
orig = r;
while (r->next) {
r = r->next;
if (!log_writer) {
return HTTP_INTERNAL_SERVER_ERROR;
return OK;
return OK;
return mls;
return add;
const char *name)
return err_string;
const char *err;
if (err)
return err;
return err_string;
const char *ret;
if (err) {
return err;
return ret;
const char *fn)
if (buffered_logs) {
return NULL;
{NULL}
return NULL;
return cls;
const char *dummy;
const char *format;
if (format) {
if (format) {
return DONE;
if (format) {
return DONE;
return OK;
if (!buffered_logs)
return APR_SUCCESS;
for (; s; s = s->next) {
if (log_list) {
return APR_SUCCESS;
int res;
if (buffered_logs) {
return res;
int mpm_threads;
if (buffered_logs) {
#if APR_HAS_THREADS
return old;
return old;
void *handle,
const char **strs,
int *strl,
int nelts,
char *str;
s += strl[i];
return rv;
const char* name)
return NULL;
if (!fname) {
return NULL;
return NULL;
return fd;
const char* name)
buffered_log *b;
if (b->handle) {
return NULL;
void *handle,
const char **strs,
int *strl,
int nelts,
char *str;
return rv;
apr_size_t w;
s += strl[i];
w = len;
s += strl[i];
return rv;
if (log_pfn_register) {
buffered_logs = 0;
return OK;
return OK;
return !OK;
return OK;
s = s->next;
return rv;