热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

log4j解析(包含源码)

为什么80%的码农都做不了架构师?读前问题:1:log4j的日志流程是怎么样的?2:log4j的配置文件

为什么80%的码农都做不了架构师?>>>   hot3.png

读前问题:

    1:log4j的日志流程是怎么样的?

    2:log4j的配置文件各项都是什么含义?特别是有些配置里面有包名到底有什么用?

    3:log4j的输出都是什么含义?具体见log4j conversion pattern各格式含义

一。log4j全局说明

    log4j采用logger,appender模式,其中logger含有层级信息,顶级logger为rootLogger,其他logger在在解析时会以.(英文点号)为分隔符

    划分层级,在获取logger时名字决定了要获取的logger实例

二。log4j配置文件解析

    解析流程:

解析全局配置 => 解析log4j.rootLogger  => 解析log4j.appender.* =>解析logFactory => 解析log4j.logger.* => 解析renderers

 

    2.1:解析全局配置

    全局配置包含:

log4j.debug=true : Defining this value makes log4j print log4j-internal debug statements to System.out.log4j.reset=true : If property set to true, then hierarchy will be reset before configurationlog4j.threshold=INFO #全局级别设定,不超过这个级别的一律不输出

 

    2.2:解析log4j.rootLogger

    格式:log4j.rootLogger=priority,appenderName1,appenderName2

    说明:priority是日志级别,包含由低到高DEBUG,INFO,WARN,ERROR,FATAL五个级别

              appenderName是自己定义的名称,只要与后面的一致就可以了,标示了在这个logger下面的输出器

    ps:根logger必须有,是所有其余logger的顶级parent,他自身parent为null

           rootLogger的名称为root,默认的

 

    2.3:解析log4j.appender.*
    格式:

log4j.appender.appenderName=appenderClass
log4j.appender.appenderName.threshold=priority
log4j.appender.appenderName.layout=layoutClass
log4j.appender.appenderName.layout.ConversionPattern=conversionPattern
log4j.appender.appenderName.filter.filterName=filterClass
log4j.appender.appenderName.errorhandler=errorhandlerClass
log4j.appender.appenderName.errorhandler.root-ref=[true|false]
log4j.appender.appenderName.errorhandler.logger-ref=loggerName

    说明:上面只是列出了一部分,像filter跟errorhandler平常我们基本不会用到,其实只要记住log4j.appender.appenderName后面的配置都是appender的属性就可以了

        譬如自己继承了AppenderSkeleton这个类,里面有一个attr的属性 可以用log4j.appender.appenderName.attr=anyValue

        appender自身也有级别过滤日志是否输出,可以用log4j.appender.appenderName.threshold=ERROR 这样就设定这个appender只输出ERROR级别的日志

    2.4:解析logFactory

    格式:log4j.loggerFactory=loggerFactoryClass

    就是讲log4j默认的日志工厂替换为自定义的,基本没有必要这么做

    2.5:解析log4j.logger.*

    格式:log4j.logger.loggerName=priority,appenderName1,appenderName2

    说明:这个logger的解析流程与rootLogger的基本一致,不同点在于logger是有层级的

        假设我们有这几个配置:log4j.logger.com.oschina.net=DEBUG,appenderName

                                             log4j.logger.com.oschina.net.web.action=INFO,appenderName

                                             log4j.logger.com=ERROR,appenderName

        log4j解析规则为:

                解析loggerName = log4j.logger.后面的内容,譬如loggerName为com.oschina.net.web.action

                解析上下级关系:com.oschina.net.web.action的有效parent为com.oschina.net,

                                           com.oschina.net的有效parent为com

                                           com的有效parent为root

                ps:这里所说为有效parent,实际上com.oschina.net的直接parent为com.oschina,再上级的parent才是com,这里log4j做了一个处理,将com.oschina这一级

                    设定为一个占位符ProvisionNode,没有任何的appender

    2.6:解析renderers

        格式:log4j.renderer.renderedClass=renderingClass  #定制对象显示 使用renderingClass来render renderedClass

        说明:renderer就是为了解决我们在直接打印对象的时候如何输出值的问题,而不是直接调用toString方法

三:log4j的日志打印规则

    通常我们都是这样来获取一个logger实例:

Logger logger = LoggerFactory.getLogger(ObjectClass.class);

    这里面的获取逻辑为:

        假设ObjectClass.class的全限定路径为com.oschina.net.web.action.controller,那么LoggerFactory会生成一个名称为com.oschina.net.web.action.controller的logger(会缓存起来,下次直接使用),并初始化他的parent,此时logger的层级关系为:

                                                                           

日志打印时会自底向上用各自的appender输出日志内容,贴一下代码:

for (Category c = this; c != null; c = c.parent) {// Protected against simultaneous call to addAppender, removeAppender,...synchronized (c) {if (c.aai != null) {writes += c.aai.appendLoopOnAppenders(event);}if (!c.additive) {break;}}}

   不过这里有一点需要说明,因为在日志打印的时候需要判断logger的threshold,但是生成的最下面的com.oschina.net.web.action.controller这个loggerthreshold为null,

    log4j会自底向上找到第一个不为null的logger来判定是否可以输出当前日志,因此在logger级别设定的时候就需要注意parent的级别需要比child的级别低,不然很容易导致

    日志文件中输出了2条或以上的日志信息

四。appender类图

    由于Logger相关类只有两个(另一个是Category类),configure相关类和filter类继承相关都很简单,这里只贴一个自己做的appender相关的类图

    

在看到DailyRollingFileAppender时,看到里面判断时间使用的System.currentTimeMillis(),在高并发下场景下是很耗时的一个操作,因此自己写了一个

加缓存的DailyRollingFileAppenderWithCache实现,具体可见github

五。总结

    总的来说已经熟悉了log4j的流程,对曾经的疑问也已经有了解答,欢迎大家留言交流。

 

 


转:https://my.oschina.net/liufq/blog/872484



推荐阅读
  • Zabbix自定义监控与邮件告警配置实践
    本文详细介绍了如何在Zabbix中添加自定义监控项目,配置邮件告警功能,并解决测试告警时遇到的邮件不发送问题。 ... [详细]
  • Beetl是一款先进的Java模板引擎,以其丰富的功能、直观的语法、卓越的性能和易于维护的特点著称。它不仅适用于高响应需求的大型网站,也适合功能复杂的CMS管理系统,提供了一种全新的模板开发体验。 ... [详细]
  • spring boot使用jetty无法启动 ... [详细]
  • 本文详细介绍了如何正确设置Shadowsocks公共代理,包括调整超时设置、检查系统限制、防止滥用及遵守DMCA法规等关键步骤。 ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 长期从事ABAP开发工作的专业人士,在面对行业新趋势时,往往需要重新审视自己的发展方向。本文探讨了几位资深专家对ABAP未来走向的看法,以及开发者应如何调整技能以适应新的技术环境。 ... [详细]
  • 本文探讨了如何通过优化 DOM 操作来提升 JavaScript 的性能,包括使用 `createElement` 函数、动画元素、理解重绘事件及处理鼠标滚动事件等关键主题。 ... [详细]
  • 本文探讨了如何将个人经历,特别是非传统的职业路径,转化为职业生涯中的优势。通过作者的亲身经历,展示了舞蹈生涯对商业思维的影响。 ... [详细]
  • 使用TabActivity实现Android顶部选项卡功能
    本文介绍如何通过继承TabActivity来创建Android应用中的顶部选项卡。通过简单的步骤,您可以轻松地添加多个选项卡,并实现基本的界面切换功能。 ... [详细]
  • 一、Advice执行顺序二、Advice在同一个Aspect中三、Advice在不同的Aspect中一、Advice执行顺序如果多个Advice和同一个JointPoint连接& ... [详细]
  • 近期尝试从www.hub.sciverse.com网站通过编程手段获取数据时遇到问题,起初尝试使用WebBrowser控件进行数据抓取,但发现使用GET方法翻页时,返回的HTML代码始终相同。进一步探究后了解到,该网站的数据是通过Ajax异步加载的,可通过HTTP查看详细的JSON响应。 ... [详细]
  • 问题场景用Java进行web开发过程当中,当遇到很多很多个字段的实体时,最苦恼的莫过于编辑字段的查看和修改界面,发现2个页面存在很多重复信息,能不能写一遍?有没有轮子用都不如自己造。解决方式笔者根据自 ... [详细]
  • 解决JavaScript中法语字符排序问题
    在开发一个使用JavaScript、HTML和CSS的Web应用时,遇到从SQLite数据库中提取的法语词汇排序不正确的问题,特别是带重音符号的字母未按预期排序。 ... [详细]
  • 深入理解:AJAX学习指南
    本文详细探讨了AJAX的基本概念、工作原理及其在现代Web开发中的应用,旨在为初学者提供全面的学习资料。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有