Search code examples
log4j2grayloggelfgraylog3

How do I customize a GELF appender for log4j2?


We have a log4j2-graylog.xml file that we use to bridge our log4j output to GrayLog 3.0 using the biz.paluch.logging.gelf.log4j2 package. This config file is based on this example:

<?xml version="1.0" encoding="utf-8"?>
<Configuration monitorInterval="60" packages="biz.paluch.logging.gelf.log4j2">
    <Appenders>
        <Gelf name="gelf"
              host="10.13.10.192"
              port="12201"
              version="1.1"
              extractStackTrace="true"
              filterStackTrace="true"
              mdcProfiling="true"
              includeFullMdc="true"
              maximumMessageSize="8192"
              originHost="swarm"
              additionalFieldTypes="environment=String,application=String">
            <Field name="timestamp" pattern="%d{dd MMM yyyy HH:mm:ss,SSS}"/>
            <Field name="level" pattern="%level"/>
            <Field name="simpleClassName" pattern="%C{1}"/>
            <Field name="className" pattern="%C"/>
            <Field name="server.fqdn" pattern="%host{fqdn}"/>
            <Field name="threadName"/><!-- didn't seem to work -->
       
            <!-- This is a static field -->
            <Field name="application" literal="PISM-webapp"/>
        </Gelf>
    </Appenders>
    <Loggers>
        <Logger name="com.xxx" level="DEBUG" additivity="false">
            <AppenderRef ref="gelf"/>
        </Logger>
    </Loggers>
</Configuration>

It basically works. Our Java calls to log4j logging show up in GrayLog.

Based on the information from here, it seems like it ought to be easy to add a field that captures the thread data, but our attempts thus far have failed. Also we would like a field that reports the value of a certain environment variable. Can anybody tell me how to do either of these two things?


Solution

  • Based on information from the log4j2 manual, I was able to get the thread name by adding threadName to the additionalFieldTypes and using a %t pattern specifier like so:

    <Gelf name="gelf"
          host="10.13.10.192"
          port="12201"
          version="1.1"
          extractStackTrace="true"
          filterStackTrace="true"
          mdcProfiling="true"
          includeFullMdc="true"
          maximumMessageSize="8192"
          originHost="swarm"
          additionalFieldTypes="environment=String,application=String,threadName=String,fbHost=String">
        ...
        <Field name="threadName" pattern="%t"/>
    

    However, when I tried to use the syntax provided on the page to retrieve the value of an environment variable like so:

    <Field name="fbHost" pattern="$${env:LB_COOKIE_VALUE}" />
    

    I didn't get the value of the LB_COOKIE_VALUE environment value in GrayLog. Instead, I got the literal string - "${env:LB_COOKIE_VALUE}". This StackOverflow post gave enough information to debug the problem. When I provided a default value,

    <Field name="fbHost" pattern="$${env:LB_COOKIE_VALUE:-unset_env_LB_COOKIE_VALUE}" />
    

    I got "unset_env_LB_COOKIE_VALUE" in the output, indicating that the environment variable was not set. However, the Java system property was set, so

    <Field name="fbHost" pattern="$${sys:LB_COOKIE_VALUE:-unset_sys_LB_COOKIE_VALUE}" />
    

    provided the value I was looking for.