Analyze HTTP requests with Java log filter
javax.servlet.Filterto implement a convenient way to parse the contents of HTTP requests and output logs.FilterClasses.
This log filter uses "java.util.logging.Logger" for log output, and the information output can be changed by changing the log level.
What is javax.servlet.Filter?
When building a web application, in addition to the main business processing, it is necessary to perform common secondary processing before and after the main business processing.
For example, client authentication, authority checking, logging, etc.
Coding such side processing in each resource becomes a major cause of hindering software maintainability, resulting in an application that is difficult to maintain.
If you implement javax.servlet.Filter, you can have this secondary process commonly performed before the request is passed to the servlet class.
Filters can be configured in web.xml, giving you the flexibility to add or remove filters without changing the source code.
Try using log filters
Let's actually use the log filter to analyze HTTP requests by passing filters through HTTP requests.
In this issue.TomcatThe examples application is available from the beginning in the
This filter can be run immediately with the following settings
2. Place the compiled class files under "/examples/WEB-INF/classes".
3. Set the following definitions in web.xml.
LogFilter LogFilter logging.Level FINE LogFilter /*
The url-pattern when using the Struts framework is as follows.
*.do
Check the log output results of running the Sessions Example screen.
Output log information and log level
Log output contents
log information | log level |
---|---|
Cookie Information | fine |
HTTP Header Information | fine |
HTTP and other information | fine |
HTTP Request Parameters | CONFIG |
Objects in the request scope | CONFIG |
Session Scope Objects | CONFIG |
Memory usage before and after request | CONFIG |
Screen transition information | INFO |
Log levels should be used as follows
- FINE: Outputs the most detailed logs; set this if you want to analyze HTTP requests in detail.
- CONFIG ... Outputs a somewhat detailed log. It is recommended to keep this level during the development period.
- INFO・・・・ outputs screen transition information only.
How to change the log level
The logging output level can be changed by setting the initialization parameter logging.Level.
Example:
logging.Level INFO
source code
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Implement javax.servlet.Filter to analyze the content of HTTP requests and output logs
* Filter class.
*/
public class LogFilter implements Filter {
private static Logger logger =
Logger.getLogger(LogFilter.class.getName());
private static final String LINE_SEPA =
System.getProperty(“line.separator”);
private static final String NEXT_PAGE = “LogFilter.NEXT_PAGE”;
/**
* Initialize this log filter.
* @param mapping
*/
public void init(FilterConfig mapping) {
String str = mapping.getInitParameter(“logging.Level”);
System.out.println(“Set log level to “+str+”.”);
Level level = null;
try {
level = Level.parse(str);
} catch (Exception e) {
e.printStackTrace();
level = Level.INFO;
}
LogManager.getLogManager().reset();
Handler handler = new CustomConsoleHandler();
handler.setFormatter(new CustomFormatter());
handler.setLevel(level);
logger.setLevel(level);
logger.getParent().addHandler(handler);
}
/**
* This is a filter that outputs logs.
* @param request HTTP request being processed
* @param response HTTP response being generated
* @param chain
*/
public void doFilter(ServletRequest _request, ServletResponse _response,
FilterChain chain) throws IOException, ServletException {
// --------------------" Preprocessing "
HttpServletRequest request = (HttpServletRequest) _request;
HttpServletResponse response = (HttpServletResponse) _response;
if (logger.isLoggable(Level.CONFIG)) {
logger.config(
“============ Request Start!!”
+”Thread ID:”
+ Thread.currentThread().hashCode()
+ ” ========================================================”);
}
// memory usage
String actionMemory = null;
if (logger.isLoggable(Level.CONFIG)) {
actionMemory = getMemoryInfo(” ”
+ new Time(System.currentTimeMillis()) + ”Request[previous]”);
}
if (logger.isLoggable(Level.FINE)) {
logger.fine(“Cookie Information” + getCookieInfo(request));
}
if (logger.isLoggable(Level.FINE)) {
logger.fine(“HTTP header information” + getHeadersInfo(request));
}
if (logger.isLoggable(Level.FINE)) {
logger
.fine(“HTTP other information” + getRequestOtherInfo(request));
}
if (logger.isLoggable(Level.CONFIG)) {
String reqlog = getRequestParametersInfo(request);
logger.config(“HTTP request parameters” + reqlog);
}
if (logger.isLoggable(Level.CONFIG)) {
logger.config(“request scope object”
+ getRequestAttributeInfo(request));
}
if (logger.isLoggable(Level.CONFIG)) {
String sessionlog = getSessionInfo(request,true);
logger.config(“session scope object (before request processing)”
+ sessionlog);
}
// call next filter
chain.doFilter(request, response);
// ———————————————————- “Post-processing”
if (logger.isLoggable(Level.CONFIG)) {
String sessionlog = getSessionInfo(request,false);
logger.config(“session scope object (after request processing)”
+ sessionlog);
}
// memory usage
if (logger.isLoggable(Level.CONFIG)) {
actionMemory = ”Memory usage before and after request”+LINE_SEPA
+ actionMemory + LINE_SEPA
+ getMemoryInfo(” ” + new Time(System.currentTimeMillis())
+ ”request[after]”);
logger.config(actionMemory+LINE_SEPA);
}
// Screen transition information
if (logger.isLoggable(Level.INFO)) {
String nextPage = (String) request.getAttribute(NEXT_PAGE);
if (nextPage == null || nextPage.length() == 0) {
nextPage = request.getRequestURI();
}
logger.info(“NEXT_PAGE=[” + nextPage + “], ”
+ “IP_ADDRESS=[” + request.getRemoteAddr() + “], ”
+ “SESSION_ID=[” + request.getSession().getId() + “], ”
+ “USER-AGENT=[” + request.getHeader(“user-agent”) + “]”);
}
if (logger.isLoggable(Level.CONFIG)) {
logger.config(
“============ Request End!!”
+”Thread ID:”+ Thread.currentThread().hashCode()
+ ” =========================================================”
+LINE_SEPA+LINE_SEPA);
}
}
/**
*
*/
public void destroy() {
}
// ---------- Private method below -----------
private static String getMemoryInfo(String message) {
DecimalFormat dFromat = new DecimalFormat(“#,###KB”);
long free = Runtime.getRuntime().freeMemory() / 1024;
long total = Runtime.getRuntime().totalMemory() / 1024;
long max = Runtime.getRuntime().maxMemory() / 1024;
long used = total – free;
String msg = message + ” : ” + “total=” + dFromat.format(total) + “, ”
+ “Used amount=” + dFromat.format(used) + ” (” + (used * 100 / total)
+ “%), maximum available=” + dFromat.format(max);
return msg;
}
/**
* Output all request headers to the log.
*/
private static String getHeadersInfo(HttpServletRequest request) {
StringBuffer buff = new StringBuffer(LINE_SEPA);
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
buff.append(” “);
buff.append(headerName);
buff.append(“=”);
buff.append(request.getHeader(headerName));
buff.append(LINE_SEPA);
}
return buff.toString();
}
private static String getCookieInfo(HttpServletRequest request) {
StringBuffer buff = new StringBuffer();
Cookie[] cookies = request.getCookies();
if (cookies == null) {
return “”;
}
for (int i = 0; i < cookies.length; i++) {
buff.append(“\n — Cookie[” + i + “] —\n”);
buff.append(” “);
buff.append(cookies[i].getName());
buff.append(“=”);
buff.append(cookies[i].getValue());
buff.append(LINE_SEPA);
buff.append(” “);
buff.append(“getVersion()”);
buff.append(“=”);
buff.append(cookies[i].getVersion());
buff.append(LINE_SEPA);
buff.append(” “);
buff.append(“getComment()”);
buff.append(“=”);
buff.append(cookies[i].getComment());
buff.append(LINE_SEPA);
buff.append(” “);
buff.append(“getDomain()”);
buff.append(“=”);
buff.append(cookies[i].getDomain());
buff.append(LINE_SEPA);
buff.append(” “);
buff.append(“getMaxAge()”);
buff.append(“=”);
buff.append(cookies[i].getMaxAge());
buff.append(LINE_SEPA);
buff.append(” “);
buff.append(“getPath()”);
buff.append(“=”);
buff.append(cookies[i].getPath());
buff.append(LINE_SEPA);
buff.append(” “);
buff.append(“getSecure()”);
buff.append(“=”);
buff.append(cookies[i].getSecure());
buff.append(LINE_SEPA);
}
return buff.toString();
}
private static String getRequestParametersInfo(HttpServletRequest request) {
StringBuffer buff = new StringBuffer(LINE_SEPA);
Map map = convertRequest(request);
TreeMap trr = new TreeMap(map);
Iterator itr = trr.keySet().iterator();
while (itr.hasNext()) {
String key = (String) itr.next();
buff.append(” “);
buff.append(key);
buff.append(“=”);
Object value = map.get(key);
String[] values = (String[]) value;
if (values.length == 1) {
buff.append(values[0]);
} else {
// String array is converted
String strValue = stratum(values);
buff.append(strValue);
}
buff.append(LINE_SEPA);
}
return buff.toString();
}
private static String getRequestAttributeInfo(HttpServletRequest request) {
StringBuffer buff = new StringBuffer(LINE_SEPA);
Enumeration e = request.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String) e.nextElement();
buff.append(” name=” + name + “, attributeClass= ”
+ request.getAttribute(name).getClass().getName()
+ “, toString() = ” + request.getAttribute(name)
+ LINE_SEPA);
}
return buff.toString();
}
private static String getRequestOtherInfo(HttpServletRequest request) {
StringBuffer buff = new StringBuffer();
buff.append(LINE_SEPA);
buff.append(”getCharacterEncoding()=”);
buff.append(request.getCharacterEncoding());
buff.append(LINE_SEPA);
buff.append(”getContentLength()=”);
buff.append(request.getContentLength());
buff.append(LINE_SEPA);
buff.append(”getContentType()=”);
buff.append(request.getContentType());
buff.append(LINE_SEPA);
buff.append(”getLocale()=”);
buff.append(request.getLocale());
buff.append(LINE_SEPA);
buff.append(”getProtocol()=”);
buff.append(request.getProtocol());
buff.append(LINE_SEPA);
buff.append(”getRemoteAddr()=”);
buff.append(request.getRemoteAddr());
buff.append(LINE_SEPA);
buff.append(”getRemoteHost()=”);
buff.append(request.getRemoteHost());
buff.append(LINE_SEPA);
buff.append(”getScheme()=”);
buff.append(request.getScheme());
buff.append(LINE_SEPA);
buff.append(”getServerName()=”);
buff.append(request.getServerName());
buff.append(LINE_SEPA);
buff.append(”getServerPort()=”);
buff.append(request.getServerPort());
buff.append(LINE_SEPA);
buff.append(”isSecure()=”);
buff.append(request.isSecure());
buff.append(LINE_SEPA);
buff.append(”getAuthType()=”);
buff.append(request.getAuthType());
buff.append(LINE_SEPA);
buff.append(”getContextPath()=”);
buff.append(request.getContextPath());
buff.append(LINE_SEPA);
buff.append(”getMethod()=”);
buff.append(request.getMethod());
buff.append(LINE_SEPA);
buff.append(”getPathInfo()=”);
buff.append(request.getPathInfo());
buff.append(LINE_SEPA);
buff.append(”getPathTranslated()=”);
buff.append(request.getPathTranslated());
buff.append(LINE_SEPA);
buff.append(”getQueryString()=”);
buff.append(request.getQueryString());
buff.append(LINE_SEPA);
buff.append(”getRemoteUser()=”);
buff.append(request.getRemoteUser());
buff.append(LINE_SEPA);
buff.append(”getRequestedSessionId()=”);
buff.append(request.getRequestedSessionId());
buff.append(LINE_SEPA);
buff.append(”getRequestURI()=”);
buff.append(request.getRequestURI());
buff.append(LINE_SEPA);
buff.append(”getServletPath()=”);
buff.append(request.getServletPath());
buff.append(LINE_SEPA);
buff.append(”getUserPrincipal()=”);
buff.append(request.getUserPrincipal());
buff.append(LINE_SEPA);
buff.append(”isRequestedSessionIdFromCookie()=”);
buff.append(request.isRequestedSessionIdFromCookie());
buff.append(LINE_SEPA);
buff.append(”isRequestedSessionIdFromURL()=”);
buff.append(request.isRequestedSessionIdFromURL());
buff.append(LINE_SEPA);
buff.append(”isRequestedSessionIdValid()=”);
buff.append(request.isRequestedSessionIdValid());
buff.append(LINE_SEPA);
return buff.toString();
}
private static String getSessionInfo(HttpServletRequest request,boolean before) {
HttpSession session = request.getSession();
StringBuffer buff = new StringBuffer();
buff.append(LINE_SEPA);
if (before) {
buff.append(” session.isNew() = ” + session.isNew());
buff.append(LINE_SEPA);
buff.append(” session.getId() = ” + session.getId());
buff.append(LINE_SEPA);
}
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String sessionName = (String) e.nextElement();
String sessionClassName = session.getAttribute(sessionName)
.getClass().getName();
buff.append(” name =” + sessionName + “, value =”
+ session.getAttribute(sessionName) + “, attributeClass = ”
+ sessionClassName+LINE_SEPA);
}
return buff.toString();
}
private static Hashtable convertRequest(HttpServletRequest request) {
Hashtable tempHash = new Hashtable();
Enumeration e = request.getParameterNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
String[] values = request.getParameterValues(key);
String[] parameterValues = new String[values.length];
for (int i = 0; i < values.length; i++) {
parameterValues[i] = convUnicode(values[i]);
}
tempHash.put(key, parameterValues);
}
return tempHash;
}
private static String stratum(Object value) {
if (value == null) {
return “null”;
} else if (value instanceof String[]) {
return convString((String[]) value);
} else {
return value.toString();
}
}
/**
* Returns the contents of the string array [strArray] as a String like the one below.
* “[temp1,temp2,temp3]”
* @param strArray String array to be evaluated
* @return String after conversion
*/
private static String convString(String[] strArray) {
if (strArray == null)
return null;
StringBuffer buff = new StringBuffer(“[“);
for (int i = 0; i < strArray.length; i++) {
buff.append(strArray[i] + “, “);
}
buff.delete(buff.length() – 2, buff.length());
buff.append(“]”);
return buff.toString();
}
/**
* Convert [str] to Unicode.
* @param str
* @return
*/
private static String convUnicode(String str) {
if (str == null)
return null;
try {
return new String(str.getBytes(“8859_1”), “JISAutoDetect”);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
// ———————————————————————–
static class CustomFormatter extends Formatter {
static final String pattern = “yyyy/MM/dd HH:mm:ss”;
public synchronized String format(LogRecord record) {
StringBuffer buf = new StringBuffer();
// set date and time
Date date = new Date();
date.setTime(record.getMillis());
SimpleDateFormat formatter = new SimpleDateFormat(pattern);
buf.append(formatter.format(date));
buf.append(“:”);
// set level
buf.append(“[” + record.getLevel().getName() + “]”);
buf.append(“:”);
buf.append(record.getMessage());
buf.append(LINE_SEPA);
return buf.toString();
}
}
static class CustomConsoleHandler extends StreamHandler {
public CustomConsoleHandler() {
super();
setOutputStream(System.out);
}
/**
* Issues a LogRecord.
* Initially, logging requests are sent to a Logger object.
* and this object initializes the LogRecord and
*Redirected here.
*
* @param record Description of the log event. null records are simply ignored
* and no notification will be sent.
*/
public void publish(LogRecord record) {
super.publish(record);
flush();
}
/**
* Override StreamHandler.close to flush, but
* Output stream is not closed. In other words, System.err is not closed.
*/
public void close() {
flush();
}
}
}