诊断日志注入
在代码的关键执行路径上注入 ILogger 诊断日志,帮助用户收集运行时数据以定位 bug。
输入分析
收到用户请求后,分析以下输入(优先级从高到低):
- 堆栈跟踪 — 解析文件名:行号,锁定异常抛出位置和调用链
- 错误消息 — 根据异常类型和消息推断涉及的模块
- 症状描述 — 用户口头描述的异常行为,需推断可能涉及的代码路径
- 指定方法 — 用户直接指定的入口方法
定位策略
有堆栈跟踪时
- 从堆栈底部(入口)到顶部(异常点)提取调用链中本项目的文件和行号
- 对每个方法,识别:方法入口、关键分支(if/switch)、循环、return 前的值
- 沿调用链向上追溯 2-3 层,覆盖数据传递的关键节点
无堆栈跟踪时
- 根据错误信息搜索相关类/方法(Grep 关键词)
- 识别主入口方法(通常是 Service/Manager/Handler 层的 public 方法)
- 沿调用链展开 2-3 层深度
- 重点关注:数据转换、条件分支、集合操作、外部调用
自动判断范围
- 错误信息明确(如 NullReferenceException 在具体行)→ 聚焦该方法及其调用者
- 错误信息模糊(如"结果不对""偶尔失败")→ 扩大范围,覆盖整个流程链
- 涉及数据流(如计算结果异常)→ 从数据入口到出口全链路加日志
注入规则
日志框架
- 使用
ILogger,禁止Console.WriteLine - 通过构造函数 DI 注入
ILogger<ClassName> - 如果类中已有
_logger字段,直接使用
日志级别
| 级别 | 场景 |
|---|---|
LogInformation |
方法入口/出口、关键数据值、分支走向 |
LogWarning |
意外分支、边界条件、null/空集合 |
LogError |
catch 块中、异常重抛前 |
日志内容格式
"[方法名] 描述: {ParamName}", ParamValue
示例:
_logger.LogInformation("[CalculateOffset] 输入: point={Point}, config={Config}", point, config);
_logger.LogInformation("[CalculateOffset] 分支: 使用线性插值, factor={Factor}", factor);
_logger.LogInformation("[CalculateOffset] 结果: offset={Offset}", offset);
注入位置(按优先级)
- 方法入口 — 记录所有输入参数
- 条件分支 — 记录走了哪个分支及关键判断值
- 计算/转换结果 — 记录中间结果和最终返回值
- 循环体 — 记录迭代索引和每次迭代的中间值(仅在循环体较复杂时)
- 外部调用前后 — 记录调用参数和返回值
- catch 块 — 补充异常上下文信息
注意事项
- 不修改任何业务逻辑,只添加日志语句
- 日志消息以方法名开头,方便 grep 过滤
- 用结构化日志参数
{Name}而非字符串插值$"" - 如果方法已存在足够的诊断日志,跳过不重复添加
- 对于简单的属性 getter/setter 或无逻辑的透传方法,不加日志
执行步骤
- 分析输入,确定涉及的代码文件和方法
- 读取相关源文件,理解执行流程
- 按上述规则在每个关键位置注入日志
- 汇总报告:修改了哪些文件、哪些方法、加了什么级别的日志
- 提示用户下一步:编译 → 运行 → 复现问题 → 收集日志输出
输出格式
完成后输出简要总结:
已注入诊断日志:
- FileA.cs::MethodX — 入口参数 + 分支判断 (Info)
- FileA.cs::MethodY — 循环迭代值 (Info) + 异常上下文 (Error)
- FileB.cs::MethodZ — 外部调用前后 (Info)
下一步:编译项目,运行并复现问题,然后用日志输出继续定位。