以下是我在所有项目中都遵循的以确保良好性能的一组准则。我是根据互联网上各种来源的输入来形成这套准则的。
与今天一样,我相信Log4j 2是迄今为止登录Java的最佳选择。
基准可在此处获得。为了获得最佳性能,我遵循以下做法:
- 由于以下原因,我暂时避免使用SLF4J:
- 使用异步记录器执行所有常规记录,以提高性能
- 使用同步记录器将错误消息记录在单独的文件中,因为我们希望尽快查看错误消息
- 请勿在常规日志记录中使用位置信息,例如文件名,类名,方法名,行号,因为为了导出这些信息,框架会获取堆栈快照并逐步遍历。这会影响性能。因此,仅在错误日志中使用位置信息,而不在常规日志中使用位置信息
- 对于跟踪由单独的线程来处理单个请求的目的,可以考虑使用线程上下文和随机UUID作为解释这里
- 由于我们将错误记录在一个单独的文件中,因此将上下文信息也记录在错误日志中非常重要。例如,如果应用程序在处理文件时遇到错误,请在错误日志文件中打印文件名和正在处理的文件记录以及stacktrace
- 日志文件应该是可重复的并且易于理解。例如,如果应用程序处理多个文件中的客户记录,则每个日志消息应如下所示:
12:01:00,127 INFO FILE_NAME=file1.txt - Processing starts
12:01:00,127 DEBUG FILE_NAME=file1.txt, CUSTOMER_ID=756
12:01:00,129 INFO FILE_NAME=file1.txt - Processing ends
- 使用SQL标记记录所有SQL语句,如下所示,并使用过滤器启用或禁用它:
private static final Marker sqlMarker =
MarkerManager.getMarker("SQL");
private void method1() {
logger.debug(sqlMarker, "SELECT * FROM EMPLOYEE");
}
- 使用Java 8 Lambdas记录所有参数。当给定的日志级别被禁用时,这将使应用程序免于格式化消息:
int i=5, j=10;
logger.info("Sample output {}, {}", ()->i, ()->j);
不要使用字符串连接。使用上面显示的参数化消息
使用动态重载日志记录配置,以便应用程序自动重载日志记录配置中的更改,而无需重新启动应用程序
请勿使用printStackTrace()或System.out.println()
该应用程序应在退出之前关闭记录器:
LogManager.shutdown();
- 最后,供大家参考,我使用以下配置:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorinterval="300" status="info" strict="true">
<Properties>
<Property name="filePath">${env:LOG_ROOT}/SAMPLE</Property>
<Property name="filename">${env:LOG_ROOT}/SAMPLE/sample
</Property>
<property name="logSize">10 MB</property>
</Properties>
<Appenders>
<RollingFile name="RollingFileRegular" fileName="${filename}.log"
filePattern="${filePath}/sample-%d{yyyy-dd-MM}-%i.log">
<Filters>
<MarkerFilter marker="SQL" onMatch="DENY"
onMismatch="NEUTRAL" />
</Filters>
<PatternLayout>
<Pattern>%d{HH:mm:ss,SSS} %m%n
</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy
interval="1" modulate="true" />
<SizeBasedTriggeringPolicy
size="${logSize}" />
</Policies>
</RollingFile>
<RollingFile name="RollingFileError"
fileName="${filename}_error.log"
filePattern="${filePath}/sample_error-%d{yyyy-dd-MM}-%i.log"
immediateFlush="true">
<PatternLayout>
<Pattern>%d{HH:mm:ss,SSS} %p %c{1.}[%L] [%t] %m%n
</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy
interval="1" modulate="true" />
<SizeBasedTriggeringPolicy
size="${logSize}" />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<AsyncLogger name="com"
level="trace">
<AppenderRef ref="RollingFileRegular"/>
</AsyncLogger>
<Root includeLocation="true" level="trace">
<AppenderRef ref="RollingFileError" level="error" />
</Root>
</Loggers>
</Configuration>
- 所需的Maven依赖项在这里:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.6</version>
</dependency>
<!-- (Optional)To be used when working
with the applications using Log4j 1.x -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>2.8.1</version>
</dependency>