Log4j 2 API
日志构建器
Log4j 传统上与以下日志语句一起使用
logger.error("Unable to process request due to {}", code, exception);
logger.atError().withThrowable(exception).log("Unable to process request due to {}", code);
使用此语法,很明显异常将被 Log4j 视为可抛出对象。
Logger 类现在在调用 atTrace、atDebug、atInfo、atWarn、atError、atFatal、always 或 atLevel(Level) 方法时返回一个 LogBuilder。然后,logBuilder 允许在记录事件之前向事件添加标记、可抛出对象和/或位置。对 log 方法的调用始终会导致日志事件被最终确定并发送。
带有标记、可抛出对象和位置的日志语句将如下所示
logger.atInfo().withMarker(marker).withLocation().withThrowable(exception).log("Login for user {} failed", userId);
在 LogBuilder 上提供 location 方法提供了两个明显的优势
- 日志记录包装器可以使用它来提供 Log4j 要使用的位置信息。
- 在不带参数的情况下使用 location 方法时捕获位置信息的开销远好于在需要时计算位置信息。Log4j 可以简单地请求堆栈跟踪条目在固定索引处,而不是必须遍历堆栈跟踪以确定调用类。当然,如果布局不使用位置信息,这将导致性能下降。
位置性能
下表显示了 log4j-perf 项目中 FileAppenderBenchmark 和 FileAppenderWithLocationBenchmark 类在配置为使用 4 个线程时的一些结果。结果表明,延迟包含位置信息比不包含位置信息慢约 8 倍。虽然使用 LogBuilder 的 withLocation 方法比延迟计算位置信息快约 3 倍,但它仍然比不包含位置信息慢约 2.5 倍。
这些测试是在 2018 款 MacBook Pro 上运行的,该机器配备 2.9 GHz 英特尔酷睿 i9 处理器,拥有 6 个核心、32 GB 内存和 1 TB 的 SSD 存储空间,在 Java 11 上使用 Log4j 2.13.0 和 Logback 1.2.3。
测试 | 打印位置信息 | 未打印位置信息 |
---|---|---|
Log4j2 文件 | 191,509.724 ± 11339.978 ops/s | 1,407,329.130 ± 22595.997 ops/s |
Log4j2 Log Builder withLocation() | 469,200.684 ± 50025.985 ops/s | 577,127.463 ± 11464.342 ops/s |
Logback 文件 | 159,116.538 ± 1884.969 ops/s | 1,240,438.384 ± 76619.873 ops/s |
正如预期的那样,当使用 LogBuilder 并调用 withLocation() 方法时,在输出中使用位置信息时日志记录速度要快得多,但在不使用位置信息时速度要慢得多。
注意:在不同时间运行测试会提供不同的结果。虽然有些结果高出 10%,但所有结果通常都会受到类似的影响,因此它们之间的比较保持不变。