How do I roll the logs on either time elapsed or size exceeded using logback 1.0.0? - spring

I would like to roll a log after either one minute elapsed or 1MB size exceeded. But with the below configuration, only the first log is created taking the size in regard. Lets say:
myapp.2012-11-21_15-07.log (size:1026KB - 1MB)
myapp.log (size: 89KB)
Lets say that time passes (but we are still within that minute) and the log gets filled (exceeds 1MB), it won't create another file. Another file is only created when the time is exceeded with no regard to the size.
Is this a bug or the intended feature? How do I configure this using logback? Do I need a custom implementation?
as much as I read in the current manual when I want a log rolled after either one minute elapsed or 1MB size exceeded, I would do the following configuration:
<configuration>
<appender name="file"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${catalina.base}/logs/myapp.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${catalina.base}/logs/myapp.%d{yyyy-MM-dd_HH-mm}.log</fileNamePattern>
<maxHistory>90</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%-5level %date{ISO8601} [%thread]: [%class: %method] %message%n</pattern>
</encoder>
</appender>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5level %date{ISO8601} [%thread]: [%class: %method] %message%n</pattern>
</encoder>
</appender>
</appender>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5level %date{ISO8601} [%thread]: [%class: %method] %message%n</pattern>
</encoder>
</appender>
<logger name="org.springframework.core">
<level value="all"/>
</logger>
<logger name="org.springframework.beans">
<level value="all"/>
</logger>
<logger name="org.springframework.context">
<level value="all"/>
</logger>
<logger name="org.springframework.web">
<level value="all"/>
</logger>
<root level="error,info,debug">
<appender-ref ref="file"/>
<!-- <appender-ref ref="console"/> -->
</root>
</configuration>
The dependencies (I'm excluding commons-logging in each dependency that is using it to gain the power of logback - not shown below):
<!-- LOGGING -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.6.6</version>
</dependency>
<!--END LOGGING-->
Some additional info:
I also tried the 1.0.7 version (the last one although not available through the central repository - had to manually include it in the local maven repository), but the same happened.
My project was using 0.9.11 version of logback and I couldn't set up a rolling policy cause I couldn't find any valid documentation/manual. Perhaps someone could also point out some old manuals for those who need to work with legacy dependencies.
Kind Regards,
despot

You have to set the rolling policy to use SizeAndTimeBasedFNATP
Here is the documentation with an example
http://logback.qos.ch/manual/appenders.html#SizeAndTimeBasedFNATP
You are missing the %i:
<fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
Note the "%i" conversion token in addition to "%d". Each time the current log file reaches maxFileSize before the current time period ends, it will be archived with an increasing index, starting at 0.

Related

Spring 5 Framework Logging with slf4j/log4j2

I have a application that I've put together to become familiar with Spring Framework 5, using Maven and Java 8. Once executed, it extracts some information from a PostgreSQL database table and logs it to the console (via slf4j/log4j2).
The actual application logic is working fine - I'm seeing the info retrieved from the database on the console as expected. However, I'm not seeing any of the expected Spring/DBCP2 logging. After the application finishes executing, there are only 15 lines printed on the console - all lines that I specifically logged via logger.debug("...").
The dependencies section of my pom.xml looks like this:
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jdbc</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.1</version>
</dependency>
</dependencies>
My log4j2.xml file looks like this...
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE Configuration>
<Configuration status="INFO" strict="true">
<Properties>
<Property name="CONSOLE_PATTERN">%-5level %c{1} %M - %m%n</Property>
</Properties>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="${CONSOLE_PATTERN}" />
</Console>
</Appenders>
<Loggers>
<Logger name="local.spring5" level="DEBUG" additivity="false">
<AppenderRef ref="STDOUT" />
</Logger>
<Logger name="org.apache.commons.dbcp2" level="DEBUG" additivity="false">
<AppenderRef ref="STDOUT" />
</Logger>
<Logger name="org.springframework" level="INFO" additivity="false">
<AppenderRef ref="STDOUT" />
</Logger>
<Root level="INFO">
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>
Note that if I change the org.springframework logging level to DEBUG or TRACE, I see spring logging appropriate for those levels. Setting the log level to INFO, WARN or ERROR results in no logging from spring at all. I'm sceptical, to say the least, that spring doesn't log anything at those levels.
Does anyone have any ideas on how to get the spring framework logging to appear?

Logback file (testlog.log) is not created

I was using slf4j for logging purposes and everything worked well (file was created on a path I specified and all my logs were there), however, due to my requirements I had to make logger use the JSON format. I decided to use Logback for that purpose but my log file is not created (even tho in the console I see logs written in the JSON format - but for some reason file is not created so I can see those logs only in the console)
Here is my setup:
application.properties
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
logging.file.path=./install/my-project/logs
logging.file.name=${logging.file.path}/testlog.log
POM.xml
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-jackson</artifactId>
<version>${logback.contrib.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-json-classic</artifactId>
<version>${logback.contrib.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
logback.xml
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
<timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSX</timestampFormat>
<timestampFormatTimezoneId>Etc/UTC</timestampFormatTimezoneId>
<jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
<prettyPrint>true</prettyPrint>
</jsonFormatter>
</layout>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="stdout"/>
</root>
</configuration>
So with this setup, I see my logs in the console formatted as JSON, however,log file is not created. If I remove these dependencies, and delete logback.xml file and then I restart my application, then my logging works perfectly (log file is created on a specified location) however it's not a JSON format.
I've tried a lot of different options but I cannot figure out why I'm having this strange problem.
Hope you guys can help me
As "Simon Martinelli" pointed out, I had to add file appender as well so my logback.xml file now looks like this:
<configuration>
<property name="HOME_LOG" value="./install/my-project/logs"/>
<appender name="FILE-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${HOME_LOG}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/archived/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<!-- each archived file, size max 10MB -->
<maxFileSize>10MB</maxFileSize>
<!-- total size of all archive files, if total size > 20GB, it will delete old archived file -->
<totalSizeCap>20GB</totalSizeCap>
<!-- 60 days to keep -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
<timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSX</timestampFormat>
<timestampFormatTimezoneId>Etc/UTC</timestampFormatTimezoneId>
<jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
<prettyPrint>true</prettyPrint>
</jsonFormatter>
</layout>
</encoder>
</appender>
<logger name="com.mkyong" level="debug" additivity="false">
<appender-ref ref="FILE-ROLLING"/>
</logger>
<root level="error">
<appender-ref ref="FILE-ROLLING"/>
</root>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
<timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSX</timestampFormat>
<timestampFormatTimezoneId>Etc/UTC</timestampFormatTimezoneId>
<jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
<prettyPrint>true</prettyPrint>
</jsonFormatter>
</layout>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="stdout"/>
</root>
</configuration>
Thanks!

How to add a rolling file logger to SpringBoot?

I am learning SpringBoot using this very good example here.
But one thing I wanted to learn how to add into this project is RollingFileAppender.
In my previous projects I always did the following:
1) Added these dependencies
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
2) Add the following file log4j.properties in the src/main/resources folder.
# Root logger option
log4j.rootLogger=INFO, stdout, loggerId
log4j.appender.loggerId=org.apache.log4j.RollingFileAppender
log4j.appender.loggerId.layout=org.apache.log4j.PatternLayout
log4j.appender.loggerId.layout.ConversionPattern=%d [%t] %-5p (%F:%L) - %m%n
log4j.appender.loggerId.File=logs/app.log
log4j.appender.loggerId.MaxFileSize=100MB
log4j.appender.loggerId.MaxBackupIndex=30
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Silence unnecessary logs
log4j.logger.net.schmizz=OFF
log4j.logger.io.javalin=OFF
log4j.logger.net.dv8tion.jda.core.requests=OFF
3) In the code I can just invoke the logger:
private Logger LOG = LoggerFactory.getLogger(<class>)
(...)
LOG.info("logging a message")
And this would throw up logs to the console, and to a rolling file called logs/app.log with maximum size of 100MB (as defined in the properties file).
What is the correct way for doing this, in modern SpringBoot projects like the one I linked above in GitHub, possibly using the logger that comes with SpringBoot?
Thanks!
Logging in Spring Boot isn't fundamentally different than in a vanilla Java project. Spring Boot uses Commons Logging for all internal logging but leaves the underlying log implementation open. Default configurations are provided for Java Util Logging, Log4J2, and Logback. In each case, loggers are pre-configured to use console output with optional file output also available. By default, if you use the “Starters”, Logback is used for logging.1
If you want to stick with Log4J2, you'll have to exclude the default Logback dependency and include Log4J2:
<!-- exclude logback , add log4j2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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>
Then add a new file called log4j2.xml or (log4j2.properties) in src/main/resources
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="loggerId" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logs/app.log"/>
<param name="MaxBackupIndex" value="30"/>
<param name="MaxFileSize" value="100MB"/>
<layout class="org.apache.log4j.PatternLayout ">
<param name="ConversionPattern" value="%d [%t] %-5p (%F:%L) - %m%n"/>
</layout>
</appender>
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
</layout>
</appender>
<logger name="io.javalin">
<level value="OFF"/>
</logger>
<logger name="net.dv8tion.jda.core.requests">
<level value="OFF"/>
</logger>
<logger name="net.schmizz">
<level value="OFF"/>
</logger>
<root>
<level value="INFO"/>
<appender-ref ref="stdout"/>
<appender-ref ref="loggerId"/>
</root>
</configuration>
For more information, baeldung.com is my goto place for good to-the-point tutorials on how to do this stuff. Since you're asking specifically for advice on Rolling File Appenders, I recommend A Guide to Rolling File Appenders. There's also a more generic article on Logging in Spring Boot.
Personally, I like to use Lombok annotations like #Slf4j to get rid of the logging boilerplate and prevent copy-and-paste mistakes.
Code on!

log4j2 does not log in webapplication deployed on tomcat

I am upgrading the version of log4j for a web application running on Tomcat 8. I am upgrading from version 1.2.12 to the latest 2.11.1.
The application is using Maven. So I added the following dependencies to my application pom.xml (version is managed in parent pom):
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
I removed the old configuration file log4j.properties and replaced it by a new log4j2.xml file in the folder src/main/resources (find below my log4j2 file content).
When I am running directly a main function, the logs are correctly written in console and in a file. However when I deploy the application on Tomcat, and run it, no log is written.
I checked my application WAR, and both libraries are present in WEB-INF/lib folder.
I also tested by adding exclusions to log4j-1** to external libraries that have dependency on it, but nothing changed...
Did someone already had the same issue, and how did you correct it?
Regards,
Matthieu
PS: content of my log4j2.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status=WARN strict="true">
<Properties>
<Property name="pattern">%d [%t] (%F:%L) %x %-5p [%c{1}] %m%n</Property>
<Property name="filePath">C:/temp/logs/my_app/my_app.log</Property>
</Properties>
<Appenders>
<Appender type="Console" name="STDOUT">
<Layout type="PatternLayout" pattern="${pattern}"/>
</Appender>
<Appender type="RollingFile" name="FILE" fileName="${filePath}" filePattern="${filePath}.%i">
<Layout type="PatternLayout" pattern="${pattern}"/>
<Policies>
<SizeBasedTriggeringPolicy size="500KB"/>
</Policies>
<DefaultRolloverStrategy max="1"/>
</Appender>
</Appenders>
<Loggers>
<Logger name="my.package.debug" level="DEBUG" additivity="false">
<AppenderRef ref="STDOUT"/>
<AppenderRef ref="FILE"/>
</Logger>
<Root level="WARN">
<AppenderRef ref="STDOUT"/>
<AppenderRef ref="FILE"/>
</Root>
</Loggers>
</Configuration>
I finally found my issue, it was due to another library (infinispan-embeded) which was redefining Log4j classes, such as LogManager. I was loading thoses classes instead of those in log4j libraries, and they was in older version than what I wanted.
I just replaced the library, and logs are correctly written in file.

Overriding logback.xml with Spring Boot 1.5.x application

I'm trying to write logback configuration in Spring Boot(1.5.x) application.
Problem -
The problem is that it doesn't create any log file/folder (or may be not in correct path).
CODE -
logback.xml
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<property name="LOG_PATH" value="logs" />
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/mylog.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${LOG_PATH}/mylog-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
<maxFileSize>100MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
</configuration>
Either pass the LOG_PATH while variable while running the application or define it in the same file as follows <property name="LOG_PATH" value="logs"/>
And also add
<root level="INFO">
<appender-ref ref="ROLLING"/>
</root>
Add this at the end before </configuration>
<root level="INFO">
<appender-ref ref="ROLLING"/>
</root>

Resources