All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.server.CustomRequestLog Maven / Gradle / Ivy

There is a newer version: 2024.11.18598.20241113T125352Z-241000
Show newest version
// 
// ========================================================================
// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// 
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// 
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// 
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
// 
package org.eclipse.jetty.server;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.QuotedCSV;
import org.eclipse.jetty.http.pathmap.PathMappings;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import static java.lang.invoke.MethodHandles.dropArguments;
import static java.lang.invoke.MethodHandles.foldArguments;
import static java.lang.invoke.MethodType.methodType;

/**
 *  A flexible RequestLog, which produces log strings in a customizable format.
 *  The Logger takes a format string where request characteristics can be added using "%" format codes which are
 *  replaced by the corresponding value in the log output.
 *  

* The terms server, client, local and remote are used to refer to the different addresses and ports * which can be logged. Server and client refer to the logical addresses which can be modified in the request * headers. Where local and remote refer to the physical addresses which may be a proxy between the * end-user and the server. * *

Percent codes are specified in the format %MODIFIERS{PARAM}CODE *

 *  MODIFIERS:
 *      Optional list of comma separated HTTP status codes which may be preceded by a single "!" to indicate
 *      negation. If the status code is not in the list the literal string "-" will be logged instead of
 *      the resulting value from the percent code.
 *  {PARAM}:
 *      Parameter string which may be optional depending on the percent code used.
 *  CODE:
 *      A one or two character code specified by the {@link CustomRequestLog} table of format codes.
 *  
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Format Codes
Format StringDescription
%%The percent sign.
%{format}a * Address or Hostname. Valid formats are {server, client, local, remote} * Optional format parameter which will be server by default. *
* Where server and client are the logical addresses which can be modified in the request headers, while local and * remote are the physical addresses so may be a proxy between the end-user and the server. *
%{format}p * Port. Valid formats are {server, client, local, remote} * Optional format parameter which will be server by default. *
* Where server and client are the logical ports which can be modified in the request headers, while local and * remote are the physical ports so may be to a proxy between the end-user and the server. *
%{CLF}I * Size of request in bytes, excluding HTTP headers. * Optional parameter with value of "CLF" to use CLF format, i.e. a '-' rather than a 0 when no bytes are sent. *
%{CLF}O * Size of response in bytes, excluding HTTP headers. * Optional parameter with value of "CLF" to use CLF format, i.e. a '-' rather than a 0 when no bytes are sent. *
%{CLF}S * Bytes transferred (received and sent). This is the combination of %I and %O. * Optional parameter with value of "CLF" to use CLF format, i.e. a '-' rather than a 0 when no bytes are sent. *
%{VARNAME}C * The contents of cookie VARNAME in the request sent to the server. Only version 0 cookies are fully supported. * Optional VARNAME parameter, without this parameter %C will log all cookies from the request. *
%DThe time taken to serve the request, in microseconds.
%{VARNAME}eThe contents of the environment variable VARNAME.
%fFilename.
%HThe name and version of the request protocol, such as "HTTP/1.1".
%{VARNAME}iThe contents of VARNAME: header line(s) in the request sent to the server.
%kNumber of keepalive requests handled on this connection. * Interesting if KeepAlive is being used, so that, for example, a '1' means the first keepalive request * after the initial one, '2' the second, etc...; otherwise this is always 0 (indicating the initial request).
%mThe request method.
%{VARNAME}oThe contents of VARNAME: header line(s) in the response.
%qThe query string (prepended with a ? if a query string exists, otherwise an empty string).
%rFirst line of request.
%RThe handler generating the response (if any).
%sResponse status.
%{format|timeZone|locale}t * The time that the request was received. * Optional parameter in one of the following formats {format}, {format|timeZone} or {format|timeZone|locale}.

* *
 *  Format Parameter: (default format [18/Sep/2011:19:18:28 -0400] where the last number indicates the timezone offset from GMT.)
 *      Must be in a format supported by {@link DateCache}
 *
 *  TimeZone Parameter:
 *      Default timeZone GMT
 *      Must be in a format supported by {@link TimeZone#getTimeZone(String)}
 *
 *  Locale Parameter:
 *      Default locale {@link Locale#getDefault()}
 *      Must be in a format supported by {@link Locale#forLanguageTag(String)}
*
%TThe time taken to serve the request, in seconds.
%{UNIT}TThe time taken to serve the request, in a time unit given by UNIT. * Valid units are ms for milliseconds, us for microseconds, and s for seconds. * Using s gives the same result as %T without any format; using us gives the same result as %D.
%{d}u * Remote user if the request was authenticated with servlet authentication. May be bogus if return status (%s) is 401 (unauthorized). * Optional parameter d, with this parameter deferred authentication will also be checked, * this is equivalent to {@link HttpServletRequest#getRemoteUser()}. *
%UThe URL path requested, not including any query string.
%X * Connection status when response is completed: *
 *  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.
*
%{VARNAME}^tiThe contents of VARNAME: trailer line(s) in the request sent to the server.
%{VARNAME}^toThe contents of VARNAME: trailer line(s) in the response sent from the server.
* * @deprecated The Eclipse Jetty and Apache Felix Http Jetty packages are no longer supported. */ @ManagedObject("Custom format request log") @Deprecated(since = "2021-05-27") public class CustomRequestLog extends ContainerLifeCycle implements RequestLog { protected static final Logger LOG = Log.getLogger(CustomRequestLog.class); public static final String DEFAULT_DATE_FORMAT = "dd/MMM/yyyy:HH:mm:ss ZZZ"; public static final String NCSA_FORMAT = "%{client}a - %u %t \"%r\" %s %O"; public static final String EXTENDED_NCSA_FORMAT = NCSA_FORMAT + " \"%{Referer}i\" \"%{User-Agent}i\""; private static final ThreadLocal _buffers = ThreadLocal.withInitial(() -> new StringBuilder(256)); private final RequestLog.Writer _requestLogWriter; private final MethodHandle _logHandle; private final String _formatString; private transient PathMappings _ignorePathMap; private String[] _ignorePaths; public CustomRequestLog(RequestLog.Writer writer, String formatString) { _formatString = formatString; _requestLogWriter = writer; addBean(_requestLogWriter); try { _logHandle = getLogHandle(formatString); } catch (NoSuchMethodException | IllegalAccessException e) { throw new IllegalStateException(e); } } public CustomRequestLog(String file) { this(file, EXTENDED_NCSA_FORMAT); } public CustomRequestLog(String file, String format) { this(new RequestLogWriter(file), format); } @ManagedAttribute("The RequestLogWriter") public RequestLog.Writer getWriter() { return _requestLogWriter; } /** * Writes the request and response information to the output stream. * * @see org.eclipse.jetty.server.RequestLog#log(Request, Response) */ @Override public void log(Request request, Response response) { try { if (_ignorePathMap != null && _ignorePathMap.getMatched(request.getRequestURI()) != null) return; StringBuilder sb = _buffers.get(); sb.setLength(0); _logHandle.invoke(sb, request, response); String log = sb.toString(); _requestLogWriter.write(log); } catch (Throwable e) { LOG.warn(e); } } /** * Extract the user authentication * * @param request The request to extract from * @param checkDeferred Whether to check for deferred authentication * @return The string to log for authenticated user. */ protected static String getAuthentication(Request request, boolean checkDeferred) { Authentication authentication = request.getAuthentication(); if (checkDeferred && authentication instanceof Authentication.Deferred) authentication = ((Authentication.Deferred) authentication).authenticate(request); String name = null; if (authentication instanceof Authentication.User) name = ((Authentication.User) authentication).getUserIdentity().getUserPrincipal().getName(); return name; } /** * Set request paths that will not be logged. * * @param ignorePaths array of request paths */ public void setIgnorePaths(String[] ignorePaths) { _ignorePaths = ignorePaths; } /** * Retrieve the request paths that will not be logged. * * @return array of request paths */ public String[] getIgnorePaths() { return _ignorePaths; } /** * Retrieve the format string. * * @return the format string */ @ManagedAttribute("format string") public String getFormatString() { return _formatString; } /** * Set up request logging and open log file. * * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() */ @Override protected synchronized void doStart() throws Exception { if (_ignorePaths != null && _ignorePaths.length > 0) { _ignorePathMap = new PathMappings<>(); for (String ignorePath : _ignorePaths) { _ignorePathMap.put(ignorePath, ignorePath); } } else _ignorePathMap = null; super.doStart(); } private static void append(StringBuilder buf, String s) { if (s == null || s.length() == 0) buf.append('-'); else buf.append(s); } private static void append(String s, StringBuilder buf) { append(buf, s); } private MethodHandle getLogHandle(String formatString) throws NoSuchMethodException, IllegalAccessException { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle append = lookup.findStatic(CustomRequestLog.class, "append", methodType(void.class, String.class, StringBuilder.class)); MethodHandle logHandle = lookup.findStatic(CustomRequestLog.class, "logNothing", methodType(void.class, StringBuilder.class, Request.class, Response.class)); List tokens = getTokens(formatString); Collections.reverse(tokens); for (Token t : tokens) { if (t.isLiteralString()) logHandle = updateLogHandle(logHandle, append, t.literal); else if (t.isPercentCode()) logHandle = updateLogHandle(logHandle, append, lookup, t.code, t.arg, t.modifiers, t.negated); else throw new IllegalStateException("bad token " + t); } return logHandle; } private static List getTokens(String formatString) { /* Extracts literal strings and percent codes out of the format string. We will either match a percent code of the format %MODIFIERS{PARAM}CODE, or a literal string until the next percent code or the end of the formatString is reached. where MODIFIERS is an optional comma separated list of numbers. {PARAM} is an optional string parameter to the percent code. CODE is a 1 to 2 character string corresponding to a format code. */ final Pattern PATTERN = Pattern.compile("^(?:%(?!?[0-9,]+)?(?:\\{(?[^}]+)})?(?(?:(?:ti)|(?:to)|[a-zA-Z%]))|(?[^%]+))(?.*)", Pattern.DOTALL | Pattern.MULTILINE); List tokens = new ArrayList<>(); String remaining = formatString; while (remaining.length() > 0) { Matcher m = PATTERN.matcher(remaining); if (m.matches()) { if (m.group("CODE") != null) { String code = m.group("CODE"); String arg = m.group("ARG"); String modifierString = m.group("MOD"); List modifiers = null; boolean negated = false; if (modifierString != null) { if (modifierString.startsWith("!")) { modifierString = modifierString.substring(1); negated = true; } modifiers = new QuotedCSV(modifierString).getValues().stream().map(Integer::parseInt).collect(Collectors.toList()); } tokens.add(new Token(code, arg, modifiers, negated)); } else if (m.group("LITERAL") != null) { String literal = m.group("LITERAL"); tokens.add(new Token(literal)); } else { throw new IllegalStateException("formatString parsing error"); } remaining = m.group("REMAINING"); } else { throw new IllegalArgumentException("Invalid format string"); } } return tokens; } // @deprecated The Eclipse Jetty and Apache Felix Http Jetty packages are no longer supported. @Deprecated(since = "2021-05-27") private static class Token { public final String code; public final String arg; public final List modifiers; public final boolean negated; public final String literal; public Token(String code, String arg, List modifiers, boolean negated) { this.code = code; this.arg = arg; this.modifiers = modifiers; this.negated = negated; this.literal = null; } public Token(String literal) { this.code = null; this.arg = null; this.modifiers = null; this.negated = false; this.literal = literal; } public boolean isLiteralString() { return (literal != null); } public boolean isPercentCode() { return (code != null); } } @SuppressWarnings("unused") private static boolean modify(List modifiers, Boolean negated, StringBuilder b, Request request, Response response) { if (negated) return !modifiers.contains(response.getStatus()); else return modifiers.contains(response.getStatus()); } private MethodHandle updateLogHandle(MethodHandle logHandle, MethodHandle append, String literal) { return foldArguments(logHandle, dropArguments(dropArguments(append.bindTo(literal), 1, Request.class), 2, Response.class)); } private MethodHandle updateLogHandle(MethodHandle logHandle, MethodHandle append, MethodHandles.Lookup lookup, String code, String arg, List modifiers, boolean negated) throws NoSuchMethodException, IllegalAccessException { MethodType logType = methodType(void.class, StringBuilder.class, Request.class, Response.class); MethodType logTypeArg = methodType(void.class, String.class, StringBuilder.class, Request.class, Response.class); // TODO should we throw IllegalArgumentExceptions when given arguments for codes which do not take them MethodHandle specificHandle; switch(code) { case "%": { specificHandle = dropArguments(dropArguments(append.bindTo("%"), 1, Request.class), 2, Response.class); break; } case "a": { if (StringUtil.isEmpty(arg)) arg = "server"; String method; switch(arg) { case "server": method = "logServerHost"; break; case "client": method = "logClientHost"; break; case "local": method = "logLocalHost"; break; case "remote": method = "logRemoteHost"; break; default: throw new IllegalArgumentException("Invalid arg for %a"); } specificHandle = lookup.findStatic(CustomRequestLog.class, method, logType); break; } case "p": { if (StringUtil.isEmpty(arg)) arg = "server"; String method; switch(arg) { case "server": method = "logServerPort"; break; case "client": method = "logClientPort"; break; case "local": method = "logLocalPort"; break; case "remote": method = "logRemotePort"; break; default: throw new IllegalArgumentException("Invalid arg for %p"); } specificHandle = lookup.findStatic(CustomRequestLog.class, method, logType); break; } case "I": { String method; if (StringUtil.isEmpty(arg)) method = "logBytesReceived"; else if (arg.equalsIgnoreCase("clf")) method = "logBytesReceivedCLF"; else throw new IllegalArgumentException("Invalid argument for %I"); specificHandle = lookup.findStatic(CustomRequestLog.class, method, logType); break; } case "O": { String method; if (StringUtil.isEmpty(arg)) method = "logBytesSent"; else if (arg.equalsIgnoreCase("clf")) method = "logBytesSentCLF"; else throw new IllegalArgumentException("Invalid argument for %O"); specificHandle = lookup.findStatic(CustomRequestLog.class, method, logType); break; } case "S": { String method; if (StringUtil.isEmpty(arg)) method = "logBytesTransferred"; else if (arg.equalsIgnoreCase("clf")) method = "logBytesTransferredCLF"; else throw new IllegalArgumentException("Invalid argument for %S"); specificHandle = lookup.findStatic(CustomRequestLog.class, method, logType); break; } case "C": { if (StringUtil.isEmpty(arg)) { specificHandle = lookup.findStatic(CustomRequestLog.class, "logRequestCookies", logType); } else { specificHandle = lookup.findStatic(CustomRequestLog.class, "logRequestCookie", logTypeArg); specificHandle = specificHandle.bindTo(arg); } break; } case "D": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logLatencyMicroseconds", logType); break; } case "e": { if (StringUtil.isEmpty(arg)) throw new IllegalArgumentException("No arg for %e"); specificHandle = lookup.findStatic(CustomRequestLog.class, "logEnvironmentVar", logTypeArg); specificHandle = specificHandle.bindTo(arg); break; } case "f": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logFilename", logType); break; } case "H": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logRequestProtocol", logType); break; } case "i": { if (StringUtil.isEmpty(arg)) throw new IllegalArgumentException("No arg for %i"); specificHandle = lookup.findStatic(CustomRequestLog.class, "logRequestHeader", logTypeArg); specificHandle = specificHandle.bindTo(arg); break; } case "k": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logKeepAliveRequests", logType); break; } case "m": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logRequestMethod", logType); break; } case "o": { if (StringUtil.isEmpty(arg)) throw new IllegalArgumentException("No arg for %o"); specificHandle = lookup.findStatic(CustomRequestLog.class, "logResponseHeader", logTypeArg); specificHandle = specificHandle.bindTo(arg); break; } case "q": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logQueryString", logType); break; } case "r": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logRequestFirstLine", logType); break; } case "R": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logRequestHandler", logType); break; } case "s": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logResponseStatus", logType); break; } case "t": { String format = DEFAULT_DATE_FORMAT; TimeZone timeZone = TimeZone.getTimeZone("GMT"); Locale locale = Locale.getDefault(); if (arg != null && !arg.isEmpty()) { String[] args = arg.split("\\|"); switch(args.length) { case 1: format = args[0]; break; case 2: format = args[0]; timeZone = TimeZone.getTimeZone(args[1]); break; case 3: format = args[0]; timeZone = TimeZone.getTimeZone(args[1]); locale = Locale.forLanguageTag(args[2]); break; default: throw new IllegalArgumentException("Too many \"|\" characters in %t"); } } DateCache logDateCache = new DateCache(format, locale, timeZone); MethodType logTypeDateCache = methodType(void.class, DateCache.class, StringBuilder.class, Request.class, Response.class); specificHandle = lookup.findStatic(CustomRequestLog.class, "logRequestTime", logTypeDateCache); specificHandle = specificHandle.bindTo(logDateCache); break; } case "T": { if (arg == null) arg = "s"; String method; switch(arg) { case "s": method = "logLatencySeconds"; break; case "us": method = "logLatencyMicroseconds"; break; case "ms": method = "logLatencyMilliseconds"; break; default: throw new IllegalArgumentException("Invalid arg for %T"); } specificHandle = lookup.findStatic(CustomRequestLog.class, method, logType); break; } case "u": { String method; if (StringUtil.isEmpty(arg)) method = "logRequestAuthentication"; else if ("d".equals(arg)) method = "logRequestAuthenticationWithDeferred"; else throw new IllegalArgumentException("Invalid arg for %u: " + arg); specificHandle = lookup.findStatic(CustomRequestLog.class, method, logType); break; } case "U": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logUrlRequestPath", logType); break; } case "X": { specificHandle = lookup.findStatic(CustomRequestLog.class, "logConnectionStatus", logType); break; } case "ti": { if (StringUtil.isEmpty(arg)) throw new IllegalArgumentException("No arg for %ti"); specificHandle = lookup.findStatic(CustomRequestLog.class, "logRequestTrailer", logTypeArg); specificHandle = specificHandle.bindTo(arg); break; } case "to": { if (StringUtil.isEmpty(arg)) throw new IllegalArgumentException("No arg for %to"); specificHandle = lookup.findStatic(CustomRequestLog.class, "logResponseTrailer", logTypeArg); specificHandle = specificHandle.bindTo(arg); break; } default: throw new IllegalArgumentException("Unsupported code %" + code); } if (modifiers != null && !modifiers.isEmpty()) { MethodHandle dash = updateLogHandle(logHandle, append, "-"); MethodHandle log = foldArguments(logHandle, specificHandle); MethodHandle modifierTest = lookup.findStatic(CustomRequestLog.class, "modify", methodType(Boolean.TYPE, List.class, Boolean.class, StringBuilder.class, Request.class, Response.class)); modifierTest = modifierTest.bindTo(modifiers).bindTo(negated); return MethodHandles.guardWithTest(modifierTest, log, dash); } return foldArguments(logHandle, specificHandle); } // -----------------------------------------------------------------------------------// @SuppressWarnings("unused") private static void logNothing(StringBuilder b, Request request, Response response) { } @SuppressWarnings("unused") private static void logServerHost(StringBuilder b, Request request, Response response) { append(b, request.getServerName()); } @SuppressWarnings("unused") private static void logClientHost(StringBuilder b, Request request, Response response) { append(b, request.getRemoteHost()); } @SuppressWarnings("unused") private static void logLocalHost(StringBuilder b, Request request, Response response) { append(b, request.getHttpChannel().getEndPoint().getLocalAddress().getAddress().getHostAddress()); } @SuppressWarnings("unused") private static void logRemoteHost(StringBuilder b, Request request, Response response) { append(b, request.getHttpChannel().getEndPoint().getRemoteAddress().getAddress().getHostAddress()); } @SuppressWarnings("unused") private static void logServerPort(StringBuilder b, Request request, Response response) { b.append(request.getServerPort()); } @SuppressWarnings("unused") private static void logClientPort(StringBuilder b, Request request, Response response) { b.append(request.getRemotePort()); } @SuppressWarnings("unused") private static void logLocalPort(StringBuilder b, Request request, Response response) { b.append(request.getHttpChannel().getEndPoint().getLocalAddress().getPort()); } @SuppressWarnings("unused") private static void logRemotePort(StringBuilder b, Request request, Response response) { b.append(request.getHttpChannel().getEndPoint().getRemoteAddress().getPort()); } @SuppressWarnings("unused") private static void logResponseSize(StringBuilder b, Request request, Response response) { long written = response.getHttpChannel().getBytesWritten(); b.append(written); } @SuppressWarnings("unused") private static void logResponseSizeCLF(StringBuilder b, Request request, Response response) { long written = response.getHttpChannel().getBytesWritten(); if (written == 0) b.append('-'); else b.append(written); } @SuppressWarnings("unused") private static void logBytesSent(StringBuilder b, Request request, Response response) { b.append(response.getHttpChannel().getBytesWritten()); } @SuppressWarnings("unused") private static void logBytesSentCLF(StringBuilder b, Request request, Response response) { long sent = response.getHttpChannel().getBytesWritten(); if (sent == 0) b.append('-'); else b.append(sent); } @SuppressWarnings("unused") private static void logBytesReceived(StringBuilder b, Request request, Response response) { b.append(request.getHttpInput().getContentReceived()); } @SuppressWarnings("unused") private static void logBytesReceivedCLF(StringBuilder b, Request request, Response response) { long received = request.getHttpInput().getContentReceived(); if (received == 0) b.append('-'); else b.append(received); } @SuppressWarnings("unused") private static void logBytesTransferred(StringBuilder b, Request request, Response response) { b.append(request.getHttpInput().getContentReceived() + response.getHttpOutput().getWritten()); } @SuppressWarnings("unused") private static void logBytesTransferredCLF(StringBuilder b, Request request, Response response) { long transferred = request.getHttpInput().getContentReceived() + response.getHttpOutput().getWritten(); if (transferred == 0) b.append('-'); else b.append(transferred); } @SuppressWarnings("unused") private static void logRequestCookie(String arg, StringBuilder b, Request request, Response response) { Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie c : cookies) { if (arg.equals(c.getName())) { b.append(c.getValue()); return; } } } b.append('-'); } @SuppressWarnings("unused") private static void logRequestCookies(StringBuilder b, Request request, Response response) { Cookie[] cookies = request.getCookies(); if (cookies == null || cookies.length == 0) b.append("-"); else { for (int i = 0; i < cookies.length; i++) { if (i != 0) b.append(';'); b.append(cookies[i].getName()); b.append('='); b.append(cookies[i].getValue()); } } } @SuppressWarnings("unused") private static void logEnvironmentVar(String arg, StringBuilder b, Request request, Response response) { append(b, System.getenv(arg)); } @SuppressWarnings("unused") private static void logFilename(StringBuilder b, Request request, Response response) { UserIdentity.Scope scope = request.getUserIdentityScope(); if (scope == null || scope.getContextHandler() == null) b.append('-'); else { ContextHandler context = scope.getContextHandler(); int lengthToStrip = scope.getContextPath().length() > 1 ? scope.getContextPath().length() : 0; String filename = context.getServletContext().getRealPath(request.getPathInfo().substring(lengthToStrip)); append(b, filename); } } @SuppressWarnings("unused") private static void logRequestProtocol(StringBuilder b, Request request, Response response) { append(b, request.getProtocol()); } @SuppressWarnings("unused") private static void logRequestHeader(String arg, StringBuilder b, Request request, Response response) { append(b, request.getHeader(arg)); } @SuppressWarnings("unused") private static void logKeepAliveRequests(StringBuilder b, Request request, Response response) { long requests = request.getHttpChannel().getConnection().getMessagesIn(); if (requests >= 0) b.append(requests); else b.append('-'); } @SuppressWarnings("unused") private static void logRequestMethod(StringBuilder b, Request request, Response response) { append(b, request.getMethod()); } @SuppressWarnings("unused") private static void logResponseHeader(String arg, StringBuilder b, Request request, Response response) { append(b, response.getHeader(arg)); } @SuppressWarnings("unused") private static void logQueryString(StringBuilder b, Request request, Response response) { append(b, "?" + request.getQueryString()); } @SuppressWarnings("unused") private static void logRequestFirstLine(StringBuilder b, Request request, Response response) { append(b, request.getMethod()); b.append(" "); append(b, request.getOriginalURI()); b.append(" "); append(b, request.getProtocol()); } @SuppressWarnings("unused") private static void logRequestHandler(StringBuilder b, Request request, Response response) { append(b, request.getServletName()); } @SuppressWarnings("unused") private static void logResponseStatus(StringBuilder b, Request request, Response response) { b.append(response.getCommittedMetaData().getStatus()); } @SuppressWarnings("unused") private static void logRequestTime(DateCache dateCache, StringBuilder b, Request request, Response response) { b.append('['); append(b, dateCache.format(request.getTimeStamp())); b.append(']'); } @SuppressWarnings("unused") private static void logLatencyMicroseconds(StringBuilder b, Request request, Response response) { long currentTime = System.currentTimeMillis(); long requestTime = request.getTimeStamp(); long latencyMs = currentTime - requestTime; long latencyUs = TimeUnit.MILLISECONDS.toMicros(latencyMs); b.append(latencyUs); } @SuppressWarnings("unused") private static void logLatencyMilliseconds(StringBuilder b, Request request, Response response) { long latency = System.currentTimeMillis() - request.getTimeStamp(); b.append(latency); } @SuppressWarnings("unused") private static void logLatencySeconds(StringBuilder b, Request request, Response response) { long latency = System.currentTimeMillis() - request.getTimeStamp(); b.append(TimeUnit.MILLISECONDS.toSeconds(latency)); } @SuppressWarnings("unused") private static void logRequestAuthentication(StringBuilder b, Request request, Response response) { append(b, getAuthentication(request, false)); } @SuppressWarnings("unused") private static void logRequestAuthenticationWithDeferred(StringBuilder b, Request request, Response response) { append(b, getAuthentication(request, true)); } @SuppressWarnings("unused") private static void logUrlRequestPath(StringBuilder b, Request request, Response response) { append(b, request.getRequestURI()); } @SuppressWarnings("unused") private static void logConnectionStatus(StringBuilder b, Request request, Response response) { b.append(request.getHttpChannel().isResponseCompleted() ? (request.getHttpChannel().isPersistent() ? '+' : '-') : 'X'); } @SuppressWarnings("unused") private static void logRequestTrailer(String arg, StringBuilder b, Request request, Response response) { HttpFields trailers = request.getTrailers(); if (trailers != null) append(b, trailers.get(arg)); else b.append('-'); } @SuppressWarnings("unused") private static void logResponseTrailer(String arg, StringBuilder b, Request request, Response response) { Supplier supplier = response.getTrailers(); if (supplier != null) { HttpFields trailers = supplier.get(); if (trailers != null) append(b, trailers.get(arg)); else b.append('-'); } else b.append("-"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy