Java Project Reactor管道日志:.log()与doOn系列选型及优化方案咨询
Spring WebFlux/Reactor 管道日志怎么选?
一、两种日志方式的实际用法
1. .log() 操作符
- 省心省力,自带订阅、请求、成功、错误、取消等全生命周期日志,默认DEBUG级别。
- 适合开发调试阶段,想快速查看整个管道的流转情况,不用手写日志的时候直接加就行。
- 缺点:日志格式固定,没法自定义业务相关内容(比如你要记“找到事件XXX”这种业务信息),也没法给不同事件设置不同日志级别。
2. doOnXXX/doOnError 系列操作符
- 完全自定义,能在订阅、成功处理、出错、完成等各个阶段插入任意日志逻辑,想记录什么业务信息、用什么级别都随你。
- 适合生产环境,比如你示例里要记录找到的事件ID,用
doOnNext就刚好。 - 注意:别用
onErrorResume单纯记录错误日志——它的作用是返回替代流,记录错误用doOnError就行,不然会把上游的错误吞掉,导致问题无法排查。
二、生产环境更优的日志方案
推荐混搭+全局兜底的组合方式:
- 调试用
.log():开发时排查管道流转问题,快速加个.log()就能查看整体流程。 - 业务关键节点用
doOnXXX:只在核心步骤(比如查库、调用外部服务、核心过滤逻辑)埋点,示例如下:
return repositoryName.findById(event.eventId()) .doOnSubscribe(sub -> log.info("开始查询事件,ID: {}", event.eventId())) .filter(event -> event.completedDate() == null) .doOnNext(event -> log.debug("过滤出未完成事件: {}", event.id())) .filterWhen(event -> externalService.getEventSummary(event.getUser().userId())) .doOnNext(event -> log.info("找到符合条件的事件: {},将标记为已发现", event.id())) .doOnError(e -> log.error("处理事件ID: {}时出错", event.eventId(), e)) .doOnComplete(() -> log.info("事件处理流程完成,ID: {}", event.eventId()))
- 全局错误兜底:用
@ControllerAdvice结合WebExceptionHandler统一处理所有未捕获的错误,不用每个管道都重复写错误日志逻辑。 - 避免过度日志:只在关键节点加日志,不然日志爆炸反而会增加排查难度。
三、你的代码示例优化
你给出的代码里filterWhen的括号未闭合,同时可以补充关键节点的日志,修正后如下:
return repositoryName.findById(event.eventId()) .doOnSubscribe(sub -> log.info("查询事件,ID: {}", event.eventId())) .filter(event -> event.completedDate() == null) .doOnNext(event -> log.debug("事件[{}]未完成,进入用户摘要校验", event.id())) .filterWhen(event -> externalService.getEventSummary(event.getUser().userId()) .doOnNext(summary -> log.debug("获取用户[{}]的事件摘要成功", event.getUser().userId())) .doOnError(e -> log.error("获取用户[{}]的事件摘要失败", event.getUser().userId(), e)) ) .doOnNext(event -> log.info("事件[{}]校验通过,将标记为已发现", event.id())) .doOnError(e -> log.error("处理事件ID[{}]失败", event.eventId(), e))
这样既保留了响应式特性,又能精准记录业务关键信息,出问题时更容易定位。
内容的提问来源于stack exchange,提问作者dalmanza9119
相关产品推荐
相关产品推荐

