📄 mod_log_nw.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'. * %...c: 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. * %...{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. * %...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 port the request was served to * %...P: the process ID of the child 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. * %...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 * * 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 */#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"#include "httpd.h"#include "http_config.h"#include "http_core.h" /* For REMOTE_NAME */#include "http_log.h"#include <limits.h>module MODULE_VAR_EXPORT config_log_module;static int xfer_flags = (O_WRONLY | O_APPEND | O_CREAT);#if defined(OS2) || defined(WIN32) || defined(NETWARE)/* OS/2 dosen't support users and groups */static mode_t xfer_mode = (S_IREAD | S_IWRITE);#elsestatic mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);#endif/* 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 in 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 { char *default_format_string; array_header *default_format; array_header *config_logs; array_header *server_config_logs; table *formats; int rotatedaily; int rotateinterval;} 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_fd is -1 before the log file is opened and * set to a valid fd after it is opened. */typedef struct { char *fname; char *format_string; array_header *format; int log_fd; char *condition_var;#ifdef BUFFERED_LOGS int outcnt; char outbuf[LOG_BUFSIZE];#endif time_t time_jump;} config_log_state;/* * Format items... * Note that many of these could have ap_sprintfs replaced with static buffers. */typedef const char *(*item_key_func) (request_rec *, char *);typedef struct { item_key_func func; char *arg; int condition_sense; int want_orig; array_header *conditions;} log_format_item;static char *format_integer(pool *p, int i){ return ap_psprintf(p, "%d", i);}static char *pfmt(pool *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_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME);}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_get_remote_logname(r);}static const char *log_remote_user(request_rec *r, char *a){ char *rvalue = r->connection->user; if (rvalue == NULL) { rvalue = "-"; } else if (strlen(rvalue) == 0) { 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 (r->parsed_uri.password) ? ap_pstrcat(r->pool, r->method, " ", ap_unparse_uri_components(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 r->filename;}static const char *log_request_uri(request_rec *r, char *a){ return r->uri;}static const char *log_request_method(request_rec *r, char *a){ return r->method;}static const char *log_request_protocol(request_rec *r, char *a){ return r->protocol;}static const char *log_request_query(request_rec *r, char *a){ return (r->args != NULL) ? ap_pstrcat(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) { return "-"; } else { long int bs; ap_bgetopt(r->connection->client, BO_BYTECT, &bs); return ap_psprintf(r->pool, "%ld", bs); }}static const char *log_bytes_sent(request_rec *r, char *a){ if (!r->sent_bodyct) { return "0"; } else { long int bs; ap_bgetopt(r->connection->client, BO_BYTECT, &bs); return ap_psprintf(r->pool, "%ld", bs); }}static const char *log_header_in(request_rec *r, char *a){ return ap_table_get(r->headers_in, a);}static const char *log_header_out(request_rec *r, char *a){ const char *cp = ap_table_get(r->headers_out, a); if (!strcasecmp(a, "Content-type") && r->content_type) { cp = ap_field_noparam(r->pool, r->content_type); } if (cp) { return cp; } return ap_table_get(r->err_headers_out, a);}static const char *log_note(request_rec *r, char *a){ return ap_table_get(r->notes, a);}static const char *log_env_var(request_rec *r, char *a){ return ap_table_get(r->subprocess_env, a);}static const char *log_request_time(request_rec *r, char *a){ int timz; struct tm *t; char tstr[MAX_STRING_LEN]; t = ap_get_gmtoff(&timz); if (a && *a) { /* Custom format */ strftime(tstr, MAX_STRING_LEN, a, t); } else { /* CLF format */ char sign = (timz < 0 ? '-' : '+'); if (timz < 0) { timz = -timz; } ap_snprintf(tstr, sizeof(tstr), "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]", t->tm_mday, ap_month_snames[t->tm_mon], t->tm_year+1900, t->tm_hour, t->tm_min, t->tm_sec, sign, timz / 60, timz % 60); } return ap_pstrdup(r->pool, tstr);}static const char *log_request_duration(request_rec *r, char *a){ return ap_psprintf(r->pool, "%ld", time(NULL) - r->request_time);}/* These next two routines use the canonical name:port so that log * parsers don't need to duplicate all the vhost parsing crud. */static const char *log_virtual_host(request_rec *r, char *a){ return r->server->server_hostname;}static const char *log_server_port(request_rec *r, char *a){ return ap_psprintf(r->pool, "%u", r->server->port ? r->server->port : ap_default_port(r));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -