Home
avatar

.𝙃𝙖𝙣

为什么做完这个项目以后,我会越来越在意日志、异常处理和权限

这篇还是接在 vchoo 这条线后面写。

前面几篇已经把故事生成、分镜拆分、生图任务调度、超时和降级这些主链路拆开了。那段时间我最大的变化,不只在“把 AI 能力接进业务”这件事上。项目越往后做,我越能感觉到,系统能不能长期跑下去,很多时候要看的反而是几件很基础、平时又很容易被嫌麻烦的东西:日志、异常处理和权限。

1. 一开始做项目时,最容易把注意力都放在“功能通没通”上

刚开始接 vchoo 这类项目时,人的注意力很自然会落在主链路上。

比如:

  • 故事能不能生成
  • 分镜能不能拆出来
  • 生图能不能跑
  • 任务状态能不能查

因为这些东西最直观,也最容易被看到。

前端点一下,页面一转,接口一回,大家先看的都是这些。

那时候我对很多基础能力的理解还偏“辅助项”。

会觉得:

  • 日志先打一点就行
  • 异常先 catch 住别炸掉就行
  • 权限后面再慢慢补

这种想法在项目前期很常见,短时间内看起来也不是完全跑不动。

但 vchoo 这种链路一旦开始变长,调用层一多、任务一多、状态一多,问题就会集中冒出来。那个时候我才真正体会到,很多东西前面不补,后面会连本带利地还回来。

2. 我最先开始在意日志,是因为很多问题光靠“现象”根本定位不动

做普通小功能的时候,有些问题其实挺直给的。

  • 页面没显示
  • 接口报错
  • 参数传错

这类问题顺着报错点往回找,很多时候还能查得动。

但 vchoo 这条链不一样。

它中间隔着很多层:

  • 用户输入
  • LLM 生成故事
  • 分镜拆分
  • 生图任务下发
  • ComfyUI 执行
  • 回调回流
  • 状态更新

到了这个阶段,很多问题给到你时,表面现象会非常弱。

比如:

  • 用户说“这次卡住了”
  • 前端看到任务一直在执行中
  • 某个分镜最后没出图
  • 某次重试之后结果不对

这些问题如果没有日志,后端视角其实非常被动。

因为你根本不知道问题到底卡在哪一段:

  • 是故事生成慢了
  • 还是分镜拆分结构有问题
  • 是任务根本没下发出去
  • 还是 ComfyUI 已经执行了,但结果没回写
  • 是回调迟到
  • 还是状态更新被后面的逻辑覆盖了

到这个阶段,日志不再只是“记一记发生了什么”,而是:

系统出了问题以后,你还有没有能力把它倒着推回去。

这个价值我是在真实链路里被教育出来的。

3. 后来我对日志的理解,慢慢从“打印调试信息”变成了“保留链路证据”

刚开始写代码时,打日志很容易带着一种临时感。

比如:

  • 到这里了,打印一下
  • 这个变量值是什么,打印一下
  • 这个接口有没有进来,打印一下

这种日志在本地调试时当然有用,但放到业务系统里,很快就不够了。

因为真要查问题的时候,光有一两行零散信息根本不够,你需要的是一条能串起来的过程证据。

所以我后来会更在意日志里到底有没有这些东西:

  • 当前是哪一次创作任务
  • 当前是哪一个分镜
  • 当前在哪个阶段
  • 输入参数大概是什么
  • 外部调用结果是什么
  • 状态从什么变成了什么
  • 失败发生在什么时候

这些信息一旦能留住,很多问题就开始能被顺着看了。

我后来对日志的感觉越来越像:

它比“随手打印出来的附属输出”重要得多,更像是系统留给自己的一条时间线。

这条时间线在平时可能没什么存在感,但一出问题,它就是最值钱的东西。

4. 异常处理这件事,我后来越来越在意,是因为“报错”并不是最可怕的状态

这点在 AI 业务里尤其明显。

一开始很容易把异常处理理解成:

  • 别让接口 500
  • 报错了就 catch
  • 给前端返回一句失败

但项目做深一点以后,我更在意的反而是另外几种状态:

  • 没报错,但结果不可用
  • 失败了,但状态没改
  • 某一层吞掉了异常,后面继续往下跑
  • 前端看到的是成功,系统内部其实已经半失败

这种情况比直接抛异常更难受。

因为直接报错至少还算明确,系统会立刻提醒你出了问题。

最麻烦的是那种:

  • 没完全成功
  • 也没完全失败
  • 状态挂在中间
  • 用户还以为可以继续等

前面写任务调度、超时、降级的时候,其实已经碰到不少这种问题了。

所以我后来对异常处理的要求也开始变高。

我不再只满足于“捕获住别炸”,而是会更关注:

  • 失败以后状态有没有明确落下来
  • 前端拿到的是不是可解释的结果
  • 这次失败会不会影响后续链路
  • 以后如果重试,系统能不能接得住

这个时候,异常处理已经直接影响业务行为了,不再只是代码卫生问题。

5. 到这个阶段,我开始能体会到“统一异常处理”为什么重要

如果异常只是散在每个接口、每个服务方法里零零碎碎地处理,短时间看着也能跑。

但项目一多以后,很快就会出几个问题:

  • 每个接口返回风格不一样
  • 有的地方抛异常,有的地方吞掉
  • 有的地方写日志,有的地方什么都不记
  • 同一种失败,在不同位置会被处理成不同结果

这对前后端和后续维护都很不友好。

因为它意味着:

  • 前端很难统一处理
  • 后端很难统一排查
  • 运维和测试也很难快速判断问题严重度

所以我后来会越来越认可统一异常处理这件事。

它的意义在我看来主要有三点:

第一,统一收口

不管底层哪里出问题,至少最后给出去的结果风格要一致。

第二,统一留痕

异常信息、上下文、任务标识这些东西,最好能有固定方式被记下来。

第三,统一状态转换

失败以后系统到底该标什么状态、返回什么结果,不要每个地方自己发挥。

这个思路一旦有了,项目整体会稳很多。

6. 权限这件事,我一开始确实有点低估了,觉得后台先能用再说

只看功能推进节奏,权限往往不是最先被盯上的点。

尤其是做内部后台时,很容易默认:

  • 都是内部人在用
  • 功能先跑起来更重要
  • 后面再细化角色和权限也来得及

我当时也有过这种心态。

但随着后台功能一点点变多,这个问题很快就开始冒头。

因为后台一旦开始管理:

  • 素材
  • 活动配置
  • 状态切换
  • 任务结果
  • 运营开关

这些东西其实已经不是“看一眼数据”那么简单了。

很多操作都在直接影响线上展示和业务结果。

这时候你就不能只问“这个功能做没做”,还得问:

  • 谁能看
  • 谁能改
  • 谁能发起关键动作
  • 谁能改状态
  • 谁能重试、取消或者重新发布

权限这件事一旦不清楚,后面很容易出现两种问题:

第一,越权太宽

谁都能碰关键配置,风险很大。

第二,边界太糊

某个动作到底算运营操作、管理操作,还是开发辅助操作,说不清楚。

我后来对权限越来越在意,就是因为我开始意识到:

后台系统真正危险的地方,很多时候不在“能看到什么”,而在“能改动什么”。

7. 做完这个项目后,我对权限的理解也从“页面访问控制”走到了“动作控制”

刚开始接触权限时,最容易想到的是页面级别:

  • 这个菜单能不能看到
  • 这个页面能不能进

这些当然重要,但往后做一点,很快就会发现它不够。

因为很多真正关键的风险点,都落在动作上,很少落在页面本身。

比如:

  • 能不能切活动状态
  • 能不能替换素材
  • 能不能删除配置
  • 能不能重试任务
  • 能不能查看某些敏感记录

这些动作如果不单独收住,就算页面入口拦住了,也不一定真的安全。

所以我后来会更在意:

  • 菜单权限是一层
  • 接口权限是一层
  • 数据权限是一层
  • 关键动作权限又是一层

这个理解一出来,我对权限这件事的态度就完全不一样了。

它不再只是“后台常规配置项”,而是系统边界的一部分。

8. 回头看,日志、异常处理、权限这三件事,其实都在回答同一个问题:系统失控时,你能不能把它拉回来

这可能是我做完 vchoo 这一段以后,感受最深的一点。

表面上看,这三件事属于完全不同的主题:

  • 日志偏排查
  • 异常处理偏稳定性
  • 权限偏安全和边界

但放到真实项目里,它们其实在回答一个共同的问题:

系统开始复杂之后,一旦事情没按预期走,你还有没有办法把局面收回来。

日志解决的是:

  • 你还看不看得见发生了什么

异常处理解决的是:

  • 失败以后状态会不会继续扩散

权限解决的是:

  • 哪些动作本来就不该被随便触发

这三层一旦都没有,系统表面上功能再全,后面也会非常脆。

9. 所以这段经历带给我最大的变化,是我开始知道“长期维护”靠什么支撑

只看功能清单,vchoo 这一段当然能列出很多东西:

  • 故事生成
  • 分镜拆分
  • 生图调度
  • 重试取消
  • 超时降级

这些都是真的,也确实重要。

但我现在回头看,更影响我后面做事方式的,其实是另一层:

我开始知道,一个系统能不能长期维护,关键得看底下这些基础能力有没有慢慢补齐,而不是功能点堆得多快。

因为业务一变、任务一多、状态一复杂,最后最先救命的,往往不是你又多会了一个接口,更多是下面这些基础能力:

  • 日志能不能追
  • 异常能不能收
  • 权限边界清不清楚

这个认识对我来说挺重要。

它让我后面再做东西时,会自然多问几句:

  • 这一步失败了以后系统怎么办
  • 这个动作有没有必要留操作痕迹
  • 这个接口谁都能调吗
  • 以后查问题时,我能不能把链路倒回来

这些问题以前我不太会主动问,现在会了。

10. 这篇先记一个阶段结论

做完 vchoo 这段以后,我现在先给自己记几个比较明确的结论:

  1. 功能链越复杂,日志就越像系统的回放能力
  2. 异常处理不能只停在 catch 住别炸,还要关心状态有没有收住
  3. 统一异常处理的价值,在于统一结果、统一留痕、统一收口
  4. 权限控制真正关键的地方,更多在关键动作和接口边界,不只在页面入口
  5. 日志、异常处理、权限这些基础能力,决定的是系统能不能长期维护,也决定它是不是只能勉强跑通

这篇先写到这里。

.NET 日志 异常处理 权限 后端