- 浏览: 98122 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
penuel:
保护日志发生现场LocationInfo(日志发生时的类、方法 ...
Log4j笔记 第九章 封装Log4j -
imu2008:
good~
如何创建一个org.eclipse.core.resources.IFile对象实例 -
mwhgJava:
bluepenguin2008 写道你好,请问这个封装后怎么用 ...
Log4j笔记 第九章 封装Log4j -
bluepenguin2008:
你好,请问这个封装后怎么用啊。每个类还是要像下面这样声明吗?p ...
Log4j笔记 第九章 封装Log4j
log4j日志现场背后的秘密
1、什么是日志现场
调用Logger打印日志的地方,称为日志现场。日志现场的属性有:类名、方法名、java文件名、和行数。
下面是一个例子。
LoggerTest.java
2、让log4j在打印日志消息时,也打印出日志现场
在classpath下,添加一个log4j.xml的文件。内容如下:
log4j.xml
再运行上面的文件,
在控制台中,可以看到如下信息:日志现场(类名、方法名、java文件名、和行数)和消息。
consoleView
3、封装log4j
在打印需要格式化的字符串时,使用Message.format()会出现如下代码。
当日志级别大于debug时,不需要打印该消息。但是format方法还是会被调用。这造成了浪费。早期log4j官网推荐如下使用方式。
这样就有了早期对log4j的封装版本。
CLogger.java
DLogger
4、使用封装的Logger出现的问题
一切安好,使用之。
LoggerTestThree.java
使用上例的log4j.xml
在控制台看到如下信息:
console view
打印的日志现场是,调用Logger的debug的地方。经过我们的封装,我们希望日志现场为,调用DLogger的debug方法的地方。于是问题出来了,我们封装了日志类,也转移了日志现场。怎样找到日志现场呢?
5、如果是你,会如何定位日志现场的
首先得理解,java函数调用堆栈。从应用的入口函数(main函数)出发,对其他函数的调用,形成了函数调用堆栈。在java方法中,新建一个Throwable对象,该对象的StackTraceElement[]属性,就包括函数调用堆栈。
看如下代码:
LoggerTestTwo.java
MyLogger.java
运行上面代码,在控制台中可以看到如下信息:创建Throwable时的函数调用堆栈。
consoleView
设定我们的MyLogger.debug()方法对应,log4j中的Logger.debug()方法。那么日志现场LoggerTestTwo.test(LoggerTestTwo.java:10)就在其中。我们发现,在被MyLogger.debug() 调用的所有 (包括直接和间接调用) 方法中,新建一个Throwable,其函数调用堆栈都包括这些信息。
6、log4j是如何定位日志现场的
在被Logger的debug方法调用的方法中,创建一个Throwable对象,解析其函数调用堆栈,确认日志现场。
秘密1: fqcn( fqnOfCallingClass,fqnOfCategoryClass) class name of first class considered part of the logging framework. Location will be site that calls a method on this class.
fqcn是Logger的全类名。在与函数调用堆栈比对中,离开Logger类的下一个地址,就是日志现场。
在logger的debug方法,创建LoggingEvent时,传入一个名为fqcn值为Logger的全类名的字符串。这样在LoggingEven的 getLocationInformation()方法中,创建LocationInfo时,传入一个新建的Throwable和fqcn。
从LocationInfo中,既可得到日志现场。
7、改进封装log4j的技术
在log4j_1.2.16中,logMF和logSF提供了参考意见。
于是就有了上一章的封装log4j的实现。
1、什么是日志现场
调用Logger打印日志的地方,称为日志现场。日志现场的属性有:类名、方法名、java文件名、和行数。
下面是一个例子。
LoggerTest.java
import org.apache.log4j.Logger; public class LoggerTest { private static final Logger logger = Logger.getLogger(LoggerTest.class); public static void main(String[] args) { new LoggerTest().test(); } private void test() { // 下面一行就是日志现场 LoggerTest类,test方法,LoggerTest.java文件,第12行。 logger.debug("Hello, log4j!"); } }
2、让log4j在打印日志消息时,也打印出日志现场
在classpath下,添加一个log4j.xml的文件。内容如下:
log4j.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" > <appender name="SYSTEM_OUT" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <!-- %l表示日志现场,%m表示日志消息,%n表示换行。--> <param name="ConversionPattern" value="%l: %m%n"/> </layout> </appender> <root> <!-- root 引用SYSTEM_OUT appender--> <appender-ref ref="SYSTEM_OUT"/> </root> </log4j:configuration>
再运行上面的文件,
在控制台中,可以看到如下信息:日志现场(类名、方法名、java文件名、和行数)和消息。
consoleView
LoggerTest.test(LoggerTest.java:12): Hello, log4j!
3、封装log4j
在打印需要格式化的字符串时,使用Message.format()会出现如下代码。
logger.debug(MessageFormat.format(“Hello, {0}!”, “log4j”));
当日志级别大于debug时,不需要打印该消息。但是format方法还是会被调用。这造成了浪费。早期log4j官网推荐如下使用方式。
if(logger.isDebugEnabled()){ logger.debug(MessageFormat.format(“Hello, {0}!”, “log4j”)); }
这样就有了早期对log4j的封装版本。
CLogger.java
public class CLogger { public static void debug(Logger logger, String pattern, Object[] arguments) { if (logger.isDebugEnabled()) { logger.debug(MessageFormat.format(pattern, arguments)); } } }
DLogger
import java.text.MessageFormat; import org.apache.log4j.Logger; public class DLogger { public static DLogger getLogger(Class<?> clazz) { return new DLogger(clazz); } private final Logger logger; private DLogger(Class<?> clazz) { logger = Logger.getLogger(clazz); } public void debug(String pattern, Object... arguments) { if (logger.isDebugEnabled()) { logger.debug(MessageFormat.format(pattern, arguments)); } } }
4、使用封装的Logger出现的问题
一切安好,使用之。
LoggerTestThree.java
public class LoggerTestThree { private static final DLogger logger = DLogger .getLogger(LoggerTestThree.class); public static void main(String[] args) { LoggerTestThree loggerTestTwo = new LoggerTestThree(); loggerTestTwo.test(); } private void test() { logger.debug("Hello,{0}!", "log4j"); //我们想将日志现场定在这里。 } }
使用上例的log4j.xml
在控制台看到如下信息:
console view
DLogger.debug(DLogger.java:19): Hello,log4j!
打印的日志现场是,调用Logger的debug的地方。经过我们的封装,我们希望日志现场为,调用DLogger的debug方法的地方。于是问题出来了,我们封装了日志类,也转移了日志现场。怎样找到日志现场呢?
5、如果是你,会如何定位日志现场的
首先得理解,java函数调用堆栈。从应用的入口函数(main函数)出发,对其他函数的调用,形成了函数调用堆栈。在java方法中,新建一个Throwable对象,该对象的StackTraceElement[]属性,就包括函数调用堆栈。
看如下代码:
LoggerTestTwo.java
public class LoggerTestTwo { private static final MyLogger logger = new MyLogger(); public static void main(String[] args) { LoggerTestTwo loggerTestTwo = new LoggerTestTwo(); loggerTestTwo.test(); } private void test() { logger.debug(); } }
MyLogger.java
public class MyLogger { public void debug() { Throwable throwable = new Throwable(); StackTraceElement[] stackTraceElements = throwable.getStackTrace(); for (StackTraceElement element : stackTraceElements) { System.out.println(element); } } }
运行上面代码,在控制台中可以看到如下信息:创建Throwable时的函数调用堆栈。
consoleView
MyLogger.debug(MyLogger.java:3) LoggerTestTwo.test(LoggerTestTwo.java:10) LoggerTestTwo.main(LoggerTestTwo.java:6)
设定我们的MyLogger.debug()方法对应,log4j中的Logger.debug()方法。那么日志现场LoggerTestTwo.test(LoggerTestTwo.java:10)就在其中。我们发现,在被MyLogger.debug() 调用的所有 (包括直接和间接调用) 方法中,新建一个Throwable,其函数调用堆栈都包括这些信息。
6、log4j是如何定位日志现场的
在被Logger的debug方法调用的方法中,创建一个Throwable对象,解析其函数调用堆栈,确认日志现场。
秘密1: fqcn( fqnOfCallingClass,fqnOfCategoryClass) class name of first class considered part of the logging framework. Location will be site that calls a method on this class.
fqcn是Logger的全类名。在与函数调用堆栈比对中,离开Logger类的下一个地址,就是日志现场。
在logger的debug方法,创建LoggingEvent时,传入一个名为fqcn值为Logger的全类名的字符串。这样在LoggingEven的 getLocationInformation()方法中,创建LocationInfo时,传入一个新建的Throwable和fqcn。
new LocationInfo(new Throwable(), fqnOfCategoryClass);
从LocationInfo中,既可得到日志现场。
7、改进封装log4j的技术
在log4j_1.2.16中,logMF和logSF提供了参考意见。
于是就有了上一章的封装log4j的实现。
发表评论
-
log4j 配置
2011-08-26 09:15 0<!-- 运行时,需要配置log4j配置文件,可以 配置 ... -
Log4j笔记 第十章 Log4j日志现场的秘密2_反射
2011-03-13 12:43 0log4j还有一个秘密:java反射 log4j的日志定位功能 ... -
Log4j笔记 第十章 Log4j日志现场的秘密
2011-03-13 12:20 0log4j日志现场背后的秘密 1、什么是日志现场 调用log ... -
Log4j笔记 第八章 log4j.dtd
2011-02-25 23:43 3654熟练配置log4j.xml必须理解log4j.dtd。 在lo ... -
Log4j笔记 第七章 log4j.xml
2011-02-25 23:41 2027下面是一个简单的log4j.xml配置文件内容。 < ... -
Log4j笔记 第九章 封装Log4j
2011-02-25 15:55 4601封装log4j要素: 1、对外不暴露log4j的包名和类名。 ... -
Log4j笔记 第六章 常用的Layout
2010-12-26 10:46 2060SimpleLayout,仅包括消息等级和消息。 Patter ... -
Log4j笔记 第五章 常用的Appender
2010-12-26 10:44 2038第一节 NullAppender org.apache.log ... -
Log4j笔记 第三章 Log4j结构
2010-12-26 10:41 1564第一节 主要组件 Log4j有三个主要组件: loggers、 ... -
Log4j笔记 第二章 消息等级与日志等级
2010-12-26 09:57 1825日志工具的主要功能,能够关闭一些日志陈述,而不影响其他的日志陈 ... -
Log4j笔记 第四章 名称空间与遗传
2010-12-26 09:15 1106第一节 日志名称空间和等级遗传 每一个日志都可以通过配置文件设 ... -
Log4j笔记 第一章 简单用上Log4j
2010-12-25 23:27 3312第一节 概述 Log4j诞生,为减轻对成千上万的 System ... -
Log4j笔记 序言
2010-12-25 22:50 1093前言 本文为log4j_1.2手册的补充。不试图替代log4j ... -
第九章 常用问题
2010-12-18 08:36 0指定外部文件。等。待续。 -
Log4j笔记 第八章 扩展log4j
2010-12-18 08:33 01、扩展PatternLayout 2、扩展Level -
一个简单的 Log4j.xml例子。
2010-12-11 20:47 0一个简单的 Log4j.xml例子。 <?xml v ... -
封装Log4j的Logger
2010-11-09 17:18 0Log4j是好东西,但在类开头定义这样的变量实在让众多开发者还 ... -
log4j:WARN Please initialize the log4j system properly 解决方案
2010-11-08 17:01 2873使用log4j时候,出现这个警告: log4j:WARN No ...
相关推荐
下面我们将从配置文件类型、核心JAR包、文件渲染和Log调用四个方面来比较Log4j和Log4j2的区别。 配置文件类型 Log4j通过一个.properties文件作为主配置文件,而Log4j2则弃用了这种方式,采用的是.xml、.json或者....
《Log4j笔记 第九章 封装Log4j》 在Java开发中,日志记录是一项非常重要的任务,它帮助我们追踪程序运行时的状态,定位和解决错误。Log4j是Apache组织提供的一款强大的日志框架,因其高效、灵活和可配置性而广受...
Log4j 是一个功能强大且广泛使用的日志记录工具,特别是在 SSM(Spring、Spring MVC、Mybatis)整合项目中,合理地配置 Log4j 对项目的日志记录和输出至关重要。本文将详细介绍 SSM 整合中的 Log4j 配置详情,帮助...
Log4j是一个广泛使用的Java日志记录框架,它允许开发者在应用程序中轻松地记录各种级别的日志信息,如DEBUG、INFO、WARN、ERROR等。在2021年底,一个重大的安全漏洞(CVE-2021-44228)被发现在Log4j2的早期版本中,...
Log4j是一款广泛使用的Java日志记录框架,它允许开发者按照功能模块或特定需求记录应用程序运行过程中的事件信息。在“log4j按功能保存日志”的场景中,我们通常会利用Log4j的配置灵活性,将不同功能的日志分别写入...
### Tomcat 下的 Log4j 日志配置详解 在日常的 Web 开发中,日志记录对于调试问题、监控系统状态以及后期维护来说至关重要。在使用 Apache Tomcat 作为服务器时,合理配置日志框架(如 Log4j)能够极大地提高开发...
Log4j作为Java领域广泛应用的日志框架,提供了强大的日志记录功能和灵活的配置。本文将深入探讨log4j的配置以及配置文件的详解。** 首先,我们要理解什么是`log4j.properties`文件。这是log4j框架的配置文件,使用...
Log4j 是一款广泛使用的Java日志记录框架,它提供了灵活的日志配置和丰富的日志级别,便于开发者调试和监控应用程序。在Java开发过程中,如果遇到"log4j:WARN Please initialize the log4j system properly"这样的...
Log4j2是Apache软件基金会开发的日志框架Log4j的升级版,它具有更高的性能、灵活性和可配置性。Log4j2支持多种日志记录级别(如DEBUG、INFO、WARN、ERROR),并允许通过XML、JSON、YAML或纯Java配置文件进行灵活配置...
**Log4j学习笔记** Log4j是一款广泛应用于Java编程中的日志记录框架,由Apache软件基金会开发。它提供了一套灵活的日志记录系统,帮助开发者在开发过程中追踪应用程序的行为,便于调试、性能分析和问题排查。Log4j...
压缩包中的"**lib**"目录可能包含Log4j的必要依赖库,比如`log4j.jar`,这是运行Log4j的日志记录功能所必需的。确保这些库文件被添加到Tomcat的`lib`目录,使得所有部署的应用都能访问Log4j。 综上所述,通过正确...
Log4j和SLF4J(Simple Logging Facade for Java)是两个广泛使用的日志框架,它们各有优势并常被一起使用以提供更灵活的日志解决方案。本文将详细探讨如何通过SLF4J接口来使用Log4j进行日志记录,并展示一个测试代码...
Log4j2是Apache软件基金会推出的日志框架,它是Log4j 1.x的重构版本,旨在提供更为高效且灵活的日志解决方案。与Log4j 1.x相比,Log4j2在设计上进行了重大改进,并解决了Logback等其他日志框架中存在的某些体系结构...
3. **配置Tomcat**:在`$CATALINA_HOME/lib`目录下添加`log4j-api.jar`和`log4j-slf4j-impl.jar`,这将使Tomcat使用Log4j2作为其内部的日志系统。 4. **排除其他日志实现**:确保你的应用中没有引入其他的日志实现...
1. **配置文件**:Log4j的配置文件通常是`log4j.properties`或`log4j.xml`,它定义了日志的级别(如DEBUG、INFO、WARN、ERROR、FATAL)、输出目的地(控制台、文件、数据库等)以及布局格式。 2. **日志类**:在...
Log4j是Apache提供的一款广泛使用的日志框架,它提供了丰富的功能和灵活的配置,使得我们可以根据需要动态地改变日志的输出路径。本文将深入探讨如何在Log4j中实现日志输出路径的动态配置。 首先,我们要理解Log4j...
Log4j2是一款广泛使用的日志框架,它提供了灵活且高效的日志记录功能。本示例将详细介绍如何配置并使用Log4j2将日志信息记录到MySQL数据库中。 首先,我们要理解Log4j2的核心概念。Log4j2主要包括以下几个组件: 1...
Log4j是Apache提供的一款广泛使用的日志框架,它提供了丰富的配置选项,允许开发者灵活地控制日志输出。当我们面对特定项目需求,比如需要自定义日志文件名和日志输出格式时,Log4j同样提供了相应的解决方案。 首先...
分别有disruptor-3.3.4.jar(Log4j2异步日志的底层实现)、log4j-api-2.19.0.jar(log4j门面)、log4j-core-2.19.0.jar(log4j实现)、log4j-slf4j-impl-2.19.0.jar(SLF4J与Log4j绑定)、slf4j-api-1.7.30.jar(SLF...
Log4j是Apache提供的一款广泛使用的日志框架,它提供了丰富的功能,包括控制日志级别、定制日志格式、支持多种输出方式等。本示例将详细介绍如何使用Log4j来控制指定类或包的日志级别。 首先,我们来理解日志级别的...