All posts by tomsriddle

Spring & Vertx

I recently decided to compare 2 frameworks for building micro services, one of them is the popular Spring framework which recently launched the Web Flux module that allows you to write reactive MVC applications. It uses Reactor under the hood and can be deployed on light weight run times like Netty and Undertow. The other framework I chose was Vertx which promises to be a light weight framework to build micro services.

The focus of this post is on performance measured in terms of throughput and CPU utilization. For the comparison, my code ran on EC2 instances that connected to a Cassandra database hosted within our VPC which itself ran on EC2 instances. All instances were in the same region and availability zones and the load tests were done through Jmeter which was also executed from an EC2 instance in the same VPC. I used t2 instances for this exercise and ran several tests with the same configuration.

About the code: There was just 1 GET end point that looked up a record from a table in Cassandra. The Cassandra table also had just 2-3 records and the table itself was simple to have a primary key with which we were looking up.

About the Tests: I ran tests with 3 frameworks with the above functionality

Spring MVC

Spring Web Flux

Vertx

Observations

Both Spring MVC & Spring Web Flux performed nearly the same. At about 4000 requests per second I started getting errors and the error rates increased as I increased the threads to achieve about 5000 requests/second. Throughout the tests the CPU appeared to be pegged at around 100%

With Vertx however, I observed that I could go up to 6000 requests/second without getting any errors. The CPU continued to remain at 30-40%

Custom Layout in Log4J2

Logging is probably one of the last things that a developer focusses on and yet is probably the most critical tool in the armory of developers and operation engineers in troubleshooting and more importantly understanding their applications as they run in Production.

In this post, I am going to talk about how you can write a custom layout using Log4J2 which is version 2 of one of the 2 popular frameworks for logging information from a Java application.

For starters I want to provide a disclaimer that writing a custom layout is not something that you do on a regular basis since the options available in Log4J2 both with respect to layouts and appenders covers all possible use cases. However there might be occasions when you may want to write a custom layout, in my case it was to force an opinionated log line across all applications as a part of a centralized logging strategy across our set of micro services.

In order to write a custom layout, you first have to include the following Maven dependency

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>2.6.2</version>
</dependency>

Write a Java class that extends a log4j2 class. Notice the annotation for @Plugin where you define the actual name of the element that will eventually go into the log4j2.xml file. In this example the value of the name attribute EventJsonLayout will appear as <EventJsonLayout/> in your log4j2.xml file. The re

/**
 * Custom JsonLayout to print out the audit log data
 */
@Plugin(name = "EventJsonLayout", category = "Core", elementType = "layout", printObject = true)
public final class EventJsonLayout extends AbstractStringLayout {
....
}

The above class then needs to have a static factory method annotated with @PluginFactory to tell Log4j2 to use this to initialize the layout. All attributes that you want to make available to clients to modify through their log4j2.xml should be annotated with @PluginAttribute

@PluginFactory
    public static EventJsonLayout createLayout(@PluginAttribute(value = "charset", defaultString = "UTF-8") Charset charset) {
        return new EventJsonLayout(charset);
    }

Finally the key method that needs to be implemented is the toSerializable method which is responsible for taking the actual log event which log4j2 will pass via the LogEvent argument and convert it into a String that the framework can use while sending the output

/**
     * Write data to the output stream
     *
     * @param event
     * @return
*/
public String toSerializable(LogEvent event) {
        ....
}

Lastly and most importantly, the above in itself does not tell Log4J2 to respect this layout. You need to generate the plugin listing files for your custom layout. W/o the final step elaborated below, you will get a compile time error if you reference this layout in your log4j2.xml file. To glue all of this you need to use. By default you don’t have to do anything since the log4j annotation processor is picked up by the Java compiler but in case it has been disabled then the following maven plugin will make that happen

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${compiler.plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <debug>${debug.state}</debug>
                </configuration>
                <executions>
                    <execution>
                        <id>log4j-plugin-processor</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <phase>process-classes</phase>
                        <configuration>
                            <proc>only</proc>
                            <annotationProcessors>
                                <annotationProcessor>
                                    org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor
                                </annotationProcessor>
                            </annotationProcessors>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

For more information on plugin listing files go to Log4J2 Plugin Listing Files

For more information on writing custom layouts go to Log4J2 Custom Layouts