@logfilter是声明式链路日志增强开关,支持路径/方法/条件类匹配、类/方法粒度控制及span/mdc上下文感知,通过可插拔logfilterevaluator引擎解耦判断逻辑,复用skywalking/sleuth上下文,并支持配置中心热更新。

要为分布式链路追踪系统开发一个通用的自定义 @LogFilter 断言,核心不是写个注解完事,而是让这个注解能在请求入口(如 Spring WebMvc 的 HandlerInterceptor 或 WebFilter)中自动识别、解析并决定是否对当前调用链路开启日志增强(如打印 traceId、入参、耗时、异常等),同时兼容不同服务的差异化过滤策略。
明确 @LogFilter 的职责边界
它不该做日志输出本身,也不该侵入业务逻辑;它的唯一职责是「声明式地表达:在什么条件下,对该请求/方法开启链路日志增强」。因此设计需包含三要素:
- 匹配目标:支持按 Controller 方法、Rest API 路径(Ant 风格或正则)、甚至自定义条件类(如 `@LogFilter(condition = AuthCheckCondition.class)`)
- 粒度控制:可作用于类(全局生效)、方法(精准控制)、或通过组合注解支持 exclude/include 白黑名单
- 上下文感知:能读取当前 span、traceId、request attributes、甚至 MDC 中的链路字段,用于动态判断(例如:仅对 error 级别 span 或 debug 模式下的请求记录详细日志)
实现可插拔的断言评估引擎
不要把判断逻辑硬编码在拦截器里。建议抽象出 LogFilterEvaluator 接口:
boolean shouldLog(HttpServletRequest request, HandlerMethod handlerMethod, Span currentSpan);
}
每个 @LogFilter 注解实例背后绑定一个 evaluator 实现(可通过 Spring 的 @ConditionalOnBean 或 SPI 自动注册)。例如:
-
PathPatternLogFilterEvaluator:解析@LogFilter(pattern = "/api/v1/order/**") -
AnnotationBasedLogFilterEvaluator:检查目标方法是否标注了@Sensitive或@Audit等业务语义注解 -
CustomConditionLogFilterEvaluator:反射调用用户传入的conditionClass().getDeclaredConstructor().newInstance().test(request, handler)
与主流链路追踪框架对齐(以 SkyWalking / Sleuth 为例)
避免重复造 span 上下文轮子。直接复用已有能力:
- 在
HandlerInterceptor.preHandle()中,通过Tracer.getCurrentSpan()(SkyWalking)或Tracing.currentTracer().currentSpan()(Sleuth)获取活跃 span - 利用
MDC.get("traceId")或SpanContext.traceId()补充日志上下文,确保 logback/log4j 输出自动携带 traceId - 若需跳过采样率限制(比如即使 trace 被采样为 false,仍想记录关键错误日志),可在 evaluator 中绕过 tracer 的 isSampled() 判断,改用自定义规则
支持运行时动态生效与配置中心联动
线上不能重启生效。推荐结合配置中心(Nacos/Apollo)实现热更新:
- 将常用 filter 规则(如“所有 /admin/** 接口默认开启 debug 日志”)定义为 YAML 配置项
- 监听配置变更,刷新内存中的
LogFilterRegistry(ConcurrentMap) - 拦截器执行时,先查 registry 获取匹配的 evaluator,再执行 shouldLog —— 这样无需改代码就能开关某类接口的日志增强











