1. 结论先行
本报告统计的是服务器上实际生成的日志文件大小,不是 Kibana message 字段长度,也不是 Elasticsearch 索引占用。
| 项目 | 2026-08-26 | 2026-08-27 | 变化 | 归因结论 |
|---|---|---|---|---|
| DGJ-AI,10.80.21.92/93 | 约 38.00 GB | 约 46.11 GB | +8.11 GB,+21.35% | 不能直接判定优化失效;27 号新增了 26 号未找到的日期日志文件,目录集合不一致 |
| dgj-robot,10.80.22.21–26 | 约 40.69 GB | 约 40.37 GB | -0.31 GB,-0.77% | 本轮没有修改 Robot 网关代码,变化主要是流量和内容差异,不作为 dgj2.0 优化收益 |
AI 的可比同名大文件 robot-inquiry/kafka 从约 37.96 GB 降到约 37.46 GB,减少约 0.50 GB、1.32%。但 Kafka 入口代码本轮没有删除完整 payload,因此这一下降不能完全归因于代码优化。
本次代码优化的直接收益是:下游部分节点不再重复打印完整 message、notify、contact 和 preConversation;searchWxList 的返回值统一限制为最多 500 个字符。setContact:设置联系人 和当前 conversation 按保守策略仍保留完整对象,详见第 5 节。入口完整 Kafka 消息、格式错误原文和未知异常堆栈仍保留,保证可以按 RequestId、msg_id、sid 等字段排查。
2. 统计范围和口径
2.1 代码证据
- 优化分支:
bugfix/20260827-log。 - 最新日志统一截断提交:
801e22d706 日志优化。 - 前一批链路去重提交:
dd297f437f 日志精简修改。 - 本机当前工作区在
feature/P1500,且存在与本报告无关的未提交改动;本报告没有修改当前工作区,代码证据直接读取bugfix/20260827-log引用。
2.2 服务器文件证据
- AI:
10.80.21.92、10.80.21.93,目录/data/logs/dgj。 - Robot:
10.80.22.21–10.80.22.26,目录/data/logs/inner-robot。 - 26 号和 27 号均按文件名明确带日期的日志统计。
- 精确值使用文件字节数汇总;截图中的
du -sh会按文件系统单位显示并四舍五入,因此报告表中的十进制 GB 可能和终端显示的G不完全相同。 - 未把不带日期、可能横跨多天的轮转文件直接算入某一天,例如 AI 的
robotMessageConsumer.log、.1–.10和 Robot 的gateway/swoole.log。否则会把历史内容重复归到当天。
统计命令形态如下,均为只读:
find /data/logs/dgj -type f \
\( -name '*2026-08-26*' -o -name '*20260826*' \) -printf '%s\t%p\n'
find /data/logs/inner-robot -type f \
\( -name '*2026-08-27*' -o -name '*20260827*' \) -printf '%s\t%p\n'
3. 26/27 号实际文件大小对比
3.1 AI 每台服务器合计
| 服务器 | 26 号 | 27 号 | 变化 |
|---|---|---|---|
prod-dgj-php-ai-92 | 19.021 GB | 23.081 GB | +4.060 GB,+21.34% |
prod-dgj-php-ai-93 | 18.977 GB | 23.030 GB | +4.052 GB,+21.35% |
| AI 合计 | 37.999 GB | 46.111 GB | +8.112 GB,+21.35% |
3.2 AI 按日期日志文件对比
| 日志文件 | 26 号合计 | 27 号合计 | 变化 | 说明 |
|---|---|---|---|---|
robot-inquiry/kafka-YYYY-MM-DD.log | 37.960 GB | 37.457 GB | -0.503 GB,-1.32% | 最大文件;入口完整 Kafka payload 仍保留 |
inner/robot_inquiry-YYYY-MM-DD.log | 未找到 | 7.939 GB | 新增可见文件 | 27 号日期文件;包含 RobotInquiry 链路节点 |
Services/info-YYYY-MM-DD.log | 未找到 | 0.448 GB | 新增可见文件 | 包含验证码处理、商品查询等 Services 日志 |
inner/simpleNameSer-YYYY-MM-DD.log | 未找到 | 0.220 GB | 新增可见文件 | 27 号新出现的日期文件 |
quote-manager/quote-manager-channel-YYYY-MM-DD.log | 0.037 GB | 0.038 GB | +0.001 GB,+2.01% | 量小,属于流量波动 |
inner/smart_inquiry-YYYY-MM-DD.log | 未找到 | 0.007 GB | 新增可见文件 | 量小 |
robot_v2/im_inquiry-YYYY-MM-DD.log | 0.001 GB | 0.001 GB | -43.14% | 绝对量很小 |
robot-inquiry/robot_inquiry_sort-YYYY-MM-DD.log | 0.001 GB | 0.001 GB | -43.14% | 绝对量很小 |
| 其它日期文件 | 约 0.0002 GB | 约 0.0002 GB | 基本不变 | 包括 price、ImCenter、api 等 |
这里的“未找到”不是“确认当天没有产生日志”,而是服务器当前目录中没有找到对应日期命名文件。因此 AI 26→27 的目录总量不具备严格的同集合可比性。需要先确认 26 号相关日志是否被归档、清理、写入了轮转文件,或者 27 号发布后改变了日志文件命名/创建方式。
3.3 Robot 每台服务器合计
| 服务器 | 26 号 | 27 号 | 变化 |
|---|---|---|---|
prod-dgj-robot-21 | 6.862 GB | 6.728 GB | -0.134 GB,-1.96% |
prod-dgj-robot-22 | 6.803 GB | 6.664 GB | -0.139 GB,-2.05% |
prod-dgj-robot-23 | 6.714 GB | 6.686 GB | -0.028 GB,-0.42% |
prod-dgj-robot-24 | 6.829 GB | 6.824 GB | -0.005 GB,-0.07% |
prod-dgj-robot-25 | 6.849 GB | 6.822 GB | -0.027 GB,-0.40% |
prod-dgj-robot-26 | 6.629 GB | 6.650 GB | +0.021 GB,+0.32% |
| Robot 合计 | 40.686 GB | 40.373 GB | -0.313 GB,-0.77% |
3.4 Robot 按日志节点对比
| 日志节点 | 26 号合计 | 27 号合计 | 变化 | 27 号占 Robot |
|---|---|---|---|---|
gateway/info/20260827.INFO.log | 35.443 GB | 35.020 GB | -0.423 GB,-1.19% | 86.74% |
gateway/request/20260827.INFO.log | 4.104 GB | 4.215 GB | +0.110 GB,+2.69% | 10.44% |
gateway/webot/robot_20260827.log | 1.125 GB | 1.125 GB | -0.0003 GB,-0.03% | 2.79% |
gateway/trigger/*.WARNING.log | 0.011 GB | 0.012 GB | +0.0004 GB,+3.14% | 0.03% |
gateway/error/*.ERROR.log | 0.002 GB | 0.002 GB | -0.00003 GB,-1.47% | 0.006% |
gateway/trigger/*.NOTICE.log | 0.00001 GB | 0.000009 GB | 绝对量极小 | 约 0% |
Robot 的 27 号最大问题仍然是网关 info,其次是 request;本轮 dgj2.0 只修改 AI 应用侧代码,没有修改 Robot 网关项目,因此这里应作为后续独立治理项,而不是本次代码优化的效果证明。
4. 代码修改与日志内容对照
下面的示例均使用脱敏占位符,不包含真实客户、手机号、微信号或完整请求内容。
4.1 Kafka 消费入口:完整原始消息保留
代码位置:application/controllers/inner/moveMall/Robot.php:1880-1895。
当前代码仍然保留:
KzLogger::getLogger('robot-inquiry', 'kafka')->info('收到消息', [
'topic' => $message->topic_name,
'payload' => $message->payload,
]);
日志形态:
[INFO][kafka] RequestId#<入口请求ID># 收到消息
{"topic":"product.price...","payload":"{...完整原始消息...}"}
格式错误仍保留完整 payload:
KzLogger::getLogger('robot-inquiry', 'kafka')->error('消息格式错误', [
'payload' => $message->payload,
]);
结论:这一份是整条链路的原始档案,本轮不删除。后续若要继续降低 AI 的 37 GB 大头,必须另行设计“原始消息低成本存储/压缩/按异常保留”方案,不能在下游重复日志上继续压缩来解决 Kafka 本身的占用。
4.2 parseNotify:去掉第二份完整 payload
代码位置:application/Providers/WechatRobot/Module/NotifyModule.php:15-30。
原来:
if ($this->isJson($notifyData)) {
$logger && $logger->info($notifyData);
$notifyData = json_decode($notifyData, true);
// ...
}
原日志实质上是第二份完整微信消息:
[INFO][robot_inquiry] RequestId#<id>#
{"event":200,"out_app":"ZGJ","robot_wxid":"<robot>","...":"...大量字段..."}
现在:
$logger && $logger->info('parseNotify:解析微信消息', [
'request_id' => $notifyData['request_id'] ?? '',
'msg_id' => $notifyData['msg_id'] ?? '',
'event' => $notifyData['event'] ?? '',
'from_wxid' => $notifyData['from_wxid'] ?? '',
'robot_wxid' => $notifyData['robot_wxid'] ?? '',
]);
现在的日志形态:
[INFO][robot_inquiry] RequestId#<id># parseNotify:解析微信消息
{"request_id":"<id>","msg_id":"<msg>","event":200,"from_wxid":"<from>","robot_wxid":"<robot>"}
保留能力:确认进入了解析节点,并可用 request_id/msg_id/event/robot_wxid 回到 Kafka 原始消息。
4.3 onMessage 开始:保留入口诊断信息,去掉重复 message
代码位置:application/Services/MoveMall/RobotInquirySer.php:104-115。
原来:
$this->logger->info('===== onMessage 开始 =====', [
'message' => is_string($message) ? $message : json_encode($message, 256),
'memory_limit' => ini_get('memory_limit'),
'trace_id' => $this->getRequestId(),
]);
原日志会把 Kafka 已经记录过的完整 message 再写一次:
===== onMessage 开始 =====
{"message":"{...完整 payload...}","memory_limit":"2000M","trace_id":"<id>"}
现在:
$this->logger->info('===== onMessage 开始 =====', [
'memory_limit' => ini_get('memory_limit'),
'trace_id' => $this->getRequestId(),
]);
现在日志只表示“已经进入 onMessage”:
===== onMessage 开始 ===== {"memory_limit":"2000M","trace_id":"<id>"}
memory_limit 按原要求继续保留;trace_id 继续用于关联。入口节点没有被删除。
4.4 setContact 调用完成和初始化完成:保留节点,不重复对象
代码位置:application/Services/MoveMall/RobotInquirySer.php:255-277。
原来一条消息会重复打印:
onMessage:setContact done
{"contact":{...完整联系人...},"notify":{...完整消息...}}
onMessage:初始化环境完成
{"contact":{...完整联系人...},"conversation":{...会话...}}
现在:
onMessage:setContact done
onMessage:初始化环境完成
这两条日志的作用是判断“联系人初始化是否完成、环境初始化是否完成”,不需要再次携带对象。联系人查询和会话查询本身仍有独立节点。
4.5 loadConversation:只压缩 preConversation,保留当前 conversation
代码位置:application/Services/MoveMall/RobotInquiryBaseSer.php:236-256。
开始节点原来把 contact 再打印一遍:
loadConversation:开始加载会话
{"cvKey":"<key>","contact":{...完整联系人...}}
现在只保留会话键:
loadConversation:开始加载会话 {"cvKey":"<key>"}
完成节点原来同时打印两个完整对象:
loadConversation:会话加载完成
{"conversation":{...完整会话...},"preConversation":{...完整预会话...}}
现在的代码:
$this->logger->info('loadConversation:会话加载完成', [
'conversation' => $this->conversation,
'pre_conversation_id' => $this->preConversation['id'] ?? '',
'pre_conversation_status' => $this->preConversation['status'] ?? '',
]);
现在的日志形态是:
loadConversation:会话加载完成
{"conversation":{...当前会话...},"pre_conversation_id":"<id>","pre_conversation_status":"<status>"}
这里没有删除当前 conversation,因此当前会话内容仍然可查;本轮只消除了 preConversation 完整对象的重复输出。由于 conversation 仍可能较大,它是下一批压缩候选,但不能在没有确认字段用途前直接删除。
4.6 verifyBindContactCode:完整 notify 改成链路摘要
代码位置:application/Services/MoveMall/WechatSer.php:946-966。
原来:
$this->logger->info('处理verifyBindContactCode', ['notify' => $notify]);
日志会在 Services/info 中写入完整 NotifyEntry,和入口 Kafka、解析节点、RobotInquiry 节点重复:
处理verifyBindContactCode
{"notify":{"event":200,"out_app":"ZGJ","robot_wxid":"<robot>","content":"...","...":"大量字段..."}}
现在:
$this->logger->info('处理verifyBindContactCode', [
'request_id' => $notify->getRequestId(),
'msg_id' => $notify->getMsgId(),
'event' => $notify->getEvent(),
'final_from_wxid' => $notify->getFinalFromWxId(),
'robot_wxid' => $notify->getRobotWxId(),
]);
现在的日志形态:
处理verifyBindContactCode
{"request_id":"<id>","msg_id":"<msg>","event":200,"final_from_wxid":"<from>","robot_wxid":"<robot>"}
保留能力:能确认验证码处理函数被进入,并用 request_id/msg_id 回查原始输入。
当前限制:这条日志没有记录 has_code 或 code_in_range,因此单独看它不能判断正则是否提取到验证码、验证码是否命中范围。若以后需要定位“进入了验证码处理但没有绑定成功”,应优先查询后续绑定结果、Redis/绑定记录和错误日志;如果仍不足,再增加两个布尔字段,而不是恢复完整 notify。
4.7 未绑定客户:预期业务分支不打印无意义 trace
代码位置:application/Services/MoveMall/RobotInquirySer.php:318-325。
原来所有异常都打印堆栈:
消息处理失败
{"error":"未绑定客户","trace":"#0 ... RobotInquiryBaseSer.php(255) ..."}
现在:
$errorContext = ['error' => $error];
if ($error !== '未绑定客户') {
$errorContext['trace'] = $exception->getTraceAsString();
}
$this->logger->error('消息处理失败', $errorContext);
预期业务分支变成:
[ERROR][robot_inquiry] RequestId#<id># 消息处理失败 {"error":"未绑定客户"}
未知 PHP 异常、外部接口异常、数据库异常仍保留 trace;本次不是“一律删除异常堆栈”。
4.8 searchWxList:统一公共方法,结果最多 500 字符
代码位置:
application/Services/BaseSer.php:108-138:新增formatLogContext()。application/Services/MoveMall/MoveMallGoodsSer.php:1184-1208:searchWxList-self和searchWxList两处统一调用。
原来:
$this->logger->info('searchWxList:查询到商城商品数量', $res);
虽然日志文案写的是“商品数量”,实际写入的是完整 $res,可能包含数百 KB 的 rows/filter/category/car_list:
searchWxList:查询到商城商品数量
{"rows":[{...大量商品...}],"filter":{"category":[...],"car_list":[...]},"...":"..."}
现在:
$this->logger->info(
'searchWxList:查询到商城商品数量',
$this->formatLogContext($res)
);
统一方法的行为:
- JSON 序列化数据。
- 使用
mb_strlen/mb_substr按 UTF-8 字符截断。 - 最多保留 500 个字符,超出时保留 497 个字符并追加
...。 - 缺少 mbstring 时退化为
strlen/substr,仍然限制上限。 - JSON 序列化失败只记录短错误提示。
- 只改变日志上下文,不改变原始
$res,后续业务仍使用完整返回值。
优化后的形态:
searchWxList:查询到商城商品数量
{"result":"{\"rows\":[{...前497字符}..."}
这里“500 字符”指 result 字段中的序列化内容上限,日志前缀、时间、RequestId 和字段名会额外占少量字符。预发已验证超长 result 严格截断并以 ... 结尾,业务接口仍返回 success。
5. 已完成优化与未完成高量节点
5.1 已完成
| 日志节点 | 改动 | 排查能力 |
|---|---|---|
parseNotify:解析微信消息 | 完整 notify 改为 5 个链路字段 | 能确认解析节点、消息和机器人,完整内容回 Kafka 入口查 |
onMessage 开始 | 删除重复完整 message,保留 memory_limit/trace_id | 能确认进入处理,并继续串联链路 |
onMessage:setContact done | 删除完整 contact/notify | 保留节点标志,联系人详情由独立节点查 |
onMessage:初始化环境完成 | 删除完整 contact/conversation | 保留初始化完成标志,会话由会话节点查 |
loadConversation:开始加载会话 | 删除重复 contact,保留 cvKey | 可核对会话键生成 |
loadConversation:会话加载完成 | 保留 conversation,preConversation 改为 ID/状态 | 仍可判断主会话和预会话状态 |
verifyBindContactCode | 完整 notify 改为 request/msg/event/微信 ID 摘要 | 能回查入口原文,不再在 Services 重复存储 |
未绑定客户 | 删除预期业务异常 trace | 错误原因保留,未知异常 trace 不丢 |
searchWxList 两处 | 公共 500 字符截断 | 能看结果结构开头,业务返回值不变 |
5.2 当前仍然较大、没有在本批删除的节点
| 节点/文件 | 当前状态 | 为什么不能直接删除 | 下一步 |
|---|---|---|---|
robot-inquiry/kafka-YYYY-MM-DD.log | 27 号约 37.46 GB,AI 最大文件 | 目前是唯一完整原始消息证据 | 单独设计压缩/对象存储/异常保留策略;必须先定义“一条消息完整证据”的保存周期 |
inner/robot_inquiry-YYYY-MM-DD.log | 27 号约 7.94 GB | 多个业务节点仍在这里汇聚 | 先按文案统计;优先处理完整 contact、conversation、商品数组 |
setContact:设置联系人 | 当前仍打印完整 $this->contact | 需要保留联系人进入和服务站匹配证据,但不需要完整对象 | 改为 contact_id/sid/chat_group_id/wxid/wxname 摘要,异常保留绑定站点差异 |
loadConversation:会话加载完成 | 当前仍打印完整 $conversation | 用户要求当前 conversation 暂时保留 | 统计内部字段后只保留 cv ID、状态、消息条数、最后更新时间等摘要 |
setConversationRecord:生成会话记录 | 当前仍可能打印完整 $data | 需要证明记录是否生成及记录 ID | 保留 record/cv/contact/sid、内容长度、关键类型,删除完整 source/text/keyword |
处理optionPrivateChat | 当前仍可能打印完整 notify | 需要确认是否进入验证码/私聊分支 | 只保留 message/event/微信 ID/content_length |
Robot gateway/info | 27 号约 35.02 GB,占 86.74% | 属于 Robot 网关项目,本轮未改 | 单独建立 Robot 网关日志治理任务 |
Robot gateway/request | 27 号约 4.21 GB,占 10.44% | 请求审计需要保留,但不一定要完整 body | 保留 URL、状态、耗时、request_id;body 摘要/异常保留 |
5.3 VinAudit 请求/响应整包:当前量级与治理方案
当前量级
生产 Kibana 统计窗口为 2026-09-09 10:00~10:15,匹配 VinAudit 请求和响应整包日志:
| 指标 | 结果 |
|---|---|
| 日志条数 | 95,608 条 |
| 日志字符量 | 1,858.9M |
| 占窗口总日志量 | 36.9% |
| 平均单条 | 约 19.4KB |
该口径包含请求和响应,不等同于全天磁盘量。当前样例日志来源为 prod-dgj-vinaudit 的 providers/VinAudit 日志。
当前记录方式
DGJ2 每次同步调用分别记录:
请求:url + headers + data
响应:完整 response 原文
请求和响应通过同一个 requestId 关联。当前完整响应主要来自:
| 接口 | 大字段 |
|---|---|
/product/search | 商品、车型、筛选项、属性 |
/product/getAttributes | 属性树、车型适配 |
/product/images | 图片 URL 数组 |
/product/get_attributes_by_sku_ids | 批量 SKU 属性 |
Sale 服务的 VinAudit Provider 也会把 config 和 responseBody 作为一条 http_client 事件整包记录,因此 DGJ2 和 Sale 两侧需要分别治理。
建议改法
| 场景 | 保留内容 | 处理方式 |
|---|---|---|
| 正常成功 | RequestId、接口、耗时、业务码、查询条件、返回数量、关键 ID | 不记录完整商品/车型/属性/图片数组,改为摘要 |
| 慢请求 | 上述摘要 + 完整脱敏请求/响应 | 按可配置耗时阈值保留 |
| HTTP/业务异常 | 请求条件、业务码、错误信息、异常堆栈、完整脱敏响应 | 保留整包,便于定位失败原因 |
| 临时排查 | 指定 RequestId 的完整脱敏请求/响应 | 通过临时开关精准采集,不扩大正常日志量 |
成功日志只需保留 products_count、car_count、attribute_count、image_count 等数量字段,以及 VIN、SKU、分类等关键查询条件。sign、Authorization、完整 User-Agent 和重复 IP 不写入正常日志。
业务影响边界
日志摘要只能作用于日志变量,原始响应仍原样交给 Sale/DGJ 业务解析;不能用摘要内容替换业务 $response。这样不会改变商品、车型、属性和图片的实际返回,也不会改变超时、异常和重试逻辑。
落地顺序
- 先按接口拆分请求量、响应量、字符量和最大单条,确认第一优先级接口。
- 优先改
/product/search、/product/getAttributes、/product/images的成功日志摘要。 - 保留超时、非 2xx、业务码异常、解析失败和慢请求的完整脱敏日志。
- 预发验证正常、空结果、超时、业务异常和 JSON 异常,再用相同 15 分钟窗口复测字符量、平均单条和最大单条。
6. 已有同窗口验证证据
下面是上线后已经记录的 15 分钟/短窗口证据,不能和 26/27 日文件总量混为同一个指标,但可以证明“单条日志是否变小”。
| 日志点 | 优化前样本 | 优化后样本 | 结果 |
|---|---|---|---|
robot_inquiry 合计 | 88.59M 字符 | 1.81M 字符 | 约下降 97.96% |
onMessage 开始 平均单条 | 52,893 字符 | 156 字符 | 完整 message 已去掉 |
loadConversation:会话加载完成 平均单条 | 2,411 字符 | 约 755 字符 | preConversation 已摘要,conversation 仍保留 |
消息处理失败 平均单条 | 929 字符 | 106 字符 | 未绑定客户不再打印 trace |
searchWxList 预发单条 | 最大历史约 220KB | result 最多 500 字符 | 已验证 ... 截断 |
这些数据说明本批修改确实减少了重复大对象,但 AI 日文件总量仍被 Kafka 完整 payload 主导;如果要让 AI 从几十 GB 继续显著下降,必须处理原始入口证据的存储策略,单纯继续删除下游节点会逐渐损失排查能力。
7. 一条消息如何排查
Kafka 收到消息(唯一完整 payload,入口证据)
|
+--> onMessage 开始(trace_id、memory_limit)
|
+--> parseNotify(request_id、msg_id、event、微信 ID)
|
+--> setContact(bindWxId、联系人摘要、服务站匹配)
|
+--> loadConversation(cvKey、conversation、pre 会话 ID/状态)
|
+--> 商品/库存/排序(数量、ID、耗时;当前仍有部分完整对象)
|
+--> 会话记录(record/cv/contact ID;当前仍需继续压缩)
|
+--> onMessage 结束 或 消息处理失败
推荐查询顺序:
- 先按 Kafka 入口的
request_id或内部RequestId找到完整原始消息。 - 用
msg_id确认确实是同一条微信消息,避免只依赖可能在不同系统重新生成的 request ID。 - 查
parseNotify、setContact、loadConversation,判断消息解析、联系人、会话分别停在哪一步。 - 查
sid/contact_id/cv_id/record_id,定位业务数据。 - 遇到验证码绑定问题,查
verifyBindContactCode后续绑定结果;当前摘要日志本身不记录验证码命中情况。 - 遇到未知异常,查
消息处理失败的error + trace;遇到“未绑定客户”,只看业务原因和绑定微信 ID,不需要堆栈。
8. 风险判断
8.1 已验证为低风险
- 删除的都是日志上下文字段,不改变
$message/$notify/$contact/$conversation/$res的业务变量。 - Kafka 完整入口消息没有删除;格式错误仍保留完整 payload。
memory_limit按要求保留。- 未知异常仍保留 trace;只对明确的“未绑定客户”去掉堆栈。
formatLogContext()只在日志参数中序列化和截断,searchWxList后续仍使用原始返回值。searchWxList与searchWxList-self两条路径都使用公共方法,避免只修改一条路径。
8.2 需要继续关注
- AI 26/27 日期文件集合不一致,不能仅用目录总量判断收益;需要先确认旧文件归档和日志配置。
- 当前
setContact:设置联系人仍输出完整 contact,说明下游重复大对象尚未全部清除。 - 当前
loadConversation:会话加载完成保留完整 conversation,符合当前保守策略,但仍是后续大日志候选。 verifyBindContactCode当前没有验证码匹配结果字段;排查绑定失败时必须依赖后续日志或数据,不能只看这一条。- Kafka 完整 payload 是 AI 的不可忽略存储底座;如果改变保存方式,必须验证 RequestId、msg_id、原始 payload 可回查和保留周期。
- Robot 网关本轮未修改,不能把 Robot 27 号的轻微下降写成 dgj2.0 代码收益。
8.3 AI 26号日志完整性专项核查
核查范围
本次直接只读检查 prod-dgj-php-ai-92(10.80.21.92) 和 prod-dgj-php-ai-93(10.80.21.93) 的 /data/logs/dgj,核对 2026-08-26 日期文件、2026-08-27 对照文件、压缩归档和进程仍持有的 deleted-open 文件;没有执行删除、重启或其他线上写操作。
日期文件结果
| 主机 | 26号可见日期文件合计 | 其中 Kafka 主日志 | 26号缺失的关键日期文件 |
|---|---|---|---|
| AI-92 | 19,021,473,480 bytes(约 19.02GB) | 19,001,506,225 bytes(约 19.00GB) | inner/robot_inquiry、Services/info、inner/simpleNameSer、inner/smart_inquiry |
| AI-93 | 18,977,440,677 bytes(约 18.98GB) | 18,958,491,173 bytes(约 18.96GB) | inner/robot_inquiry、Services/info、inner/simpleNameSer、inner/smart_inquiry |
两台机器的 26 号 Kafka 文件都存在,并且都在 26 号 23:59 左右完成写入;因此不能判断为“26 号 AI 日志全部被删除”。但是,26 号四类关键业务日期文件在两台机器上同时缺失,说明按 /data/logs/dgj 日期文件统计出来的 26 号总量不是完整的 AI 应用日志基线。
作为对照,27 号两台机器均出现了这些文件:inner/robot_inquiry 各约 3.95–3.99GB、Services/info 各约 223–224MB、inner/simpleNameSer 各约 109–111MB,说明 26/27 的日志文件集合发生过变化,不能直接用两天目录总量下结论。
是否发现删除痕迹
| 检查项 | AI-92 | AI-93 | 判断 |
|---|---|---|---|
/data/logs 下常见压缩归档 | 未发现 | 未发现 | 没有在本机找到 26 号压缩备份 |
| deleted-open 唯一 inode | 26 个 | 26 个 | 两台机器都有被 unlink 的滚动日志 |
| deleted-open 文件大小合计 | 134,908,087 bytes(约 128.7MiB) | 135,912,289 bytes(约 129.6MiB) | 量级约 260MiB,无法解释约 38GB 的 Kafka 主体 |
| deleted-open 路径 | robotMessageConsumer.log.10 | robotMessageConsumer.log.10 | 属于 Supervisor 滚动 stdout/stderr,不是带 26 日期的业务文件 |
根因倾向
两台 AI 的 Supervisor 配置都为 robotMessageConsumer 启动 36 个进程,并让所有进程的 stdout 和 stderr 共享同一个 /data/logs/dgj/robotMessageConsumer.log,且没有显式配置独立的轮转参数。Supervisor 默认注释配置为单文件约 50MB、保留 10 个备份;在多进程共享同一轮转文件时,容易出现多个进程各自持有同名 .10、旧 inode 已从目录 unlink 但仍被进程占用的情况。
这可以确认“部分滚动 stdout/stderr 历史内容存在被清理/轮转的风险”,但当前证据不能证明这些 deleted-open 内容就是 26 号四类业务日期文件,也不能证明 26 号 19GB Kafka 文件被删除。
结论和后续动作
- 26 号 AI 日志统计应标记为“日期文件集合不完整”,不能把约 37.99GB 当成完整日总量。
- 26 号 Kafka 主日志仍在,是目前最主要的完整原始消息证据;两台机器合计约 37.96GB。
- 需要优先核对 Monolog channel 的文件创建规则、26 号发布/重启时间和采集端索引,确认四类日期文件是“当日未生成”还是“后续被清理”。
- Supervisor 配置需要单独整改:为 36 个消费者设置按进程区分的 stdout/stderr 文件,或将正常 stdout 关闭、把格式错误/异常改为结构化应用日志;在整改前不能把当前滚动文件当作可完整回溯的审计证据。
- 本次核查没有执行线上写操作;若要恢复已 unlink 文件,只能在明确批准后制定取证方案,避免直接重启或关闭进程导致仍占用 inode 的内容彻底释放。
9. 下一阶段落地顺序
P0:先处理 AI 应用侧仍然重复打印完整对象
setContact:设置联系人:保留contact_id/sid/chat_group_id/wxid/wxname和匹配结果,删除完整 contact。setConversationRecord:生成会话记录:保留 record/cv/contact/sid、内容长度、关键词类型,删除完整 source/text/keyword。处理optionPrivateChat:保留事件、微信 ID、内容长度和分支结果,删除完整 notify。- 商品查询/库存/排序:保留数量、ID、原因、耗时;删除循环内完整商品数组。
P1:明确原始消息证据的成本边界
- 入口仍保留完整原始消息,但评估压缩、独立索引、对象存储或按异常保留。
- 统一原始消息和下游日志的关联键:
request_id + msg_id + sid,必要时加record_id/cv_id。 - 设定保留策略:正常消息和异常消息的保留时长、查询入口、恢复流程必须明确。
P2:单独治理 Robot 网关项目
gateway/info先按 35.02 GB 文件拆出“完整 Kafka 回调业务体”“私聊消息过滤”“发送/回调结果”等文案。gateway/request保留 URL、状态、耗时、request_id,正常请求 body 截断,异常请求保留必要上下文。gateway/webot的 HTTP debug 报文单条较大,应改为开关或仅异常采集;这项不能通过修改 dgj2.0 代码完成。
10. 汇报时可以直接使用的表述
8 月 27 日完成 DGJ2 AI 报价日志的第一阶段治理:保留 Kafka 消费入口唯一完整原始消息,删除下游部分节点重复的完整 message、notify、contact 和 preConversation;未知异常仍保留堆栈,预期业务异常只保留错误原因;商品查询返回统一限制为 500 字符。服务器实际文件统计显示,AI 27 号可明确归属日期的日志约 46.11 GB,Robot 网关约 40.37 GB。AI 总量与 26 号相比增加,主要是 27 号新增了独立日期日志文件,不能直接判定优化失效;同名 Kafka 大文件下降约 1.32%。当前最大剩余来源是 Kafka 入口完整 payload 和 AI 内部仍保留的完整 contact/conversation/商品对象,下一阶段将优先在不丢失 RequestId、msg_id、业务 ID 和异常证据的前提下继续摘要化。