Open techiall opened 4 years ago
生产环境上出现了问题,但线上日志的等级一般是 INFO ,错误日志没有打印出来。
INFO
不知道内部是怎么调用的,这个时候,怎么办?
发个版本,把所有函数的入口加上日志,返回值也打印出来。
发布后,让测试再次测试,打开日志,发现问题,改完重新发布 ……
日志统一打印怎么解决,不可能要求项目里面所有人都在在函数的输入和返回值打印出来结果,怎么办?利用 Spring Aspect 即可。
先添加 Spring Aop 依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
假设我们的包为 top.techial.knowledge,
top.techial.knowledge
我们需要查看这个包下加了 @Repository,@Service 和 @RestController 注解的类内函数 参数 和 返回值 。
@Repository
@Service
@RestController
参数
返回值
使用 @Around("applicationPackagePointcut() && springBeanPointcut()") 进行环绕。
@Around("applicationPackagePointcut() && springBeanPointcut()")
@Log4j2 是 lombok 中的一个注解。
@Log4j2
设置打印出来参数的日志等级为 DEBUG。
DEBUG
import lombok.extern.log4j.Log4j2; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import java.util.Arrays; @Aspect @Log4j2 @Component public class LoggingAspect { @Pointcut("within(@org.springframework.stereotype.Repository *)" + " || within(@org.springframework.stereotype.Service *)" + " || within(@org.springframework.web.bind.annotation.RestController *)") public void springBeanPointcut() { } @Pointcut("within(top.techial.knowledge..*)") public void applicationPackagePointcut() { } @AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e") public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { if (log.isErrorEnabled()) { log.error( "Exception in {}.{}() with cause = '{}' and exception = '{}'", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), e.getCause() != null ? e.getCause() : "NULL", e.getMessage(), e ); } } @Around("applicationPackagePointcut() && springBeanPointcut()") public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { if (log.isDebugEnabled()) { log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs())); } try { Object result = joinPoint.proceed(); if (log.isDebugEnabled()) { log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), result); } return result; } catch (IllegalArgumentException e) { if (log.isErrorEnabled()) { log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()); } throw e; } } }
有了这个 日志切面,我们再配合 Spring Actuator,actuator 可以在不重启的情况下修改日志的等级。
依赖如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
application.yml 添加如下配置:
# spring actuator management: server: port: 8080 endpoint: health: show-details: always endpoints: enabled-by-default: true web: base-path: /actuator exposure: include: - loggers - health - info
我们就可以通过发送请求 查看 / 修改 日志输出等级,以 curl 为例,其他的以此类推。
curl
查看某个包的日志等级,包以 top.techial.knowledge 为例。
# curl http://localhost:8080/actuator/loggers/{package} curl http://localhost:8080/actuator/loggers/top.techial.knowledge
修改某个包的日志等级,修改成 DEBUG 等级。包以 top.techial.knowledge 为例。
# curl -X POST http://localhost:8080/actuator/loggers/{package} \ # -H "Content-Type: application/json" \ # --data '{"configuredLevel":"{level}"}' curl -X POST http://localhost:8080/actuator/loggers/top.techial.knowledge \ -H "Content-Type: application/json" \ --data '{"configuredLevel":"debug"}
再也不用线上出问题,打包加日志!!!
真香。
其实有更香的东西,推荐 https://alibaba.github.io/arthas/
背景
生产环境上出现了问题,但线上日志的等级一般是
INFO
,错误日志没有打印出来。不知道内部是怎么调用的,这个时候,怎么办?
发个版本,把所有函数的入口加上日志,返回值也打印出来。
发布后,让测试再次测试,打开日志,发现问题,改完重新发布 ……
日志统一打印怎么解决,不可能要求项目里面所有人都在在函数的输入和返回值打印出来结果,怎么办?利用 Spring Aspect 即可。
依赖
先添加 Spring Aop 依赖。
代码
假设我们的包为
top.techial.knowledge
,我们需要查看这个包下加了
@Repository
,@Service
和@RestController
注解的类内函数参数
和返回值
。使用
@Around("applicationPackagePointcut() && springBeanPointcut()")
进行环绕。@Log4j2
是 lombok 中的一个注解。设置打印出来参数的日志等级为
DEBUG
。线上错误定位
有了这个 日志切面,我们再配合 Spring Actuator,actuator 可以在不重启的情况下修改日志的等级。
依赖如下:
application.yml 添加如下配置:
我们就可以通过发送请求 查看 / 修改 日志输出等级,以
curl
为例,其他的以此类推。查看某个包的日志等级,包以
top.techial.knowledge
为例。修改某个包的日志等级,修改成
DEBUG
等级。包以top.techial.knowledge
为例。再也不用线上出问题,打包加日志!!!
真香。