Skip to content

Commit fa4e878

Browse files
wodifyabatkin
authored andcommitted
Add support for %I, %S, %T and %q in access log PatternLayout
1 parent 993b3cc commit fa4e878

File tree

9 files changed

+213
-6
lines changed

9 files changed

+213
-6
lines changed

logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import ch.qos.logback.access.pattern.ContentLengthConverter;
1717
import ch.qos.logback.access.pattern.DateConverter;
18+
import ch.qos.logback.access.pattern.ElapsedSecondsConverter;
1819
import ch.qos.logback.access.pattern.ElapsedTimeConverter;
1920
import ch.qos.logback.access.pattern.EnsureLineSeparation;
2021
import ch.qos.logback.access.pattern.FullRequestConverter;
@@ -23,6 +24,7 @@
2324
import ch.qos.logback.access.pattern.LocalIPAddressConverter;
2425
import ch.qos.logback.access.pattern.LocalPortConverter;
2526
import ch.qos.logback.access.pattern.NAConverter;
27+
import ch.qos.logback.access.pattern.QueryStringConverter;
2628
import ch.qos.logback.access.pattern.RemoteHostConverter;
2729
import ch.qos.logback.access.pattern.RemoteIPAddressConverter;
2830
import ch.qos.logback.access.pattern.RemoteUserConverter;
@@ -37,8 +39,10 @@
3739
import ch.qos.logback.access.pattern.RequestURLConverter;
3840
import ch.qos.logback.access.pattern.ResponseContentConverter;
3941
import ch.qos.logback.access.pattern.ResponseHeaderConverter;
42+
import ch.qos.logback.access.pattern.SessionIDConverter;
4043
import ch.qos.logback.access.pattern.ServerNameConverter;
4144
import ch.qos.logback.access.pattern.StatusCodeConverter;
45+
import ch.qos.logback.access.pattern.ThreadNameConverter;
4246
import ch.qos.logback.access.spi.IAccessEvent;
4347
import ch.qos.logback.core.pattern.PatternLayoutBase;
4448
import ch.qos.logback.core.pattern.color.*;
@@ -98,18 +102,27 @@ public class PatternLayout extends PatternLayoutBase<IAccessEvent> {
98102
defaultConverterMap.put("i", RequestHeaderConverter.class.getName());
99103
defaultConverterMap.put("header", RequestHeaderConverter.class.getName());
100104

105+
defaultConverterMap.put("I", ThreadNameConverter.class.getName());
106+
defaultConverterMap.put("threadName", ThreadNameConverter.class.getName());
107+
101108
defaultConverterMap.put("l", NAConverter.class.getName());
102109

103110
defaultConverterMap.put("m", RequestMethodConverter.class.getName());
104111
defaultConverterMap.put("requestMethod", RequestMethodConverter.class
105112
.getName());
106113

114+
defaultConverterMap.put("q", QueryStringConverter.class.getName());
115+
defaultConverterMap.put("queryString", QueryStringConverter.class.getName());
116+
107117
defaultConverterMap.put("r", RequestURLConverter.class.getName());
108118
defaultConverterMap.put("requestURL", RequestURLConverter.class.getName());
109119

110120
defaultConverterMap.put("s", StatusCodeConverter.class.getName());
111121
defaultConverterMap.put("statusCode", StatusCodeConverter.class.getName());
112122

123+
defaultConverterMap.put("S", SessionIDConverter.class.getName());
124+
defaultConverterMap.put("sessionID", SessionIDConverter.class.getName());
125+
113126
defaultConverterMap.put("t", DateConverter.class.getName());
114127
defaultConverterMap.put("date", DateConverter.class.getName());
115128

@@ -151,6 +164,9 @@ public class PatternLayout extends PatternLayoutBase<IAccessEvent> {
151164
defaultConverterMap.put("fullRequest", FullRequestConverter.class.getName());
152165
defaultConverterMap.put("fullResponse", FullResponseConverter.class.getName());
153166

167+
defaultConverterMap.put("elapsedSeconds", ElapsedSecondsConverter.class.getName());
168+
defaultConverterMap.put("T", ElapsedSecondsConverter.class.getName());
169+
154170
defaultConverterMap.put("elapsedTime", ElapsedTimeConverter.class.getName());
155171
defaultConverterMap.put("D", ElapsedTimeConverter.class.getName());
156172

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Logback: the reliable, generic, fast and flexible logging framework.
3+
* Copyright (C) 1999-2013, QOS.ch. All rights reserved.
4+
*
5+
* This program and the accompanying materials are dual-licensed under
6+
* either the terms of the Eclipse Public License v1.0 as published by
7+
* the Eclipse Foundation
8+
*
9+
* or (per the licensee's choosing)
10+
*
11+
* under the terms of the GNU Lesser General Public License version 2.1
12+
* as published by the Free Software Foundation.
13+
*/
14+
package ch.qos.logback.access.pattern;
15+
16+
import ch.qos.logback.access.spi.IAccessEvent;
17+
18+
public class ElapsedSecondsConverter extends AccessConverter {
19+
20+
public String convert(IAccessEvent accessEvent) {
21+
return Long.toString(accessEvent.getElapsedSeconds());
22+
}
23+
24+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Logback: the reliable, generic, fast and flexible logging framework.
3+
* Copyright (C) 1999-2013, QOS.ch. All rights reserved.
4+
*
5+
* This program and the accompanying materials are dual-licensed under
6+
* either the terms of the Eclipse Public License v1.0 as published by
7+
* the Eclipse Foundation
8+
*
9+
* or (per the licensee's choosing)
10+
*
11+
* under the terms of the GNU Lesser General Public License version 2.1
12+
* as published by the Free Software Foundation.
13+
*/
14+
package ch.qos.logback.access.pattern;
15+
16+
import ch.qos.logback.access.spi.IAccessEvent;
17+
18+
public class QueryStringConverter extends AccessConverter {
19+
20+
public String convert(IAccessEvent accessEvent) {
21+
return accessEvent.getQueryString();
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Logback: the reliable, generic, fast and flexible logging framework.
3+
* Copyright (C) 1999-2013, QOS.ch. All rights reserved.
4+
*
5+
* This program and the accompanying materials are dual-licensed under
6+
* either the terms of the Eclipse Public License v1.0 as published by
7+
* the Eclipse Foundation
8+
*
9+
* or (per the licensee's choosing)
10+
*
11+
* under the terms of the GNU Lesser General Public License version 2.1
12+
* as published by the Free Software Foundation.
13+
*/
14+
package ch.qos.logback.access.pattern;
15+
16+
import ch.qos.logback.access.spi.IAccessEvent;
17+
18+
public class SessionIDConverter extends AccessConverter {
19+
20+
public String convert(IAccessEvent accessEvent) {
21+
return accessEvent.getSessionID();
22+
}
23+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Logback: the reliable, generic, fast and flexible logging framework.
3+
* Copyright (C) 1999-2013, QOS.ch. All rights reserved.
4+
*
5+
* This program and the accompanying materials are dual-licensed under
6+
* either the terms of the Eclipse Public License v1.0 as published by
7+
* the Eclipse Foundation
8+
*
9+
* or (per the licensee's choosing)
10+
*
11+
* under the terms of the GNU Lesser General Public License version 2.1
12+
* as published by the Free Software Foundation.
13+
*/
14+
package ch.qos.logback.access.pattern;
15+
16+
import ch.qos.logback.access.spi.IAccessEvent;
17+
18+
public class ThreadNameConverter extends AccessConverter {
19+
20+
public String convert(IAccessEvent accessEvent) {
21+
return accessEvent.getThreadName();
22+
}
23+
24+
}

logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import javax.servlet.http.Cookie;
2121
import javax.servlet.http.HttpServletRequest;
2222
import javax.servlet.http.HttpServletResponse;
23+
import javax.servlet.http.HttpSession;
2324

2425
import java.io.Serializable;
2526
import java.util.ArrayList;
@@ -51,14 +52,17 @@ public class AccessEvent implements Serializable, IAccessEvent {
5152
private transient final HttpServletRequest httpRequest;
5253
private transient final HttpServletResponse httpResponse;
5354

55+
String queryString;
5456
String requestURI;
5557
String requestURL;
5658
String remoteHost;
5759
String remoteUser;
5860
String remoteAddr;
61+
String threadName;
5962
String protocol;
6063
String method;
6164
String serverName;
65+
String sessionID;
6266
String requestContent;
6367
String responseContent;
6468
long elapsedTime;
@@ -125,6 +129,18 @@ public void setTimeStamp(long timeStamp) {
125129
}
126130
}
127131

132+
/**
133+
* @param threadName The threadName to set.
134+
*/
135+
public void setThreadName(String threadName) {
136+
this.threadName = threadName;
137+
}
138+
139+
@Override
140+
public String getThreadName() {
141+
return threadName == null ? NA : threadName;
142+
}
143+
128144
@Override
129145
public String getRequestURI() {
130146
if (requestURI == null) {
@@ -137,6 +153,24 @@ public String getRequestURI() {
137153
return requestURI;
138154
}
139155

156+
@Override
157+
public String getQueryString() {
158+
if (queryString == null) {
159+
if (httpRequest != null) {
160+
StringBuilder buf = new StringBuilder();
161+
final String qStr = httpRequest.getQueryString();
162+
if (qStr != null) {
163+
buf.append(AccessConverter.QUESTION_CHAR);
164+
buf.append(qStr);
165+
}
166+
queryString = buf.toString();
167+
} else {
168+
queryString = NA;
169+
}
170+
}
171+
return queryString;
172+
}
173+
140174
/**
141175
* The first line of the request.
142176
*/
@@ -148,11 +182,7 @@ public String getRequestURL() {
148182
buf.append(httpRequest.getMethod());
149183
buf.append(AccessConverter.SPACE_CHAR);
150184
buf.append(httpRequest.getRequestURI());
151-
final String qStr = httpRequest.getQueryString();
152-
if (qStr != null) {
153-
buf.append(AccessConverter.QUESTION_CHAR);
154-
buf.append(qStr);
155-
}
185+
buf.append(getQueryString());
156186
buf.append(AccessConverter.SPACE_CHAR);
157187
buf.append(httpRequest.getProtocol());
158188
requestURL = buf.toString();
@@ -213,6 +243,21 @@ public String getMethod() {
213243
return method;
214244
}
215245

246+
@Override
247+
public String getSessionID() {
248+
if (sessionID == null) {
249+
if (httpRequest != null) {
250+
final HttpSession session = httpRequest.getSession();
251+
if (session != null) {
252+
sessionID = session.getId();
253+
}
254+
} else {
255+
sessionID = NA;
256+
}
257+
}
258+
return sessionID;
259+
}
260+
216261
@Override
217262
public String getServerName() {
218263
if (serverName == null) {
@@ -408,6 +453,10 @@ public int getStatusCode() {
408453
return statusCode;
409454
}
410455

456+
public long getElapsedSeconds() {
457+
return elapsedTime < 0 ? elapsedTime : elapsedTime / 1000;
458+
}
459+
411460
public long getElapsedTime() {
412461
return elapsedTime;
413462
}

logback-access/src/main/java/ch/qos/logback/access/spi/IAccessEvent.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,21 @@ public interface IAccessEvent extends DeferredProcessingAware {
6161
long getTimeStamp();
6262

6363
/**
64-
* The time elapsed between receiving the request and logging it.
64+
* The number of seconds elapsed between receiving the request and logging it.
65+
*/
66+
long getElapsedSeconds();
67+
68+
/**
69+
* The time elapsed in ms between receiving the request and logging it.
6570
*/
6671
long getElapsedTime();
6772

73+
void setThreadName(String threadName);
74+
75+
String getThreadName();
76+
77+
String getQueryString();
78+
6879
String getRequestURI();
6980

7081
/**
@@ -80,6 +91,8 @@ public interface IAccessEvent extends DeferredProcessingAware {
8091

8192
String getMethod();
8293

94+
String getSessionID();
95+
8396
String getServerName();
8497

8598
String getRemoteAddr();

logback-access/src/main/java/ch/qos/logback/access/tomcat/LogbackValve.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ public void invoke(Request request, Response response) throws IOException,
193193
TomcatServerAdapter adapter = new TomcatServerAdapter(request, response);
194194
IAccessEvent accessEvent = new AccessEvent(request, response, adapter);
195195

196+
try {
197+
final String threadName = Thread.currentThread().getName();
198+
if (threadName != null) {
199+
accessEvent.setThreadName(threadName);
200+
}
201+
} catch (Exception ignored) { }
202+
196203
if (getFilterChainDecision(accessEvent) == FilterReply.DENY) {
197204
return;
198205
}

logback-site/src/site/pages/manual/layouts.html

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,6 +2082,14 @@ <h3 class="doAnchor" name="AccessPatternLayout">PatternLayout</h3>
20822082
</p>
20832083
</td>
20842084
</tr>
2085+
<tr>
2086+
<td class="word" name="elapsedSeconds"><b>T / elapsedSeconds</b></td>
2087+
<td>
2088+
<p>
2089+
The time taken to serve the request, in seconds.
2090+
</p>
2091+
</td>
2092+
</tr>
20852093
<tr>
20862094
<td class="word" name="dateAccess"><b>t / date</b></td>
20872095
<td>
@@ -2106,6 +2114,14 @@ <h3 class="doAnchor" name="AccessPatternLayout">PatternLayout</h3>
21062114
</p>
21072115
</td>
21082116
</tr>
2117+
<tr>
2118+
<td class="word" name="queryString"><b>q / queryString</b></td>
2119+
<td>
2120+
<p>
2121+
Request query string, prepended with a '?'.
2122+
</p>
2123+
</td>
2124+
</tr>
21092125
<tr>
21102126
<td class="word" name="requestURI"><b>U / requestURI</b></td>
21112127
<td>
@@ -2114,12 +2130,24 @@ <h3 class="doAnchor" name="AccessPatternLayout">PatternLayout</h3>
21142130
</p>
21152131
</td>
21162132
</tr>
2133+
<tr>
2134+
<td class="word" name="sessionID"><b>S / sessionID</b></td>
2135+
<td>
2136+
<p>Session ID.</p>
2137+
</td>
2138+
</tr>
21172139
<tr >
21182140
<td class="word" name="server"><b>v / server</b></td>
21192141
<td>
21202142
<p>Server name.</p>
21212143
</td>
21222144
</tr>
2145+
<tr>
2146+
<td class="word" name="threadName"><b>I / threadName</b></td>
2147+
<td>
2148+
<p>Name of the thread which processed the request.</p>
2149+
</td>
2150+
</tr>
21232151
<tr class="b">
21242152
<td class="word" name="localPort"><b>localPort</b></td>
21252153
<td>

0 commit comments

Comments
 (0)