auto-log

auto-log 是一款为 java 设计的自动日志监控框架。

前面已经写过了两篇:

java 注解结合 spring aop 实现自动输出日志

java 注解结合 spring aop 实现日志 traceId 唯一标识

经过前面2篇的代码实现,发现依然存在下列问题:

(1)注解的使用依然不够便捷。

如果每一个方法上都指定 @AutoLog,依然会比较麻烦。个人在使用的时候也不想这么麻烦。

于是想添加基于类的注解。

后期考虑是否可以基于包,动态指定 AOP 的扫描包范围。

(2)对于日志的处理过于单一。

比如我想添加所有操作的审计日志,然后存储到数据库。同时日志输出不变。

发现以前的日志框架,不能很好的支撑。于是想添加日志输出的拦截器。

(3)对于参数的过滤

以前是直接基于 toString() 实现,发现有些人比较懒不写 toString(比如我),那么参数打印的信息就没有意义。

于是替换成立 FastJSON,但是引来了新的问题,比如 HttpRequest 等参数直接序列化是会报错的,于是想添加基于参数的过滤器实现。

需求,才是最好的创作动力。

目前共计经过了 12 个版本的迭代,上面 3 个特性已经满足。

特性

  • 基于注解+字节码,配置灵活

  • 自动适配常见的日志框架

  • 支持编程式的调用

  • 支持注解式,完美整合 spring

  • 支持整合 spring-boot

  • 支持慢日志阈值指定,耗时,入参,出参,异常信息等常见属性指定

  • 支持 traceId 特性

  • 支持类级别定义注解

  • 支持自定义拦截器和过滤器

快速开始

maven 引入

  [xml]
1
2
3
4
5
<dependency> <group>com.github.houbb</group> <artifact>auto-log-core</artifact> <version>${最新版本}</version> </dependency>

入门案例

  [java]
1
2
UserService userService = AutoLogHelper.proxy(new UserServiceImpl()); userService.queryLog("1");
  • 日志如下
  [plaintext]
1
2
[INFO] [2020-05-29 16:24:06.227] [main] [c.g.h.a.l.c.s.i.AutoLogMethodInterceptor.invoke] - public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) param is [1] [INFO] [2020-05-29 16:24:06.228] [main] [c.g.h.a.l.c.s.i.AutoLogMethodInterceptor.invoke] - public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) result is result-1

代码

其中方法实现如下:

  • UserService.java
  [java]
1
2
3
4
5
public interface UserService { String queryLog(final String id); }
  • UserServiceImpl.java

直接使用注解 @AutoLog 指定需要打日志的方法即可。

  [java]
1
2
3
4
5
6
7
8
9
public class UserServiceImpl implements UserService { @Override @AutoLog public String queryLog(String id) { return "result-"+id; } }

TraceId 的例子

代码

  [java]
1
2
UserService service = AutoLogProxy.getProxy(new UserServiceImpl()); service.traceId("1");

其中 traceId 方法如下:

  [java]
1
2
3
4
5
@AutoLog @TraceId public String traceId(String id) { return id+"-1"; }

测试效果

  [plaintext]
1
2
信息: [ba7ddaded5a644e5a58fbd276b6657af] <traceId>入参: [1]. 信息: [ba7ddaded5a644e5a58fbd276b6657af] <traceId>出参:1-1.

其中 ba7ddaded5a644e5a58fbd276b6657af 就是对应的 traceId,可以贯穿整个 thread 周期,便于我们日志查看。

注解说明

@AutoLog

核心注解 @AutoLog 的属性说明如下:

属性 类型 默认值 说明
enable boolean true 是否启用
param boolean true 是否打印入参
result boolean true 是否打印出参
costTime boolean false 是否打印耗时
exception boolean true 是否打印异常
slowThresholdMills long -1 当这个值大于等于 0 时,且耗时超过配置值,会输出慢日志
description string ”” 方法描述,默认选择方法名称
interceptor Class[] 默认实现 拦截器实现,支持指定多个和自定义
paramFilter Class 入参过滤器,支持自定义

@TraceId

@TraceId 放在需要设置 traceId 的方法上,比如 Controller 层,mq 的消费者,rpc 请求的接受者等。

属性 类型 默认值 说明
id Class 默认为 uuid traceId 的实现策略
putIfAbsent boolean false 是否在当前线程没有值的时候才设置值
enable boolean true 是否启用
interceptor Class[] 默认实现 拦截器实现,支持指定多个和自定义

自定义策略

自定义日志拦截器(interceptor)

内置拦截器

AutoLogInterceptor 默认实现

定义

直接继承自 AbstractAutoLogInterceptor 类,并且实现对应的方法即可。

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MyAutoLogInterceptor extends AbstractAutoLogInterceptor { @Override protected void doBefore(AutoLog autoLog, IAutoLogInterceptorContext context) { System.out.println("自定义入参:" + Arrays.toString(context.filterParams())); } @Override protected void doAfter(AutoLog autoLog, Object result, IAutoLogInterceptorContext context) { System.out.println("自定义出参:" + result); } @Override protected void doException(AutoLog autoLog, Exception exception, IAutoLogInterceptorContext context) { System.out.println("自定义异常:"); exception.printStackTrace(); } }

使用

如下,这样日志输出,就会使用上面的指定策略。

  [java]
1
2
3
4
@AutoLog(interceptor = MyAutoLogInterceptor.class) public String my() { return "自定义策略"; }

自定义入参过滤器(paramFilter)

内置

WebParamFilter 主要用于过滤 HttpRequest HttpServlet 等无法直接 JSON 序列化的对象。

自定义

直接继承 AbstractParamFilter 类实现对应的方法即可。

  [java]
1
2
3
4
5
6
7
8
9
10
public class MyParamFilter extends AbstractParamFilter { @Override protected Object[] doFilter(Object[] params) { Object[] newParams = new Object[1]; newParams[0] = "设置我我想要的值"; return newParams; } }

使用

指定对应的参数过滤器。这样,无论入参是什么,都会变成我们指定的 [设置我我想要的值]

  [java]
1
2
3
4
@AutoLog(paramFilter = MyParamFilter.class) public String paramFilter() { return "自定义入参过滤器"; }

spring 整合使用

完整示例参考 SpringServiceTest

注解声明

使用 @EnableAutoLog 启用自动日志输出

  [java]
1
2
3
4
5
@Configurable @ComponentScan(basePackages = "com.github.houbb.auto.log.test.service") @EnableAutoLog public class SpringConfig { }

测试代码

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
@ContextConfiguration(classes = SpringConfig.class) @RunWith(SpringJUnit4ClassRunner.class) public class SpringServiceTest { @Autowired private UserService userService; @Test public void queryLogTest() { userService.queryLog("1"); } }
  • 输出结果
  [plaintext]
1
2
3
4
信息: public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) param is [1] 五月 30, 2020 12:17:51 下午 com.github.houbb.auto.log.core.support.interceptor.AutoLogMethodInterceptor info 信息: public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) result is result-1 五月 30, 2020 12:17:51 下午 org.springframework.context.support.GenericApplicationContext doClose

springboot 整合使用

maven 引入

  [xml]
1
2
3
4
5
<dependency> <groupId>com.github.houbb</groupId> <artifactId>auto-log-springboot-starter</artifactId> <version>最新版本</version> </dependency>

只需要引入 jar 即可,其他的什么都不用配置。

使用方式和 spring 一致。

测试

  [java]
1
2
3
4
5
6
7
@Autowired private UserService userService; @Test public void queryLogTest() { userService.query("spring-boot"); }

开源地址

Github: https://github.com/houbb/auto-log

Gitee: https://gitee.com/houbinbin/auto-log

Road-Map

  • 优化日志中的方法路径名称

考虑补全对应的类信息

  • 全局配置

比如全局的慢日志阈值设置等

  • jvm-sandbox 特性

  • 编译时注解特性

原文地址

java 注解结合 spring aop 自动输出日志新增拦截器与过滤器

公众号

参考资料

auto-log