Created
October 21, 2014 07:09
-
-
Save mp911de/c558d1bc48effe4844e2 to your computer and use it in GitHub Desktop.
GelfAccessLogValve for Tomcat 7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package biz.paluch.logging.accesslogvalve; | |
import java.util.Collections; | |
import java.util.Date; | |
import java.util.HashMap; | |
import java.util.Map; | |
import org.apache.catalina.LifecycleException; | |
import org.apache.catalina.connector.Request; | |
import org.apache.catalina.connector.Response; | |
import org.apache.catalina.valves.AccessLogValve; | |
import org.apache.juli.logging.Log; | |
import org.apache.juli.logging.LogFactory; | |
import biz.paluch.logging.RuntimeContainer; | |
import biz.paluch.logging.gelf.intern.ErrorReporter; | |
import biz.paluch.logging.gelf.intern.GelfMessage; | |
import biz.paluch.logging.gelf.intern.GelfSender; | |
import biz.paluch.logging.gelf.intern.GelfSenderFactory; | |
import biz.paluch.logging.gelf.intern.sender.DefaultGelfSenderProvider; | |
import biz.paluch.logging.gelf.standalone.DefaultGelfSenderConfiguration; | |
/** | |
* @author <a href="mailto:mpaluch@paluch.biz">Mark Paluch</a> | |
* @since 21.10.14 08:13 | |
*/ | |
public class GelfAccessLogValve extends AccessLogValve { | |
private final static Map<Class, String> names = Collections.unmodifiableMap(new HashMap<Class, String>() { | |
{ | |
put(HeaderElement.class, "Header"); | |
put(CookieElement.class, "Cookie"); | |
put(ResponseHeaderElement.class, "ResponseHeader"); | |
put(SessionAttributeElement.class, "SessionAttribute"); | |
put(RemoteAddrElement.class, "RemoteAddr"); | |
put(LocalAddrElement.class, "LocalAddr"); | |
put(ByteSentElement.class, "ByteSent"); | |
put(ElapsedTimeElement.class, "ElapsedTime"); | |
put(HostElement.class, "Host"); | |
put(ProtocolElement.class, "Protocol"); | |
put(MethodElement.class, "Method"); | |
put(LocalPortElement.class, "LocalPort"); | |
put(QueryElement.class, "Query"); | |
put(RequestElement.class, "Request"); | |
put(FirstByteTimeElement.class, "FirstByteTime"); | |
put(HttpStatusCodeElement.class, "HttpStatusCode"); | |
put(SessionIdElement.class, "SessionId"); | |
put(DateAndTimeElement.class, "DateAndTime"); | |
put(UserElement.class, "User"); | |
put(RequestURIElement.class, "RequestURI"); | |
put(LocalServerNameElement.class, "LocalServerName"); | |
put(ThreadNameElement.class, "ThreadName"); | |
} | |
}); | |
public static final String SYSLOG_LEVEL = "6"; | |
private String host = "localhost"; | |
private int port = DefaultGelfSenderProvider.DEFAULT_PORT; | |
private GelfSender gelfSender; | |
@Override | |
public void log(Request request, Response response, long time) { | |
if (gelfSender == null || !getState().isAvailable() || !getEnabled() || logElements == null || condition != null | |
&& null != request.getRequest().getAttribute(condition) || conditionIf != null | |
&& null == request.getRequest().getAttribute(conditionIf)) { | |
return; | |
} | |
/** | |
* XXX This is a bit silly, but we want to have start and stop time and duration consistent. It would be better to keep | |
* start and stop simply in the request and/or response object and remove time (duration) from the interface. | |
*/ | |
long start = request.getCoyoteRequest().getStartTime(); | |
Date date = new Date(start + time); | |
GelfMessage message = new GelfMessage(); | |
message.setFacility(getClass().getSimpleName()); | |
message.setFullMessage(request.getMethod() + " " + request.getRequestURI()); | |
message.setShortMessage(request.getMethod() + " " + request.getRequestURI()); | |
message.setJavaTimestamp(start + time); | |
message.setHost(RuntimeContainer.FQDN_HOSTNAME); | |
message.setLevel(SYSLOG_LEVEL); | |
for (int i = 0; i < logElements.length; i++) { | |
String name = names.get(logElements[i].getClass()); | |
if (name == null) { | |
continue; | |
} | |
StringBuilder result = new StringBuilder(128); | |
logElements[i].addElement(result, date, request, response, time); | |
message.addField(name, result.toString()); | |
} | |
gelfSender.sendMessage(message); | |
} | |
private void createSender() { | |
DefaultGelfSenderConfiguration configuration = new DefaultGelfSenderConfiguration(new ErrorReporter() { | |
private final Log log = LogFactory.getLog(getClass()); | |
@Override | |
public void reportError(String message, Exception e) { | |
log.error(message, e); | |
} | |
}); | |
configuration.setHost(host); | |
configuration.setPort(port); | |
gelfSender = GelfSenderFactory.createSender(configuration); | |
} | |
@Override | |
protected synchronized void startInternal() throws LifecycleException { | |
createSender(); | |
super.startInternal(); | |
} | |
@Override | |
protected synchronized void stopInternal() throws LifecycleException { | |
if (gelfSender != null) { | |
gelfSender.close(); | |
gelfSender = null; | |
} | |
super.stopInternal(); | |
} | |
public String getHost() { | |
return host; | |
} | |
public void setHost(String host) { | |
this.host = host; | |
} | |
public int getPort() { | |
return port; | |
} | |
public void setPort(int port) { | |
this.port = port; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns="http://maven.apache.org/POM/4.0.0" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>biz.paluch.logging</groupId> | |
<artifactId>gelf-accesslog-valve</artifactId> | |
<version>1.0-SNAPSHOT</version> | |
<dependencies> | |
<dependency> | |
<groupId>biz.paluch.logging</groupId> | |
<artifactId>logstash-gelf</artifactId> | |
<version>1.5.1</version> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.tomcat</groupId> | |
<artifactId>tomcat-catalina</artifactId> | |
<version>7.0.56</version> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.tomcat</groupId> | |
<artifactId>tomcat-coyote</artifactId> | |
<version>7.0.56</version> | |
</dependency> | |
</dependencies> | |
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Server port="8005" shutdown="SHUTDOWN"> | |
... | |
<Service name="Catalina"> | |
... | |
<Engine name="Catalina" defaultHost="localhost"> | |
<Host name="localhost" appBase="webapps" | |
unpackWARs="true" autoDeploy="true"> | |
<Valve className="biz.paluch.logging.accesslogvalve.GelfAccessLogValve" host="localhost" | |
port="12201" pattern="%h %m %U %I %l %u %t "%r" %s %b" resolveHosts="false" /> | |
</Host> | |
</Engine> | |
</Service> | |
</Server> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
how can i add extend field to my tomcat access log? like linux env or string, please help me.