Skip to content

Instantly share code, notes, and snippets.

@mp911de
Created October 21, 2014 07:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mp911de/c558d1bc48effe4844e2 to your computer and use it in GitHub Desktop.
Save mp911de/c558d1bc48effe4844e2 to your computer and use it in GitHub Desktop.
GelfAccessLogValve for Tomcat 7
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;
}
}
<?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>
<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 &quot;%r&quot; %s %b" resolveHosts="false" />
</Host>
</Engine>
</Service>
</Server>
@halcyonone
Copy link

how can i add extend field to my tomcat access log? like linux env or string, please help me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment