Java日志指南
作者:网络转载 发布时间:[ 2015/7/20 10:19:19 ] 推荐标签:测试开发技术 编程语言
Log4j版本2中将MDC和NDC合并到一个单独的组件中,这个组件被称为线程上下文。线程上下文是针对MDC和NDC的进化,它分别用线程上下文Map映射线程上下文栈来表示MDC和NDC。我们可以通过ThreadContext静态类来管理线程上下文,这个类在实现上类似于Log4j版本1中的MDC和NDC。
When using the Thread Context Stack, data is pushed to and popped from a stack just like with NDC:
当使用线程上下文栈时,我们可以向NDC那样向栈中添加或者删除数据:
import org.apache.logging.Log4j.ThreadContext;
...
ThreadContext.push(username);
ThreadContext.push(sessionID);
// Logging methods go here
ThreadContext.pop();
...
当使用线程上下文映射时,我们可以像MDC那样将值和键结合在一起:
import org.apache.logging.Log4j.ThreadContext;
...
ThreadContext.put(“username”,"admin");
ThreadContext.put("sessionID", "1234");
// Logging methods go here
ThreadContext.clearMap();
...
ThreadContext类提供了一些方法,用于清除栈、清除MDC、清除存储在上下文中的所有值,对应的方法是ThreadContext.clearAll()、ThreadContext.clearMap()和ThreadContext.clearStack()。
和在MDC以及NDC中一样,我们可以使用Layouts在线程上下文中访问这些值。使用PatternLayout时,%x转换模式会从栈中获取值,%X和%X(键)会从图中获取值。
ThreadContext过滤
一些框架允许你基于某些属性对日志进行过滤。例如,Log4j的DynamicThresholdFilter 会在键满足特定条件的情况下,自动调整日志级别。再比如,如果我们想要触发TRACE级别的日志消息,我们可以创建一个名为trace-logging-enabled的键,并向log4j配置文件中添加一个过滤器:
<Configuration name="MyApp">
<DynamicThresholdFilter key="trace-logging-enabled" onMatch="ACCEPT" onMismatch="NEUTRAL">
<KeyValuePair key="true" value="TRACE" />
</DynamicThresholdFilter>
...
如果ThreadContext包含一个名为trace-logging-enabled的键,onMatch 和 onMismatch 会决定如何处理它。关于 onMatch 和 onMismatch,我们有三个可选项:ACCEPT,它会处理过滤器的规则;DENY,它会忽略过滤器的规则;NEUTRAL,它会推迟到下一个过滤器。除了这些,我们还定义一个键值对,当值为true时,我们启用TRACE级别的日志。
现在,当trace-logging-enabled被设置成true时,即使根Logger设置的日志级别高于TRACE,Appender也会记录TRACE级别的消息。
你可能还想过滤一些特定的日志到特定的Appender中,Log4j中提供了ThreadContextMapFilter来实现这一点。如果我们想要限制某个特定的Appender,只记录针对某个用户的TRACE级别的消息,我们可以基于username键添加一个ThreadContextMapFilter:
<Console name="ConsoleAppender" target="SYSTEM_OUT">
<ThreadContextMapFilter onMatch="ACCEPT" onMismatch="DENY">
<KeyValuePair key="username" value="admin" />
</ThreadContextMapFilter>
...
如果想了解更多信息,你可以查看Log4j和Logback文档中关于DynamicThresholdFilter部分。
Markers
Markers允许你对单独的日志记录添加一些的数据。它可以用来对日志记录进行分组,触发一些行为,或者对日志记录进行过滤,并将过滤结果输出到指定的Appender中。你甚至可以将Markers和ThreadContext结合在一起使用,以提高搜索和过滤日志数据的能力。
例如,假设我们有一个可以连接到数据库的类,如果在打开数据库的时候发生了异常,我们需要把异常记录成fatal错误。我们可以创建一个名为DB_ERROR的Marker,然后将其应用到日志事件中:
import org.apache.logging.Log4j.Marker;
import org.apache.logging.Log4j.MarkerManager;
...
final static Marker DB_ERROR = MarkerManager.getMarker("DATABASE_ERROR");
...
logger.fatal(DB_ERROR, "An exception occurred.");
为了在日志输出中显示Marker信息,我们需要在PatternLayout中添加%marker转换模式:
<PatternLayout pattern="%p %marker: %m%n" />
[FATAL] DATABASE_ERROR: An exception occurred.
或者对于JSON和XML格式的Layouts,会自动在输出中包含Marker信息:
...
"thread" : "main",
"level" : "FATAL",
"loggerName" : "DBClass",
"marker" : {
"name" : "DATABASE_ERROR"
},
"message" : "An exception occurred.",
...
通过对Marker数据进行自动解析和排序,集中式的日志服务可以很容易对日志进行搜索处理。
Markers过滤
Marker过滤器可以让你决定哪些Marker由哪些Logger来处理。marker字段会比较在日志事件里面的Marker名字,如果名字匹配,那么Logger会执行后续的行为。例如,在Log4j中,我们可以配置一个Appender来只显示哪些使用了DB_ERROR Marker的消息,这可以通过log4j2.xml中的Appender添加如下信息来实现:
<MarkerFilter marker="DATABASE_ERROR" onMatch="ACCEPT" onMismatch="DENY" />
如果日志记录中某一条的Marker可以匹配这里的marker字段,那么onMatch会决定如何处理这条记录。如果不能够匹配,或者日志记录中没有Marker信息,那么onMismatch会决定如何处理这条记录。对于onMatch和onMismatch来说,有3个可选项:ACCEPT,它允许记录事件;DENY,它会阻塞事件;NEUTRAL,它不会对事件进行任何处理。
在Logback中,我们需要更多一些设置。首先,想Appender中添加一个新的EvaluatorFilter,并如上所述指定onMatch和onMismatch行为。然后,添加一个OnMarkerEvaluator并将Marker的名字传递给它:
<filter class="ch.qos.Logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.Logback.classic.boolex.OnMarkerEvaluator">
<marker>DATABASE_ERROR</marker>
</evaluator>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
将Markers和NDC、MDC以及ThreadContext结合使用
Marker的功能和ThreadContext类似,它们都是向日志记录中添加的数据,这些数据可以被Appender访问。如果把这两者结合使用,可以让你更容易的对日志数据进行索引和搜索。如果能够知道何时使用哪一种技术,会对我们有所帮助。
NDC、MDC和ThreadContext被用于将相关日志记录结合在一起。如果你的应用程序会处理多个同时存在的用户,ThreadContext可以让你将针对某个特定用户的一组日志记录组合在一起。因为ThreadContext针对每个线程都是不一样的,所以你可以使用同样的方法来对相关的日志记录进行自动分组。
另一方面,Marker通常用于标记或者高亮显示某些特殊事件。在上述示例中,我们使用DB_ERROR Marker来标明在方法中发生的SQL相关异常。我们可以使用DB_ERROR Marker来将这些事件的处理过程和其他事件区分开来,例如我们可以使用SMTP Appender来将这些事件通过邮件发送给数据库管理员。
额外资源
指南和教程
Java Logging(Jakob Jenkov)——使用Java Logging API进行日志开发教程
Java Logging Overview(Oracle)—— Oracle提供的在Java中进行日志开发的指南
Log4J Tutorial(Tutorials Point)——使用log4j 版本1进行日志开发的指南
日志抽象层
Apache Commons Logging(Apache)——针对Log4j、Avalon LogKit和java.util.logging的抽象层
SLF4J(QOS.ch)——一个流程的抽象层,应用在多个日志框架上,包括Log4j、Logback以及java.util.logging
日志框架
Java Logging API(Oracle)—— Java默认的日志框架
Log4j(Apache)——开源日志框架
Logback(Logback Project)——开源项目,被设计成Log4j版本1的后续版本
tinylog(tinylog)——轻量级开源logger
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
Java性能测试有哪些不为众人所知的原则?Java设计模式??装饰者模式谈谈Java中遍历Map的几种方法Java Web入门必知你需要理解的Java反射机制知识总结编写更好的Java单元测试的7个技巧编程常用的几种时间戳转换(java .net 数据库)适合Java开发者学习的Python入门教程Java webdriver如何获取浏览器新窗口中的元素?Java重写与重载(区别与用途)Java变量的分类与初始化JavaScript有这几种测试分类Java有哪四个核心技术?给 Java开发者的10个大数据工具和框架Java中几个常用设计模式汇总java生态圈常用技术框架、开源中间件,系统架构及经典案例等

sales@spasvo.com