Spring Context startup, silence preamble - spring

I'm running a command line application. I'm running Lo4j2. Everything works, but I would like to silence the Spring preamble that seems to run before Log4J has been loaded. Let me be clear, Log4J is working correctly, but the preamble of Spring logging messages arrives as soon as the application context is loaded.
i.e. I DON'T want to see this
Oct 24, 2015 9:07:29 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext#42a48628: startup date [Sat Oct 24 09:07:29 BST 2015]; root of context hierarchy
Oct 24, 2015 9:07:29 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [springConfig.xml]
Any help much appreciated, thanks!

You must have following dependencies:* including log4j-1.2-api*
compile group: 'org.apache.logging.log4j', name: 'log4j', version: log4j2_version
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: log4j2_version
compile group: 'org.apache.logging.log4j', name: 'log4j-1.2-api', version: log4j2_version
compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: log4j_slfj_binder_version
Have your log4j2.xml configured like this. I tested with Log4j2
<Configuration >
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout pattern=">%d{dd MMM yyyy HH:mm:ss,SSS} [%-5p] %X{trxID} %.20X{userName}[%c{2}] %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.springframework.context.support" level="ERROR" additivity="false">
<AppenderRef ref="CONSOLE" level="ERROR"/>
</Logger>
<Logger name="org.springframework.beans.factory.xml" level="ERROR" additivity="false">
<AppenderRef ref="CONSOLE" level="ERROR"/>
</Logger>
<Root level="INFO" additivity="false">
<AppenderRef ref="CONSOLE"/>
</Root>
</Loggers>
</Configuration>
My Test Program :
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestLog {
String springConfig = "spring-config/insight-test-context.xml";
private static final Logger slf4jLogger = LoggerFactory.getLogger(TestLog.class);
private AbstractApplicationContext ctx;
public static void main(String[] args) {
new TestLog().doTest();
}
public void doTest() {
slf4jLogger.info("--------Staring TestLog---------------");
ctx = new ClassPathXmlApplicationContext(springConfig);
ctx.registerShutdownHook();
slf4jLogger.info("----------Completed TestLog------------");
}
}

Related

Spring boot log level does not work for subpackage

I have a spring boot application where I need to change log level to info for my application and error for the library it uses. Both of them have the same parent package structure:
com.org.product.library
com.org.product.module
I added the following to the application.yml
logging:
level:
com.org.product.library: ERROR
com.org.product.module: INFO
But now the module is also logging only errors.
This is how Logger is invoked:
public static void info(String msgCode, String msg) {
if (isInfoEnabled()) {
getLoggerEngine().info(msgCodeMarker(msgCode), msg);
}
}
static Logger getLoggerEngine() {
//slf4j LoggerFactory
return LoggerFactory.getLogger(Log.class);
}
Also there is this spring-logback.xml configuration in the library:
<logger name="com.org" level="info" additivity="false">
<appender-ref ref="json" />
</logger>
<!-- By default will log warnings and above-->
<!-- set to other level for development if needed -->
<root level="warn">
<appender-ref ref="json" />
</root>

Logback with spring-boot: use ${user.home} does not work

I can't figure out why logback does not take into account the variable defined in the corresponding application-{env}.yml file.
Here is the content of logback-spring.xml file:
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<springProperty scope="context" name="LOG_FILE" source="logging.file"
defaultValue="localhost"/>
<property name="LOG_FILE" value="${LOG_FILE}"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
<!-- keep 30 days' worth of history capped at 3GB total size -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.example.demospringweb" level="INFO">
<appender-ref ref="FILE" />
</logger>
<springProfile name="default">
<root level="debug">
<appender-ref ref="CONSOLE"/>
</root>
<logger name="com.demospringweb" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE" />
</logger>>
</springProfile>
<springProfile name="qa, prod">
<logger name="com.demospringweb" level="WARN" additivity="false">
<appender-ref ref="FILE" />
</logger>
</springProfile>
</configuration>
And here is the content of the application.yml file:
greeting: Default greeting
password: default-pass
logging:
path: ${user.home}
file: ${logging.path}/demo_localhost
max-history: 30
level:
com:
example: debug
org:
hibernate: ERROR
springframework:
web: DEBUG
When I start the spring-boot app, it does not create a required log file.
UPDATE
I removed completely spring-logback.xml and kept profile-specific properties in corresponding application.yml files.
Here is the application.yml file and it never writes (creates) a log file:
greeting: Default greeting
password: default-pass
spring:
application:
name: demo-spring
logging:
file: demo-dev
pattern:
file: "%d{dd-MM-yyyy HH:mm:ss.SSS} %logger.%M - %msg%n"
console: "%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger.%M - %msg%n"
level:
root: debug
org:
hibernate: ERROR
springframework:
web: DEBUG
What am I missing?
Finally, I figured out how to achieve that.
Remove logback-spring.xml or logback.xml file if there is any. In this case, Spring boot will use the default values defined by Logback if they are not overridden in your application.yml (or application.properties) file.
Create application.yml and application-prod.yml. file (you can add as many as you want, depending on how many environments you are going to have.
Here is the content of application.yml file used for development:
spring:
application:
name: demo-spring
greeting: Development greeting
password: dev-pass
logging:
pattern:
console: "%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger.%M - %msg%n"
level:
root: debug
org:
hibernate: ERROR
springframework:
web: debug
com:
example:
demospringweb: info
In this case, the output will be printed to the console only using the provided pattern. The root log level is set to debug but the package com.example.demospringweb is set to info(you can use either UPPERCASE or lower cased versions of log levels).
Create a profile-specific application-prod.yml file that will be used when the app is started with the prod activated:
spring:
application:
name: demo-spring
greeting: Production greeting
password: prod-pass
logging:
path: ${user.home}/logs
file: ${logging.path}/prod.log
total-size-cap: 100MB
max-history: 10
max-file-size: 5MB
pattern:
console: off
file: "%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n"
rolling-file-name: ${logging.path}/plage_%d{dd-MM-yyyy}_%i.log
level:
root: info
org:
hibernate: ERROR
springframework:
web: warn
com:
example:
demospringweb: info
As you see, when starting the app with spring-boot:run -Dspring-boot.run.profiles=prod Spring Boot will use the values defined in application-prod.yml file:
write the logs to the file prod.log created in the user $HOME/logs directory. We also defined a rolling policy to keep 10 days history of max 5Mb by file max. The total size of all the log files is set to 100 Mb. Once it is achieved, the oldest file will be removed.
We also defined different log levels (root and by package).
To check how the logging varies depending on the active profile, take a look at the GreetingController:
package com.example.demospringweb.controllers;
import com.example.demospringweb.models.Greeting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.atomic.AtomicLong;
#RestController
public class GreetingsController {
private static final Logger LOGGER = LoggerFactory.getLogger(GreetingsController.class);
private final AtomicLong counter = new AtomicLong();
#Value("${greeting}")
private String greeting;
#Value("${password}")
private String password;
#GetMapping("/greeting")
public Greeting greeting() {
LOGGER.debug("This is a debug message");
LOGGER.info("This is an info message");
LOGGER.warn("This is a warn message");
LOGGER.error("This is an error message");
String message = greeting + "/pwd: " + password;
return new Greeting(counter.incrementAndGet(), message);
}
}
Voilà.

Log4j log file not getting created at specified location springboot

I am trying to configure log4j2 in springboot.I have removed(excluded) the logback dependency already from pom.xml.I am using this xml under resource folder named log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="DEBUG">
<Appenders>
<Console name="LogToConsole" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="LogToFile" fileName="logs/app.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="com.ashish" level="debug" additivity="false">
<AppenderRef ref="LogToFile"/>
<AppenderRef ref="LogToConsole"/>
</Logger>
<Logger name="org.springframework.boot" level="error" additivity="false">
<AppenderRef ref="LogToConsole"/>
</Logger>
<Root level="error">
<AppenderRef ref="LogToFile"/>
<AppenderRef ref="LogToConsole"/>
</Root>
</Loggers>
</Configuration>
This is my controller class.
package com.ashish;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Arrays;
import java.util.List;
#Controller
public class HelloController {
private static final Logger logger = LogManager.getLogger(HelloController.class);
private List<Integer> num = Arrays.asList(1, 2, 3, 4, 5);
#GetMapping("/")
public String main(Model model) {
if (logger.isDebugEnabled()) {
logger.debug("Hello from Log4j 2 - num : {}", num);
}
logger.debug("Hello from Log4j 2 - num : {}", () -> num);
model.addAttribute("tasks", num);
return "welcome";
}
private int getNum() {
return 100;
}
}
Am i missing anything here?I tried to set it using application.properties too using latest version of Log4j2.But still it's not getting created.When i run the application i can't see any log file getting dynamically created at the path specified in xml.
First, you have status="DEBUG" specified in your configuration. So you will see Log4j configure itself on the console (or wherever system.out is getting routed to). If you do not then you aren't really using Log4j.
If you do see the output then check the debug lines. I have a suspicion your log file is either not getting created due to a permissions problem or it isn't being written where you expect it.
Your configuration specifies a relative directory named "logs". Whatever directory is the working directory when the app is started should contain your logs directory. Frequently on Linux that will end up being "/". You almost certainly won't have permission to create a logs directory there so configuration will fail.
I can't comment on the content of the log4j2 config file itself, probably it will make sense to print on console first and make sure that its driven by log4j2 indeed.
However, I'll refer to the beginning of the question:
I am trying to configure log4j2 in springboot.I have removed(excluded) the logback dependency already from pom.xml
You don't present the pom.xml but in general in order to switch spring boot to work with log4j2 you should:
"Exclude" the default logging mechanism of spring boot:
<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>
Add a log4j2 starter that will in turn (transitively) add log4j2 dependency of the versions compatible with your spring boot version:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
Quick googling has revealed this tutorial that contains all the steps including end-to-end example of such an integration.

Configure Spring logging piror to application context loading

I have a CLI tool that is based on Spring framework (3.2.12) and using logback (1.23) for logging.
My problem is that the logging config does not take effect until the app cxt is loaded, thus polluting the command line with the logs of the init procedure.
Is there a way to force Spring to load and use the log configuration in the first place?
Main class:
public class MyCliMain {
private static final JcanLogger LOG = SessionLogFactory.getLog(MyCliMain.class);
public static void main(String[] args) {
int exitCode;
ApplicationContext cxt = initApplicationContext();
exitCode = cxt.getBean(CommandRunner.class).run(args);
System.exit(exitCode);
}
private static ApplicationContext initApplicationContext() {
AbstractApplicationContext cxt = new ClassPathXmlApplicationContext("spring-pay-bus-cli-G8Q.xml");
cxt.registerShutdownHook();
return cxt;
}}
Logback config in resources:
<appender name="writeToConsole" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
<encoder>
<pattern>%level %logger{5} - %msg%n</pattern>
</encoder>
</appender>
<appender name="writeToFile" class="ch.qos.logback.core.FileAppender">
<file>${log.output}</file>
<encoder>
<pattern>%-30(%d{HH:mm:ss.SSS} [%thread]) %-5level %logger{32} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN"/>
<logger name="com..." level="DEBUG" appender-ref="writeToFile"/>
<logger name="com... level="DEBUG"/>
<root level="WARN">
<appender-ref ref="writeToConsole"/>
<appender-ref ref="writeToFile" />
</root>
Console log out put:
Apr 01, 2021 4:07:23 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext#7c16905e: startup date [Thu Apr 01 16:07:23 CEST 2021]; root of context hierarchy
Apr 01, 2021 4:07:23 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
...
logging config takes effect:
WARN o.a.c.j.u.ResourceUtils - No resource methods have been found for resource class org.apache.cxf.jaxrs.client.WebClient
WARN o.a.c.j.u.ResourceUtils - No resource methods have been found for resource class org.apache.cxf.jaxrs.client.WebClient
WARN o.a.c.j.u.ResourceUtils - No resource methods have been found for resource class org.apache.cxf.jaxrs.client.WebClient
INFO c.u.s.v.c.CommandRunner -

How to enable Logback-access in Spring Boot?

I'm trying to enable logback-access in a spring boot app to log all http requests that hit the application.
I've tried implementing this using: https://github.com/akihyro/logback-access-spring-boot-starter
Adding the XML file shown in the example doesn't do anything, is there anything more that needs to be added to enable?
Any other suggestions to achieve the same result would be welcomed :)
you still need to wire a bean to your application...like this code snippet wires the filter to your application:
#SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
// ... your other methods here
#Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
filter.setIncludeQueryString(true);
return filter;
}
}
I am pretty sure you are talking about the logback logger for SpringBoot. If I am not wrong, this is how you can do this
a. Add the dependency in your POM
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
b. Now there are may ways you can ask spring to configure logback. For example
In the application.properties file
In the logback.xml file
The advantage of using logback.xml file is that, you might have different xml file for different build profile. But in the application.properties, you don’t have this freedom.
Sample entries in the application.properties file from one of my project
logging.level.org.springframework.web = INFO
logging.level.com.company.app = DEBUG
#logging.level.org.hibernate=ERROR
logging.file=logs/spring-boot-logging.log
## Hibernate Logging
logging.level.org.hibernate.SQL = DEBUG
If you are using XML, configuration probably will look like this
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
<logger name="org.springframework" level="error" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<logger name="org.springframework" level="info" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<logger name="org.springframework" level="warn" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<logger name="com.memorynotfound" level="debug" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<configuration scan="true"/>
</configuration>
I recommend you to do some Googling for better understating.
Good luck!

Resources