乐于分享
好东西不私藏

在开发过程中,AI能够帮你做的几件小事 · 第五篇:日志打点——让先理解业务再给你建议

在开发过程中,AI能够帮你做的几件小事 · 第五篇:日志打点——让先理解业务再给你建议

写在开头

hi,我是可乐,今天我们来聊一聊日志

有一次线上出问题,反馈说导入了一批商品数据,系统提示成功,但页面就是搜不到。我查了半天数据库,发现一条都没进去。

我去翻日志,想看看导入过程中发生了什么,结果只找到两条:

INFO  - 开始导入INFO  - 导入完成

中间解析了多少条?校验失败了几个?入库成功了多少?一概不知。最后是把Excel文件要过来,本地跑了一遍才定位到问题——有一行的价格字段格式不对,导致整批数据回滚了。

那天我学到一个道理:日志不是打给自己看的,是打给半夜被叫起来排查问题的自己看的。

但问题来了:什么时候该打日志?打什么内容?用info还是error?这事如果直接问AI,它大概率会给你一个“看起来都对但没什么用”的答案。因为它根本不知道你这导入流程是怎么设计的。

今天聊聊正确的姿势:先让AI理解你的业务逻辑,再让它给出日志建议。

一、场景痛点:一个“哑巴”式的导入方法

假设我们做了一个商品信息的Excel导入功能。Controller接收文件,Service负责解析和入库。代码大概长这样:

@ServicepublicclassProductImportService{privatestaticfinal Logger logger = LoggerFactory.getLogger(ProductImportService.class);@Autowiredprivate ProductMapper productMapper;@TransactionalpublicvoidimportProducts(MultipartFile file){        logger.info("开始导入商品");        List<ProductExcelDTO> excelData = ExcelUtils.read(file, ProductExcelDTO.class);        List<Product> products = new ArrayList<>();for (ProductExcelDTO dto : excelData) {if (StringUtils.isBlank(dto.getName()) || dto.getPrice() == null) {continue;            }            Product p = new Product();            p.setName(dto.getName());            p.setPrice(dto.getPrice());            p.setCategory(dto.getCategory());            products.add(p);        }        productMapper.batchInsert(products);        logger.info("导入完成");    }}

这段代码的日志有什么问题?

  • 导入了多少条数据?不知道。
  • 跳过了多少条无效数据?不知道。
  • 批量插入成功了多少条?不知道。
  • 整个导入花了多长时间?没打。
  • 万一入库失败,能看到的只有异常堆栈,没有业务上下文。

排查问题的时候,你只能对着一个“导入完成”发呆——更可气的是,如果入库失败了,这条“导入完成”根本不会打印,但“开始导入”之后发生了什么,完全是个黑盒。

二、正确的姿势:先让AI理解业务,再让它给日志建议

直接把代码丢给AI让它“加日志”,AI只会机械地在每个循环里塞一句logger.info("处理第{}行", i)。正确的方式是:先用自然语言告诉AI这个导入流程是怎么设计的,有哪些关键节点,再让它判断哪里该打日志。

提示词示例:我有一段Excel导入的Java代码,请先理解业务逻辑,然后给出日志打点建议。业务背景描述:- 用户通过Web页面上传一个Excel文件,文件中每一行是一条商品信息- 系统需要解析Excel,逐行校验数据(商品名称和价格不能为空)- 校验通过的数据批量插入数据库- 校验不通过的行直接跳过,不影响其他行的处理- 整个导入过程在一个事务中,如果入库失败则整体回滚请你先复述你对这个业务流程的理解,然后回答:1. 这个流程中有哪些“关键时刻”需要记录日志?2. 每个关键时刻应该记录什么信息?3. 哪些地方用info,哪些用warn,哪些用error?4. 最后给出修改后的代码。代码如下:[粘贴代码]

AI先复述业务,再给建议

如果提示词写到位,AI会先输出它对业务的理解:

我的业务理解:这是一个Excel导入功能,包含以下关键步骤:

  1. 接收文件:用户上传了一个Excel文件
  2. 解析文件:将Excel每一行转换为DTO对象
  3. 数据校验:过滤掉商品名称或价格为空的行
  4. 批量入库:将有效数据批量插入数据库
  5. 事务控制:整个过程在事务内,入库失败则全部回滚

然后基于这个理解给出日志建议:

日志打点建议:

  • 入口处:记录文件名和文件大小,方便追溯
  • 解析完成后:记录总行数
  • 校验阶段:记录跳过的无效数据条数
  • 入库前:记录待入库的有效数据条数
  • 入库后:记录成功入库的条数
  • 出口处:记录整个导入的统计信息和耗时
  • 异常处理:解析失败或入库失败时记录完整的错误堆栈和业务上下文

三、优化后代码:日志能讲故事了

@ServicepublicclassProductImportService{privatestaticfinal Logger logger = LoggerFactory.getLogger(ProductImportService.class);@Autowiredprivate ProductMapper productMapper;@TransactionalpublicvoidimportProducts(MultipartFile file){long startTime = System.currentTimeMillis();        String fileName = file.getOriginalFilename();long fileSize = file.getSize();        logger.info("开始导入商品, fileName={}, fileSize={}bytes", fileName, fileSize);// 1. 解析Excel        List<ProductExcelDTO> excelData;try {            excelData = ExcelUtils.read(file, ProductExcelDTO.class);        } catch (Exception e) {            logger.error("Excel解析失败, fileName={}", fileName, e);thrownew BusinessException("Excel文件解析失败,请检查文件格式");        }        logger.info("Excel解析完成, 总行数={}", excelData.size());// 2. 校验和转换        List<Product> validProducts = new ArrayList<>();int skipCount = 0;for (ProductExcelDTO dto : excelData) {if (StringUtils.isBlank(dto.getName()) || dto.getPrice() == null) {                skipCount++;continue;            }            Product p = new Product();            p.setName(dto.getName());            p.setPrice(dto.getPrice());            p.setCategory(dto.getCategory());            validProducts.add(p);        }if (skipCount > 0) {            logger.warn("校验阶段跳过无效数据, 跳过条数={}", skipCount);        }        logger.info("校验完成, 有效数据条数={}", validProducts.size());// 3. 入库if (validProducts.isEmpty()) {            logger.info("无有效数据需要导入, fileName={}, 导入结束", fileName);return;        }try {            productMapper.batchInsert(validProducts);            logger.info("批量入库成功, 入库条数={}", validProducts.size());        } catch (Exception e) {            logger.error("批量入库失败, 事务将回滚, 待入库条数={}, fileName={}"                    validProducts.size(), fileName, e);thrownew BusinessException("数据入库失败,已回滚");        }long costTime = System.currentTimeMillis() - startTime;        logger.info("导入完成, fileName={}, 总行数={}, 有效行数={}, 跳过行数={}, 耗时={}ms",                fileName, excelData.size(), validProducts.size(), skipCount, costTime);    }}

关键改动说明:

原日志
新日志
为什么这样改
logger.info("开始导入商品")
记录文件名和文件大小
知道是哪个文件、多大,方便追溯
解析完成后记录总行数
知道文件里有多少条数据
跳过无效数据时用warn记录条数
发现数据质量问题,方便反馈给运营
校验完成后记录有效数据条数
知道有多少条数据准备入库
入库成功后记录入库条数
核对入库数量是否符合预期
logger.info("导入完成")
记录总行数、有效行数、跳过行数、耗时
一眼看清整个导入过程的统计信息
入库失败时记录待入库条数和文件名
出问题能快速定位是哪批数据

特别注意:最后那条“导入完成”日志放在入库成功之后、方法正常返回之前。如果入库抛异常,根本走不到这行,不会出现“入库失败却打印导入完成”的逻辑矛盾。

四、这个方法的本质:让AI扮演Code Review的同事

你想想,平时你怎么让同事帮你看日志打得合不合适?

你会把代码往他面前一丢说“帮我看看”吗?不会。你会先跟他讲:这个导入流程分几步,先解析Excel,再校验,最后批量入库,校验不通过的跳过。他理解了这些,才能告诉你“解析完应该打一条,记录总行数”、“校验完应该打一条,记录跳过了多少”。

AI也是一样。你不给它业务上下文,它就给你废话。

直接让AI优化日志
先描述业务再让AI优化
AI看到:一个循环,调了个batchInsert
AI看到:解析→校验→入库三步流程
AI建议:每行都加日志
AI建议:只在关键节点打统计日志
结果:日志刷屏,磁盘告警
结果:几条日志把整个导入过程说清楚

五、AI提示词模板(可直接复制)

我有一段Java业务代码,请先理解业务逻辑,然后给出日志打点建议。【业务背景描述】- 这个功能是做什么的?(例如:用户上传Excel批量导入商品)- 处理流程分几步?(例如:解析文件→逐行校验→批量入库)- 有哪些业务规则?(例如:名称和价格不能为空,为空的行跳过)- 事务范围是怎样的?(例如:整体一个事务,失败则回滚)请你:1. 用你自己的话复述一遍你对这个业务流程的理解2. 列出这个流程中的“关键时刻”,以及每个时刻该记录什么信息3. 给出日志级别的建议(info/warn/error)4. 最后给出修改后的完整代码代码如下:[在此粘贴你的代码]

今天分享到这里,我们下期再见

喜欢的话记得点赞哦