Java日志体系(八)最佳实践
java常用日志框架关系
Log4j 2与Log4j 1发生了很大的变化,Log4j 2不兼容Log4j 1。
Logback必须配合Slf4j使用。由于Logback和Slf4j是同一个作者,其兼容性不言而喻。
比较常用的组合使用方式是Slf4j与Logback组合使用,Commons Logging与Log4j组合使用。
项目中选择日志框架选择
如果是在一个新的项目中建议使用Slf4j与Logback组合,这样有如下的几个优点。
Slf4j实现机制决定Slf4j限制较少,使用范围更广。由于Slf4j在编译期间,静态绑定本地的LOG库使得通用性要比Commons Logging要好。
Logback拥有更好的性能。Logback声称:某些关键操作,比如判定是否记录一条日志语句的操作,其性能得到了显著的提高。这个操作在Logback中需要3纳秒,而在Log4J中则需要30纳秒。LogBack创建记录器(logger)的速度也更快:13毫秒,而在Log4J中需要23毫秒。更重要的是,它获取已存在的记录器只需94纳秒,而Log4J需要2234纳秒,时间减少到了1/23。跟JUL相比的性能提高也是显著的。
Commons Logging开销更高
# 在使Commons Logging时为了减少构建日志信息的开销,通常的做法是
if(log.isDebugEnabled()){
log.debug("User name: " +
user.getName() + " buy goods id :" + good.getId());
} # 在Slf4j阵营,你只需这么做:
log.debug("User name:{} ,buy goods id :{}", user.getName(),good.getId()); # 也就是说,Slf4j把构建日志的开销放在了它确认需要显示这条日志之后,减少内存和Cup的开销,使用占位符号,代码也更为简洁- Logback文档免费。Logback的所有文档是全面免费提供的,不象Log4J那样只提供部分免费文档而需要用户去购买付费文档。
几点最佳实践:
- 总是使用 Log Facade,而不是具体的 Log Implementation
正如之前所说的,使用 Log Facade 可以方便的切换具体的日志实现。而且,如果依赖多个项目,使用了不同的Log Facade,还可以方便的通过 Adapter 转接到同一个实现上。如果依赖项目使用了多个不同的日志实现,就麻烦的多了。具体来说,现在推荐使用 Log4j-API 或者 SLF4j,不推荐继续使用 JCL。
- 只添加一个 Log Implementation 依赖
在项目中,Log Implementation的依赖强烈建议设置为runtime scope,并且设置为optional。例如项目中使用了 SLF4J 作为 Log Facade,然后想使用 Log4j2 作为 Implementation,那么使用 maven 添加依赖的时候这样设置:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
毫无疑问,项目中应该只使用一个具体的 Log Implementation,建议使用 Logback 或者Log4j2。如果有依赖的项目中,使用的 Log Facade不支持直接使用当前的 Log Implementation,就添加合适的桥接器依赖。
- 具体的日志依赖应该设置为 optional,并使用 runtime scope
设为optional,依赖不会传递,这样如果你是个lib项目,然后别的项目使用了你这个lib,不会被引入不想要的Log Implementation 依赖;
Scope设置为runtime,是为了防止开发人员在项目中直接使用Log Implementation中的类,而不使用Log Facade中的类。
- 如果有必要, 排除依赖的第三方库中的Log Impementation依赖
这是很常见的一个问题,第三方库的开发者未必会把具体的日志实现或者桥接器的依赖设置为optional,然后你的项目继承了这些依赖——具体的日志实现未必是你想使用的,比如他依赖了Log4j,你想使用Logback,这时就很尴尬。另外,如果不同的第三方依赖使用了不同的桥接器和Log实现,也极容易形成环。
这种情况下,推荐的处理方法,是使用exclude来排除所有的这些Log实现和桥接器的依赖,只保留第三方库里面对Log Facade的依赖。
比如阿里的JStorm就没有很好的处理这个问题,依赖jstorm会引入对Logback和log4j-over-slf4j的依赖,如果你想在自己的项目中使用Log4j或其他Log实现的话,就需要加上excludes:
<dependency>
<groupId>com.alibaba.jstorm</groupId>
<artifactId>jstorm-core</artifactId>
<version>2.1.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
参考:https://zhuanlan.zhihu.com/p/24275518
Java日志体系(八)最佳实践的更多相关文章
- java日志体系的思考(转)
Java 日志缓存机制的实现 Java 日志管理最佳实践 混乱的 Java 日志体系 log日志远程统一记录 浅谈后端日志系统 Java异常处理和接口约定 用SLF4j/Logback打印日志-1 用 ...
- Java日志体系居然这么复杂?——架构篇
本文是一个系列,欢迎关注 日志到底是何方神圣?为什么要使用日志框架? 想必大家都有过使用System.out来进行输出调试,开发开发环境下这样做当然很方便,但是线上这样做就有麻烦了: 系统一直运行,输 ...
- Atitit.log日志技术的最佳实践attilax总结
Atitit.log日志技术的最佳实践attilax总结 1. 日志的意义与作用1 1.1. 日志系统是一种不可或缺的单元测试,跟踪调试工具1 2. 俩种实现[1]日志系统作为一种服务进程存在 [2] ...
- paip.java gui swt/jface 最佳实践
paip.java gui swt/jface 最佳实践 1. 工具:Eclipse +jigloo4 1 2. 安装插件: 1 1. IMPORT swt lib 2 2. 新建立窗体 2 3. 运 ...
- java 日志体系目录
java 日志体系目录 1.1 java 日志体系(一)log4j1.log4j2.logback.jul.jcl.slf4j 1.2 java 日志体系(二)jcl 和 slf4j 2.1 java ...
- java 日志体系(四)log4j 源码分析
java 日志体系(四)log4j 源码分析 logback.log4j2.jul 都是在 log4j 的基础上扩展的,其实现的逻辑都差不多,下面以 log4j 为例剖析一下日志框架的基本组件. 一. ...
- java 日志体系(三)log4j从入门到详解
java 日志体系(三)log4j从入门到详解 一.Log4j 简介 在应用程序中添加日志记录总的来说基于三个目的: 监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作: 跟踪代 ...
- Java 日志体系(二)jcl 和 slf4j
Java 日志体系(二)jcl 和 slf4j <java 日志体系(一)统一日志>:https://www.cnblogs.com/binarylei/p/9828166.html &l ...
- Java 日志体系
Java 日志体系 <java 日志和 SLF4J 随想>:http://ifeve.com/java-slf4j-think/ 一.常用的日志组件 名称 jar 描述 log4j log ...
- paip.提升性能--多核编程中的java .net php c++最佳实践 v2.0 cah
paip.提升性能--多核编程中的java .net php c++最佳实践 v2.0 cah 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax ...
随机推荐
- java线程基础巩固---如何捕获线程运行期间的异常
对于友盟统计我想搞程序的应该无人不晓,其中对于里面用得最多的功能就是对线上的崩溃进行修复,而这些异常都是运行期的,如: 其实也就是可以对线程中出现了这种运行期异常是提供有一种捕获机制对其进行统一处理, ...
- __builtin_ _Find_first()
•int __builtin_ffs (unsigned int x) 返回x的最后一位1的是从后向前第几位,比如7368(1110011001000)返回4. •int __builtin_clz ...
- Python3学习笔记36-PEP8代码规范
在使用PyCharm时,最右边会有波浪线警告提示代码不符合PEP8代码规范.记录一下犯的错和解决方式 PEP8是风格错误,而不是编码错误.只是为了让代码更具有阅读性. 1)block comment ...
- Spring入门篇——第1章 概述
第1章 概述 本章对课程的情况进行介绍,并介绍框架和Spring概况. 1-1 Spring入门课程简介 1-2 Spring概况 1-3 Spring框架
- iOS 中通过kvc 获取数组的均值、求和、最大最小值等
NSArray *values = @[@, @, @, @, @, @, @, @, @, @, @, @, @, @, @, @, @]; NSNumber *avg = [values valu ...
- 详解Object.create(null)
在Vue和Vuex的源码中,作者都使用了Object.create(null)来初始化一个新对象.为什么不用更简洁的{}呢? 在SegmentFault和Stack Overflow等开发者社区中也有 ...
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 (LCT维护深度)
要维护深度,就维护一下size就行了.access一下x,那么从根->x这一条链就独立成为一棵splay,那么splay的size节点数就是x的深度. 删边的时候直接access一下,splay ...
- Codeforces工具总结
本总结针对Linux用户,由于笔者一直使用Ubuntu系统打Codeforces 打Codeforcecs,想精确能力,打出究极罚时,可以考虑以下套餐 套餐一 vim选手 使用vim + fish + ...
- Debug .NET Framework Source
1.Microsoft Reference Source 在线source http://referencesource.microsoft.com/#System.Data.Linq 可以下载离线s ...
- IP地址正则表达式的写法
IP地址的正则表达式写法 这里讲的是IPv4的地址格式,总长度 32位=4段*8位,每段之间用.分割, 每段都是0-255之间的十进制数值. 将0-255用正则表达式表示,可以分成一下几块来分别考虑: ...