SemIf 负责语义决策、日志负责回放差异

文章导读
要让 SemIf 的语义判断和日志回放形成可解释链路,关键动作只有两个:SemIf 输出侧留下最小决策记录,应用日志侧携带同一请求标识。适用场景是同一请求事后出现“为什么这样判”的追问;操作时先固定字段,再在日志系统里用请求标识检索两侧记录;验证方式是同一请求能找到成对的决策记录与业务阶段日志;风险边界是摘要不能替代原始输入,脱敏字段和日志采样会让对照出现假差异。
📋 目录
  1. Ⅰ 在 SemIf 输出侧固定记录输入摘要、输出摘要和调用时间
  2. Ⅱ 把应用日志中的请求标识与 SemIf 决策记录关联
  3. Ⅲ 回放同一请求时对比日志顺序和决策输出
  4. Ⅳ 标记是日志缺失、时间错位还是决策输入不同
  5. Ⅴ 整理成可复用的对照表模板
A A

要让 SemIf 的语义判断和日志回放形成可解释链路,关键动作只有两个:SemIf 输出侧留下最小决策记录,应用日志侧携带同一请求标识。适用场景是同一请求事后出现“为什么这样判”的追问;操作时先固定字段,再在日志系统里用请求标识检索两侧记录;验证方式是同一请求能找到成对的决策记录与业务阶段日志;风险边界是摘要不能替代原始输入,脱敏字段和日志采样会让对照出现假差异。

适用场景:SemIf 参与决策且业务日志需要事后回放。操作动作:SemIf 记录输入摘要、输出摘要、调用时间、版本和请求标识;应用日志在入口、调用前后、结果处理处写同一请求标识。验证方式:用请求标识检索两侧记录并按时间排序核对。风险边界:涉敏输入需脱敏或只存摘要;时钟偏差、异步日志和采样会造成差异,先排除这些因素再判断规则问题。

在 SemIf 输出侧固定记录输入摘要、输出摘要和调用时间

SemIf 输出侧不宜只落最终结果。建议最小字段包括:decision_id、request_id(或 trace_id)、sem_version/rule_version、input_digest、input_summary、output_digest、output_summary、decision_result、reason_code、called_at、duration_ms、caller、status/error。适用场景是每次语义判断都要能被回查;操作动作是在 SemIf 返回前统一写一条结构化记录;验证方式是任意 response 都能通过 decision_id 反查该条记录;风险边界是 input_summary 要脱敏,digest 只用于一致性比对,不能反推原始大字段。

示例记录格式如下,字段名可按现有日志规范替换,但语义不要省:

{
  "decision_id": "sem-8f3c",
  "request_id": "req-123",
  "trace_id": "trace-abc",
  "sem_version": "rule-42",
  "input_digest": "sha256:aaaa",
  "input_summary": {"intent": "refund", "amount": 128.0, "user_tier": "gold"},
  "output_digest": "sha256:bbbb",
  "output_summary": {"decision": "allow", "reason_code": "tier_match"},
  "decision_result": "allow",
  "called_at": "2024-01-01T00:00:00.000Z",
  "duration_ms": 12,
  "caller": "order-service",
  "status": "ok"
}

这条记录应尽量在调用返回前写入,或至少写入本地异步缓冲区;如果只能异步,需要在应用日志里留下待写入标记,否则回放时会遇到缺口。验证方式是查 decision_id 是否唯一、called_at 是否可排序、input_digest 是否与传入摘要一致。

SemIf 负责语义决策、日志负责回放差异

把应用日志中的请求标识与 SemIf 决策记录关联

关联字段的选择方法很直接:入口生成 request_id,跨服务传递 trace_id,同一请求内多次 SemIf 决策再加 decision_id。应用日志至少在入口、调用 SemIf 前、收到 SemIf 结果后、业务结果落库前写同一 request_id;如果语义决策发生在异步任务里,还要把根请求标识带入任务上下文。验证方式是用 request_id 在应用日志和 SemIf 决策记录中各检索一次,正常应能互相命中;如果任一为空,先查日志级别、采样、字段映射和异步上下文丢失,不要先改规则。风险边界是客户端传入的 request_id 不能直接当审计主键,建议在服务端生成或做格式校验。

结构化日志示例:

{
  "ts": "2024-01-01T00:00:00.000Z",
  "level": "INFO",
  "service": "order-service",
  "request_id": "req-123",
  "trace_id": "trace-abc",
  "span_id": "span-1",
  "sem_decision_id": "sem-8f3c",
  "stage": "before_refund",
  "msg": "call semif"
}

如果日志系统支持字段索引,优先把 request_id、trace_id、sem_decision_id 设成可检索字段;如果不支持,至少用 key=value 让文本检索能定位。验证方式是在页面按 request_id 过滤,观察应用日志与 SemIf 记录是否成对出现。

SemIf 负责语义决策、日志负责回放差异

回放同一请求时对比日志顺序和决策输出

回放步骤建议固定为:1)从应用日志按 request_id 拉出入口到结果处理的全链路记录;2)用同一 request_id 或 trace_id 拉取 SemIf 决策记录;3)按 ts 和阶段标记排序,而不是只看文件行号;4)核对每次 SemIf 调用的输入摘要是否等于当时传入摘要;5)核对决策输出、reason_code 和业务分支是否一致;6)如果 SemIf 支持按版本重放,固定 sem_version 再重放,否则只做当时记录比对。适用场景是事后解释同一请求为什么走了不同分支;验证方式是比对表里每一行都能找到两侧证据;风险边界是重放时规则版本或外部特征已变化,新输出不能直接当作旧决策。

比对表可按下表填写,至少覆盖日志时间、决策输入、决策输出:

比对项应用日志值SemIf 决策记录值是否一致备注
请求入口时间2024-01-01T00:00:00.000Z不适用—记录阶段标记
SemIf 调用时间2024-01-01T00:00:00.050Z2024-01-01T00:00:00.060Z接近结合时钟偏差判断
决策输入摘要sha256:aaaasha256:aaaa是字段一致
决策输出allow/tier_matchallow/tier_match是分支一致

表格里的时间字段用占位示例即可,实际排查要保留原始时区。若应用日志只记录本地时间,先转换成 UTC 再排序。

SemIf 负责语义决策、日志负责回放差异

标记是日志缺失、时间错位还是决策输入不同

差异归类的目的不是争论谁对,而是把问题分到可修复环节。三类判定特征和修复方向如下:

  • 日志缺失:判定特征是请求在应用日志存在,但 SemIf 决策记录为空,或 SemIf 有记录而应用侧没有消费日志;检索同一 request_id 时两侧数量不匹配。修复方向是先查日志级别、采样率、异步刷盘、采集 agent 和字段映射,再查 SemIf 客户端是否在异常分支未写记录。验证方式是在测试环境把相关日志级别调至更详细级别并复现一次。风险边界:提高日志级别可能增加磁盘和采集压力。
  • 时间错位:判定特征是两侧都有记录,但顺序与业务阶段不符,例如 SemIf 调用时间早于请求入口,或响应日志早于决策日志;跨主机时差也可能造成假错位。修复方向是统一时钟源、在日志里同时写墙上时间和单调时长,并用 trace 时间线校准。验证方式是同一主机内先对比,再对比跨主机;风险边界是时钟调整可能让时间回跳,不能只看单条时间戳排序。
  • 决策输入不同:判定特征是同一 request_id 下 input_digest 不一致,或 input_summary 关键字段不同,输出 reason_code 与输入明显不匹配。修复方向是固定输入快照和序列化顺序,记录 sem_version,检查上游是否重试、并发修改同一字段或缓存返回旧值。验证方式是对比调用方传入摘要与 SemIf 接收摘要;风险边界是摘要算法或字段顺序变化也会导致 digest 不同,需先确认算法版本。

整理成可复用的对照表模板

把一次排查沉淀成固定列名,后续直接套用。建议列名:排查批次、request_id、trace_id、应用日志时间、SemIf 调用时间、输入摘要 digest、输入关键字段、sem_version、决策输出、reason_code、差异类型、证据位置、修复动作、修复后验证。填写示例可以先用占位值:

排查批次request_id应用日志时间SemIf 调用时间输入摘要 digest输入关键字段sem_version决策输出reason_code差异类型证据位置修复动作修复后验证
batch-001req-1232024-01-01T00:00:00.000Z2024-01-01T00:00:00.060Zsha256:aaaaintent=refund;amount=128;tier=goldrule-42allowtier_match时间错位app-log:line;sem-log:decision_id校准主机时钟并重跑采集同一 request_id 两侧时间差纳入可接受范围

这套模板适合放在工单或排查记录里,不要求每次填满所有列,但 request_id、输入摘要、决策输出、差异类型和修复动作建议保留。适用场景是重复出现的语义决策争议;操作动作是先归档对照表再改配置;验证方式是下一同类请求能用同一模板闭环;风险边界是模板不能替代原始日志,证据位置要能回到原始记录,不能只留结论。