📄 mod_log_config.c
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * Modified by djm@va.pubnix.com: * If no TransferLog is given explicitly, decline to log. * * This is module implements the TransferLog directive (same as the * common log module), and additional directives, LogFormat and CustomLog. * * * Syntax: * * TransferLog fn Logs transfers to fn in standard log format, unless * a custom format is set with LogFormat * LogFormat format Set a log format from TransferLog files * CustomLog fn format * Log to file fn with format given by the format * argument * * CookieLog fn For backwards compatability with old Cookie * logging module - now deprecated. * * There can be any number of TransferLog and CustomLog * commands. Each request will be logged to _ALL_ the * named files, in the appropriate format. * * If no TransferLog or CustomLog directive appears in a VirtualHost, * the request will be logged to the log file(s) defined outside * the virtual host section. If a TransferLog or CustomLog directive * appears in the VirtualHost section, the log files defined outside * the VirtualHost will _not_ be used. This makes this module compatable * with the CLF and config log modules, where the use of TransferLog * inside the VirtualHost section overrides its use outside. * * Examples: * * TransferLog logs/access_log * <VirtualHost> * LogFormat "... custom format ..." * TransferLog log/virtual_only * CustomLog log/virtual_useragents "%t %{user-agent}i" * </VirtualHost> * * This will log using CLF to access_log any requests handled by the * main server, while any requests to the virtual host will be logged * with the "... custom format..." to virtual_only _AND_ using * the custom user-agent log to virtual_useragents. * * Note that the NCSA referer and user-agent logs are easily added with * CustomLog: * CustomLog logs/referer "%{referer}i -> %U" * CustomLog logs/agent "%{user-agent}i" * * RefererIgnore functionality can be obtained with conditional * logging (SetEnvIf and CustomLog ... env=!VAR). * * But using this method allows much easier modification of the * log format, e.g. to log hosts along with UA: * CustomLog logs/referer "%{referer}i %U %h" * * The argument to LogFormat and CustomLog is a string, which can include * literal characters copied into the log files, and '%' directives as * follows: * * %...B: bytes sent, excluding HTTP headers. * %...b: bytes sent, excluding HTTP headers in CLF format, i.e. a '-' * when no bytes where sent (rather than a '0'. * %...{FOOBAR}C: The contents of the HTTP cookie FOOBAR * %...{FOOBAR}e: The contents of the environment variable FOOBAR * %...f: filename * %...h: remote host * %...a: remote IP-address * %...A: local IP-address * %...{Foobar}i: The contents of Foobar: header line(s) in the request * sent to the client. * %...k: number of keepalive requests served over this connection * %...l: remote logname (from identd, if supplied) * %...{Foobar}n: The contents of note "Foobar" from another module. * %...{Foobar}o: The contents of Foobar: header line(s) in the reply. * %...p: the canonical port for the server * %...{format}p: the canonical port for the server, or the actual local * or remote port * %...P: the process ID of the child that serviced the request. * %...{format}P: the process ID or thread ID of the child/thread that * serviced the request * %...r: first line of request * %...s: status. For requests that got internally redirected, this * is status of the *original* request --- %...>s for the last. * %...t: time, in common log format time format * %...{format}t: The time, in the form given by format, which should * be in strftime(3) format. * %...T: the time taken to serve the request, in seconds. * %...D: the time taken to serve the request, in micro seconds. * %...u: remote user (from auth; may be bogus if return status (%s) is 401) * %...U: the URL path requested. * %...v: the configured name of the server (i.e. which virtual host?) * %...V: the server name according to the UseCanonicalName setting * %...m: the request method * %...H: the request protocol * %...q: the query string prepended by "?", or empty if no query string * %...X: Status of the connection. * 'X' = connection aborted before the response completed. * '+' = connection may be kept alive after the response is sent. * '-' = connection will be closed after the response is sent. (This directive was %...c in late versions of Apache 1.3, but this conflicted with the historical ssl %...{var}c syntax.)* * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can * indicate conditions for inclusion of the item (which will cause it * to be replaced with '-' if the condition is not met). Note that * there is no escaping performed on the strings from %r, %...i and * %...o; some with long memories may remember that I thought this was * a bad idea, once upon a time, and I'm still not comfortable with * it, but it is difficult to see how to "do the right thing" with all * of '%..i', unless we URL-escape everything and break with CLF. * * The forms of condition are a list of HTTP status codes, which may * or may not be preceded by '!'. Thus, '%400,501{User-agent}i' logs * User-agent: on 400 errors and 501 errors (Bad Request, Not * Implemented) only; '%!200,304,302{Referer}i' logs Referer: on all * requests which did *not* return some sort of normal status. * * The default LogFormat reproduces CLF; see below. * * The way this is supposed to work with virtual hosts is as follows: * a virtual host can have its own LogFormat, or its own TransferLog. * If it doesn't have its own LogFormat, it inherits from the main * server. If it doesn't have its own TransferLog, it writes to the * same descriptor (meaning the same process for "| ..."). * * --- rst */#include "apr_strings.h"#include "apr_lib.h"#include "apr_hash.h"#include "apr_optional.h"#include "apr_anylock.h"#define APR_WANT_STRFUNC#include "apr_want.h"#include "ap_config.h"#include "mod_log_config.h"#include "httpd.h"#include "http_config.h"#include "http_core.h" /* For REMOTE_NAME */#include "http_log.h"#include "http_protocol.h"#include "util_time.h"#include "ap_mpm.h"#if APR_HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_LIMITS_H#include <limits.h>#endif#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"module AP_MODULE_DECLARE_DATA log_config_module;static int xfer_flags = (APR_WRITE | APR_APPEND | APR_CREATE | APR_LARGEFILE);static apr_fileperms_t xfer_perms = APR_OS_DEFAULT;static apr_hash_t *log_hash;static apr_status_t ap_default_log_writer(request_rec *r, void *handle, const char **strs, int *strl, int nelts, apr_size_t len);static apr_status_t ap_buffered_log_writer(request_rec *r, void *handle, const char **strs, int *strl, int nelts, apr_size_t len);static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s, const char* name);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 */static apr_array_header_t *all_buffered_logs = NULL;/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is * guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512 * is guaranteed. So we'll just guess 512 in the event the system * doesn't have this. Now, for file writes there is actually no limit, * the entire write is atomic. Whether all systems implement this * correctly is another question entirely ... so we'll just use PIPE_BUF * because it's probably a good guess as to what is implemented correctly * everywhere. */#ifdef PIPE_BUF#define LOG_BUFSIZE PIPE_BUF#else#define LOG_BUFSIZE (512)#endif/* * multi_log_state is our per-(virtual)-server configuration. We store * an array of the logs we are going to use, each of type config_log_state. * If a default log format is given by LogFormat, store in default_format * (backward compat. with mod_log_config). We also store for each virtual * server a pointer to the logs specified for the main server, so that if this * vhost has no logs defined, we can use the main server's logs instead. * * So, for the main server, config_logs contains a list of the log files * and server_config_logs is empty. For a vhost, server_config_logs * points to the same array as config_logs in the main server, and * config_logs points to the array of logs defined inside this vhost, * which might be empty. */typedef struct { const char *default_format_string; apr_array_header_t *default_format; apr_array_header_t *config_logs; apr_array_header_t *server_config_logs; apr_table_t *formats;} multi_log_state;/* * config_log_state holds the status of a single log file. fname might * be NULL, which means this module does no logging for this * request. format might be NULL, in which case the default_format * from the multi_log_state should be used, or if that is NULL as * well, use the CLF. * log_writer is NULL before the log file is opened and is * set to a opaque structure (usually a fd) after it is opened. */typedef struct { apr_file_t *handle; apr_size_t outcnt; char outbuf[LOG_BUFSIZE]; apr_anylock_t mutex;} buffered_log;typedef struct { const char *fname; const char *format_string; apr_array_header_t *format; void *log_writer; char *condition_var;} config_log_state;/* * Format items... * Note that many of these could have ap_sprintfs replaced with static buffers. */typedef struct { ap_log_handler_fn_t *func; char *arg; int condition_sense; int want_orig; apr_array_header_t *conditions;} log_format_item;static char *format_integer(apr_pool_t *p, int i){ return apr_itoa(p, i);}static char *pfmt(apr_pool_t *p, int i){ if (i <= 0) { return "-"; } else { return format_integer(p, i); }}static const char *constant_item(request_rec *dummy, char *stuff){ return stuff;}static const char *log_remote_host(request_rec *r, char *a){ return ap_escape_logitem(r->pool, ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL));}static const char *log_remote_address(request_rec *r, char *a){ return r->connection->remote_ip;}static const char *log_local_address(request_rec *r, char *a){ return r->connection->local_ip;}static const char *log_remote_logname(request_rec *r, char *a){ return ap_escape_logitem(r->pool, ap_get_remote_logname(r));}static const char *log_remote_user(request_rec *r, char *a){ char *rvalue = r->user; if (rvalue == NULL) { rvalue = "-"; } else if (strlen(rvalue) == 0) { rvalue = "\"\""; } else { rvalue = ap_escape_logitem(r->pool, rvalue); } return rvalue;}static const char *log_request_line(request_rec *r, char *a){ /* NOTE: If the original request contained a password, we * re-write the request line here to contain XXXXXX instead: * (note the truncation before the protocol string for HTTP/0.9 requests) * (note also that r->the_request contains the unmodified request) */ return ap_escape_logitem(r->pool, (r->parsed_uri.password) ? apr_pstrcat(r->pool, r->method, " ", apr_uri_unparse(r->pool, &r->parsed_uri, 0), r->assbackwards ? NULL : " ", r->protocol, NULL) : r->the_request);}static const char *log_request_file(request_rec *r, char *a){ return ap_escape_logitem(r->pool, r->filename);}static const char *log_request_uri(request_rec *r, char *a){ return ap_escape_logitem(r->pool, r->uri);}static const char *log_request_method(request_rec *r, char *a){ return ap_escape_logitem(r->pool, r->method);}static const char *log_request_protocol(request_rec *r, char *a){ return ap_escape_logitem(r->pool, r->protocol);}static const char *log_request_query(request_rec *r, char *a){ return (r->args) ? apr_pstrcat(r->pool, "?", ap_escape_logitem(r->pool, r->args), NULL) : "";}static const char *log_status(request_rec *r, char *a){ return pfmt(r->pool, r->status);}static const char *clf_log_bytes_sent(request_rec *r, char *a){ if (!r->sent_bodyct || !r->bytes_sent) { return "-"; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -