Java 日志体系概述与应用

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Java 日志体系概述与应用

JAVA常用的日志打印组件

名称

描述

log4j

提供Async Append异步实现,稳定

logback

异步下,速度快

log4j2

log4j2是log4j 1.x 的升级版

基于LMAX Disruptor库,实现了一个高性能的异步记录器。在异步方面比logback和log4j都快

 

 

java.util.looging

jdk内置日志

假设Spring 框架要打印日志,应该选择中其中哪一个组件?

发现哪个都不能选,只能基于应用实际使用的日志组件来。不然就会日志打印会多份。

怎么找到应用实际使用的日志组件 Apache Commons Loging 解决了这个问题

Apache Commons Loging (JCL)

Commons Loging 本身只提供日志接口,具体实现在运行时动态寻找对应组件?比如:log4j、jdk14looger 等。但这种动态绑定的方式当系统特别庞大的时候会出现绑定失败的问题。现在比较流行的slf4j 基于静态绑定的方式解决了这个问题?

Slf4j

log4j的作者觉得jcl不好用,自己又写了一个新的接口api,那么就是slf4j。关于slf4j的集成图如下所示

 

sl4j 本身也只提供日志接口,应用调了sl4j-api,即日志门面接口。日志门面接口本身通常并没有实际的日志输出能力,它底层还是需要去调用具体的日志框架API的,也就是实际上它需要跟具体的日志框架结合使用。由于具体日志框架比较多,而且互相也大都不兼容,日志门面接口要想实现与任意日志框架结合可能需要对应的桥接器,上图红框中的组件即是对应的各种桥接器!

与commons loging 不同的是其采用在classPath 加入以下jar包来表示具体采用哪种实现 :

  • slfj-log4j12.jar (表示指定 log4j)
  • slf4j-jdk14.jar(表示指定jdk Looging)
  • slf4j-jcl.jar(表示指定jcl)
  • log4j-slf4j-impl(表示指定log4j2)
  • logback-classic(表示指定logback)

 

 假设你们系统当中之前在用 JCL 打印日志,但这时想加入slf4j来打印日志,就会出现两类日志输出如何解决?

加入如下等JAR包jcl-over-slf4j、log4j-over-sl4j、jul-over-sl4j ,即可在使用原API的情况下,又统一至slf4j 的实现进行输出了。 .

 

JAVA日志体系结构图

日志级别

Java的日志框架一般会提供以下日志级别,缺省打开info级别,也就是debug,trace级别的日志在生产环境不会输出,在开发和测试环境可以通过不同的日志配置文件打开debug级别。

  1. fatal - 严重的,造成服务中断的错误;
  2. error - 其他错误运行期错误;
  3. warn - 警告信息,如程序调用了一个即将作废的接口,接口的不当使用,运行状态不是期望的但仍可继续处理等;
  4. info - 有意义的事件信息,如程序启动,关闭事件,收到请求事件等;
  5. debug - 调试信息,可记录详细的业务处理到哪一步了,以及当前的变量状态;
  6. trace - 更详细的跟踪信息;

上面数字越小级别越高,只有超越项目所设置的日志级别的日志才有希望"脱颖而出"打印出来

打印规则

必须使用参数化信息的方式:

logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol);

对于debug日志,必须判断是否为debug级别后,才进行使用

原因如下:https://blog.csdn.net/weixin_44593504/article/details/107950828

 

if (logger.isDebugEnabled()) {
   logger.debug("Processing trade with id: " +id + " symbol: " + symbol);
}

不要进行字符串拼接,那样会产生很多String对象,占用空间,影响性能。

反例(不要这么做):

logger.debug("Processing trade with id: " + id + " symbol: " + symbol);

使用[]进行参数变量隔离

如有参数变量,应该写成如下写法:

logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol);

这样的格式写法,可读性更好,对于排查问题更有帮助。

 

 

循环依赖

假设,我们在应用中调用了sl4j-api,但是呢,你引了四个jar包,slf4j-api-xx.jar,slf4j-log4j12-xx.jar,log4j-xx.jar,log4j-over-slf4j-xx.jar,于是你就会出现如下尴尬的场面

如上图所示,在这种情况下,你调用了slf4j-api,就会陷入死循环中!slf4j-api去调了slf4j-log4j12,slf4j-log4j12又去调用了log4j,log4j去调用了log4j-over-slf4j。最终,log4j-over-slf4j又调了slf4j-api,陷入死循环!

 

 

项目实战

案例一

一个项目,一个模块用log4j,另一个模块用slf4j+log4j2,如何统一输出?

其实在某些中小型公司,这种情况很常见。我曾经见过某公司的项目,因为研发不懂底层的日志原理,日志文件里头既有log4j.properties,又有log4j2.xml,各种API混用,惨不忍睹!

还有人用着jul的API,然后拿着log4j.properties,跑来问我,为什么配置不生效!简直是一言难尽!

OK,回到我们的问题,如何统一输出!OK,这里就要用上slf4j的适配器,slf4j提供了各种各样的适配器,用来将某种日志框架委托给slf4j。其最明显的集成工作方式有如下:

 

进行选择填空,将我们的案例里的条件填入,根据题意应该选log4j-over-slf4j适配器,于是就变成下面这张图

就可以实现日志统一为log4j2来输出!

ps:根据适配器工作原理的不同,被适配的日志框架并不是一定要删除!以上图为例,log4j这个日志框架删不删都可以,你只要能保证log4j的加载顺序在log4j-over-slf4j后即可。因为log4j-over-slf4j这个适配器的工作原理是,内部提供了和log4j一模一样的api接口,因此你在程序中调用log4j的api的时候,你必须想办法让其走适配器的api。如果你删了log4j这个框架,那你程序里肯定是走log4j-over-slf4j这个组件里的api。如果不删log4j,只要保证其在classpth里的顺序比log4j前即可!

 

案例二

如何让spring以log4j2的形式输出?

spring默认使用的是jcl输出日志,由于你此时并没有引入Log4j的日志框架,jcl会以jul做为日志框架。此时集成图如下

而你的应用中,采用了slf4j+log4j-core,即log4j2进行日志记录,那么此时集成图如下

那我们现在需要让spring以log4j2的形式输出?怎么办?

OK,第一种方案,走jcl-over-slf4j适配器,此时集成图就变成下面这样了

 

在这种方案下,spring框架中遇到日志输出的语句,就会如上图红线流程一样,最终以log4J2的形式输出!

OK,有第二种方案么?

有,走jul-to-slf4j适配器,此时集成图如下

 

ps:这种情况下,记得在代码中执行

SLF4JBridgeHandler.removeHandlersForRootLogger();

SLF4JBridgeHandler.install();

这样jul-to-slf4j适配器才能正常工作,详情可以查询该适配器工作原理。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
15天前
|
运维 应用服务中间件 nginx
docker运维查看指定应用log文件位置和名称
通过本文的方法,您可以更高效地管理和查看Docker容器中的日志文件,确保应用运行状态可控和可监测。
88 28
|
1月前
|
Oracle Java 关系型数据库
Java基础(一):语言概述
Java基础(一):语言概述
52 15
Java基础(一):语言概述
|
8天前
|
XML JSON Java
Java中Log级别和解析
日志级别定义了日志信息的重要程度,从低到高依次为:TRACE(详细调试)、DEBUG(开发调试)、INFO(一般信息)、WARN(潜在问题)、ERROR(错误信息)和FATAL(严重错误)。开发人员可根据需要设置不同的日志级别,以控制日志输出量,避免影响性能或干扰问题排查。日志框架如Log4j 2由Logger、Appender和Layout组成,通过配置文件指定日志级别、输出目标和格式。
|
1月前
|
存储 人工智能 JSON
RAG Logger:专为检索增强生成(RAG)应用设计的开源日志工具,支持查询跟踪、性能监控
RAG Logger 是一款专为检索增强生成(RAG)应用设计的开源日志工具,支持查询跟踪、检索结果记录、LLM 交互记录和性能监控等功能。
77 7
RAG Logger:专为检索增强生成(RAG)应用设计的开源日志工具,支持查询跟踪、性能监控
|
30天前
|
Java 编译器 开发者
Java中的this关键字详解:深入理解与应用
本文深入解析了Java中`this`关键字的多种用法
127 9
|
2月前
|
Java Maven
java项目中jar启动执行日志报错:no main manifest attribute, in /www/wwwroot/snow-server/z-server.jar-jar打包的大小明显小于正常大小如何解决
在Java项目中,启动jar包时遇到“no main manifest attribute”错误,且打包大小明显偏小。常见原因包括:1) Maven配置中跳过主程序打包;2) 缺少Manifest文件或Main-Class属性。解决方案如下:
679 8
java项目中jar启动执行日志报错:no main manifest attribute, in /www/wwwroot/snow-server/z-server.jar-jar打包的大小明显小于正常大小如何解决
|
30天前
|
Java 应用服务中间件 API
【潜意识Java】javaee中的SpringBoot在Java 开发中的应用与详细分析
本文介绍了 Spring Boot 的核心概念和使用场景,并通过一个实战项目演示了如何构建一个简单的 RESTful API。
41 5
|
30天前
|
人工智能 自然语言处理 搜索推荐
【潜意识Java】了解并详细分析Java与AIGC的结合应用和使用方式
本文介绍了如何将Java与AIGC(人工智能生成内容)技术结合,实现智能文本生成。
61 5
|
30天前
|
SQL Java 数据库连接
【潜意识Java】深入理解MyBatis,从基础到高级的深度细节应用
本文详细介绍了MyBatis,一个轻量级的Java持久化框架。内容涵盖MyBatis的基本概念、配置与环境搭建、基础操作(如创建实体类、Mapper接口及映射文件)以及CRUD操作的实现。此外,还深入探讨了高级特性,包括动态SQL和缓存机制。通过代码示例,帮助开发者更好地掌握MyBatis的使用技巧,提升数据库操作效率。总结部分强调了MyBatis的优势及其在实际开发中的应用价值。
32 1
|
2月前
|
运维 监控 Cloud Native
一行代码都不改,Golang 应用链路指标日志全知道
本文将通过阿里云开源的 Golang Agent,帮助用户实现“一行代码都不改”就能获取到应用产生的各种观测数据,同时提升运维团队和研发团队的幸福感。
208 12

热门文章

最新文章