介绍
日志概念
日志是系统生成的数据,用于记录网络、端点、物联网、应用程序、操作系统等,在运行时所发生事件的信息,便于开发人员或维护人员进行故障排查、性能优化、安全审计等工作。
日志作用
问题追踪及调试:当程序出现问题时,可以通过查看日志定位问题、辅助排查问题。
监控运行状态:通过日志查看分析程序运行状态。
安全审计:在需要记录用户行为、系统操作的场合,日志可以作为审计的依据。
常见日志框架
日志框架主要可分为日志门面、日志实现。
日志门面
日志门面定义了一组日志接口规范,并不提供底层的具体实现逻辑。
门面模式(外观模式):Facade Pattern,设计模式中的一种,核心思想是外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用。
门面模式体现了Java中的封装特性,对外的接口要尽可能的简单易用。
常见的日志门面框架:JCL、Slf4j
JCL:Jakarta Commons Logging,是Apache提供的一个通用日志API。
Slf4j:Simple Logging Facade For Java,简单日志门面,主要为了给Java日志访问提供一套标准、规范的API框架。提供了一套接口,具体的实现交由其他日志框架(如:log4j、logback、log4j2等)。(https://www.slf4j.org/)
日志实现
日志实现是日志具体的实现,包括级别控制、打印格式、输出形式(输出到数据库、文件、控制台等)。
常见的日志实现框架:JUL、Log4j、Log4j2、Logback
JUL:Java Util Logging,Java原生日志框架,功能相对简单,性能一般。
Log4j:Log For Java,是Apache的开源项目,一个老牌的日志框架,功能强大。随着时间的推移,Log4j 逐渐被新开发的 Log4j2 所取代,如果是旧项目使用 Log4j 运行良好,无特殊需求无需迁移到 Log4j2。
Log4j2:由Apache开发的一套日志框架,相比于 Log4j,Log4j2 在性能上有显著提升,同时保持了丰富的功能,支持异步日志处理,适合高性能的需求场景。Log4j2提供了对Slf4j日志门面的桥接支持,因此被视为Slf4j的具体实现。
Logback:是 Log4j 创始人开发的一套新的日志框架,Spring Boot 的默认日志框架,有轻量级、性能优秀、功能齐全等优点。
官网
log4j2(https://logging.apache.org/log4j/2.x/)
参考链接
超详细的log4j2配置说明(https://zhuanlan.zhihu.com/p/701595014)
log4j properties配置实例 log4j2 配置详解properties(https://blog.51cto.com/u_16213708/10654195)
需求
将程序运行时的日志保存到磁盘中,并每日或是超出配置的最大日志文件大小时,进行文件切分,归档入当天的目录中。
log4j2 配置使用详情
yml
Configuration:配置文件的根标签
name:日志配置的名称
status:日志打印级别(trace,debug,info,warn,error,fatal)
monitorInterval:配置该参数,项目运行时,会按照参数配置定期扫描日志配置,动态改变日志的配置。单位为秒。
Properties:定义全局变量
Property:单个变量
Appenders:日志输出位置(常见的有ConsoleAppender,FileAppender,AsyncAppender)
Console:输出到控制台
ThresholdFilter:过滤器(用于判断该appender用于处理何种日志事件)
level: 控制台只输出level及以上级别的日志信息
onMatch:#过滤器匹配时要采取的操作。可以是ACCEPT(接受)、DENY(拒绝)、NEUTRAL(中立。可以让日志经过后续的过滤器),默认是 NEUTRAL。
onMismatch:#当过滤器不匹配时要采取的操作。可以是ACCEPT、DENY、NEUTRAL,默认是DENY。
ignoreExceptions:在输出日志时,是否忽略异常,默认是true
PatternLayout:布局策略
charset:编码方式
pattern: 指定日志输出的具体格式
%c{x} Logger的名称,x 为精度说明符。说明符由十进制整数或以十进制整数开头的模式组成。
当精度说明符为整数值时,它将减小 Logger 名称的大小。如果数字为正,则布局将打印相应数量的最右边 Logger 名称组件。如果为负,则布局将删除相应数量的最左边的 Logger 名称组件。
如果精度包含任何非整数字符,则布局会根据模式缩写名称。如果精度整数小于 1,则布局仍将完整打印最右边的标记。默认情况下,布局将完整打印 Logger 名称。
org.apache.commons.Foo
%c{1} -> Foo
%c{2} -> commons.Foo
%c{10} -> org.apache.commons.Foo
%c{-1} -> apache.commons.Foo
%c{-2} -> commons.Foo
%c{-10} -> org.apache.commons.Foo
%c{1.} -> o.a.c.Foo
%c{.} -> ...Foo
%C{x} 调用者的完全限定类名, x 为精度说明符.生成调用方的类名(location information)是一项昂贵的操作,可能会影响性能。请谨慎使用
%d{x} 日期,x为日期格式
%enc{pattern}{HTML/JSON/XML} 转义特定标记语言的特殊字符
%ex 输出绑定到日志记录事件的 Throwable 跟踪,默认情况下,它将输出完整调用链
%exception
%throwable
%throwable{short} 输出异常的第一行
%throwable{short.className} 输出发生异常的类的名称
%throwable{short.methodName} 输出发生异常的方法名称
%throwable{short.lineNumber} 输出发生异常的行号
%throwable{short.message} 输出输出消息
%throwable{n} 输出堆栈跟踪的前 n 行
%throwable{none} 禁止输出异常
%throwable{0} 禁止输出异常
%f 记录日志的文件名
%highlight 突出显示,根据当前事件的日志记录级别,将ANSI颜色添加到模式的结果中
%l 类的全路径和调用处的行号
%L 行号
%m 日志内容
%M 打印该条日志的方法名
%n 换行
%N 当前时间的毫微秒。如同调用:System.nanotime()
%pid 应用的进程ID
%r 输出自应用启动到输出该log信息耗费的毫秒数
%p 日志级别
%T 线程ID
%t 线程名称
%sn 日志调用的次数
%X 按MDC(Mapped Diagnostic Context 线程映射表)输出日志. ThreadContext
%X{key} 输出指定key
%x 按NDC(Nested Diagnostic Context 线程堆栈)输出日志
RollingFile:日志持久化
name:appender的名称
fileName:输出的文件名
ignoreExceptions:在输出日志时,是否忽略异常,默认是true
filePattern:日志文件归档后的名称格式
Policies:指定滚动日志的策略。即何时进行归档、新建新日志文件操作的时间。
TimeBasedTriggeringPolicy:基于时间的滚动策略
interval:时间间隔,默认1h。
modulate:是否调制时间,如果值是true,interval为5,当前时间是10am,下次滚动的时间就是
SizeBasedTriggeringPolicy:基于文件大小的滚动策略
size:#单个日志文件最大容量,超过后将归档
DefaultRolloverStrategy:配置日志的文件个数上限,默认为7,超过会覆盖前面的文件
max:filePattern中-%i的最大值
Loggers:全局配置,默认所有的Logger都继承此配置
用来配置LoggerConfig,包含一个root logger和若干个普通logger。
additivity指定是否同时输出log到父类的appender,缺省为true。
一个Logger可以绑定多个不同的Appender。只有定义了logger并引入的appender,appender才会生效。
Root: 用于配置默认的日志事件打印
level: 指定默认的日志打印级别
RegexFilter:日志过滤器
AppenderRef:要异步调用的 Appender 的名称。可以配置多个 AppenderRef 元素。
includeLocation:如果使用<asyncRoot> 或 <asyncLogger>,includeLocation="true"是必须要设置才会有类路径等一些信息打印出来
AsyncLogger:官方推荐的异步方式。
异步日志有两种选择:全局异步和混合异步。
效果图
配置的最大文件大小为30M,每30M切分成一个文件,切分的文件归档进按日期分类的目录中。
过了凌晨0点,归档前一天的日志进前一天的目录中,新建一个新的日志文件存放当天的日志信息。
依赖
pom.xml
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<!-- 去掉SpringBoot默认的Logback配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- 加上这个才能辨认到log4j2.yml文件 -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
配置文件
application.yml
yml
logging:
config: classpath:log4j2.yml
level:
com.lm.system.mapper: debug
log4j2.yml
yml
Configuration:
status: debug #日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL
monitorInterval: 30 #Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数
Properties: #定义全局变量
Property:
- name: log.level.console
value: info
- name: log.path
value: ${sys:catalina.home:-.}/logs/${project.name} #加上 :-. 兼容Windows系统
- name: project.name
value: system
- name: info.file.name
value: info
- name: error.file.name
value: error
- name: level.info.file.name
value: info
- name: level.error.file.name
value: error
Appenders: #日志输出位置
Console: #输出到控制台
name: CONSOLE
target: SYSTEM_OUT
ThresholdFilter: #过滤器,控制台只输出level及以上级别的日志信息
level: ${sys:log.level.console} #sys:表示如果VM参数中没指定这个变量值,则使用本文件中定义的缺省全局变量值
onMatch: ACCEPT #过滤器匹配时要采取的操作。可以是ACCEPT(接受)、DENY(拒绝)、NEUTRAL(中立。可以让日志经过后续的过滤器),默认是 NEUTRAL。
onMismatch: DENY #当过滤器不匹配时要采取的操作。可以是ACCEPT、DENY、NEUTRAL,默认是DENY。
PatternLayout: #布局策略
pattern: "%clr{%d{yyyy-MM-dd HH:mm:ss}}{blue} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{%l}{cyan} %clr{:}{faint} %m%n %xwEx"
RollingFile: #日志持久化
- name: ${info.file.name}
fileName: ${log.path}/${info.file.name}.log #日志保存时的名称
ignoreExceptions: false #在输出日志时,是否忽略异常,默认是true
filePattern: "${log.path}/$${date:yyyy-MM-dd}/${info.file.name}-%d{yyyy-MM-dd}-%i.log" #日志文件归档后的名称格式
PatternLayout:
pattern: "%d{yyyy-MM-dd HH:mm}:%4p %t (%F:%L) - %m%n"
Filters:
ThresholdFilter: #注意顺序
- level: error
onMatch: DENY
onMismatch: NEUTRAL
- level: ${level.info.file.name}
onMatch: ACCEPT
onMismatch: DENY
Policies: #指定滚动日志的策略。即何时进行归档、新建新日志文件操作的时间。
#一天一存,即使文件不满足30MB
TimeBasedTriggeringPolicy: #基于时间的滚动策略
interval: "1" #时间间隔,默认1h
modulate: "true" #是否调制时间
SizeBasedTriggeringPolicy: #基于文件大小的滚动策略
size: "30 MB" #单个日志文件最大30MB,超过后将归档
DefaultRolloverStrategy: #配置日志的文件个数上限,默认为7
max: 100 #filePattern中-%i的最大值
- name: ${error.file.name}
ignoreExceptions: false
fileName: ${log.path}/${error.file.name}.log
filePattern: "${log.path}/$${date:yyyy-MM-dd}/${error.file.name}-%d{yyyy-MM-dd}-%i.log"
PatternLayout:
pattern: "%d{yyyy-MM-dd HH:mm}:%4p %t (%F:%L) - %m%n"
Filters:
ThresholdFilter:
- level: ${level.error.file.name}
onMatch: ACCEPT
onMismatch: DENY
Policies:
TimeBasedTriggeringPolicy:
interval: "1"
modulate: "true"
Loggers: #全局配置,默认所有的Logger都继承此配置
Root:
level: debug
AppenderRef:
- ref: CONSOLE
- ref: ${info.file.name}
- ref: ${error.file.name}
Logger:
- name: com #指定具体要打印的日志的包路径
additivity: false #是否继承父记录器的appender,默认为true
level: debug
AppenderRef:
- ref: CONSOLE
- ref: ${info.file.name}
- ref: ${error.file.name}