LOGIN
START FREE TRIAL

LogSense Blog

See everything, even before it happens.

Integrating Java logs with LogSense

Feb 25, 2019 4:48:40 PM |     Przemek Maciołek, PhD
image-8-1

Java and other JVM-based apps are widely popular in the enterprise world, and tracking their behavior is a critical aspect of monitoring. In this blog post, we'll describe how to send logs directly to LogSense

For the sake of simplicity, let's assume we have a standalone Java application that uses Maven for build automation. The code for the example described below is available on GitHub repository as well.

Let's start with a sample class that uses Logback SLF4J for logging. The code might look like the following:

package com.logsense;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class Wombat {
    final Logger logger = LoggerFactory.getLogger(Wombat.class);
    Integer t;
    Integer oldT;

    private void throwIfBelowAbsoluteZero(int temp) {
        if (temp < -273)
            throw new RuntimeException("That is really low temperature: " + temp);
    }

    private void tempSanitizer(int temp) {
        throwIfBelowAbsoluteZero(temp);
    }

    public void setTemperature(Integer temperature) {
        oldT = t;
        t = temperature;

        if(temperature.intValue() > 60) {
            logger.info("Current temperature: {} has risen above 60 degrees.", temperature.intValue());
        } else if (temperature.intValue() > 50) {
            logger.warn("Current temperature: {} is already above 50 degrees - that's concerning!", temperature.intValue());
        }
        try {
            tempSanitizer(temperature.intValue());
        } catch (RuntimeException re) {
            logger.error("Sanitization failed", re);
        }
    }
}

 

Step 1: Adding Dependencies

We will start with adding the logback-logsense dependency to pom.xml. This library includes the "glue" together with dependencies (including slf4j) that will allow us to push logs through the Fluent protocol to LogSense. 

<dependency>
 <groupId>com.logsense</groupId>
 <artifactId>logback-logsense</artifactId>
 <version>1.0</version>
</dependency>

Note: if you prefer to use log4j, it can be done easily by including the migration dependency, e.g.:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
	<version>1.7.25</version>
</dependency>

And then using log4j logger, i.e. org.apache.log4j.Logger

Step 2: Setting up logback.xml

Now, we need to provide configuration for logback.xml, which allows us to identify the source of the logs and also can provide additional information to track the source of the logs. In this example, we are allowing to send the local IP address, as seen by the application, and to tag each log record with a source name equal to sample-app.

Additionally, we are adding console (STDOUT) output. 

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <!-- LogSense appender. Use the correct accessToken value, as provided by the LogSense app -->
    <appender name="LOGSENSE" class="com.logsense.logback.Appender" >
        <csCustomerToken>aaaaaa-bbbb-1111-8888-ffffeeeeedddd</csCustomerToken>
        <useLocalIpAddress>true</useLocalIpAddress>
        <sourceName>sample-app</sourceName>
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern><![CDATA[%date{HH:mm:ss.SSS} [%thread] %-5level %logger{15}#%line %X{req.requestURI} %msg\n]]></pattern>
        </encoder>
    </appender>

    <root>
        <level value="DEBUG" />
        <appender-ref ref="STDOUT" />
        <appender-ref ref="LOGSENSE" />
    </root>
</configuration>
 
Step 3. Running It

Now we need the main method that will call the Wombat class introduced at the top of the blog post. To make it more sophisticated, we can add some randomness, for example:

package com.logsense;

import java.util.Random;

public class App {
    static Random r = new Random();

    public static int gaussianTemp(int mean, int sd) {
        return mean + (int) (r.nextGaussian()*sd);
    }

    public static void main( String[] args ) throws Exception
    {

        Wombat w = new Wombat();

        while (true) {
            w.setTemperature(gaussianTemp(10, 15));
            w.setTemperature(gaussianTemp(45, 10));
            w.setTemperature(gaussianTemp(100, 20));
            w.setTemperature(gaussianTemp(1000, 100));
            w.setTemperature(gaussianTemp(-200, 200));
            Thread.sleep(1000);
        }
    }
}

The code will call some valid and some invalid operations (triggering exception) in a loop, providing plenty of examples. It be can be run by issuing:

$ mvn compile
$ mvn exec:java -Dexec.mainClass=com.logsense.App

What about Java Web apps?

The exact same steps can be followed for Java Web apps, with the only additional item being to make sure logback.xml is in the resources directory (e.g. src/main/resources) and packaged into the war file. The latter can be achieved via adding following piece to pom.xml:

    ...
    <build>
        ...
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<filtering>true</filtering>
				<includes>
					<include>**/logback.xml</include>
				</includes>
			</resource>
		</resources>
	</build>
    ...

 

Working with Java Logs

Assuming the sample app was run, after logging into LogSense, we should see the incoming logs. If there are also other types of logs present, the simplest way to filter data is by using source_name=sample-app in the search box, e.g.:

 Screenshot 2019-02-19 at 23.17.57

Among the things that are easy to notice are the log patterns, automatically discovered by LogSense using our patent-pending log parsing technology:

image-2

As we can see, there are three patterns generated for the context. The system automatically discovered parameters in the text and assigned default labels. You can rename the labels using the pattern editor:

Once the labels have been renamed, you might end up with something like:

Screenshot 2019-02-19 at 23.28.11

Now let's make some use out of the patterns and build a custom chart that shows current_temp over time. The custom chart can be done in many ways. Perhaps the simplest one is by right-clicking on the record in Logs view and then selecting an option from the drop-down menu:

Once the chart has opened, you can change its type by clicking on the chart type drop-down:

and also add MIN and MAX values, by clicking the "+ add a field" option:

Finally, the dashboard might look like the one below:

image-8-1

 

If you want to investigate more specific context, it's easy to do. For example, let's say we want to check the statistics for a selected pattern. To do that, you need to click on the pattern_id:

This action populates the search box with the pattern_id and applies an additional filter:

There are no limits in filtering and selecting the context. Anything that is a field can be added there.

In fact, there are many other areas where LogSense can be utilized, e.g. investigating error logs or analyzing behavior of the system:

 

 

If you are interested to see how LogSense can help with your Java and other JVM-based apps, try it out today for no charge.

 

New call-to-action

Topics: appdev

Want more of the LogSense Blog? You got it.
Subscribe to our newsletter.

Comments