SpringBoot logging configuration based on logging level - spring

Is it possible to specify in SpringBoot's appliaction.properties different logging configuration for different logging levels?
For example to log info to file but debug only to console and specify different format for them.
I searched in SpringBoot docs but couldn't find the answer.

You can try using the log4j2 logger and specifiying withing its configurating file multiple logger elements. If you have the log4j2 dependency set up in spring, it should pick up the configuration in the file log4j2-spring.xml. Take a look at their intro docs here, but i believe something like this in the log4j2 config file would suffice:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="ConsoleAppender" target="SYSTEM_OUT">
<PatternLayout pattern="%d [%t] %-5level %logger{36} - %msg%n%throwable"/>
</Console>
<File name="FileAppender" fileName="debug.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="ConsoleAppender"/>
</Root>
<Root level="DEBUG">
<AppenderRef ref="FileAppender"/>
</Root>
</Loggers>
</Configuration>

Add following config in your application.yml
logging:
level:
root: INFO
com:
somepackage: DEBUG
someotherpackage: TRACE
Here you have set default logging to INFO (root logger) and for package com.somepackage logging level is DEBUG, for com.someotherpackage logging level is TRACE.

Related

Logs in Spring Boot not showing in terminal

I have a project in Spring Boot where I am adding logs with the #Slf4j annotation, but I can't get them to show up in the terminal when starting the project.
This is the log: log.info("totalVacations: " + totalVacations);
When I run the command mvn spring-boot: run, in terminal I can't see the message.
Very likely you are missing the configuration of the appender, if you are also using LOG4J and you don't already have it, you can create a file named: log4j2.xml within the application's class path, and then create some basic configuration like:
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%style{%d{ISO8601}}{black} %highlight{%-5level }[%style{%t}{bright,blue}] %style{%C{1.}}{bright,yellow}: %msg%n%throwable" />
</Console>
<RollingFile name="RollingFile"
fileName="./logs/spring-boot-logger-log4j2.log"
filePattern="./logs/$${date:yyyy-MM}/spring-boot-logger-log4j2-%d{-dd-MMMM-yyyy}-%i.log.gz">
<PatternLayout>
<pattern>%d %p %C{1.} [%t] %m%n</pattern>
</PatternLayout>
<Policies>
<!-- rollover on startup, daily and when the file reaches
10 MegaBytes -->
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy
size="10 MB" />
<TimeBasedTriggeringPolicy />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<!-- LOG everything at INFO level -->
<Root level="info">
<AppenderRef ref="Console" />
<AppenderRef ref="RollingFile" />
</Root>
<!-- LOG "com.baeldung*" at TRACE level -->
<Logger name="com.baeldung" level="trace"></Logger>
</Loggers>
</Configuration>
The key here is to set an appender to the console so that the logs are pushed there, and then at the logger section establish which level are you trying to get at the console appender, according to your example that should be INFO
If you are using just plain SLF4J with Logback go to src/main/resources/application.properties and add the following line:
logging.level.com=INFO
The ".com" is referencing the package to where this will apply, in this case is everything inside src/main/java/com.
and at the logback-spring.xml try this basic config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="your.name" level="INFO" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</logger>
</configuration>
You can find a very nice tutorial with more info here:
https://www.baeldung.com/spring-boot-logging
https://springframework.guru/using-logback-spring-boot/
Check whether #Slf4J import is from Lombok or some other library. I'm sure lombok #Slf4J default provides lowercase log and not LOG.

log4j2 RollingFileAppender after first rolling, each POD write exclusively current log file

I use log4j2 on a springboot web application with microservices deployed on openshift 3.11.
below the configuration of log4j2
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="${env:LOGGING_LEVEL}">
<Properties>
<Property name="log_path">/home/jboss/logs</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{dd-MM-yyyy HH:mm:ss.SSS} %green{[${hostName}]} %magenta{[%thread]} %highlight{%-5level} %logger{36}.%M - %msg%n" />
</Console>
<RollingFile name="fileLogger" fileName="${log_path}/application.log" filePattern="${log_path}/application.%i.log.zip" filePermissions="rw-rw-r-" >
<PatternLayout pattern="%d{dd-MM-yyyy HH:mm:ss.SSS} [${hostName}] [%thread] %-5level%logger{36}.%M - %msg%n" />
<Policies>
<SizeBasedTriggeringPolicy size="200MB" />
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console" level="${env:LOGGING_LEVEL}"/>
<AppenderRef ref="fileLogger" level="${env:LOGGING_LEVEL}"/>
</Root>
</Loggers>
</Configuration>
my problem is as follows:
multiple pods should write to the log file at the same time,
on the first application.log file there are no problems but when the rolling occurs and the application.log file becomes application.1.log.zip
the application.log file is written by a single pod and the same thing happens at subsequent rolling, is there a configuration that allows all pods to write the same file avoiding the situation described?
Writing multiple pods/nodes log4j logs to a single file is not a best practice or a good idea, as this creates an ambiguity problem for updating logs.

How to change log level in a spring boot project(in production enviroment) by change any property in application properties if I am using log4j2

I am developing a spring boot service (2.1.7 spring boot version) where I am using log4j2 to establish the logs and their pattern:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" name="MyService">
<Properties>
<Property name="project.component">${bundle:bootstrap:project.component}</Property>
<Property name="project.version">${bundle:bootstrap:project.version}</Property>
</Properties>
<Appenders>
<Console name="main" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss,SSSZ} ${project.component} ${project.version} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="root" level="INFO">
<AppenderRef ref="main" level="INFO"/>
</Logger>
</Loggers>
</Configuration>
I am not using log4j2.properties.
My problem is that I am only able to change the log level by log4j2.xml, I have tried with several spring boot properties in my application.properties as logging.level.root or through actuator endpoints but they did not work. When I am in a production environment and I need to change the logs level I have not a way to do it.
Any suggestion?
I am able to change the log level using a similar configuration, which even let's you configure a pattern for the log:
# Set everything to be logged to the console
log4j.rootCategory=TRACE, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
Per-class log levels can also be set, in example:
# Settings to quiet third party logs that are too verbose
log4j.logger.org.eclipse.jetty=WARN
log4j.logger.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR
log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=INFO
log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=INF
log4j.logger.org.apache.spark.sql.execution.streaming.FileStreamSource=TRACE

Removing Log4j2.xml from Tranisitive Dependecies and to use Log4j2-spring.xml instead in springboot project

I need to add file Appender in existing log4j2.xml of my existing spring-boot project. i did that and its generating two logs files for every logger specified i.e, i have only added Root level logger then also two files are getting generated.
When i searched for it i found that in spring projects log4j2-spring.xml should be used instead of Log4j2.xml which may be the cause of duplicates log files getting generated.
But when i am trying to run to change my log4j2.xml to log4j2-spring.xml its not even considering that file and is picking any other log4j2.xml that is available via classpath as i have added some external jar as dependency in this project the log4j2.xml of these exteranl dependemcies are being considered rather then my log4j2-spring.xml. Is there a way of telling it to use my log4j2-spring.xml instead of any log4j2.xml or may be is there a way to remove the usage of log4j2.xml from any dependency.
I tried doing the same with a simple spring-boot project and it worked as expected but when i am trying to do the same in my project which is multi-module maven project it does not works.
Can someone let me know what would be the way of doing above said asks.
Here is my pom.
`
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info" monitorInterval="60">
<Properties>
<Property name="log-path">${sys:app.log.path}</Property>
<Property name="archive">${log-path}/archive</Property>
<Property name="appName">${sys:spring.application.name}</Property>
<Property name="envName">${sys:app.env.name}</Property>
</Properties>
<Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout>
<pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS}{GMT} [%-5level] [%t] %c{1} - %msg%n
</pattern>
<charset>US-ASCII</charset>
</PatternLayout>
</Console>
<File name="File" fileName="${log-path}/${appName}-${envName}--${date:yyyy-MM-dd-HH-mm-ss-SSS}.log" append="true">
<PatternLayout pattern="%d{yyyy-MMM-dd HH:mm:ss a} [%t] %-5level %logger{36} - %msg%n" />
</File>
</Appenders>
<Loggers>
<Root level="INFO" additivity="false">
<AppenderRef ref="Console-Appender" level="WARN" />
<AppenderRef ref="File" level="INFO" />
</Root>
<Logger name="com.tmo.eus" level="INFO" additivity="false">
<Appender-ref ref="Console-Appender" />
</Logger>
</Loggers>
</Configuration>
`

Spring Boot Logging Properties vs Log4J 2 Properties

In a Spring Boot Web app, I have the following logging properties in application.properties.
logging.level.guru.springframework.controllers=DEBUG
logging.level.org.springframework.web=DEBUG
logging.file=logs/spring-boot-logging.log
Things work fine - DEBUG messages of both internal Spring Boot and the application gets logged to logs/spring-boot-logging.log. But, even if I add log4j2-spring.xml with different logging levels, the levels of application.properties still get picked.
My log4j2-spring.xml is this:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="60">
<Properties>
<Property name="log-path">applogs</Property>
</Properties>
<Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout>
<pattern>
[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>>
</PatternLayout>
</Console>
<File name="File-Appender" fileName="${log-path}/app_log.log" >
<PatternLayout>
<pattern>
[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="org.springframework.web" level="info">
<AppenderRef ref="File-Appender"/>
</Logger>
<Logger name="guru.springframework.controllers" level="info">
<AppenderRef ref="File-Appender"/>
</Logger>
<Root level="info">
<AppenderRef ref="Console-Appender"/>
</Root>
</Loggers>
</Configuration>
With these settings, debug (Defined in application.properties) messages are sent to applogs/app_log.log(Defined in log4j2-spring.xml)
On commenting out the logging.level.* in application properties, the log levels (info) in log4j2-spring.xml are used. I assume that by default properties of application.properties have precedence over log4j2-spring.xml. Is there any way I can configure Spring Boot to use log4j2-spring.xml properties instead of application.properties. Also, If application.properties have greater precedence, why the file appender of log4j2-spring.xml is getting used instead of the one in logging.file?
It should use your config file if you define it via this Spring Boot property:
logging.config= # Location of the logging configuration file. For instance `classpath:logback.xml` for Logback

Resources