js error_log记录错误
用户看不见,代码却挂了:实战 JS 异常捕获与日志上报
产品经理在群里吼了一句:“线上出问题了!”你立马打开浏览器控制台(Console),却发现里面干干净净,啥报错都没有。这种“薛定谔的 Bug"是不是让你头皮发麻?其实不是代码没挂,而是你的捕获机制没生效。很多人误以为 JS 有一个像 PHP 那样直接的 error_log 函数能把错误直接扔进服务器文件,但现实是 JavaScript 运行在客户端沙箱里,它没有权限直接写服务器日志。
要实现真正的错误追踪,核心思路就一个:在浏览器端拦截错误,通过网络请求发送到后端进行记录。 下面这套方案,能帮你把那些幽灵般的崩溃变成可追溯的日志。
捕获错误的两种场景
要覆盖大部分异常,你需要关注两个主要入口。一个是全局的资源加载失败或语法错误,另一个是现代开发中经常遇到的异步 Promise 异常。
对于传统的同步错误,可以直接利用浏览器的原生事件监听。记得在脚本初始化时,立刻挂载这个钩子:
window.addEventListener('error', (event) => {
// 在这里提取错误信息
const errorMsg = event.message;
const url = event.filename;
const line = event.lineno;
// 后续发送逻辑
});
如果你只盯着上面的写法,可能会漏掉很多现代前端应用特有的问题。特别是在使用 async/await 或者大量 Promise 链式调用时,未处理的拒绝往往不会触发 window.onerror。所以,必须补上一道防线来捕捉 unhandledrejection:
window.addEventListener('unhandledrejection', (event) => {
event.preventDefault();
// 提取 reason 对象中的具体错误原因
sendLog(event.reason);
});
这两段代码配合起来,基本能保证绝大多数前端异常都能被“抓个正着”。
数据上报的安全门坎
收集到错误只是第一步,如何安全、稳定地发给后端更有讲究。直接发起网络请求可能会导致死循环——比如发送日志的代码本身又报错了,结果产生无限递归,直接把内存撑爆。
为了解决这个问题,务必在上报函数内部做简单的容错处理。可以用 try-catch 包裹上报动作,或者给发送函数加上防抖节流控制,避免在短时间内高频次触发。更重要的是,千万别把用户的隐私数据混进去。错误栈里有时会暴露敏感的 Token 或个人信息,在上报前需要做一个清洗过滤,屏蔽关键字段。
后端记录的务实选择
当请求到达服务端后,如何处理这些前端发来的 JSON 数据呢?如果后端是 PHP 环境,这里才是真正用到 error_log 功能的地方。你可以创建一个专门的路由接口,接收参数后写入特定的日志文件。
这样做有个好处,能和系统级错误物理隔离。不要把所有的前端报错都扔进系统默认的错误通道,建议单独开辟一个文件路径,例如 /var/log/frontend_errors.log。这样排查问题时,不用在成百上千行系统杂讯里找鱼刺。
另外,日志内容最好包含用户行为上下文。单纯的一行 Uncaught TypeError 很难定位。如果在请求包里带上当时的 URL、浏览器版本、操作系统甚至用户的操作序列,运维团队复现问题的成本会降低一大截。
别让日志成为负担
最后提醒一点,生产环境的日志策略要有节制。不是所有错误都值得记录。如果是非阻塞性的资源加载失败,且不影响主流程,可以选择静默处理;只有导致白屏、交互失效的核心错误才需要紧急告警。过度的日志只会让存储爆炸,反而掩盖了真实风险。
构建这套体系的初衷不是为了监控别人,而是为了让自己在深夜接到报警电话时,能第一时间知道发生了什么,而不是对着空白的控制台发呆。代码会犯错,但优秀的日志系统能让修复变得有据可依。


还没有评论,来说两句吧...