logback和log4j一起用能共存吗

下次自动登录
现在的位置:
& 综合 & 正文
logback与Log4J的区别
Logback和log4j是非常相似的,如果你对log4j很熟悉,那对logback很快就会得心应手。下面列了logback相对于log4j的一些优点:
更快的实现
Logback的内核重写了,在一些关键执行路径上性能提升10倍以上。而且logback不仅性能提升了,初始化内存加载也更小了。
非常充分的测试
Logback经过了几年,数不清小时的测试。Logback的测试完全不同级别的。在作者的观点,这是简单重要的原因选择logback而不是log4j。
Logback-classic非常自然实现了SLF4j
Logback-classic实现了SLF4j。在使用SLF4j中,你都感觉不到logback-classic。而且因为logback-classic非常自然地实现了SLF4J,所以切换到log4j或者其他,非常容易,只需要提供成另一个jar包就OK,根本不需要去动那些通过SLF4JAPI实现的。
非常充分的文档
官方网站有两百多页的文档。
自动重新加载配置文件
当配置文件修改了,Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。这个技术充分保证了应用能跑得很欢在JEE环境里面。
Lilith是log事件的观察者,和log4j的chainsaw类似。而lilith还能处理大数量的log数据
谨慎的模式和非常友好的恢复
在谨慎模式下,多个FileAppender实例跑在多个JVM下,能够安全地写道同一个日志文件。RollingFileAppender会有些限制。Logback的FileAppender和它的子类包括RollingFileAppender能够非常友好地从I/O异常中恢复。
配置文件可以处理不同的情况
开发人员经常需要判断不同的Logback配置文件在不同的环境下(开发,测试,生产)。而这些配置文件仅仅只有一些很小的不同,可以通过,和来实现,这样一个配置文件就可以适应多个环境。
Filters(过滤器)
有些时候,需要诊断一个问题,需要打出日志。在log4j,只有降低日志级别,不过这样会打出大量的日志,会影响应用性能。在Logback,你可以继续保持那个日志级别而除掉某种特殊情况,如alice这个用户登录,她的日志将打在DEBUG级别而其他用户可以继续打在WARN级别。要实现这个功能只需加4行XML配置。可以参考MDCFIlter
SiftingAppender(一个非常多功能的Appender)
它可以用来分割日志文件根据任何一个给定的运行参数。如,SiftingAppender能够区别日志事件跟进用户的Session,然后每个用户会有一个日志文件。
自动压缩已经打出来的log
RollingFileAppender在产生新文件的时候,会自动压缩已经打出来的日志文件。压缩是个异步过程,所以甚至对于大的日志文件,在压缩过程中应用不会受任何影响。
堆栈树带有包版本
Logback在打出堆栈树日志时,会带上包的数据。
自动去除旧的日志文件
通过设置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory属性,你可以控制已经产生日志文件的最大数量。如果设置maxHistory为12,那那些log文件超过12个月的都会被自动移除。
总之,logback比log4j太优秀了,让我们的应用全部建立logback上吧。
&&&&推荐文章:
【上篇】【下篇】Log4j问题排查-log4j,logback到底用了哪个?
1..在某此编译后,日志莫名其妙的乱了。本来应该打印到locationservice.log下的,但是打印到了jboss_stdout.log下
slf4j,log4j,logback之间的关系式什么?
==============
解答==================================================
1.因为代码没有变过,怀疑是系统在在使用日志系统的时候出现问题,打印mvn
tree,发现同时依赖了log4j、logback,那系统使用的日志系统到底是哪一个呢?
2.查看log相关代码,原来slf4j只是日志系统的API,只是接口,称之为日志框架,类似于JDBCDriver,具体实现由各个厂家提供,而slf4j日志框架的实现目前有两个,一个是LOG4J,一个是SLF4J.
3.那么如果系统里有两套日志系统时,会选择哪个系统呢?
& 在代码里我们通常会使用& &
Logger logger =
LoggerFactory.getLogger(this.getClass());
来获取Logger,LoggerFactory是slf4j-api里的一个单例工厂类,最底层调用StaticLoggerBinder.getSingleton().getLoggerFactory()来获取实现类。
而StaticLoggerBinder则在各自的厂商中提供。
那么到底使用的是哪个StaticLoggerBinder呢,
Java代码&&
&&private&final&static&void&bind()&{&&
&&&&try&{&&
&&&&&&Set&staticLoggerBinderPathSet&=&findPossibleStaticLoggerBinderPathSet();&&
&&&&&&reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);&&
&&&&&&//&the&next&line&does&the&binding&&
&&&&&&StaticLoggerBinder.getSingleton();&&
&&&&&&INITIALIZATION_STATE&=&SUCCESSFUL_INITIALIZATION;&&
&&&&&&reportActualBinding(staticLoggerBinderPathSet);&&
&&&&&&emitSubstituteLoggerWarning();&&
&&&&}&catch&(NoClassDefFoundError&ncde)&{&&
从bind的源代码可以看到 其实是随机加载的。
回到我们的系统,到底是不是这个Binder作怪呢,搜索下StaticLoggerBinder类,发现在classpath下确实有两套。
& 于是问题就清晰了
&在classpath下存在两个StaticLoggerBinder,应用启动后加载到logback的StaticLoggerBinder,于是使用了logback的Logger,但是由于我们默认配置的是Log4j,所以找不到logback的配置,于是默认打印到了STDOUT里。
&4.简单理了下调用的顺序图
5.最后的解决方法
&MAVEN:tree找到是依赖里有建议依赖了logback-classic的包,使用mvn排除,&部署后解决
启动日志里有这么一段
其实就是因为系统存在两个日志系统,slf4j不知道比较迷茫给出的警告
Java代码&&
private&static&void&reportMultipleBindingAmbiguity(Set&staticLoggerBinderPathSet)&{&&
&&if&(isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet))&{&&
&&&&Util.report("Class&path&contains&multiple&SLF4J&bindings.");&&
&&&&Iterator&iterator&=&staticLoggerBinderPathSet.iterator();&&
&&&&while&(iterator.hasNext())&{&&
&&&&&&URL&path&=&(URL)&iterator.next();&&
&&&&&&Util.report("Found&binding&in&["&+&path&+&"]");&&
&&&&Util.report("See&"&+&MULTIPLE_BINDINGS_URL&+&"&for&an&explanation.");&&
当系统检查到有多个Binder时就出在日志里打印警告了。
另,webx的教程里对日志系统有比较详细的解释
请移步http://openwebx.org/docs/logging.html
不过还有个问题,为啥以前好的呢?费解!
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
代码偏执狂,大叔,golang爱好者,玩玩树莓派,再就是喜欢陪女儿做手工
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(789)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'使用logback时候如何兼容其他日志框架',
blogAbstract:'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t我们现在用maven来开发,',
blogTag:'logback,slf4j,java.util.logging,jul,日志框架',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:4,
publishTime:6,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'代码偏执狂,大叔,golang爱好者,玩玩树莓派,再就是喜欢陪女儿做手工',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}8651人阅读
JavaEE(57)
本帖最后由 陈明河 于
15:20 编辑
考虑到logback日志组件性能比log4j好,所以项目开发过程中抛弃log4j改用logback。
log4j迁移到logback的步骤(只要三步):
第一&&引入logback需要的jar包
&!-- logback日志配置开始 --&
& && && && && & &dependency&
& && && && && && && && &&groupId&ch.qos.logback&/groupId&
& && && && && && && && &&artifactId&logback-core&/artifactId&
& && && && && && && && &&version&1.1.2&/version&
& && && && && & &/dependency&
& && && && && & &dependency&
& && && && && && && && &&groupId&ch.qos.logback&/groupId&
& && && && && && && && &&artifactId&logback-access&/artifactId&
& && && && && && && && &&version&1.1.2&/version&
& && && && && & &/dependency&
& && && && && & &dependency&
& && && && && && && && &&groupId&ch.qos.logback&/groupId&
& && && && && && && && &&artifactId&logback-classic&/artifactId&
& && && && && && && && &&version&1.1.2&/version&
& && && && && & &/dependency&
& && && && && & &dependency&
& && && && && && && && &&groupId&org.slf4j&/groupId&
& && && && && && && && &&artifactId&log4j-over-slf4j&/artifactId&
& && && && && && && && &&version&1.7.7&/version&
& && && && && & &/dependency&
& && && && && &&!-- logback日志配置结束 --&
第二&&删除src下的log4j.properties文件,在src下创建logback.xml配置文件
项目之前的使用log4j.properties可以用转换到等价的logback配置文件。PS:转换后的配置文件,pattern参数需要修改。
如log4j的pattern配置 %-d{yyyy-MM-dd HH:mm:ss,SSS} [%c:%L]-[%p] %m%n 在logback里面不在起效。
我把它调整为 %date [%level] [%thread] %logger{80} [%file : %line] %msg%n
另外按日期产生日志文件策略的pattern也需要修改(具体查看下文的logback.xml配置文件)。
具体含义是:
& && && && && && && && &含义&&
表示日期格式(yyyy-MM-dd HH:mm:ss,SSS)
表示日志的级别
表示输出产生该日志的线程名
&&%logger{80}&&
表示logger名字最长80个字符,否则按照句点(.)分割
表示文件名
表示第几行
表示输出信息
下面粘贴出项目在替换logback之前的log4j配置文件:
### direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} %m& & [%c:%L]-[%p] %n
### log messages to file
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=../logs/vod.log
log4j.appender.R.DatePattern='.'yyyy-MM-dd
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%c:%L]-[%p] %m%n
log4j.appender.DC=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DC.File=../logs/devicecontrol.log
log4j.appender.DC.DatePattern='.'yyyy-MM-dd
log4j.appender.DC.layout=org.apache.log4j.PatternLayout
log4j.appender.DC.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%c:%L]-[%p]-[%t] %m%n
### Application log config
log4j.rootLogger=info,stdout,R
### set log levels
log4j.logger.org.springframework=error
log4j.logger.org.quartz.simpl=error
log4j.logger.org.hibernate=error
log4j.logger.org.apache=error
.thunisoft.summer=warn
.thunisoft.test=error
.thunisoft.artery=error
.thunisoft.crs=error
.thunisoft.cas.service.devicecontrol=debug,DC
log4j.logger.jdbc.sqlonly=INFO
log4j.logger.jdbc.sqltiming=DEBUG
log4j.logger.jdbc.audit=OFF
log4j.logger.jdbc.resultset=OFF
log4j.logger.jdbc.connection=OFF
下面粘贴出项目使用的logback.xml
&?xml version=&1.0& encoding=&UTF-8&?&
&configuration&
&&&appender name=&DC& class=&ch.qos.logback.core.rolling.RollingFileAppender&&
& & &File&../logs/devicecontrol.log&/File&
& & &encoder&
& && &&pattern&%date [%level] [%thread] %logger{80} [%file : %line] %msg%n&/pattern&
& & &/encoder&
& & &rollingPolicy class=&ch.qos.logback.core.rolling.TimeBasedRollingPolicy&&
& && &&fileNamePattern&../logs/devicecontrol.log.%d{yyyy-MM-dd}&/fileNamePattern&
& & &/rollingPolicy&
&&&/appender&
&&&appender name=&Console& class=&ch.qos.logback.core.ConsoleAppender&&
& & &Target&System.out&/Target&
& & &encoder&
& && &&pattern&%date [%level] [%thread] %logger{80} [%file : %line] %msg%n&/pattern&
& & &/encoder&
&&&/appender&
&&&appender name=&FILE& class=&ch.qos.logback.core.rolling.RollingFileAppender&&
& & &File&../logs/vod.log&/File&
& & &encoder&
& && &&pattern&%date [%level] [%thread] %logger{80} [%file : %line] %msg%n&/pattern&
& & &/encoder&
& & &rollingPolicy class=&ch.qos.logback.core.rolling.TimeBasedRollingPolicy&&
& & &fileNamePattern&../logs/vod.log.%d{yyyy-MM-dd}&/fileNamePattern&
& & &/rollingPolicy&
&&&/appender&
&&&logger name=&org.springframework& level=&error&/&
&&&logger name=&com.thunisoft.crs& level=&error&/&
&&&logger name=&jdbc.connection& level=&OFF&/&
&&&logger name=&com.thunisoft.artery& level=&error&/&
&&&logger name=&com.thunisoft.cas.service.devicecontrol& level=&debug&&
& & &appender-ref ref=&DC&/&
&&&/logger&
&&&logger name=&org.apache& level=&error&/&
&&&logger name=&jdbc.resultset& level=&OFF&/&
&&&logger name=&com.thunisoft.summer& level=&warn&/&
&&&logger name=&org.hibernate& level=&error&/&
&&&logger name=&jdbc.audit& level=&OFF&/&
&&&logger name=&com.thunisoft.test& level=&error&/&
&&&logger name=&jdbc.sqlonly& level=&INFO&/&
&&&logger name=&jdbc.sqltiming& level=&DEBUG&/&
&&&logger name=&org.quartz.simpl& level=&error&/&
&&&root level=&info&&
& & &appender-ref ref=&Console&/&
& & &appender-ref ref=&FILE&/&
&/configuration&
第三&&把打印日志类使用的logger类替换为SLF4J的logger类
如果软件只调用了
log4j的客户端API&
或Jakarta Commons Logging (JCL) API
或java.util.logging API
就能用SLF4J迁移工具()自动迁移到SLF4J。
下面是slf4j官网迁移log4j代码的示例:
MyClass is a sample class using JCL. Here it is before:
package some.
import mons.logging.L
import mons.logging.LogF
public MyClass {& &&
& && && && &
&&Log logger = LogFactory.getLog(MyClass.class);
&&public void someMethod() {&
& & (&Hello world&);
and after migration:
package some.
import org.slf4j.L
import org.slf4j.LoggerF
public MyClass {& &&
&&Logger logger = LoggerFactory.getLogger(MyClass.class);
&&public void someMethod() {&
& & (&Hello world&);
至此,log4j迁移到logback完成。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:133030次
积分:3607
积分:3607
排名:第6402名
原创:249篇
(9)(21)(9)(2)(1)(6)(1)(1)(2)(1)(1)(1)(3)(33)(8)(19)(1)(6)(3)(66)(55)(2)

我要回帖

更多关于 log4j和logback 的文章

 

随机推荐