diff --git a/README.md b/README.md
index 0615e92..41d2c85 100644
--- a/README.md
+++ b/README.md
@@ -102,6 +102,41 @@ default values:
```
+An complete example for logback-access
+
+```xml
+
+
+ somehost.com
+ 12201
+
+ UTF-8
+
+
+
+ common
+
+
+ combined
+
+ true
+ Test
+
+ application
+ Your-Application
+
+
+
+
+
+
+
+
+
+```
+
+
+
## GelfLayout
`me.moocar.logbackgelf.GelfLayout`
@@ -142,6 +177,33 @@ actually converts a log event into a GELF compatible JSON string.
empty
* **includeFullMDC**: See additional fields below. Default: `false`
+
+## GelfLayoutAccess
+
+`me.moocar.logbackgelf.GelfLayoutAccess`
+
+GelfLayoutAccess must be used if you want to use Gelf with "logback-access". For example, if you use the Tomcat LogbackValve.
+http://logback.qos.ch/access.html#tomcat
+
+* **useThreadName**: If true, an additional field call "_threadName"
+ will be added to each gelf message. Its contents will be the name of
+ the thread. Default: `false`
+* **host** The hostname of the host from which the log is being sent.
+ Displayed under `source` on web interface. Default:
+ `getLocalHostName()`
+* **shortMessageLayout**: The
+ [Layout/logback-access](http://logback.qos.ch/manual/layouts.html#logback-access) used to create
+ the gelf `short_message` field. Shows up in the message column of
+ the log summary in the web interface. Default: `"combined"`
+ ([AccessPatternLayout](http://logback.qos.ch/manual/layouts.html#AccessPatternLayout))
+* **fullMessageLayout**: The
+ [Layout/logback-access](http://logback.qos.ch/manual/layouts.html#logback-access) used to create
+ the gelf `full_message` field. Shows up in the message field of the
+ log details in the web interface. Default: `"combined"`
+ ([AccessPatternLayout](http://logback.qos.ch/manual/layouts.html#AccessPatternLayout))
+* **staticFields**: See static fields below. Note, now that facility
+ is deprecated, use this to set a facility Default: empty
+
## Transports
Both UDP and TCP transports are supported. UDP is the recommended
diff --git a/src/main/java/me/moocar/logbackgelf/GelfLayoutAccess.java b/src/main/java/me/moocar/logbackgelf/GelfLayoutAccess.java
new file mode 100644
index 0000000..b1d8219
--- /dev/null
+++ b/src/main/java/me/moocar/logbackgelf/GelfLayoutAccess.java
@@ -0,0 +1,185 @@
+package me.moocar.logbackgelf;
+
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+
+import me.moocar.logbackgelf.Field;
+import me.moocar.logbackgelf.InternetUtils;
+import ch.qos.logback.access.PatternLayout;
+import ch.qos.logback.access.spi.IAccessEvent;
+import ch.qos.logback.core.Layout;
+import ch.qos.logback.core.LayoutBase;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * Responsible for formatting a log event into a GELF JSON string
+ */
+public class GelfLayoutAccess extends LayoutBase {
+
+ private final String DEFAULT_FULL_MESSAGE_PATTERN = "combined";
+ private final String DEFAULT_SHORT_MESSAGE_PATTERN = "combined";
+
+ private boolean useThreadName = false;
+
+ private Map staticFields = new HashMap();
+ private String host = getLocalHostName();
+ private final Gson gson;
+ private Layout fullMessageLayout;
+ private Layout shortMessageLayout;
+
+ public GelfLayoutAccess() {
+
+ // Init GSON for underscores
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
+ this.gson = gsonBuilder.create();
+ }
+
+ @Override
+ public void start() {
+
+ if (fullMessageLayout == null) {
+ this.fullMessageLayout = initNewPatternLayout(DEFAULT_FULL_MESSAGE_PATTERN);
+ }
+
+ if (shortMessageLayout == null) {
+ this.shortMessageLayout = initNewPatternLayout(DEFAULT_SHORT_MESSAGE_PATTERN);
+ }
+
+ super.start();
+ }
+
+ private PatternLayout initNewPatternLayout(String pattern) {
+ PatternLayout layout = new PatternLayout();
+ layout.setPattern(pattern);
+ layout.setContext(this.getContext());
+ layout.start();
+ return layout;
+ }
+
+ @Override
+ public String doLayout(E event) {
+ return gson.toJson(mapFields(event));
+ }
+
+ /**
+ * Creates a map of properties that represent the GELF message.
+ * @param logEvent The log event
+ * @return map of gelf properties
+ */
+ private Map mapFields(E logEvent) {
+ Map map = new HashMap();
+
+ map.put("host", host);
+
+ map.put("full_message", fullMessageLayout.doLayout(logEvent));
+ map.put("short_message", shortMessageLayout.doLayout(logEvent));
+
+ map.put("timestamp", logEvent.getTimeStamp() / 1000.0);
+
+ map.put("version", "1.1");
+
+ additionalFields(map, logEvent);
+
+ staticAdditionalFields(map);
+
+ return map;
+ }
+
+ /**
+ * Converts the additional fields into proper GELF JSON
+ * @param map The map of additional fields
+ * @param eventObject The Logging event that we are converting to GELF
+ */
+ private void additionalFields(Map map, IAccessEvent eventObject) {
+
+ if (useThreadName) {
+ map.put("_threadName", eventObject.getThreadName());
+ }
+
+ }
+
+ private void staticAdditionalFields(Map map) {
+
+ for (String key : staticFields.keySet()) {
+ map.put(key, (staticFields.get(key)));
+ }
+ }
+
+ private String getLocalHostName() {
+ try {
+ return InternetUtils.getLocalHostName();
+ } catch (SocketException e) {
+ return "UNKNOWN";
+ } catch (UnknownHostException e) {
+ return "UNKNOWN";
+ }
+ }
+
+ // ////////// Logback Property Getter/Setters ////////////////
+
+ /**
+ * If true, an additional field call "_threadName" will be added to each gelf message. Its contents will be the Name of the thread.
+ * Defaults to "false".
+ */
+ public boolean isUseThreadName() {
+ return useThreadName;
+ }
+
+ public void setUseThreadName(boolean useThreadName) {
+ this.useThreadName = useThreadName;
+ }
+
+ /**
+ * static additional fields to add to every gelf message. Key is the additional field key (and should thus begin with an underscore).
+ * The value is a static string.
+ */
+ public Map getStaticFields() {
+ return staticFields;
+ }
+
+ public void setStaticFields(Map staticFields) {
+ this.staticFields = staticFields;
+ }
+
+ /**
+ * Override the local host using a config option
+ * @return the local host (defaults to getLocalHost() if not overridden in config
+ */
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ /**
+ * Add a static field. A static field is a key/value pair that should be sent in each Gelf message. This supercedes static additional
+ * fields, which can't have colon characters in their value.
+ */
+ public void addStaticField(Field entry) {
+ staticFields.put(entry.getKey(), entry.getValue());
+ }
+
+ public Layout getFullMessageLayout() {
+ return fullMessageLayout;
+ }
+
+ public void setFullMessageLayout(Layout fullMessageLayout) {
+ this.fullMessageLayout = fullMessageLayout;
+ }
+
+ public Layout getShortMessageLayout() {
+ return shortMessageLayout;
+ }
+
+ public void setShortMessageLayout(Layout shortMessageLayout) {
+ this.shortMessageLayout = shortMessageLayout;
+ }
+}