有勇气的牛排博客

SpringBoot (七) 日志管理logback、log4j、AOP统一web 请求日志

有勇气的牛排 653 Java 2023-02-25 19:27:55

文章目录

前言

1 日志级别

哈喽,大家好,我是[有勇气的牛排](全网同名)🐮🐮🐮

有问题的小伙伴欢迎在文末[评论,点赞、收藏]是对我最大的支持!!!。

官网:https://www.couragesteak.com/

ALL 最低等级的,用于打开所有日志记录。

TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。

DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。

INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。

WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示

ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。

FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。

OFF 最高等级的,用于关闭所有日志记录。

2 使用logback记录日志

2.1 Maven依赖

<!--SpringBoot热部署配置 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>

2.2 application.yml

server: port: 8080 # 指定读取logback配置文件 logging: config: classpath:log/logback.xml

2.3 logback.xml配置文件

/resources/logback.xml

<configuration> <!--本文主要输出日志为控制台日志,系统日志,sql日志,异常日志--> <!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,,,, --> <!--控制台--> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d %p (%file:%line\)- %m%n</pattern> <charset>UTF-8</charset> </encoder> </appender> <!--系统info级别日志--> <!--<File> 日志目录,没有会自动创建--> <!--<rollingPolicy>日志策略,每天简历一个日志文件,或者当天日志文件超过64MB时--> <!--encoder 日志编码及输出格式--> <appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>log/file/fileLog.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>log/file/fileLog.log.%d.%i</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- or whenever the file size reaches 64 MB --> <maxFileSize>64 MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern> %d %p (%file:%line\)- %m%n </pattern> <charset>UTF-8</charset> <!-- 此处设置字符集 --> </encoder> </appender> <!--sql日志--> <appender name="sqlFile" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>log/sql/sqlFile.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>log/sql/sqlFile.log.%d.%i</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- or whenever the file size reaches 64 MB --> <maxFileSize>64 MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <!--对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。--> <encoder> <!--用来设置日志的输入格式--> <pattern> %d %p (%file:%line\)- %m%n </pattern> <charset>UTF-8</charset> <!-- 此处设置字符集 --> </encoder> </appender> <!--异常日志--> <appender name="errorFile" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>log/error/errorFile.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>log/error/errorFile.%d.log.%i</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- or whenever the file size reaches 64 MB --> <maxFileSize>64 MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <!--对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。--> <encoder> <!--用来设置日志的输入格式--> <pattern> %d %p (%file:%line\)- %m%n </pattern> <charset>UTF-8</charset> <!-- 此处设置字符集 --> </encoder> <!-- 日志都在这里 过滤出 error 使用 try {}catch (Exception e){} 的话异常无法写入日志,可以在catch里用logger.error()方法手动写入日志 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 日志输出级别 --> <!--All\DEBUG\INFO\WARN\ERROR\FATAL\OFF--> <!--打印info级别日志,分别在控制台,fileLog,errorFile输出 异常日志在上面由过滤器过滤出ERROR日志打印 --> <root level="INFO"> <appender-ref ref="fileLog" /> <appender-ref ref="console" /> <appender-ref ref="errorFile" /> </root> <!--打印sql至sqlFile文件日志--> <logger name="com.dolphin.mapper" level="DEBUG" additivity="false"> <appender-ref ref="console" /> <appender-ref ref="sqlFile" /> </logger> </configuration>

2.4 Java后端

/* * @Author : 有勇气的牛排 * @FileName: MyIndex.java * desc : * */ package com.couragesteak.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.logging.Logger; @RestController @Slf4j public class MyIndex { // private static Logger log = Logger.getLogger(MyIndex.class); // http://127.0.0.1:8080/getInfo?name=cs&age=22 @RequestMapping("/getInfo") public String getInfo(String name, int age) { log.info("==============="); log.info("name: {}, age: {}", name, age); return name; } }

2.5 lombok

如果idea没有状lombok插件,则需要再类中添加如下代码,才能使用此日志功能。

private static Logger log = Logger.getLogger(String.valueOf(MyIndex.class));

image.png

3 使用 log4j 记录日志

机制:如果一条日志信息的级别 >= 配置文件的级别,就记录。

trace:追踪,就是程序推进一下,可以写个trace输出
debug:调试,一般作为最低级别,trace基本不用。
info:输出重要的信息,使用较多
warn:警告,有些信息不是错误信息,但也要给程序员一些提示。
error:错误信息。用的也很多。
fatal:致命错误。
输出源
CONSOLE(输出到控制台)
FILE(输出到文件)
格式
SimpleLayout:以简单的形式显示
HTMLLayout:以HTML表格显示
PatternLayout:自定义形式显示

3.1 log4j 配置文件

log4j.properties

#log4j.rootLogger=CONSOLE,info,error,DEBUG log4j.rootLogger=DEBUG,error,CONSOLE,info log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.logger.info=info log4j.appender.info=org.apache.log4j.DailyRollingFileAppender log4j.appender.info.layout=org.apache.log4j.PatternLayout log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.info.datePattern='.'yyyy-MM-dd log4j.appender.info.Threshold = info log4j.appender.info.append=true log4j.appender.info.File=E:/code/log/info.log log4j.logger.error=error log4j.appender.error=org.apache.log4j.DailyRollingFileAppender log4j.appender.error.layout=org.apache.log4j.PatternLayout log4j.appender.error.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.error.datePattern='.'yyyy-MM-dd log4j.appender.error.Threshold = error log4j.appender.error.append=true log4j.appender.error.File=E:/code/log/error.log log4j.logger.DEBUG=DEBUG log4j.appender.DEBUG=org.apache.log4j.DailyRollingFileAppender log4j.appender.DEBUG.layout=org.apache.log4j.PatternLayout log4j.appender.DEBUG.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.DEBUG.datePattern='.'yyyy-MM-dd log4j.appender.DEBUG.Threshold = DEBUG log4j.appender.DEBUG.append=true log4j.appender.DEBUG.File=E:/code/log/dubug.log

3.2 Maven依赖

<!-- spring boot start --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <!-- 排除自带的logback依赖 --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!-- springboot-log4j --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j</artifactId> <version>1.3.8.RELEASE</version> </dependency>

3.3 application.yml

server: port: 8083 logging: # 指定log4j.properties配置文件路径 config: classpath:log4j.properties

3.4 Java

private static final Logger log = Logger.getLogger(String.valueOf(MyIndex.class));

4 使用AOP统一处理 web 请求日志

在方法前后实现拦截,减少代码打印日志代码冗余。

4.1 Maven依赖

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>

4.2 拦截日志类WebLogAspect.java

/* * @Author : 有勇气的牛排 * @FileName: WebLogAspect.java * desc : * */ package com.couragesteak.aop; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; /** * 定义一个切面,拦截包 */ @Aspect @Component @Slf4j public class WebLogAspect { // private static final log logger = logFactory.getlog(WebLogAspect.class); /** * com.couragesteak.controller下所有类 * *:所有方法 * (..): 所有参数 */ @Pointcut("execution(public * com.couragesteak.controller.*.*(..))") public void webLog() { } /** * 前置通知:请求前拦截 */ @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { // 接收到请求,记录请求内容 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 记录下请求内容 log.info("URL : " + request.getRequestURL().toString()); log.info("HTTP_METHOD : " + request.getMethod()); log.info("IP : " + request.getRemoteAddr()); Enumeration<String> enu = request.getParameterNames(); while (enu.hasMoreElements()) { String name = (String) enu.nextElement(); log.info("name:{},value:{}", name, request.getParameter(name)); } } /** * 打印目标方法响应信息 * */ @AfterReturning(returning = "ret", pointcut = "webLog()") public void doAfterReturning(Object ret) throws Throwable { // 处理完请求,返回内容 log.info("RESPONSE : " + ret); } }

image.png

原文地址:https://www.couragesteak.com/article/293


留言

专栏
文章
加入群聊