Logback 手册 - 第六章:布局 - 2


来源:logback.qos.ch/manual/layo... 作者:Ceki Gülcü、Sébastien Pennec、Carl Harris 版权所有 © 2000-2022 QOS.ch Sarl

本文档采用 知识共享署名 - 非商业性使用 - 相同方式共享 2.5 许可协议


转换词选项

转换说明符后面可以跟随选项。它们总是在大括号之间声明。我们已经看到了一些选项提供的可能性,例如与 MDC 转换说明符结合使用,如:%mdc{someKey}

一个转换说明符可能有多个选项。例如,一个使用评估器的转换说明符(即将介绍)可以将评估器名称添加到选项列表中,如下所示:

perl 复制代码
<pattern>%-4relative [%thread] %-5level - %msg%n \
  %caller{2, DISP_CALLER_EVAL, OTHER_EVAL_NAME, THIRD_EVAL_NAME}</pattern>

如果选项包含特殊字符,如大括号、空格或逗号,可以用单引号或双引号将其括起来。例如,考虑下一个模式。

perl 复制代码
<pattern>%-5level - %replace(%msg){'\d{14,16}', 'XXXX'}%n</pattern>

我们将选项 \d{16}XXXX 传递给 replace 转换词。它将用 XXXX 替换消息中包含的任何 14、15 或 16 位数字序列,从而有效地混淆信用卡号码。注意,\d 是常规表达式中表示单个数字的简写。"{14,16\}" 被解释为 "{14, 16}",即重复前面的项至少 14 次但最多 16 次。

使用括号进行分组

在 logback 中,模式字符串中的括号被视为分组标记。因此,可以对子模式进行分组并对该子模式应用格式化指令。

例如,模式

perl 复制代码
%-30(%d{HH:mm:ss.SSS} [%thread]) %-5level %logger{32} - %msg%n

将对由子模式 "%d{HH:mm:ss.SSS} [%thread]" 生成的输出进行分组,如果少于 30 个字符则右对齐。

假设没有分组时的输出是

accesslog 复制代码
13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Classload hashcode is 13995234
13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Initializing for ServletContext
13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Trying platform Mbean server
13:09:30 [pool-1-thread-1] INFO  ch.qos.logback.demo.LoggingTask - Howdydy-diddly-ho - 0
13:09:38 [btpool0-7] INFO c.q.l.demo.lottery.LotteryAction - Number: 50 was tried.
13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Beginning to factor.
13:09:40 [btpool0-7] DEBUG c.q.l.d.prime.NumberCruncherImpl - Trying 2 as a factor.
13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Found factor 2

使用 "%-30()" 分组后,输出将变为

accesslog 复制代码
13:09:30 [main]            DEBUG c.q.logback.demo.ContextListener - Classload hashcode is 13995234
13:09:30 [main]            DEBUG c.q.logback.demo.ContextListener - Initializing for ServletContext
13:09:30 [main]            DEBUG c.q.logback.demo.ContextListener - Trying platform Mbean server
13:09:30 [pool-1-thread-1] INFO  ch.qos.logback.demo.LoggingTask - Howdydy-diddly-ho - 0
13:09:38 [btpool0-7]       INFO  c.q.l.demo.lottery.LotteryAction - Number: 50 was tried.
13:09:40 [btpool0-7]       INFO  c.q.l.d.prime.NumberCruncherImpl - Beginning to factor.
13:09:40 [btpool0-7]       DEBUG c.q.l.d.prime.NumberCruncherImpl - Trying 2 as a factor.
13:09:40 [btpool0-7]       INFO  c.q.l.d.prime.NumberCruncherImpl - Found factor 2

后一种形式更容易阅读。

如果需要将括号字符视为字面量,则需要在每个括号之前加上反斜杠进行转义,如 \(%d{HH:mm:ss.SSS} [%thread]\)

【颜色设置】

按照上面所解释的方式,使用括号进行分组可以对子模式进行着色。从版本 1.0.5 开始,PatternLayout 可以识别 "%black""%red""%green""%yellow""%blue""%magenta""%cyan""%white""%gray""%boldRed""%boldGreen""%boldYellow""%boldBlue""%boldMagenta""%boldCyan""%boldWhite""%highlight" 作为转换词。这些转换词旨在包含子模式。任何被染色词括起来的子模式都将以指定的颜色输出。

下面是一个演示如何进行着色的配置文件例子。请注意,"%logger{15}"%cyan 转换说明符所包含。这将输出缩写为 15 个字符的记录器名称,并以青色显示。%highlight 转换说明符会以粗体红色打印其子模式,其中 ERROR 级别的事件以红色、WARN 级别的事件以 BLUE 色、INFO 级别的事件以默认颜色打印。

演示:高亮显示级别(logback-examples/src/main/resources/chapters/layouts/highlighted.xml)

传统格式

xml 复制代码
<configuration debug="true">
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <withJansi>true</withJansi>
    <encoder>
      <pattern>[%thread] %highlight(%-5level) %cyan(%logger{15}) -%kvp -%msg %n</pattern>
    </encoder>
  </appender>
  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

规范格式 (1.3)

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration debug="true">
  <import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
  <import class="ch.qos.logback.core.ConsoleAppender"/>

  <appender name="STDOUT" class="ConsoleAppender">
    <withJansi>true</withJansi>
    <encoder class="PatternLayoutEncoder">
      <pattern>[%thread] %highlight(%-5level) %cyan(%logger{15}) -%kvp -%msg %n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT"/>
  </root>
</configuration>

withJansi 设置为 true 可以启用 Jansi 库的 ANSI 颜色代码解释,该库会在底层终端不兼容时透明地过滤掉 ANSI 转义序列。这是跨平台部署的最安全选择,但在类路径中需要具有 org.fusesource.jansi:jansi:1.17 或更高版本。请注意,基于 Unix 的操作系统(如 Linux 和 Mac OS X)本地支持 ANSI 颜色代码,通常不需要启用 Jansi 库,但这样做是无害的。然而,在 Windows 上,建议启用 Jansi 以便在 DOS 命令提示符上从颜色代码解释中受益,否则会发送 ANSI 转义序列,它们无法解释。

以下是对应的输出:

accesslog 复制代码
[main] WARN  c.l.TrivialMain - a warning message 0
[main] DEBUG c.l.TrivialMain - hello world number1
[main] DEBUG c.l.TrivialMain - hello world number2
[main] INFO  c.l.TrivialMain - hello world number3
[main] DEBUG c.l.TrivialMain - hello world number4
[main] WARN  c.l.TrivialMain - a warning message 5
[main] ERROR c.l.TrivialMain - Finish off with fireworks

创建一个彩色转换词只需要很少的代码。章节 创建自定义转换说明符 讨论了在配置文件中注册转换词所需的步骤。

【评估器】

如上所述,当需要一个转换说明符根据一个或多个 EventEvaluator 对象动态地进行处理时,选项列表非常有用。EventEvaluator 对象负责确定给定的日志事件是否符合评估器的条件。

让我们回顾一个涉及 EventEvaluator 的例子。下一个配置文件将日志事件输出到控制台,显示日期、线程、级别、消息和调用数据。鉴于提取记录器的调用者数据会比较昂贵,因此只有在日志请求来源于特定记录器并且消息包含某个字符串时,我们才会这样做。因此,我们确保仅特定的日志请求将生成并显示其调用者信息。在其他情况下,其中调用方数据是多余的,我们将不会惩罚应用程序性能。

评估器,尤其是 评估表达式 ,在 过滤器章节 中专门介绍,如果您想以任何有意义的方式使用评估器,则必须阅读该章节。还要注意,以下示例隐式基于 JaninoEventEvaluator,它需要 Janino 库。请参阅设置文档中的 相应部分

演示:EventEvaluators 的使用示例(logback-examples/src/main/resources/chapters/layouts/callerEvaluatorConfig.xml)

传统格式

xml 复制代码
<configuration>
  <evaluator name="DISP_CALLER_EVAL">
    <expression>logger.contains("chapters.layouts") &amp;&amp; \
      message.contains("who calls thee")</expression>
  </evaluator>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>
        %-4relative [%thread] %-5level -%kvp -%msg%n%caller{2, DISP_CALLER_EVAL}
      </pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

规范格式 (1.3)

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration>
  <import class="ch.qos.logback.core.ConsoleAppender"/>
  <import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
  <evaluator name="DISP_CALLER_EVAL">
    <expression>logger.contains("chapters.layouts") && \
      message.contains("who calls thee")</expression>
  </evaluator>

  <appender name="STDOUT" class="ConsoleAppender">
    <encoder class="PatternLayoutEncoder">
      <pattern>%-4relative [%thread] %-5level -%kvp -%msg%n%caller{2, DISP_CALLER_EVAL}</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT"/>
  </root>
</configuration>

上述评估表达式匹配来自名称包含字符串 "chapters.layouts" 的记录器发出的事件,并且消息包含字符串 "who calls thee"。由于 XML 编码规则,& 字符不能直接写入,需要转义为 &amp;

以下类利用了上述配置文件中提到的一些特性。

示例:EventEvaluators 的示例用法 (logback-examples/src/main/java/chapters/layouts/CallerEvaluatorExample.java)

java 复制代码
package chapters.layouts;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;

public class CallerEvaluatorExample {

  public static void main(String[] args)  {
    Logger logger = LoggerFactory.getLogger(CallerEvaluatorExample.class);
    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

    try {
      JoranConfigurator configurator = new JoranConfigurator();
      configurator.setContext(lc);
      configurator.doConfigure(args[0]);
    } catch (JoranException je) {
      // StatusPrinter will handle this
    }
    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);

    for (int i = 0; i < 5; i++) {
      if (i == 3) {
        logger.debug("who calls thee?");
      } else {
        logger.debug("I know me " + i);
      }
    }
  }
}

上述应用程序没有特别花哨的地方。发出五个日志记录请求,第三个请求发出消息 "who calls thee?"

命令

bash 复制代码
java chapters.layouts.CallerEvaluatorExample src/main/java/chapters/layouts/callerEvaluatorConfig.xml

将产生以下输出:

accesslog 复制代码
0    [main] DEBUG - I know me 0
0    [main] DEBUG - I know me 1
0    [main] DEBUG - I know me 2
0    [main] DEBUG - who calls thee?
Caller+0   at chapters.layouts.CallerEvaluatorExample.main(CallerEvaluatorExample.java:28)
0    [main] DEBUG - I know me 4

当发出日志记录请求时,相应的日志事件被评估。只有第三个日志事件符合评估标准,导致其调用者数据被显示。对于其他日志事件,评估标准不匹配,不会打印调用者数据。

可以更改表达式以对应实际情况。例如,可以结合记录器名称和请求级别。因此,从应用程序的敏感部分(例如财务交易模块)发出的级别为 WARN 及以上的日志记录请求将显示其调用者数据。

重要提示: 使用 caller 转换词,当 表达式评估为 true 时输出调用者数据。

让我们考虑另一种情况。当异常包含在日志记录请求中时,它们的堆栈跟踪也会输出。但是,有时可能希望对某些特定异常抑制堆栈跟踪。

下面显示的 Java 代码创建了三个具有异常的日志请求。第二个异常与其他异常不同:它包含字符串" do not display this",并且其类型为 chapters.layouts.TestException。现在,让我们阻止第二个异常被打印。

示例:EventEvaluators 的示例用法 (logback-examples/src/main/java/chapters/layouts/ExceptionEvaluatorExample.java)

java 复制代码
package chapters.layouts;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;

public class ExceptionEvaluatorExample {

  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(ExceptionEvaluatorExample.class);
    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

    try {
      JoranConfigurator configurator = new JoranConfigurator();
      configurator.setContext(lc);
      lc.reset();
      configurator.doConfigure(args[0]);
    } catch (JoranException je) {
       // StatusPrinter will handle this
    }
    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);

    for (int i = 0; i < 3; i++) {
      if (i == 1) {
        logger.debug("logging statement " + i, new TestException(
            "do not display this"));
      } else {
        logger.debug("logging statement " + i, new Exception("display"));
      }
    }
  }
}

在下一个配置文件中,评估表达式匹配包含 chapters.layouts.TextException 类型的可抛出事件,这恰好是我们希望抑制的异常类型。

示例:EventEvaluators 的用法示例(logback-examples/src/main/resources/chapters/layouts/exceptionEvaluatorConfig.xml)

传统格式

xml 复制代码
<configuration>

  <evaluator name="DISPLAY_EX_EVAL">
    <expression>throwable != null &amp;&amp; throwable instanceof  \
      chapters.layouts.TestException</expression>
  </evaluator>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%msg%n%ex{full, DISPLAY_EX_EVAL}</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

规范格式 (1.3)

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration>
  <import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
  <import class="ch.qos.logback.core.ConsoleAppender"/>
  <evaluator name="DISPLAY_EX_EVAL">
    <expression>throwable != null && throwable instanceof  \
      chapters.layouts.TestException</expression>
  </evaluator>

  <appender name="STDOUT" class="ConsoleAppender">
    <encoder class="PatternLayoutEncoder">
      <pattern>%msg%n%ex{full, DISPLAY_EX_EVAL}</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT"/>
  </root>
</configuration>

通过这个配置,每当 chapters.layouts.TestException 的实例被包含在日志请求中时,堆栈跟踪将被抑制。

运行以下命令

bash 复制代码
java chapters.layouts.ExceptionEvaluatorExample src/main/java/chapters/layouts/exceptionEvaluatorConfig.xml

会产生以下结果

accesslog 复制代码
logging statement 0
java.lang.Exception: display
  at chapters.layouts.ExceptionEvaluatorExample.main(ExceptionEvaluatorExample.java:43) [logback-examples-0.9.19.jar:na]
logging statement 1
logging statement 2
java.lang.Exception: display
  at chapters.layouts.ExceptionEvaluatorExample.main(ExceptionEvaluatorExample.java:43) [logback-examples-0.9.19.jar:na]

注意第二个日志语句没有堆栈跟踪。我们成功地抑制了 TextException 的堆栈跟踪。每个堆栈跟踪行末尾的方括号中的文本是之前讨论过的 打包信息

==注意== 使用 %ex 转换说明符时,当 表达式评估为 false 时显示堆栈跟踪

创建自定义转换说明符

到目前为止,我们已经介绍了 PatternLayout 中内置的转换词。但是,您也可以添加自己制作的转换词。

构建自定义转换说明符包括两个步骤。

第一步

首先,您必须扩展 ClassicConverter 类。ClassicConverter 对象负责从 ILoggingEvent 实例中提取信息并生成字符串。例如,LoggerConverter,即 %logger 转换词的基础转换器,从 ILoggingEvent 中提取 Logger 的名称并将其作为字符串返回。它可能在此过程中缩写 Logger 名称。

下面是一个返回自创建以来经过的纳秒数的自定义转换器的示例:

示例:自定义转换器示例(src/main/java/chapters/layouts/MySampleConverter.java)

java 复制代码
public class MySampleConverter extends ClassicConverter {

  long start = System.nanoTime();

  @Override
  public String convert(ILoggingEvent event) {
    long nowInNanos = System.nanoTime();
    return Long.toString(nowInNanos-start);
  }
}

这个实现非常简单。MySampleConverter 类扩展了 ClassicConverter,并实现了 convert 方法,该方法返回自创建以来经过的纳秒数的字符串。

第二步

在第二步中,我们必须让 logback 知道新的 Converter。为此,我们需要在配置文件中声明新的转换词,如下所示:

示例:示例转换器示例(src/main/java/chapters/layouts/mySampleConverterConfig.xml)

传统格式

xml 复制代码
<configuration>
  <conversionRule conversionWord="nanos"
                  converterClass="chapters.layouts.MySampleConverter" />

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%-6nanos [%thread] -%kvp -%msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

规范格式 (1.3)

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration>
  <import class="ch.qos.logback.core.ConsoleAppender"/>
  <import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>

  <appender name="STDOUT" class="ConsoleAppender">
    <encoder class="PatternLayoutEncoder">
      <pattern>%-6nanos [%thread] -%kvp -%msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT"/>
  </root>
</configuration>

一旦在配置文件中声明了新的转换词,我们就可以像其他转换词一样在 PatternLayout 模式中引用它。

以下命令:

bash 复制代码
java chapters.layouts.SampleLogging src/main/java/chapters/layouts/mySampleConverterConfig.xml

应该产生类似于以下的输出:

accesslog 复制代码
4868695 [main] DEBUG - Everything's going well
5758748 [main] ERROR - maybe not quite...

读者可能想看看其他 Converter 的实现,比如 MDCConverter,以了解更复杂的行为,比如选项处理。要创建自己的着色方案,请查看 HighlightingCompositeConverter

HTMLLayout

HTMLLayout(包含在 logback-classic 中)以 HTML 格式生成日志。HTMLLayout 将日志事件输出为 HTML 表格,其中表的每一行对应一个日志事件。

下面是使用默认 CSS 样式表生成的 HTMLLayout 的示例输出:

表列的内容通过转换模式指定。有关转换模式的文档,请参见 PatternLayout。因此,您可以完全控制表的内容和格式。您可以选择和显示 PatternLayout 所知道的任何转换器的任意组合。

关于在 HTMLLayout 中使用 PatternLayout 的一个显着例外是,转换说明符不应由空格字符或更一般地由文本文字分隔。模式中找到的每个说明符都将生成一个单独的列。同样,对于模式中找到的每个文本块,将生成一个单独的列,可能会浪费宝贵的屏幕空间。

下面是一个简单但功能齐全的配置文件示例,演示了如何使用 HTMLLayout

示例:HTMLLayout 示例(src/main/java/chapters/layouts/htmlLayoutConfig1.xml)

传统格式

xml 复制代码
<configuration debug="true">
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
      <layout class="ch.qos.logback.classic.html.HTMLLayout">
        <pattern>%relative%thread%mdc%level%logger%msg</pattern>
      </layout>
    </encoder>
    <file>test.html</file>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

规范格式 (1.3)

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration debug="true">
  <import class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"/>
  <import class="ch.qos.logback.core.FileAppender"/>
  <import class="ch.qos.logback.classic.html.HTMLLayout"/>

  <appender name="FILE" class="FileAppender">
    <encoder class="LayoutWrappingEncoder">
      <layout class="HTMLLayout">
        <pattern>%relative%thread%mdc%level%logger%msg</pattern>
      </layout>
    </encoder>
    <file>test.html</file>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE"/>
  </root>
</configuration>

TrivialMain 应用程序记录了一些以异常结束的消息。以下命令:

bash 复制代码
java chapters.layouts.TrivialMain src/main/java/chapters/layouts/htmlLayoutConfig1.xml

将在当前文件夹中创建名为 test.html 的文件。test.html 的内容应类似于以下内容:

HTML Layout Sample Image

堆栈跟踪

如果您使用 %em 转换词来显示堆栈跟踪,将创建一个表列来显示堆栈跟踪。在大多数情况下,该列将为空,浪费屏幕空间。此外,在单独的列上打印堆栈跟踪不会得到非常可读的结果。幸运的是,%ex 转换词并不是显示堆栈跟踪的唯一方法。

通过实现 IThrowableRenderer 接口,可以提供更好的解决方案来管理与异常相关的显示数据,并将其分配给 HTMLLayout。默认情况下,每个 HTMLLayout 实例都分配了一个 DefaultThrowableRenderer,它以易于阅读的方式将异常和其堆栈跟踪写在 新表行 中,如上图所示。

如果出于某种原因,您仍然希望使用 %ex 模式,则可以在配置文件中指定 NOPThrowableRenderer,以禁用为堆栈跟踪显示单独的行。我们不知道为什么您会这样做,但如果您希望,您可以这样做。

CSS

通过级联样式表(CSS)来控制 HTMLLayout 创建的 HTML 的呈现方式。如果没有特定的指令,HTMLLayout 将默认使用内部 CSS。但是,您可以指示 HTMLLayout 使用外部 CSS 文件。为此,可以在 <layout> 元素中嵌套一个 cssBuilder 元素,如下所示:

xml 复制代码
<layout class="ch.qos.logback.classic.html.HTMLLayout">
  <pattern>%relative...%msg</;pattern>
  <cssBuilder class="ch.qos.logback.classic.html.UrlCssBuilder">
    <!-- css 文件所在的 url -->
    <url>http://...</url>
  </cssBuilder>
</layout>

HTMLLayout 通常与 SMTPAppender 结合使用,以便以 HTML 格式良好地格式化发送的电子邮件。

Log4j XMLLayout

XMLLayout(属于 logback-classic)生成符合 log4j.dtd 格式的输出,以与 ChainsawVigilog 等工具进行交互,这些工具可以处理由 log4j 的 XMLLayout 生成的文件。

与 log4j 版本 1.2.15 中的原始 XMLLayout 一样,logback-classic 中的 XMLLayout 具有两个布尔属性:locationInfoproperties。将 locationInfo 设置为 true 可在每个事件中包含位置信息(调用者数据)。将 properties 设置为 true 可包含 MDC 信息。这两个选项默认情况下都设置为 false

以下是一个示例配置:

示例:Log4jXMLLayout 示例(src/main/java/chapters/layouts/log4jXMLLayout.xml)

传统格式

xml 复制代码
<configuration>
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>test.xml</file>
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
      <layout class="ch.qos.logback.classic.log4j.XMLLayout">
        <locationInfo>true</locationInfo>
      </layout>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

规范格式 (1.3)

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration>
  <import class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"/>
  <import class="ch.qos.logback.classic.log4j.XMLLayout"/>
  <import class="ch.qos.logback.core.FileAppender"/>

  <appender name="FILE" class="FileAppender">
    <file>test.xml</file>
    <encoder class="LayoutWrappingEncoder">
      <layout class="XMLLayout">
        <locationInfo>true</locationInfo>
      </layout>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE"/>
  </root>
</configuration>

Logback access

logback-access 对日志的布局大多是基于 logback-classic 进行调整的。logback-classic 和 logback-access 模块满足不同的需求,但总体上提供了类似的功能。

编写自定义布局

编写 logback access 的自定义 Layout 与 logback-classic 中的兄弟类 Layout 几乎完全相同。

PatternLayout

在 logback-access 中,可以通过配置 PatternLayout 来实现与经典模式相似的功能。然而,它还包含了适用于记录仅在 HTTP Servlet 请求和 HTTP Servlet 响应中可用的特定信息的额外转换说明符。

下面是 logback-access 中 PatternLayout 的转换说明符列表。

转换说明符 效果
a / remoteIP 远程 IP 地址。
A / localIP 本地 IP 地址。
b / B / bytesSent 响应的内容长度。
h / clientHost 远程主机。
H / protocol 请求协议。
l 远程日志名称。在 logback-access 中,此转换器始终返回值为 "-"
reqParameter{paramName} 响应的参数。 此转换词获取花括号中的第一个选项,并在请求中查找相应的参数。 %reqParameter{input_data} 显示相应的参数。
i{header } / header{header} 请求头。 此转换词获取花括号中的第一个选项,并在请求中查找相应的头部。 %header{Referer} 显示请求的引用页。 如果未指定选项,则显示所有可用的头部。
m / requestMethod 请求方法。
r / requestURL 请求的 URL。
s / statusCode 请求的状态码。
D / elapsedTime 为服务请求所花费的时间,以毫秒为单位。
T / elapsedSeconds 为服务请求所花费的时间,以秒为单位。
t / date 输出日志事件的日期。日期转换说明符后面可以跟随一个括号,其中包含 java.text.SimpleDateFormat 使用的日期和时间模式字符串。ISO8601 也是一个有效的值。 例如,%t{HH:mm:ss,SSS}%t{ddMMMyyyy;HH:mm:ss,SSS}。如果没有指定日期格式说明符,则假定为通用日志格式的日期格式,即 %t{dd/MMM/yyyy:HH:mm:ssZ}
u / user 远程用户。
q / queryString 请求查询字符串,以'?'开头。
U / requestURI 请求的 URI。
S / sessionID 会话 ID。
v / server 服务器名称。
I / threadName 处理请求的线程名称。
localPort 本地端口。
reqAttribute{attributeName} 请求属性。 此转换词获取花括号中的第一个选项,并在请求中查找相应的属性。 %reqAttribute{SOME_ATTRIBUTE} 显示相应的属性。
reqCookie{cookie} 请求 Cookie。 此转换词获取花括号中的第一个选项,并在请求中查找相应的 Cookie。 %cookie{COOKIE_NAME} 显示相应的 Cookie。
responseHeader{header} 响应头。 此转换词获取花括号中的第一个选项,并在响应中查找相应的头部。 %header{Referer} 显示响应的引用页。
requestContent 此转换词显示请求的内容,即请求的 InputStream。它与 TeeFilter 一起使用,TeeFilter 是一个 javax.servlet.Filter,它将原始的 HttpServletRequest 替换为 TeeHttpServletRequest。后者允许多次访问请求的 InputStream 而不丢失任何数据。
fullRequest 此转换器输出与请求相关的所有数据,包括所有头部和请求内容。
responseContent 此转换词显示响应的内容,即响应的 InputStream。它与 TeeFilter 一起使用,TeeFilter 是一个 javax.servlet.Filter,它将原始的 HttpServletResponse 替换为 TeeHttpServletResponse。后者允许多次访问请求的 InputStream 而不丢失任何数据。
fullResponse 此转换词获取与响应相关的所有可用数据,包括响应的所有头部和响应内容。

logback-access 的 PatternLayout 还识别三个关键字,它们像快捷方式一样起作用。

关键字 等效的转换模式
commonCLF *%h %l %u [%t] "%r" %s %b*
combined %h %l %u [%t] "%r" %s %b "%i{Referer}" "%i{User-Agent}"

common 关键字对应的模式是 '%h %l %u [%t] "%r" %s %b',显示客户端主机、远程日志名称、用户、日期、请求的 URL、状态码和响应的内容长度。

combined 关键字是 '%h %l %u [%t] "%r" %s %b "%i{Referer}" "%i{User-Agent}"' 的快捷方式。该模式与 common 模式类似,但还显示了两个请求头,即引用页和用户代理。

HTMLLayout

logback-access 中的 HTMLLayout 类与 logback-classic 中的 HTMLLayout 类相似。

默认情况下,它会创建一个包含以下数据的表格:

  • 远程 IP
  • 日期
  • 请求的 URL
  • 状态码
  • 内容长度

以下是 logback-access 中的 HTMLLayout 生成的示例输出:

Access HTML Layout Sample Image

有什么比一个真实世界的例子更好呢?我们自己的 log4j 日志配置文件中使用了 logback-access 来演示带有 HTMLLayoutRollingFileAppender 的实时输出。

每当用户在我们的 translator 网络应用程序上发起新的请求时,将向访问日志添加新条目,您可以通过 点击此链接 查看。

版权声明:本文为博主「佳佳」的原创文章,遵循 CC 4.0 BY-NC-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:www.liujiajia.me/2023/12/7/l...

相关推荐
阿飞OnePiece7 个月前
springboot工程中使用slf4j+logback实现日志唯一编号
spring boot·apache log4j
洛小豆7 个月前
SpringBoot日志管理 —— 解决Logback生成 "LOG_PATH_IS_UNDEFINED" 文件夹问题
spring boot·后端·apache log4j
半夏之沫8 个月前
十年经验竟不懂Springboot日志
spring boot·spring·apache log4j
不识君8 个月前
动态调整Logback的Appender的解决方案
java·apache log4j
用户426670591699 个月前
项目中如何配置和使用Log4j2.x
后端·apache log4j
hashcon9 个月前
【硬核】Log4j2 与 Logback 当初的选型以及在当前云原生环境下的反思与展望
java·spring·apache log4j
winjeg10 个月前
logback VS log4j2 那些你注意不到的性能差距...
java·spring·apache log4j
乐乐家的乐乐1 年前
怎么说,手写一个日志框架
java·后端·apache log4j
佳佳_1 年前
Logback 手册 - 第八章:映射诊断上下文
apache log4j