The adoption of Log4j overshadows all other java logging frameworks. With Log4j 2, Apache gave us a next-generation Asynchronous Logger based on the famous LMAX Disruptor library. Yes, we scale!

Therefore, it’s a pity that currently there is no official Logstash 2.x plugin for Log4j2. Unofficially? There is https://github.com/jurmous/logstash-log4j2, but unless you’re a Ruby expert, it would take considerable effort to compile and install it correctly. In this article we did that for you and present a small demo on docker-compose.

Prerequisites

  1. A Linux console or Apple OSX console (not tested on windows, but adaptable with little effort).
  2. A Git client to fetch the project.
  3. Docker Compose.
  4. Apache Maven installed, Maven would not work with a JRE, requires a JDK7 or greater and JAVA_HOME pointing to it. Check if 'mvn -v reports a JDK.
  5. Git Clone: Docker-elk-log4j2.

To run this tutorial we go into the project directory and execute docker-compose up.

The Docker instances fire up:

Attaching to dockerelklog4j2_elasticsearch_1, dockerelklog4j2_logstash_1, dockerelklog4j2_kibana_1

Our logstash ruby plugin gets installed:

[33mlogstash_1      | [0mValidating /etc/logstash/conf.d/logstash-input-log4j2-5.2-java.gem
[33mlogstash_1      | [0mInstalling logstash-input-log4j2
...
[33mlogstash_1      | [0mInstallation successful

If all went well we can open another console, again in the project directory and execute a small logging simulation.

mvn compile
mvn exec:java

This should lead to an stream of bank transaction logs between some fictional accounts.

transfer [bfe6 amount="68,292.32" currency="USD" fromAccount="George Washington" toAccount="Marlene Dietrich"]
transfer [68c2 amount="933,010.4" currency="USD" fromAccount="Lise Meitner" toAccount="Anna Sacher"]
transfer [09ce amount="625,818.24" currency="USD" fromAccount="Keiko Abe" toAccount="Marlene Dietrich"]
transfer [cbed amount="582,555.67" currency="USD" fromAccount="Pierre Boulez" toAccount="Massimo Carisi"]

Now in the Kibana console at http://localhost:5601, we press create:


x4YPkUKia9gWBPvhrn0SGlTPq-TBwSWGiZOmUihV
Under visualize we select new search


qUoHixGqqinWCE9t2o5C-iOslqCidynhFTh0uSCV

All you have to do is to configure a visualization of the incoming stream of logs.


image?w=602&h=321&rev=1&ac=1


  1. Y-Axis should be left to Count
  2. X-Axis needs to set to Date-Histogram, @timestamp is the preselected event timestamp
  3. Change the interval to Seconds
  4. Eventually hit reload


We have demonstrated the ability to log in realtime, but what exactly happened?

There is a SocketAppender configured in our Logging application. The socket sends serialized LogEvents over TCP (optional UDP) to a remote Host. A secure SSL connection is possible and recommended in a production environment.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Socket name="logstash" host="localhost" port="7000">
            <SerializedLayout />
        </Socket>
        <Console name="local">
        </Console>
    </Appenders>
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="logstash"/>
            <AppenderRef ref="local" />
        </Root>
    </Loggers>
</Configuration>

Code: The Log4J2 configuration is in src/main/resources/log4j2.xml with an asynchronous socket client and a console output configuration.

A drawback of this solution is that our plugin currently does not support AsyncAppender. Having the log synchronous means that connectivity can affect the performance. But log4j2 can be run entirely in async mode using the LMAX Disruptor library. In pom.xml I’ve configured this asynchronicity.

<systemProperty>
 <key>Log4jContextSelector</key>
 <value>org.apache.logging.log4j.core.async.AsyncLoggerContextSelector</value>
</systemProperty>

Code: pom.xml in the project directory contains the configuration for executing log4j2 in async mode.

The socket connects to our dockerized Logstash server, where we have the port 7000 configured for incoming TCP messages. Since Log4j2 acts as a client it is necessary to configure the log4j2 input plugin as a server.

input {
  log4j2 {
    port => 7000
    mode => "server"
  }
}

Code: In logstash/config/logstash.conf we have declared a server socket.

Conclusions

In this article I’ve presented a solution to the currently missing log4j2 plugin for Logstash. Given the popularity of Log4j in general and the rising popularity of the second version, it is hopeful that an official version is quickly supported.