This is my 18th day of the August Genwen Challenge

This series code address: github.com/HashZhang/s…

Server: undertow: # accesslog accesslog: # Log dir:./log True # format, with various placeholders specifying pattern: '{ "transportProtocol":"%{TRANSPORT_PROTOCOL}", "scheme":"%{SCHEME}", "protocol":"%{PROTOCOL}", "method":"%{METHOD}", "reqHeaderUserAgent":"%{i,User-Agent}", "cookieUserId": "%{c,userId}", "queryTest": "%{q,test}", "queryString": "%q", "relativePath": "%R, %{REQUEST_PATH}, %{RESOLVED_PATH}", "requestLine": "%r", "uri": "%U", "thread": "%I", "hostPort": "%{HOST_AND_PORT}", "localIp": "%A", "localPort": "%p", "localServerName": "%v", "remoteIp": "%a", "remoteHost": "%h", "bytesSent": "%b", "time":"%{time,yyyy-MM-dd HH:mm:ss.S}", "status":"%s", "reason":"%{RESPONSE_REASON_PHRASE}", "respHeaderUserSession":"%{o,userSession}", "respCookieUserId":"%{resp-cookie,userId}", "timeUsed":"%Dms, %Ts, %{RESPONSE_TIME}ms, %{RESPONSE_TIME_MICROS} us, %{RESPONSE_TIME_NANOS} ns",}' # access_log prefix: Log. # File suffix, default log suffix: log # Whether to create log files to write access logs, the default is true # Currently, only the date can be rotated, one log file a day rotate: trueCopy the code

Undertow accesslog processing core class abstraction is IO Undertow. Server. Handlers. The accesslog. AccesslogReceiver. There is only one because the Undertow AccesslogReceiver implementation in use, namely IO. Undertow. Server. Handlers. Accesslog. DefaultAccessLogReceiver.

View the rotate of DefaultAccessLogReceiver:

DefaultAccessLogReceiver

/** * Compute rotate time point */ private void calculateChangeOverPoint() {Calendar = calendar.getInstance (); /** * compute rotate time point */ private void calculateChangeOverPoint() {Calendar = calendar.getinstance (); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.HOUR_OF_DAY, 0); Calendar.add (calendar.date, 1); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.US); currentDateString = df.format(new Date()); // if there is an existing default log file, use the date last modified instead of the current date if (Files.exists(defaultLogFile)) { try { currentDateString = df.format(new Date(Files.getLastModifiedTime(defaultLogFile).toMillis())); } catch(IOException e){// ignore. use the current date if exception happens.} // Rotate time is 0 on the next day changeOverPoint =  calendar.getTimeInMillis(); }Copy the code

The accesslog placeholder in Undertow is a property abstracted from the HTTP Server Exchange after the Undertow Listener resolves the request.

The table in the official documentation is not exhaustive, and note that it does not specify, for example, that certain placeholders must have Undertow features on in order to use them. So let’s list it here.

First of all, the argument placeholders, such as %{I, the value of the header you want to look at} look at one of the key values of the header. Make sure there is no space after the comma, because this space will count into the key and not get the key you want.

Request related attributes

describe Abbreviation placeholder Full name placeholder Parameter placeholder The source code
Request transport protocol, equivalent toRequest protocol There is no %{TRANSPORT_PROTOCOL} There is no TransportProtocolAttribute
Request mode, such as HTTP or HTTPS %{SCHEME} There is no RequestSchemeAttribute
Request protocol, for exampleHTTP / 1.1 %H %{PROTOCOL} There is no RequestProtocolAttribute
Request methods such as GET, POST, and so on %m %{METHOD} There is no RequestMethodAttribute
Request a value of the Header There is no There is no %{I, you want to see the header value} RequestHeaderAttribute
Some value of the Cookie There is no There is no %{c, you want to see the cookie value}or%{req-cookie, you want to see the cookie value} correspondingCookieAttributeRequestCookieAttribute
The path parameter PathVariable is not processed by Undertow’s Listener or Handler, so it cannot be intercepted and cannot be confirmed whether it is a PathVariable or a URL path. So,Placeholders for PathVariable will not work. There is no There is no %{p, you want to view the path parameter key} PathParameterAttribute
The request parameter, that is, the url’s? And then key-value pairs, where you can choose to look at the value of a particular key. There is no There is no %{q, the request key you want to view} QueryParameterAttribute
The request parameter string, which is the url’s? All subsequent characters} %q(Not included?) %{QUERY_STRING}(Not included?) ;%{BARE_QUERY_STRING}(contain? There is no QueryStringAttribute
Request RelativePath (in Spring Boot, RequestPath is equivalent to RelativePath and ResolvedPath in most cases), which excludes the host, port, and request parameter strings %R %{RELATIVE_PATH}or%{REQUEST_PATH}or%{RESOLVED_PATH} There is no correspondingRelativePathAttributeRequestPathAttributeResolvedPathAttribute
Request overall string, including request method, request relative path, request parameter string, request protocol, for exampleGet /test? A = b HTTP / 1.1 %r %{REQUEST_LINE} There is no RequestLineAttribute
Request URI, including request relative path, request parameter string %U %{REQUEST_URL} There is no RequestURLAttribute
The thread that processes the request %I %{THREAD_NAME} There is no ThreadNameAttribute

Note:

  1. The path parameter PathVariable is not processed by Undertow’s Listener or Handler, so it cannot be intercepted and cannot be confirmed whether it is a PathVariable or a URL path. Therefore, placeholders for PathVariable will not work.

Request address correlation

describe Abbreviation placeholder Full name placeholder Parameter placeholder The source code
If host is null, the local address and port will be obtained. If no port is obtained, the default port will be used based on the protocol (HTTP :80, HTTPS :443). There is no %{HOST_AND_PORT} There is no HostAndPortAttribute
Request local address IP %A %{LOCAL_IP} There is no LocalIPAttribute
Request the local Port Port %p %{LOCAL_PORT} There is no LocalPortAttribute
Request the local Host name, usually the Host value in the HTTP request Header, or if Host is empty, get the local address %v %{LOCAL_SERVER_NAME} There is no LocalServerNameAttribute
Request the remote host name and get the remote host address through the connection %h %{REMOTE_HOST} There is no RemoteHostAttribute
Request a remote IP address and obtain the remote IP address through the connection %a %{REMOTE_IP} There is no RemoteIPAttribute

Note:

  1. The requested remote address is not usually obtained from the request connection, but from the Http HeaderX-forwarded-fororX-real-ipAnd so on, because now requests are sent through various VPNS, load balancers.

Response-dependent attributes

describe Abbreviation placeholder Full name placeholder Parameter placeholder The source code
Size of bytes sent, except Http headers %b(if it is empty it is -) or%B(0 if null) %{BYTES_SENT}(0 if null) There is no BytesSentAttribute
Accesslog time, which is not the time to receive the request, but the time to respond %t %{DATE_TIME} %{time, you customize the format of SimpleDateFormat in Java} DateTimeAttribute
HTTP response status code %s %{RESPONSE_CODE} There is no ResponseCodeAttribute
HTTP Response Causes There is no %{RESPONSE_REASON_PHRASE} There is no ResponseReasonPhraseAttribute
Respond to a value of the Header There is no There is no %{o, you want to see the header value} ResponseHeaderAttribute
Responds to a value of the Cookie There is no There is no %{resp-cookie, you want to see the cookie value} ResponseCookieAttribute
Response time,By default, undertow does not enable request-time statistics, which can be used to calculate response time %D(ms, for example, 56 for 56ms)%T(seconds, for example 5.067 for 5.067 seconds) %{RESPONSE_TIME}(equivalent to the%D) %{RESPONSE_TIME_MICROS}(in milliseconds)%{RESPONSE_TIME_NANOS}(ns) There is no ResponseTimeAttribute

Note: Undertow does not enable request time statistics by default. It needs to be enabled to calculate response time. How to enable it? By registering a WebServerFactoryCustomizer to Spring ApplicationContext. Look at the code below (project address: github.com/HashZhang/s…) :

spring.factories(Omit irrelevant code)

# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.github.hashjang.spring.cloud.iiford.service.common.auto.UndertowAutoConfiguration
Copy the code

UndertowAutoConfiguration

// Set proxyBeanMethods=false, because no @bean methods call each other and return the same Bean every time, no proxy is necessary, Close to increase startup @ the Configuration (proxyBeanMethods = false) @ Import (WebServerConfiguration. Class) public class UndertowAutoConfiguration { }Copy the code

WebServerConfiguration

// Set proxyBeanMethods=false, because no @bean methods call each other and return the same Bean every time, no proxy is necessary, @configuration (proxyBeanMethods = false) public class WebServerConfiguration {@bean public WebServerFactoryCustomizer<ConfigurableUndertowWebServerFactory> undertowWebServerAccessLogTimingEnabler(ServerProperties serverProperties) { return new DefaultWebServerFactoryCustomizer(serverProperties); }}Copy the code

DefaultWebServerFactoryCustomizer

public class DefaultWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableUndertowWebServerFactory> { private final ServerProperties serverProperties; public DefaultWebServerFactoryCustomizer(ServerProperties serverProperties) { this.serverProperties = serverProperties; } @Override public void customize(ConfigurableUndertowWebServerFactory factory) { String pattern = serverProperties.getUndertow().getAccesslog().getPattern(); If the response time is printed in the accesslog configuration, Open a record request start time configure if (logRequestProcessingTiming (pattern)) {factory. AddBuilderCustomizers (builder - > builder.setServerOption(UndertowOptions.RECORD_REQUEST_START_TIME, true)); } } private boolean logRequestProcessingTiming(String pattern) { if (StringUtils.isBlank(pattern)) { return false; } / / whether accesslog configuration view response time return pattern. The contains (ResponseTimeAttribute. RESPONSE_TIME_MICROS) | | pattern.contains(ResponseTimeAttribute.RESPONSE_TIME_MILLIS) || pattern.contains(ResponseTimeAttribute.RESPONSE_TIME_NANOS) || pattern.contains(ResponseTimeAttribute.RESPONSE_TIME_MILLIS_SHORT) || pattern.contains(ResponseTimeAttribute.RESPONSE_TIME_SECONDS_SHORT); }}Copy the code

other

There are also security-related attributes (SSL related, login Authentication related) that are not generally used for internal microservice calls, so we won’t go into them here. Other built-in properties, which are generally not used in a Spring Boot environment, will not be discussed here.

For example,

The example accessLog request we initially configured returns the following (JSON formatted) :

TransportProtocol: "HTTP/1.1", "Scheme ": "HTTP ", "protocol": "HTTP/1.1", "method": "GET", "reqHeaderUserAgent": PostmanRuntime/7.26.10", "cookieUserId": "testreQuestUserId ", "queryTest": "1", "queryString": "? test=1&query=2", "relativePath": "/test, /test, -", "requestLine": "GET /test? Test = 1 & query = 2 HTTP / 1.1 ", "uri" : "/ test", "thread" : "XNIO task - 2-1", "hostPort" : "127.0.0.1:8102", "localIp" : "127.0.0.1", "localPort" : "8102", "localServerName" : "127.0.0.1", "remoteIp" : "127.0.0.1", "remoteHost" : "127.0.0.1", "bytesSent" : "26", "time", "the 2021-04-08 00:07:50. 410", "status" : "200", "" reason" : "OK", "respHeaderUserSession": "testResponseHeaderUserSession", "respCookieUserId": "TestResponseCookieUserId ", "timeUsed": "3683ms, 3.683s, 3683ms, 3683149 us, 3683149200 ns",}Copy the code

In this section, we introduce how to configure Undertow’s Accesslog in detail. Various placeholders for accesslog are listed. Users can configure their desired accesslog information and format according to these information. In the next section, we’ll take a closer look at the custom code for Undertow in our framework

Wechat search “my programming meow” public account, a daily brush, easy to improve skills, won a variety of offers: