Home Java Easy logging in SpringBoot + Log4j2 + Maven

Easy logging in SpringBoot + Log4j2 + Maven

by admin

Hello, dear Habrovchans.

The material in this article is intended for beginners and will probably, like me, save you hours of searching on StackOverFlow and other sites to get a handy logging system that will understand where to log – to console, file or logstash.

At the start of a project, there is always the task of setting up logging properly, and on the local environment logs should be output to the console and to a file for ease of debugging, and on the remote server output logs to the console is not highly desirable, but instead should be written to a file, logstash or to the database.And if you have Windows locally and Linux on the remote machine, the location of this log file is different.

So there are many situations where you have to constantly manually change the configuration of the logging system depending on external circumstances.

I got bored with remembering and commenting on appenders all the time, so I figured out a way to set up Log4j2 so that depending on the Maven profile I choose, only the appenders I want are automatically enabled.

Here are the instructions for setting up a project using Spring Boot + Maven + Log4j2, which will result in a configured logging system and two appenders: CONSOLE and SOCKET.

First, we make changes to the Maven configuration (pom.xml):
In the variables at the level of the whole pom.xml we add the host address for the logstash-appender:

<properties><logstash.host> logstashcsm.example.ru</logstash.host></properties>

Add the dependencies needed to work :

<dependencies><dependency><groupId> org.springframework.boot</groupId><artifactId> spring-boot-starter-web</artifactId><exclusions><exclusion><groupId> org.springframework.boot</groupId><artifactId> spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId> org.springframework.boot</groupId><artifactId> spring-boot-starter-log4j2</artifactId></dependency></dependencies>

Note that we exclude the spring-boot-starter-web dependency from spring-boot-starter-logging.

We set up Maven profiles to dynamically manage the connected appenders.At the per-profile level, we set the variables logstash.port, logger.console.tresholdFilter, logger.socket.tresholdFilter

<profiles><profile><id> local</id><properties><logstash.port> 10000</logstash.port><logger.console.tresholdFilter> ALL</logger.console.tresholdFilter><logger.socket.tresholdFilter> OFF</logger.socket.tresholdFilter></properties></profile><profile><id> dev</id><properties><logstash.port> 10001</logstash.port><logger.console.tresholdFilter> OFF</logger.console.tresholdFilter><logger.socket.tresholdFilter> ALL</logger.socket.tresholdFilter></properties></profile></profiles>

logstash.port – is the port to which the logs should be sent.
logger.console.tresholdFilter – value specifies the filtering level of logs output to the console. In our case ALL means that all levels of log entries will be output to the console appender.
logger.socket.tresholdFilter – value specifies the level of log filtering that is sent to logstash. OFF means that no logs sent to this appender will pass through.

Now we have to make changes in application.properties, so that we can access the values of the variables defined in pom.xml from the Log4j2.xml file:

logstash.host=@logstash.host@
logstash.port=@logstash.port@
logger.console.tresholdFilter=@logger.console.tresholdFilter@
logger.socket.tresholdFilter=@logger.socket.tresholdFilter@

Finally, we configure Log4j2 itself in the log4j2.xmlfile:

<?xml version="1.0" encoding="UTF-8"?><Configuration><Properties><Property name="socket.host"> ${bundle:application:logstash.host}</Property><Property name="socket.port"> ${bundle:application:logstash.port}</Property><Property name="console.thresholdFilter"> ${bundle:application:logger.console.tresholdFilter}</Property><Property name="socket.thresholdFilter"> ${bundle:application:logger.socket.tresholdFilter}</Property></Properties><Appenders><Console name="CONSOLE" target="SYSTEM_OUT"><ThresholdFilter level="${console.thresholdFilter}"/><PatternLayout pattern="%d %-5p [%t] %c{10} - %m%n"/></Console><Socket name="SOCKET" host="${socket.host}" port="${socket.port}" immediateFlush="true"><ThresholdFilter level="${socket.thresholdFilter}"/><JSONLayout eventEol="true" compact="true"/></Socket><Async name="ASYNC"><AppenderRef ref="CONSOLE"/><AppenderRef ref="SOCKET"/></Async></Appenders><Loggers><Logger name="ru.example" level="debug" additivity="false"><AppenderRef ref="ASYNC"/></Logger><Root level="error"><AppenderRef ref="ASYNC"/></Root></Loggers></Configuration>

Now in order to call the logger in your class, you must create an instance of it :

private static Logger logger = LoggerFactory.getLogger(YourClass.class);

and address it :

logger.info("This entry will be logged");

That’s it. The logging will now work with the Maven profile active in the project.
Note that in the file listing log4j2.xml has two loggers defined – example and root , and they have different levels of event logging. The first one will work for all events generated by the ru.example.* and log everything from the DEBUG level, and root logger will log events from absolutely all classes, but from the ERROR level.
To avoid duplication of entries in the logs, the setting additivity="false"

You may also like