1、log4j2的使用
Java 中常用的日志框架:
• logback:Spring Boot 默认使用的日志框架,具有自动压缩日志、支持多样化配置、不需要重启就可以恢复 I/O 异常等特点。
• log4j2:在性能方面比 logback 更加优秀,使用上与之前版本 log4j 没什么区别(log4j基本被淘汰了,springboot高版本已经不支持log4j了),有一点区别是 log4j2 不再支持 properties 配置文件,支持 xml、json 格式的文件。
Log4j2的优势包括:
——高性能:Log4j2采用异步日志记录机制,能够提供更高的性能和吞吐量,减少对应用程序性能的影响。
——灵活配置:Log4j2支持通过配置文件或编程方式进行灵活的日志配置,可以根据需求定义不同的日志级别、输出格式、输出目标等。
——多种输出目标:Log4j2支持将日志输出到控制台、文件、数据库等多种目标,方便日志的收集和分析。
——强大的过滤和路由功能:Log4j2提供了丰富的过滤器和路由器,可以根据日志内容、级别等条件对日志进行过滤和路由,实现灵活的日志处理。
——插件化架构:Log4j2采用插件化架构,支持自定义Appender、Layout、Filter等组件,可以根据需求扩展和定制日志功能。
——在使用Log4j2时,可以结合Spring框架的特性,如AOP(面向切面编程)和依赖注入,实现更加灵活和便捷的日志记录和管理。
下面来看一下 log4j2 的具体使用:
(1)log4j2 的依赖
以 springboot 中的使用为例,需要加入以下依赖:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- 去掉logback配置 --> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <!-- 引入log4j2依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> </dependencies>
(2)log4j2 的使用
通过 LogManager.getLogger() 方法,可以获取一个用于记录日志的Logger对象,LogManager.getLogger() 接受一个参数,类的 class 对象或类名称。
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; //使用方式 private static Logger logger = LogManager.getLogger(this.getClass()); private static Logger logger = LogManager.getLogger("xxxxx"); logger.info("this is info"); logger.debug("this is debug");
(3)log4j2 日志级别
Log4j2 支持多种日志级别,包括:
• TRACE:这是最低的日志级别,通常用于跟踪详细的调试信息。
• DEBUG:用于调试目的,输出一些有用的信息,帮助开发人员了解程序的运行情况。
• INFO:用于记录程序运行的重要信息,通常用于了解程序的整体运行情况。
• WARN:用于记录可能导致问题的警告信息。虽然这些信息不会导致程序立即崩溃,但可能需要关注和解决。
• ERROR:用于记录程序运行时发生的错误信息。这些信息通常需要立即关注并解决,以防止程序崩溃或数据丢失。
• FATAL:这是能输出的最高日志级别,通常用于记录严重的错误或异常情况,这些情况可能导致程序无法继续运行。
• OFF:关闭所有日志输出。
Log4j2 还支持自定义日志级别,可以根据实际需求进行配置。通过配置 Log4j2,可以控制不同级别日志的输出格式、输出位置(如控制台、文件、数据库等)以及过滤条件等。
(4)log4j2 的配置
下面是一个 log4j2.xml 配置文件的示例,一般在项目资源目录(如 src/main/resources/log4j2.xml)中,当项目打包成 JAR 或 WAR 文件时,这个配置文件会被自动包含进去。
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="debug" strict="true" name="antiAdminLog4jConfig" packages="com.coohua.mall"> <Properties> <Property name="rootPath">${logRootPath}</Property> <Property name="sysLogFilePath">${rootPath}/sys.log</Property> <Property name="logLevel">${logLevel}</Property> <Property name="isBufferedIO">true</Property> <Property name="isImmediateFlush">true</Property> <Property name="isIgnoreExceptions">false</Property> <Property name="bufferSize">8192</Property> <Property name="encodingType">UTF-8</Property> </Properties> <Appenders>
<!-- 控制台输出 --> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%d[%p]%C{1}.%M(%L)|%m%n"/> </Console> <!-- 文件输出,输出到指定的文件 --> <RollingRandomAccessFile name="sysLogAppender" fileName="${sysLogFilePath}" filePattern="${sysLogFilePath}.%d{yyyyMMdd}.%i.log" immediateFlush="${isImmediateFlush}" ignoreExceptions="${isIgnoreExceptions}" bufferSize="${bufferSize}"> <PatternLayout> <Pattern>%d[%p]%C{1}.%M(%L)|%m%n</Pattern> <charset>${encodingType}</charset> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="250 MB" /> </Policies> <DefaultRolloverStrategy> <Delete basePath="${rootPath}" maxDepth="1"> <IfFileName glob="*.log" /> <IfLastModified age="30d" /> </Delete> </DefaultRolloverStrategy> </RollingRandomAccessFile> <Async name="asyncSysLogAppender"> <AppenderRef ref="sysLogAppender"></AppenderRef> </Async> </Appenders> <Loggers> <Root level="${logLevel}"> <AppenderRef ref="STDOUT"/> </Root> <Logger name="sysLogger" level="warn" additivity="false"> <AppenderRef ref="sysLogAppender"></AppenderRef> </Logger> <Logger name="errorLogger" level="${logLevel}" additivity="false"> <AppenderRef ref="errorLogAppender"></AppenderRef> </Logger> </Loggers> </Configuration>
配置文件说明:
• Configuration:配置文件的根元素,其中 status
属性可以设置为 "DEBUG", "INFO", "WARN", "ERROR", 或 "FATAL",用于控制 Log4j2 的内部日志级别。
• Appenders:定义了日志的输出位置和格式。在这个例子中,我们定义了一个控制台输出和一个文件输出。
• Console:定义了控制台输出的格式和目标(这里是 SYSTEM_OUT
,即标准输出)。
• RollingRandomAccessFile:定义了文件输出的格式和策略。这里使用了时间与大小两种触发策略,当文件达到指定大小或时间时,会自动滚动生成新的日志文件。filePattern
定义了滚动后的文件名格式。DefaultRolloverStrategy
定义了保留的历史文件30天。
• Loggers:定义了日志记录器,可以设置全局的日志级别和输出目标,也可以为特定的包或类设置自定义的日志级别和输出目标。在这个例子中,我们定义了一个根记录器(Root logger)和一个针对特定包的记录器。
配置详解:
<Appenders> 可以理解成管道,日志文件通过不同管道输出到不同的文件中。它支持多种日志输出策略,包括滚动文件(RollingFile)和随机访问滚动文件(RollingRandomAccessFile)。
RollingRandomAccessFile
通常用于需要随机访问日志文件的场景,比如需要快速查找日志中的特定事件。 可以配置多种策略:
• fileName
属性定义了日志文件的初始名称。
• filePattern
定义了滚动后的日志文件名称模式,包括日期和时间戳,以及文件扩展名。
• <PatternLayout>
定义了日志输出的格式。
• <Policies>
以控制日志何时(When)进行滚动。所谓「日志滚动」就是当达到设定的条件后,日志文件进行切分(即重命名原日志文件用于备份,并重新生成一个新的日志文件)
Policy常用的实现类:
——SizeBasedTriggeringPolicy
,根据日志文件的大小进行滚动。单位有:KB
,MB
,GB
——
CronTriggeringPolicy
,使用 Cron 表达式进行日志滚动,很灵活
——TimeBasedTriggeringPolicy
,这个配置需要和 filePattern
结合使用,注意 filePattern
中配置的文件重命名规则。滚动策略依赖于 filePattern
中配置的最具体的时间单位,根据最具体的时间单位进行滚动。这种方式比较简洁。CronTriggeringPolicy
策略更强大。
• <Strategy>
以控制日志如何(How)进行滚动。
Strategy常用的实现类:
——DefaultRolloverStrategy
——DirectWriteRolloverStrategy
ImmediateFlush=true
,一旦有新日志写入,立马将日志写入到磁盘的文件中。当日志很多,这种频繁操作文件显然性能很低下immediateFlush
:log4j2 接收到日志事件时,是否立即将日志刷到磁盘。默认为 true。- BufferedIO: 文件流写出是否使用缓冲,true 表示使用,默认值为 false 即不使用缓冲。测试显示,即使在启用immediateFlush 的情况下,设置
bufferedIO=true
也能提高性能。
注意点:多个 RollingRandomAccessFile 不能指向同一个日志文件,否则会报错:Configuration has multiple incompatible Appenders pointing to the same resource 'logs/mybatis-demo-warn.log'
2、slf4j 框架
slf4j 不是真正的日志框架,它是对所有日志框架制定的一种规范、标准、接口,并不是一个框架的具体的实现,因为接口并不能独立使用,需要和具体的日志框架实现配合使用。可以在软件部署的时候决定要使用的 Logging 框架,目前主要支援的有 Java logging API、log4j 及 logback 等框架。
《阿里巴巴Java开发手册》,其中有一条规范做了「强制」要求:
应用中不可直接使用日志系统(Log4j Logback)中的 API,而应依赖使用日志框架 SLF4J 中的 API,使用日志门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
基于 slf4j 框架的使用:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; // 这了两种写法都 OK,推荐第一种,不用每次都要修改类名 private static final Logger logger = LoggerFactory.getLogger(this.getClass()); private static final Logger logger = LogManager.getLogger(UserController.class); //... logger.debug("this is debug"); logger.info("this is info");
可以看出之前 log4j2 的使用是在代码中通过 LogManager.getLogger(this.getClass()) 获取 Logger,但是使用了slf4j 框架后,再将 log4j2 改为 logback 就无需改动代码了,只需改动相应的配置即可切换项目的日志框架,这也是适配器模式的一个使用场景。
使用lombok输出日志
每次都使⽤ LoggerFactory.getLogger(xxx.class) 很繁琐,且每个类都添加⼀遍,也很麻烦,可以使⽤ lombok 来更简单的输出。
(1)添加 lombok 依赖
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
(2)使用 lombok 输出日志
import lombok.extern.slf4j.Slf4j; @Slf4j public class UserService { private void shareUrl(){ //使用 log log.info("lombok log"); } }
注意:使⽤ @Slf4j 注解,在程序中使⽤ log 对象即可输⼊⽇志, 并且只能使⽤ log 对象才能输出,这是 lombok 提供的对象名。
(3)lombok 打印日志原理
lombok 能够打印⽇志的“秘密”就在 target ⽬录⾥⾯,target 为项⽬最终执⾏的代码,查看 target ⽬录如下:
也就是说我们在使用@Slf4j的注解后,lombok自动将注解转换成代码,减轻了开发者简单繁琐的工作。
3、阿里云日志服务SLS
使用Loghub Log4j Appender,可以控制日志的输出目的地为阿里云日志服务,有一点需要特别注意,Loghub Log4j Appender不支持设置日志的输出格式,写到日志服务中的日志的样式如下:
level:ERROR location:test.TestLog4jAppender.main(TestLog4jAppender.java:18) message:test log4j appender thread:main time:2016-05-27T03:15+0000
level是日志级别,location是日志打印语句的代码位置,message是日志内容,thread是线程名称,time是日志打印时间。
(1)使用Loghub Log4j Appender的好处
• 客户端日志不落盘:既数据生产后直接通过网络发往服务端。
• 对于已经使用log4j记录日志的应用,只需要简单修改配置文件就可以将日志传输到日志服务。
• 异步高吞吐,Loghub Log4j Appender会将用户的日志merge之后异步发送,提高网络IO效率。
(2)接入阿里云日志服务
step1 引入依赖:
<dependency> <groupId>com.aliyun.openservices</groupId> <artifactId>log-loghub-log4j-appender</artifactId> <version>0.1.3</version> </dependency>
step2 配置 log4j2.xml 文件:
<?xml version="1.0" encoding="UTF-8"?> <appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="${PATTERN}"/> </Console> <Loghub name="traceLogHubAppender" project="service-log4j2" logStore="pro" endpoint="cn-beijing-intranet.log.aliyuncs.com" accessKeyId="*******************" accessKeySecret="******************" totalSizeInBytes="104857600" maxBlockMs="60000" ioThreadCount="1" batchSizeThresholdInBytes="524288" batchCountThreshold="4096" lingerMs="2000" retries="10" baseRetryBackoffMs="100" maxRetryBackoffMs="100" topic="trace" source="bp-user-info" timeFormat="yyyy-MM-dd'T'HH:mmZ" timeZone="UTC" ignoreExceptions="true"> <PatternLayout pattern="%d %-5level [%thread] %logger{0}: %msg"/> </Loghub> </appenders> <loggers> <ROOT level="${OUTPUT_LOG_LEVEL}" additivity="true"> <AppenderRef ref="traceLogHubAppender"/> </ROOT> </loggers>
开通阿里云日志服务后,获取用于接入日志服务的凭证信息,包括Endpoint、ProjectName、AccessKeyId和AccessKeySecret。
(3)使用阿里云日志服务
阿里云日志可以根据特定语法很方便的查询日志,语法类似 SQL 语句,还可以配置日志告警等,使用起来很方便。
标签:输出,文件,SLS,slf4j,使用,日志,log4j2,lombok From: https://www.cnblogs.com/jing-yi/p/18139650