1.常见的日志打印组件有:
- log4j
- logback
- log4j2
- java.util.looging
2.Apache Commons Loging (JCL)
Commons Loging 本身只提供日志接口,具体实现在运行时动态寻找对应组件?比如:log4j、jdk14looger 等。但这种动态绑定的方式当系统特别宠大的时候会出现绑定失败的问题。现在比较流行的slf4j 基于静态绑定的方式解决了这个问题。
3.slf4j
sl4j 本身也只提供日志接口,与commons loging 不同的是其采用在classPath 加入以下jar包来表示具体采用哪种实现 :
- slfj-log4j12.jar (表示指定 log4j)
- slf4j-jdk14.jar(表示指定jdk Looging)
- slf4j-jcl.jar(表示指定jcl)
- log4j-slf4j-impl(表示指定log4j2)
- logback-classic(表示指定logback)
假设你们系统当中之前在用 JCL 打印日志,但这时想加入slf4j来打印日志,就会出现两类日志,解决办法是加入如下等JAR包jcl-over-slf4j、log4j-over-sl4j、jul-over-sl4j ,即可在使用原API的情况下,又统一至slf4j 的实现进行输出了。
其他日志输出转换slf4j示例图如下:
总结下各个日志组件的对应关系:
JAVA日志体系结构图
4.log4j2使用
log4j2是目前异步输出性能最好的日志组件
4.1 安装/引入
在pom.xml中加入依赖
<!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.10.0</version> </dependency>
4.2 配置文件
Log4j 2.x配置文件只能采用.xml, .json或者 .jsn,不能使用1.x中的properties文件。
程序从classpath下寻找配置文件的优先级如下:
log4j-test.json 或者log4j-test.jsn文件 > log4j2-test.xml > log4j.json 或者log4j.jsn文件 > log4j2.xml
配置文件的结构
Configuration --Appenders --Child(输出类型) --Layout(输出的模板) --Filters(日志过滤器) --Loggers --Logger(日志输出对象) --Appender-ref(引用上面定义的输出类型)
配置文件模板
<?xml version="1.0" encoding="UTF-8"?> <!-- status : 这个用于设置log4j2自身内部的信息输出,可以不设置或设置为OFF;当设置成trace时,会看到log4j2内部各种详细输出。 monitorInterval : Log4j能够自动检测修改配置文件和重新配置本身, 设置间隔秒数。此处表示每隔600秒重读一次配置文件 --> <configuration status="OFF" monitorInterval="600"> <Properties> <!-- 设置属性,相当于全局变量 --> <Property name="LOG_HOME">logs</Property> <Property name="DEBUG_FILE_NAME">debug</Property> <Property name="ERROR_FILE_NAME">error</Property> <Property name="ROLL_FILE_NAME">rollingLog</Property> </Properties> <appenders> <!-- target是指定输出的目标,默认为System.out,也可以设置成System.err --> <Console name="STDOUT" target="SYSTEM_OUT"> <ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/> <!-- 输出内容的样式、模板 --> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level [%t] %C %M %L - %msg%xEx%n" /> </Console> <File name="DEBUG" fileName="${LOG_HOME}/${DEBUG_FILE_NAME}.log" append="false"> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" /> </File> <File name="ERROR" fileName="${LOG_HOME}/${ERROR_FILE_NAME}.log" append="true"> <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" /> </File> <!-- fileName : 指定当前日志文件的位置和文件名称 filePattern : 指定当发生Rolling时,文件的转移和重命名规则 SizeBasedTriggeringPolicy : 指定当文件体积大于size指定的值时,触发Rolling TimeBasedTriggeringPolicy : 这个配置需要和filePattern结合使用 DefaultRolloverStrategy : 指定最多保存的文件个数 注意filePattern中配置的文件重命名规则是${ROLL_FILE_NAME}_%d{yyyy-MM-dd}_%i,最小的时间粒度是dd,即天, TimeBasedTriggeringPolicy指定的size是1,结合起来就是每1天生成一个新文件 --> <RollingFile name="RollingFile" fileName="${LOG_HOME}/${ROLL_FILE_NAME}.log" filePattern="${LOG_HOME}/${ROLL_FILE_NAME}_%d{yyyy-MM-dd}_%i.log"> <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" /> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="false" /> <SizeBasedTriggeringPolicy size="1 MB" /> </Policies> <DefaultRolloverStrategy max="100"/> </RollingFile> <!--配置异步写日志--> <Async name="Async"> <AppenderRef ref="ALL"/> </Async> <!--输出到MongoDB中--> <NoSql name="databaseAppender"> <MongoDb databaseName="test" collectionName="errorlog" server="localhost" port="27017" /> </NoSql> </appenders> <loggers> <logger name="STDOUT"> <appender-ref ref="STDOUT"/> </logger> <logger name="ROLLLOG" additivity="false"> <appender-ref ref="RollingFile"/> </logger> <root level="trace"> <appender-ref ref="RollingFile"/> <appender-ref ref="ERROR" /> </root> </loggers> </configuration>
输出类型
- Appender 设置在哪输出日志信息
- FileAppender 普通地输出到本地文件
- FlumeAppender 将几个不同源的日志汇集、集中到一处。
- JMSQueueAppender VS. JMSTopicAppender 与JMS相关的日志输出
- RewriteAppender 对日志事件进行掩码或注入信息
- RollingFileAppender 对日志文件进行封存(详细)
- RoutingAppender 在输出地之间进行筛选路由
- SMTPAppender 将LogEvent发送到指定邮件列表
- SocketAppender 将LogEvent以普通格式发送到远程主机
- SyslogAppender 将LogEvent以RFC 5424格式发送到远程主机
- AsynchAppender 将一个LogEvent异步地写入多个不同输出地
- ConsoleAppender 将LogEvent输出到命令行
- FailoverAppender 维护一个队列,系统将尝试向队列中的Appender依次输出LogEvent,直到有一个成功为止
1,Console Appender
把信息输出结果控制台。
2,File Appender
输出结果到指定文件。
3,Rolling File Appender
自动追加日志信息到文件中,直至文件达到预定的大小,然后自动重新生成另外一个文件来记录之后的日志。
日志级别
TRACE < DEBUG < INFO < WARN < ERROR < FATAL
输出信息为>=当前设置级别的信息,因此TRACE的信息是最大的。
过滤器
log4j2有多种过滤器,最简单的是Threshold过滤器,其有三个配置项
配置项 | 描述 |
level | 最低的输出日志级别 |
onMatch | ACCEPT/DENY/NEUTRAL,匹配时是否输出日志或由后面的过滤器决定 |
onMismatch | ACCEPT/DENY/NETURAL,不匹配时是否输出日志或由后面的过滤器决定 |
log4j2 logger 加载规则
- logger name 相同时,以 level 级别高的为准
- logger name=”org” 会被 name=”org.xxx” 继承,”root”默认被所有logger继承。
- logger 中的 additivity=”true” 表示子日志所获得的日志也会在父日志中出现,即使父日志的 level 远高于子日志的 level
- 当子日志 level 大于父日志时,父日志只能接收到子日志过滤后的日志
代码中使用
模板样式
可用的转换字符详解:
http://logging.apache.org/log4j/2.x/manual/layouts.html
常用的有:
转换字符 | 表示的含义 |
c | 用于输出的记录事件的类别。例如,对于类别名称”a.b.c” 模式 %c{2} 会输出 “b.c” |
C | 用于输出呼叫者发出日志请求的完全限定类名。例如,对于类名 “org.apache.xyz.SomeClass”, 模式 %C{1} 会输出 “SomeClass”. |
d | 用于输出的记录事件的日期。例如, %d{HH:mm:ss,SSS} 或 %d{dd MMM yyyy HH:mm:ss,SSS}. |
F | 用于输出被发出日志记录请求,其中的文件名 |
l | 用于将产生的日志事件调用者输出位置信息 |
L | 用于输出从被发出日志记录请求的行号 |
m | 用于输出使用日志事件相关联的应用程序提供的消息 |
M | 用于输出发出日志请求所在的方法名称 |
n | 输出平台相关的行分隔符或文字 |
p | 用于输出的记录事件的优先级 |
r | 用于输出毫秒从布局的结构经过直到创建日志记录事件的数目 |
t | 用于输出生成的日志记录事件的线程的名称 |
x | 用于与产生该日志事件的线程相关联输出的NDC(嵌套诊断上下文) |
X | 在X转换字符后面是键为的MDC。例如 X{clientIP} 将打印存储在MDC对键clientIP的信息 |
% | 文字百分号 %%将打印%标志 |