当前位置:网站首页>Solve the problem that slf4j logs are not printed
Solve the problem that slf4j logs are not printed
2022-06-23 23:37:00 【Ask North】
The log does not print , It's a headache , It is also a problem we often encounter .
Abnormal logs are found during daily site status patrol , Navigate to the log location , When I look at the user-defined output log of the online document, I find that , The logs you added were not output . After checking, we found that , The log output in this class uses lombok Of @Slf4j The function of annotation , Browse through other classes that use this annotation , The user-defined logs are not printed online . While using LoggerFactory.getLogger(Class<?> clazz) Acquired Logger Object print log , It can print normally online .
Local boot , The use of lombok Of @Slf4j Annotated classes , Logs can also be printed , The test environment can also . It's strange !
Anyone with some experience will guess ,jar Package conflict .
How to verify and solve it ?
maven Dependency tree log
First of all, you can use maven The order of mvn dependency:tree
as follows , take maven Dependency tree output to file , Easy to view and retrieve
mvn dependency:tree > log.txt
You can search log Other keywords , Look at what you've done log Outside the bag , Is there any other version or other logging implementation indirectly introduced through other third-party packages jar( Such as , You used log4j, You rely on a third-party package logback etc. ). In this way, most conflicting dependencies can be found .
Such as , I introduced it zkClient My bag , It depends on log The version is different from mine 
I can eliminate it in the following way jar Inside log package . There are other things excluded as well , There is no point enumerating .
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.4</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
Slf4j The principle of binding log implementation
This way is actually not so convenient to find , After reading this elder brother's post , Understand the principle of conflict . Probably quote the original text
The system uses SLF4J Frame printing log4j2 Log . View the... Introduced in the system jar Bao found that there were many SLF4J The bridge package for . So eliminate the conflict jar package , Then, when online, all machines print logs normally .
We all know ,SLF4J It's a log facade , The picture below is SLF4J frame 、 Diagram of various log implementations and corresponding bridging packages , From that article .

SLF4J Frame as facade frame , There is no concrete implementation of the log . Instead, it is associated with other specific log implementations , A log is configured in the system to print .
So it's easy to cause jar Package introduction conflict , This results in multiple log implementations . When SLF4J When the log implementation selected by the framework is inconsistent with our configuration , Will not print out the log .
SLF4J When the framework finds multiple log implementations , It will print prompt information . But because it is standard error output , On the console (Tomcat Of catalina.out) Print in 【 When there is no log print in the business log file , You can see catalina.out Is there a hint 】


Because of every SLF4J All bridging packages have org.slf4j.impl.StaticLoggerBinder, and SLF4J Will randomly select one to use . When the selection is the same as the system configuration, you can print the log , Otherwise, it will not print . So there will be some machines printing logs , Some machines may not print logs .
Quickly sense whether there are multiple bridging packets
Just passed maven Depending on how the tree looks with the naked eye , Not very convenient , I understand Slf4j The principle of binding log implementation , We can call it findPossibleStaticLoggerBinderPathSet Method returns Set Collection to get the current number of bridging packets , Then search the specific package name in the log output from the dependency tree .
Specific way :
- Realization spring Of
BeanFactoryPostProcessor, And leave it to spring management . Ensure that after the system is started , Automatic log conflict verification . - Use reflection to get
LoggerFactoryExamples andfindPossibleStaticLoggerBinderPathSetmethod . - Judge whether it is abnormal according to the number of bridging packets , Customize the alarm .
- According to the alarm information , Search the dependency tree log for , It is indirectly introduced from that dependency , Then arrange the package .
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.URL;
import java.util.Set;
/** * journal jar Package conflict check */
@Component
public class LogJarConflictCheck implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
try {
Class<LoggerFactory> loggerFactoryClazz = LoggerFactory.class;
Constructor<LoggerFactory> constructor = loggerFactoryClazz.getDeclaredConstructor();
constructor.setAccessible(true);
LoggerFactory instance = constructor.newInstance();
Method method = loggerFactoryClazz.getDeclaredMethod("findPossibleStaticLoggerBinderPathSet");
// Forced entry
method.setAccessible(true);
Set<URL> staticLoggerBinderPathSet = (Set<URL>)method.invoke(instance);
if (CollectionUtils.isEmpty(staticLoggerBinderPathSet)) {
handleLogJarConflict(staticLoggerBinderPathSet, "Class path is Empty. Add corresponding log jar package ");
}
if (staticLoggerBinderPathSet.size() == 1) {
return;
}
handleLogJarConflict(staticLoggerBinderPathSet, "Class path contains multiple SLF4J bindings. Pay attention to packing ");
} catch (Throwable t) {
t.getStackTrace();
}
}
/** * journal jar Packet conflict alarm * @param staticLoggerBinderPathSet jar Package path * @param tip Hint */
private void handleLogJarConflict (Set<URL> staticLoggerBinderPathSet, String tip) {
String ip = getLocalHostIp();
StringBuilder detail = new StringBuilder();
detail.append("ip by ").append(ip).append("; The prompt is ").append(tip);
if (CollectionUtils.isNotEmpty(staticLoggerBinderPathSet)) {
String path = JsonUtils.toJson(staticLoggerBinderPathSet);
detail.append("; The duplicate package paths are ").append(path);
}
String logDetail = detail.toString();
// You can customize the alarm
System.out.println("====>"+logDetail);
}
private String getLocalHostIp() {
String ip;
try {
InetAddress addr = InetAddress.getLocalHost();
ip = addr.getHostAddress();
} catch (Exception var2) {
ip = "";
}
return ip;
}
}
Once and for all through configuration
The above methods only help us quickly perceive the log jar Packet collision , Manual packing is still required .
Is there a solution , Can help us solve this problem completely ?
The answer is yes. .
About what we need to introduce jar Bags and things that need to be sorted out jar Package declaration to maven At the top of , Declare the packages to be excluded as provided that will do
The solution is to use maven Packet scanning strategy :
Rely on the shortest path first principle ;
The dependent paths are the same , Affirm the principle of priority
When we put all jar After the package is declared as a direct dependency , Will be used preferentially . The package we need to exclude is just declared as provided, You won't break into the bag . Thus, the required packages are subject to our Declaration , Packages that need to be discarded will not be affected by indirect dependencies
<properties>
<slf4j.version>1.7.7</slf4j.version>
<logback.version>1.2.3</logback.version>
<log4j.version>1.2.17</log4j.version>
<log4j2.version>2.3</log4j2.version>
<jcl.version>1.2</jcl.version>
</properties>
<dependencies>
<!-- System use log4j2 As a system log slf4J As a facade -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Use log4j2 As an actual log implementation -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<!-- take log4j、logback、JCL Of jar Package set to provided, Not in the bag -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${jcl.version}</version>
<scope>provided</scope>
</dependency>
<!-- To prevent cyclic conversion , Get rid of it log4j2 turn slf4j The bridge package for -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j2.version}</version>
<scope>provided</scope>
</dependency>
<!-- Statement log4j、JCL、JUL turn slf4j The bridge package for , The corresponding log in the code can be converted to SLF4J-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Statement slf4j turn SLF4J The bridge package for -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
</dependency>
<!-- Get rid of it slf4j turn log4j、JCL、JUL turn slf4j Bridge package of bridge package , Prevent log implementation jar Packet collision -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>${slf4j.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jcl</artifactId>
<version>${slf4j.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
I didn't do it this way , The reason is that there are too many changes , Too risky . I prefer the above way , Each time a third-party dependency is introduced , Manual detection once , Or use the above method for automatic detection , Then manually eliminate .
Welcome to pay attention to :BiggerBoy
Reference resources :https://blog.csdn.net/zy1817204670/article/details/121154660
边栏推荐
- What to check for AIX system monthly maintenance (II)
- 评估和选择最佳学习模型的一些指标总结
- E: 无法获得锁 /var/lib/dpkg/lock
- How does the fortress connection key server associate with the server host?
- Bitmap load memory analysis
- TDD开发模式流程推荐
- The fortress computer is connected to the server normally, but what's wrong with the black screen? What should I do?
- 数据解读!理想L9冲刺「月销过万」,从BBA手中抢份额
- The 12 SQL optimization schemes summarized by professional "brick moving" old drivers are very practical!
- Telecommuting: how to become a master of time management| Community essay solicitation
猜你喜欢

The national post office and other three departments: strengthen the security management of personal information related to postal express delivery, and promote the de identification technology of per

短视频挺进在线音乐腹地

“山大地纬杯”第十二届山东省ICPC大学生程序设计竞赛

PyQt5_QTableWidget分页单选右键菜单控件

The Sandbox 归属周来啦!

HDLBits-&gt; Circuits-&gt; Arithmetic Circuitd-&gt; 3-bit binary adder
Several cases of index invalidation caused by MySQL
![[Xilinx ax7103 microbalze Learning Notes 6] MicroBlaze custom IP core packaging experiment](/img/26/c4e6be2e3b17c7925108e95943c558.png)
[Xilinx ax7103 microbalze Learning Notes 6] MicroBlaze custom IP core packaging experiment

Bitmap load memory analysis

Bitmap加载内存分析
随机推荐
19 MySQL optimizations commonly used in projects
解决Slf4j日志不打印问题
Bilibili × Blue bridge cloud course | online programming practice competition is new!
Bitmap加载内存分析
Stm32 - - - - interruption externe
laravel之任务队列
Activity的onSaveInstanceState回调时机
Aicon2021 | AI technology helps content security and promotes the healthy development of Internet Environment
Bitmap load memory analysis
网站如何在Google建立索引
The Sandbox 归属周来啦!
Kotlin 协程 异步 异步流
CTF go topic recurrence
Summary of cloud native pipeline tools
Eight models of data analysis: detailed PEST model
Analysis of Alibaba cloud Tianchi competition -- prediction of o2o coupon
不同网络结构的特征也能进行对比学习?蚂蚁&美团&南大&阿里提出跨架构自监督视频表示学习方法CACL,性能SOTA!...
思考(八十六):主从实现思路
Bilibili×蓝桥云课|线上编程实战赛全新上新!
How does the fortress connection key server associate with the server host?