📄 mod_log_config.c
字号:
}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 { return apr_off_t_toa(r->pool, r->bytes_sent); }}static const char *log_bytes_sent(request_rec *r, char *a){ if (!r->sent_bodyct || !r->bytes_sent) { return "0"; } else { return apr_psprintf(r->pool, "%" APR_OFF_T_FMT, r->bytes_sent); }}static const char *log_header_in(request_rec *r, char *a){ return ap_escape_logitem(r->pool, apr_table_get(r->headers_in, a));}static const char *log_header_out(request_rec *r, char *a){ const char *cp = apr_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 ap_escape_logitem(r->pool, cp); } return ap_escape_logitem(r->pool, apr_table_get(r->err_headers_out, a));}static const char *log_note(request_rec *r, char *a){ return ap_escape_logitem(r->pool, apr_table_get(r->notes, a));}static const char *log_env_var(request_rec *r, char *a){ return ap_escape_logitem(r->pool, apr_table_get(r->subprocess_env, a));}static const char *log_cookie(request_rec *r, char *a){ const char *cookies; const char *start_cookie; if ((cookies = apr_table_get(r->headers_in, "Cookie"))) { if ((start_cookie = ap_strstr_c(cookies,a))) { char *cookie, *end_cookie; start_cookie += strlen(a) + 1; /* cookie_name + '=' */ cookie = apr_pstrdup(r->pool, start_cookie); /* kill everything in cookie after ';' */ end_cookie = strchr(cookie, ';'); if (end_cookie) { *end_cookie = '\0'; } return ap_escape_logitem(r->pool, cookie); } } return NULL;}static const char *log_request_time_custom(request_rec *r, char *a, apr_time_exp_t *xt){ apr_size_t retcode; char tstr[MAX_STRING_LEN]; apr_strftime(tstr, &retcode, sizeof(tstr), a, xt); return apr_pstrdup(r->pool, tstr);}#define DEFAULT_REQUEST_TIME_SIZE 32typedef struct { unsigned t; char timestr[DEFAULT_REQUEST_TIME_SIZE]; unsigned t_validate;} cached_request_time;#define TIME_CACHE_SIZE 4#define TIME_CACHE_MASK 3static cached_request_time request_time_cache[TIME_CACHE_SIZE];static const char *log_request_time(request_rec *r, char *a){ apr_time_exp_t xt; /* ### I think getting the time again at the end of the request * just for logging is dumb. i know it's "required" for CLF. * folks writing log parsing tools don't realise that out of order * times have always been possible (consider what happens if one * process calculates the time to log, but then there's a context * switch before it writes and before that process is run again the * log rotation occurs) and they should just fix their tools rather * than force the server to pay extra cpu cycles. if you've got * a problem with this, you can set the define. -djg */ if (a && *a) { /* Custom format */ /* The custom time formatting uses a very large temp buffer * on the stack. To avoid using so much stack space in the * common case where we're not using a custom format, the code * for the custom format in a separate function. (That's why * log_request_time_custom is not inlined right here.) */#ifdef I_INSIST_ON_EXTRA_CYCLES_FOR_CLF_COMPLIANCE ap_explode_recent_localtime(&xt, apr_time_now());#else ap_explode_recent_localtime(&xt, r->request_time);#endif return log_request_time_custom(r, a, &xt); } else { /* CLF format */ /* This code uses the same technique as ap_explode_recent_localtime(): * optimistic caching with logic to detect and correct race conditions. * See the comments in server/util_time.c for more information. */ cached_request_time* cached_time = apr_palloc(r->pool, sizeof(*cached_time));#ifdef I_INSIST_ON_EXTRA_CYCLES_FOR_CLF_COMPLIANCE apr_time_t request_time = apr_time_now();#else apr_time_t request_time = r->request_time;#endif unsigned t_seconds = (unsigned)apr_time_sec(request_time); unsigned i = t_seconds & TIME_CACHE_MASK; memcpy(cached_time, &(request_time_cache[i]), sizeof(*cached_time)); if ((t_seconds != cached_time->t) || (t_seconds != cached_time->t_validate)) { /* Invalid or old snapshot, so compute the proper time string * and store it in the cache */ char sign; int timz; ap_explode_recent_localtime(&xt, request_time); timz = xt.tm_gmtoff; if (timz < 0) { timz = -timz; sign = '-'; } else { sign = '+'; } cached_time->t = t_seconds; apr_snprintf(cached_time->timestr, DEFAULT_REQUEST_TIME_SIZE, "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]", xt.tm_mday, apr_month_snames[xt.tm_mon], xt.tm_year+1900, xt.tm_hour, xt.tm_min, xt.tm_sec, sign, timz / (60*60), (timz % (60*60)) / 60); cached_time->t_validate = t_seconds; memcpy(&(request_time_cache[i]), cached_time, sizeof(*cached_time)); } return cached_time->timestr; }}static const char *log_request_duration(request_rec *r, char *a){ apr_time_t duration = apr_time_now() - r->request_time; return apr_psprintf(r->pool, "%" APR_TIME_T_FMT, apr_time_sec(duration));}static const char *log_request_duration_microseconds(request_rec *r, char *a){ return apr_psprintf(r->pool, "%" APR_TIME_T_FMT, (apr_time_now() - 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 ap_escape_logitem(r->pool, r->server->server_hostname);}static const char *log_server_port(request_rec *r, char *a){ return apr_psprintf(r->pool, "%u", r->server->port ? r->server->port : ap_default_port(r));}/* This respects the setting of UseCanonicalName so that * the dynamic mass virtual hosting trick works better. */static const char *log_server_name(request_rec *r, char *a){ return ap_escape_logitem(r->pool, ap_get_server_name(r));}static const char *log_pid_tid(request_rec *r, char *a){ if (*a == '\0' || !strcmp(a, "pid")) { return apr_psprintf(r->pool, "%" APR_PID_T_FMT, getpid()); } else if (!strcmp(a, "tid")) {#if APR_HAS_THREADS apr_os_thread_t tid = apr_os_thread_current();#else int tid = 0; /* APR will format "0" anyway but an arg is needed */#endif return apr_psprintf(r->pool, "%pT", &tid); } /* bogus format */ return a;}static const char *log_connection_status(request_rec *r, char *a){ if (r->connection->aborted) return "X"; if (r->connection->keepalive == AP_CONN_KEEPALIVE && (!r->server->keep_alive_max || (r->server->keep_alive_max - r->connection->keepalives) > 0)) { return "+"; } return "-";}/***************************************************************** * * Parsing the log format string */static char *parse_log_misc_string(apr_pool_t *p, log_format_item *it, const char **sa){ const char *s; char *d; it->func = constant_item; it->conditions = NULL; s = *sa; while (*s && *s != '%') { s++; } /* * This might allocate a few chars extra if there's a backslash * escape in the format string. */ it->arg = apr_palloc(p, s - *sa + 1); d = it->arg; s = *sa; while (*s && *s != '%') { if (*s != '\\') { *d++ = *s++; } else { s++; switch (*s) { case '\\': *d++ = '\\'; s++; break; case 'r': *d++ = '\r'; s++; break; case 'n': *d++ = '\n'; s++; break; case 't': *d++ = '\t'; s++; break; default: /* copy verbatim */ *d++ = '\\'; /* * Allow the loop to deal with this *s in the normal * fashion so that it handles end of string etc. * properly. */ break; } } } *d = '\0'; *sa = s; return NULL;}static char *parse_log_item(apr_pool_t *p, log_format_item *it, const char **sa){ const char *s = *sa; ap_log_handler *handler; if (*s != '%') { return parse_log_misc_string(p, it, sa); } ++s; it->condition_sense = 0; it->conditions = NULL; if (*s == '%') { it->arg = "%"; it->func = constant_item; *sa = ++s; return NULL; } it->want_orig = -1; it->arg = ""; /* For safety's sake... */ while (*s) { int i; switch (*s) { case '!': ++s; it->condition_sense = !it->condition_sense; break; case '<': ++s; it->want_orig = 1; break; case '>': ++s; it->want_orig = 0; break; case ',': ++s; break; case '{': ++s;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -