一、什么是log4j

几乎每个大型应用程序都包含自己的日志或跟踪API。为了符合这一规则,欧盟SEMPRER项目决定编写自己的跟踪API。这是在1996年初。经过无数次的增强、几个版本和大量的工作之后,API演变成了log4j,这是一个流行的Java日志包。这个包是在Apache Software License下发布的,Apache Software License是由开源组织认证的完全成熟的开源许可证。

在代码中插入日志语句是一种调试代码的低技术方法。它也可能是唯一的方法,因为调试器并不总是可用或适用的。这通常是多线程应用程序和分布式应用程序的情况。

经验表明,日志记录是开发周期的一个重要组成部分。它有几个优点。它提供关于应用程序运行的精确上下文。一旦插入到代码中,日志输出的生成就不需要人为干预了。此外,日志输出可以保存在持久介质中,以便以后研究。除了在开发周期中使用之外,一个足够丰富的日志包也可以被视为审计工具。

正如Brian W. Kernighan和Rob Pike在他们真正优秀的书《编程的实践》中所说:“作为个人选择,除了获得堆栈跟踪或一两个变量的值之外,我们倾向于不使用调试器。一个原因是,它很容易迷失在复杂的数据结构和控制流的细节中;我们发现,与更努力地思考并在关键位置添加输出语句和自检代码相比,逐步执行程序的效率更低。单击语句要比扫描正确放置的显示的输出花费更长的时间。决定在何处放置print语句比单步进入代码的关键部分花费更少的时间,即使我们知道关键部分在哪里。更重要的是,调试语句保留在程序中;调试会话是短暂的。”

日志记录也有其缺点。它会减慢应用程序的速度。如果太啰嗦,可能会导致滚动失明。为了减轻这些问题,log4j被设计成可靠、快速和可扩展的。由于日志记录很少是应用程序的主要关注点,所以log4j API努力使其易于理解和使用。

二、Log4j的体系结构

主要部件

Log4j使用下图所示类:

使用 Log4j 2 API 的应用程序将从 LogManager 请求具有特定名称的 Logger。 LogManager 将找到适当的 LoggerContext,然后从中获取 Logger。如果必须创建 Logger,它将与 LoggerConfig 关联,该 LoggerConfig 包含
a)与 Logger 相同的名称
b)父程序包的名称
c)根 LoggerConfig。
LoggerConfig 对象是根据配置中的 Logger 声明创建的。 LoggerConfig 与实际提供 LogEvent 的 Appender 关联。

Logger Hierarchy

与普通的System.out.println相比,任何日志API的第一个也是最重要的优点在于它能够禁用某些日志语句,同时允许其他语句不受阻碍地打印。这种功能假设日志空间,即所有可能的日志语句的空间,是根据开发人员选择的一些标准进行分类的。

在Log4j 1.x。通过Logger之间的关系来维护Logger层次结构。
在Log4j 2中,这种关系不再存在。相反,层次结构是在LoggerConfig对象之间的关系中维护的。

Logger和loggerconfig是命名实体。Logger的名称是大小写敏感的,它们遵循分层命名规则:

如果 LoggerConfig 的名称后跟一个点,则该 LoggerConfig 被称为另一个 LoggerConfig 的祖先。
如果 LoggerConfig 与子 LoggerConfig 之间没有祖先,则称该 LoggerConfig 为子 LoggerConfig 的父级。

例如,名为“ com.foo”的 LoggerConfig 是名为“ com.foo.Bar”的 LoggerConfig 的父级。同样,“ java”是“ java.util”的父代,也是“ java.util.Vector”的祖先。大多数开发人员都应该熟悉这种命名方案。

根 LoggerConfig 位于 LoggerConfig 层次结构的顶部。它的特殊之处在于它始终存在,并且是每个层次结构的一部分。直接链接到根 LoggerConfig 的 Logger 可以通过以下方式获得:

Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);

或者,更简单地说:

Logger logger = LogManager.getRootLogger();

可以通过传递所需 Logger 的名称,使用LogManager.getLogger静态方法检索所有其他 Logger。

LoggerContext

LoggerContext充当 Logging 系统的定位点。但是,根据情况,一个应用程序中可能有多个活动 LoggerContext。有关 LoggerContext 的更多详细信息,我们将在后面的内容中讲到。

Configuration

每个 LoggerContext 都有一个活动的Configuration。该配置包含所有 Appender,上下文范围的过滤器,LoggerConfigs,并包含对 StrSubstitutor 的引用。在重新配置期间,将存在两个配置对象。一旦所有 Logger 都重定向到新的配置,旧的配置将被停止并丢弃。

Logger

如前所述,Logger 是通过调用LogManager.getLogger来创建的。Logger 本身不执行任何直接操作。它仅具有一个名称,并与 LoggerConfig 关联。它扩展了AbstractLogger并实现了所需的方法。修改配置后,Logger 可能与其他 LoggerConfig 关联,从而导致其行为被修改。

Retrieving Loggers

用相同名称调用 LogManager.getLogger 方法将始终返回对完全相同的 Logger 对象的引用。
例如,在

Logger x = LogManager.getLogger("wombat");
Logger y = LogManager.getLogger("wombat");

x 和 y 引用完全相同的 Logger 对象。

log4j 环境的配置通常在应用程序初始化时完成。首选方法是读取配置文件。 Configuration中对此进行了讨论。

Log4j 使按软件组件命名 Logger 变得容易。这可以通过在每个类中实例化一个 Logger 来实现,其 Logger 名称等于该类的完全限定名称。这是定义 Logger 的有用且直接的方法。由于日志输出带有生成的 Logger 的名称,因此这种命名策略使识别日志消息的来源变得容易。但是,这只是命名 Logger 的一种可能的策略,尽管很常见。 Log4j 不会限制可能的 Logger 集。开发人员可以根据需要随意命名 Logger。

由于在他们自己的类后给 Logger 命名是一种常见的习惯用法,因此提供了便捷方法 LogManager.getLogger()以自动使用调用类的完全限定类名作为 Logger 名称。

尽管如此,以它们所在的类命名Logger似乎是目前已知的最佳策略。

LoggerConfig

在日志记录配置中声明日志 Logger 时,将创建LoggerConfig对象。 LoggerConfig 包含一组过滤器,必须允许 LogEvent 通过,然后才能将其传递给任何 Appender。它包含对应用于处理事件的一组 Appender 的引用。

Log Levels

LoggerConfigs 将被分配一个 Log Level。内置级别集包括 TRACE,DEBUG,INFO,WARN,ERROR 和 FATAL。

Log4j 2 还支持自定义日志级别。获得更大粒度的另一种机制是使用Markers。

Log4j 1.x和Logback都具有“级别继承”的概念。在 Log4j 2 中,Logger 和 LoggerConfig 是两个不同的对象,因此此概念的实现方式有所不同。每个 Logger 都引用适当的 LoggerConfig,后者又可以引用其父级,从而达到相同的效果。

以下是五个表,这些表具有各种分配的级别值以及将与每个 Logger 关联的级别。请注意,在所有这些情况下,如果未配置根 LoggerConfig,则将为其分配默认级别。

在上面的示例 1 中,仅配置了根 Logger 并具有日志级别。其他所有 Logger 都引用根 LoggerConfig 并使用其级别。

在示例 2 中,所有 Logger 都配置了 LoggerConfig 并从中获取其 Level。


在示例 3 中,loggersroot,X 和 X.Y.Z 每个都具有一个配置的具有相同名称的 LoggerConfig。 Logger X.Y 没有配置的名称匹配的 LoggerConfig,因此使用 LoggerConfig X 的配置,因为它是名称与 Logger 名称的开头最长匹配的 LoggerConfig。

在示例 4 中,Logger 的根和 X 均具有相同名称的 Configured LoggerConfig。LoggerX.Y 和 X.Y.Z 尚未配置 LoggerConfig,因此从分配给它们 X 的 LoggerConfig 中获取其级别,因为它是 LoggerConfig,其名称与 Logger 名称的开头最长匹配。


在示例 5 中,loggersroot.X 和 X.Y 都具有一个具有相同名称的 Configured LoggerConfig。LoggerX.YZ 尚未配置 LoggerConfig,因此从分配给它的 LoggerConfig X 获取其级别,因为它是名称与 Logger 名称的开头最长匹配的 LoggerConfig。它与 LoggerConfig X.Y 不关联,因为句点后的令牌必须完全匹配。

在示例 6 中,LoggerConfig X.Y 没有配置的级别,因此它从 LoggerConfig X 继承其级别。LoggerX.Y.Z 使用 LoggerConfig X.Y,因为它没有名称完全匹配的 LoggerConfig。它也从 LoggerConfig X 继承其日志记录级别。

下表说明了级别过滤的工作原理。在表中,垂直标题显示 LogEvent 的级别,而水平标题显示与适当的 LoggerConfig 关联的级别。相交标识是否允许 LogEvent 通过以进行进一步处理(是)还是将其丢弃(否)。

Filter

除了上一节所述的自动日志级别过滤之外,Log4j 还提供了Filter,可以在将控制权传递给任何 LoggerConfig 之前,将控制权传递给 LoggerConfig 之后但在调用任何 Appender 之前,在控制完成之后应用Filter。传递给 LoggerConfig,但在调用特定的 Appender 之前以及在每个 Appender 上传递。以与防火墙过滤器非常相似的方式,每个过滤器可以返回以下三个结果之一:“接受”,“拒绝”或“中性”。

  1. 接受的响应表示不应调用其他任何筛选器,并且事件应 continue 进行。
  2. 拒绝的响应意味着应立即忽略该事件,并将控制权返回给调用方。
  3. 中性的响应表示该事件应传递给其他过滤器。如果没有其他过滤器,则事件将被处理。

尽管某个事件可能被过滤器接受,但该事件可能仍未记录。当事件被 LoggerConfig 之前的过滤器接受但被 LoggerConfig 过滤器拒绝或被所有 Appender 拒绝时,就会发生这种情况。

Appender

基于Logger有选择地启用或禁用日志请求的能力只是问题的一部分。 Log4j 允许记录请求打印到多个目标。用 log4j 来说,输出目标称为Appender。当前,存在用于控制台,文件,远程套接字服务器,Apache Flume,JMS,远程 UNIX Syslog 守护程序和各种数据库 API 的附加程序。一个 Logger 可以连接多个 Appender。

可以通过调用当前配置的addLoggerAppender方法将 Appender 添加到 Logger。如果不存在与 Logger 名称匹配的 LoggerConfig,将创建一个 Logger,将附加 Appender,然后将通知所有 Logger 更新其 LoggerConfig 引用。

针对给定 Logger 的每个启用的记录请求都将转发给该 Logger 的 LoggerConfig 中的所有添加程序以及 LoggerConfig 的父项的 Appender. 换句话说,Appender 继承自 LoggerConfig 层次结构。例如,如果将控制台附加程序添加到根 Logger,则所有启用的记录请求将至少在控制台上打印。如果另外将文件追加程序添加到 LoggerConfig 中,例如 C,则针对 C 和 C 的子级启用的日志记录请求将在文件中和控制台上打印。可以覆盖此默认行为,以便通过在配置文件中的 Logger 声明中设置 additivity =“ false”来不再增加 Appender 的累积量。

下面概述了控制追加程序可加性的规则。

Appender Additivity

Logger L 的 log 语句的输出将转到与 L 关联的 LoggerConfig 中的所有 Appender 和该 LoggerConfig 的祖先。这就是术语“ addLoggerAppender”的含义。

但是,如果与 Logger L 关联的 LoggerConfig 的祖先(例如 P)将可加性标志设置为 false,则 L 的输出将定向到 L 的 LoggerConfig 中的所有追加器,并且其祖先直到 P(包括 P),但不包括 Pender P 的任何祖先。

Logger 默认将其可加性标志设置为 true。

下表显示了一个示例:

Layout

通常,用户不仅希望自定义输出目标,还希望自定义输出格式。这是通过将Layout与 Appender 相关联来实现的。布局负责根据用户的意愿格式化 LogEvent,而附加程序负责将格式化的输出发送到其目的地。标准 log4j 发行版的PatternLayout,使用户可以根据类似于 C 语言 printf 函数的转换模式来指定输出格式。

例如,带有转换模式“%r [%t]%-5p%c-%m%n”的 PatternLayout 将输出类似于:

176 [main] INFO  org.foo.Bar - Located nearest gas station.

第一个字段是自程序启动以来经过的毫秒数。第二个字段是发出日志请求的线程。第三个字段是 log 语句的级别。第四个字段是与日志请求关联的 Logger 的名称。 “-”之后的文本是该语句的消息。

Log4j 带有许多不同的Layouts,用于各种用例,例如 JSON,XML,HTML 和 Syslog(包括新的 RFC 5424 版本)。其他附加程序(例如数据库连接器)将填充指定的字段,而不是特定的文本布局。

同样重要的是,log4j 将根据用户指定的标准呈现日志消息的内容。例如,如果您经常需要记录当前项目中使用的对象类型 Oranges,则可以创建一个 OrangeMessage 来接受 Orange 实例并将其传递给 Log4j,以便Orange对象可以在需要时被格式化为适当的字节数组。

StrSubstitutor 和 StrLookup

从Apache Commons Lang借用了StrSubstitutor类和StrLookup接口,然后对其进行了修改以支持评估 LogEvents。另外,Interpolator类是从 Apache Commons Configuration 借用的,以允许 StrSubstitutor 评估来自多个 StrLookups 的变量。它也被修改为支持评估 LogEvents。这些一起提供了一种机制,允许配置引用来自 LogEvent 中的系统属性,配置文件,ThreadContextMap,StructuredData 的变量。如果组件能够处理,则可以在处理配置时或在处理每个事件时解析变量。

log4j(一)——什么是Log4j以及Log4j的体系结构相关推荐

  1. log4j:WARN Error initializing output writer. log4j:WARN Unsupported encoding?

    javaWeb在使用log.4j打印日志文件的时候提示: log4j:WARN Error initializing output writer. log4j:WARN Unsupported enc ...

  2. log4j警告:WARN Please initialize the log4j system properly 的解决方法

    出现这个问题的原因则是因为没有为log4j建立配置文件导致的.所以解决问题的方法很简单,只要在 src文件目录下建立配置文件即可: 右键点击src  -> New  ->  File 文件 ...

  3. java log4j 多个文件_为什么log4j会记录到两个单独的文件? [重复]

    这个问题在这里已有答案: 我有以下 log4j.properties 文件,默认的appender和特定类的单独的appender log4j.rootLogger=DEBUG, STDOUT, de ...

  4. Log4j配置学习文档之一 log4j配置

    #Log4j配置 Log4J的配置文件(Configuration File)就是用来设置记录器的级别.存放器和布局的,它可接key=value格式的设置或xml格式的设置信息.通过配置,可以创建出L ...

  5. 解决log4j:WARN Error initializing output writer. log4j:WARN Unsupported encoding?的问题

    解决log4j:WARN Error initializing output writer. log4j:WARN Unsupported encoding?的问题 参考文章: (1)解决log4j: ...

  6. log4j 新建日志 重启_Java中log4j控制写入日志开关

    本文原文出自我的个人网站[思考者日记]原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明. 上篇说到tomcat jndi(连接池)的使用方法,这次的项目里还使用到了一 ...

  7. log4j日志文件的使用及log4j日志文件失效原因分析

    log4j的使用步骤 1.导入log4j-*.jar,例:log4j-1.2.17-jar; <dependency><groupId>log4j</groupId> ...

  8. Log4j 使用方法和输出格式控制--log4j的PatternLayout参数含义

    Log4j 由 Apache 推出的开源免费日志处理的类库 可以控制日志信息输送的目的地是控制台.文件-等 可以控制每一条日志的输出格式 使用时导入 log4j 的 jar 包,并在 src 中 配置 ...

  9. java 初始化log4j_java – log4j:WARN请正确初始化log4j系统

    如何解决以下这些错误-我错过了一些jar文件??? log4j:WARN No appenders could be found for logger (smslib). log4j:WARN Ple ...

  10. log4j与log4j2性能对比及log4j升级至log4j2方案

    1.前言 之前某个服务在压测环境中出现了问题,分析之后得知是log4jLogger对象争用厉害,很多线程阻塞在此. 以上问题证明log4j在高并发高QPS情况下,是存在性能问题的. 之后把log4j升 ...

最新文章

  1. 互联网协议 — IPSec 安全隧道协议 — NAT-T
  2. 【AWR】调整AWR数据采样时间间隔及历史快照保留时间
  3. 腾讯实习笔试:关于几个有序数组求交集的问题
  4. java中如何设计答题小系统_java的一点问题,设计一个答题的程序
  5. Fedora Linux中配置JDK5或JDK6环境变量
  6. JAVA中for循环缩制表位_用vim中的空格替换制表符
  7. 实时检测input的长度_目标检测——TinyYOLOv3
  8. LibreOJ #6001. 「网络流 24 题」太空飞行计划 最大权闭合图
  9. ubintu yum装mysql_Ubuntu 下安装Mysql centos8 下安装mysql8.0
  10. Find Any File for Mac(本地文件搜索查找工具)
  11. python运行空白_解决pyecharts运行后产生的html文件用浏览器打开空白
  12. PHP7.0,PHP7.1.x新特性
  13. gridview的sort_GridView中排序问题
  14. 1.7 新概念 量词
  15. 安装与部署Exchange server 2013
  16. 2020年10月最新免费加速下载百度网盘文件方法
  17. 优秀笔记课件——WORD使用技巧
  18. linux设备号——常见设备的主次设备号
  19. 奶爸日记-沉迷看小猪
  20. 社群运营中品牌化和IP化运营实践

热门文章

  1. C++ 输出各种图形
  2. 《炬丰科技-半导体工艺》--技术资料合集26
  3. PS 画笔 取消 圆角
  4. USB扫码枪二维码读取(一)——U3D篇
  5. 车辆监控php原码下载,物流车辆视频监控系统解决方案
  6. 广色域图片Android,Android Q将支持广色域照片,观感更加真实
  7. DC-DC直流升压模块电源12V升24V(5A)FP5207
  8. CleanMyMac2022Mac电脑免费好用的清理软件
  9. 蘑菇云「行空板Python入门教程」第十课:多节点智慧农业系统
  10. 如何用python提取音频