加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.beijidao.cn/)- 应用程序、AI行业应用、CDN、低代码、区块链!
当前位置: 首页 > 百科 > 正文

网站上线流量归零?日志盲区正 silently 吞噬用户

发布时间:2026-10-28 08:04:38 所属栏目:百科 来源:DaWei
导读:  去年元旦,上线前夜三点十七分,我盯着 Grafana 里那条平得像尺子量出来的流量线——不是低,是零。真零。连爬虫的毛都没蹭出个波纹。PM 在钉钉发了个哭脸表情包,后面跟了句“老板问是不是 CDN 挂了”,我没回。CDN 健康

  去年元旦,上线前夜三点十七分,我盯着 Grafana 里那条平得像尺子量出来的流量线——不是低,是零。真零。连爬虫的毛都没蹭出个波纹。PM 在钉钉发了个哭脸表情包,后面跟了句“老板问是不是 CDN 挂了”,我没回。CDN 健康检查全绿,日志采集端口监听正常,Kafka lag 是个位数……可 ELK 里搜 request_url: /,空。搜 status: 200,空。搜 user_agent,空。整个上游 HTTP 流量,在 nginx access_log 之后就蒸发了。


文章配图,仅供参考

  我原以为是日志采集中间件崩了——比如 Filebeat 的 inotify 队列溢出,或者 Fluentd 的 buffer 占满磁盘。结果一查,Filebeat 本身 log 疯狂刷 warn:`input type 'tail' skip line due to invalid utf-8`。但问题不在它——nginx 日志文件里,所有新写入的行末尾都少了一个换行符。少得极其克制,每三十七行缺一个。不多不少。我敢打包票:这是上游 syslog-ng 的 `syslog_format` 和 `template` 里混用了 `$MSG` 和 `$MESSAGE`,而 `$MSG` 在某些特殊字符场景下截断了换行。没人动过 syslog-ng 配置,但它就是从元旦零点开始错。为什么是零点?因为那个时间点,运维同事顺手 reload 了 rsyslog(他后来说就为了清个 `/var/log/messages` 的 rotation 乱码),结果触发了 syslog-ng 的配置继承冲突。他倒水去了,水杯还搁在隔壁工位键盘上,我盯着他屏幕上 Chrome DevTools 正切在 Console tab,光标停在 `console.warn("⚠️ legacy logger init")` 那行,没往下执行。


  双屏左边壁纸还是去年年会抓拍的,穿蓝围裙的测试小妹举着半截烤肠对着镜头笑;右边壁纸换了,是张模糊的地铁线路图截图,右下角有油渍印——我忘了哪天外卖汤洒了一滴,没擦,现在干成褐色环状物,直径约两厘米。键盘 F5 键有点卡,按下去要多使三分力,松手时弹簧声慢半拍;我抬手、按键、松手、再抬手、再按键——F5 按了六次,第七次才刷出 devtools Network tab 里那个 200,但 response body 是空的。Network tab 右上角写着 “147 requests”,可 filter 写 `method: GET` 后只剩七条。我切到 Sources tab 才发现,前端 JS 加载失败了两次,但没报错——被 try/catch 吞了,连 Sentry 都没捕获。那个 catch 里只有一行 `console.log('ignore')`,连时间戳都不打。


  后来翻 git blame,发现这行 `console.log('ignore')` 是上个月 PR review 时,后端老张批注写的:“别让前端瞎报错,影响大盘指标”。PM 跟着点头,说“用户感知不到的错误就不是错误”。我说“那日志呢”,PM 回:“日志不也是给人看的?”——他边说边把咖啡杯挪开,杯底在桌面划出半道浅痕。我盯着那道痕想,CSS class 命名也是这么来的:`.btn-primary-active-hover-focused-disabled-loading-override`,六个修饰词,最后发现是 loading 状态覆盖了 disabled 的 pointer-events。这种东西修起来比查日志快,因为至少它不会假装自己存在。


  真正要命的不是少日志,是日志在“说话”——但说的是假话。access_log 里全是 200,status_code 字段值全对;nginx 配置也没改,log_format 明明写着 `$status $body_bytes_sent $request_time`;metric 上 QPS 稳定、P99 延迟压得死死的……可真实请求在哪?我搜 `host: xxx.com`,返回一千四百条;搜 `host: xxx.com AND upstream_status: -`,返回零条。那个 upstream_status 字段,是日志解析 pipeline 里硬加的字段,靠正则从 `upstream_response_time` 字符串里抠出来的——但这个字符串,早在半年前就被运维换成 `-` 代替空值了。而正则没改。于是整个 upstream 链路在日志里被格式化成了“一切正常”。这不是盲区,是精心布置的无害假象。优胜劣汰?我看是淘汰掉第一个质疑字段为空的人。第一个看到 `-` 还去查文档的,已经被调去搞可观测性平台二期了。


  我试过重放一段原始日志文本给 Logstash,它吐出的 JSON 里 upstream_status 真是 `-`。我把它改成 `null`,pipeline 就崩溃。改成 `""`,又变成 `0`。改成 `"-"`,居然过了。但生产环境不能改。我就只能在 Kibana query bar 里敲:`upstream_status: "-" OR NOT upstream_status:`——括号漏了个,查了八分钟才反应过来。旁边同事说“你这语法像古希腊语”,我点头,顺手把键盘右下角 Alt 键按下去,没弹起,卡住了。现在它永远处于 pressed 状态,Ctrl+C 都失效,我只能用鼠标右键复制。


  所以现在我的方案是:在 nginx 里加一行 log_format,额外打个 `raw_upstream: "$upstream_http_x_real_upstream"`,哪怕它是空的;然后让 Logstash 把这整段 raw 字符串原样塞进 ES,不动解析;最后 Kibana 用 script_fields 强制判断是否含 `-` 字符——笨,但可靠。至少它不会“优胜劣汰”掉怀疑的眼睛。至于要不要推这个方案?等等。我刚看见测试小妹又在群里发截图:她用 iPhone 12 Safari 打开首页,白屏五秒,console 显示 `ReferenceError: globalThis is not defined`。我点开她发的截图放大,发现她手机屏幕左上角信号格是空的——三格变零格。这事儿我说不准,但我知道:她昨天提的 bug 单,状态还是“已复现,待排期”。


  先改 nginx 配置吧。别的,等我把 Alt 键撬出来再说。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!