一、错误日志收集方案
1. 全局错误捕获
// 全局错误捕获
window.onerror = function(message, source, lineno, colno, error) {
const errorData = {
message,
source,
line: lineno,
column: colno,
stack: error?.stack,
timestamp: new Date().toISOString()
};
// 发送错误日志到服务器
sendErrorToServer(errorData);
return true; // 阻止默认错误处理
};
// 未捕获的Promise异常
window.addEventListener('unhandledrejection', event => {
const errorData = {
type: 'unhandledrejection',
message: event.reason?.message || String(event.reason),
stack: event.reason?.stack,
timestamp: new Date().toISOString()
};
sendErrorToServer(errorData);
});
2. 框架特定错误处理
// React错误边界
class ErrorBoundary extends React.Component {
componentDidCatch(error, info) {
const errorData = {
message: error.message,
stack: error.stack,
componentStack: info.componentStack,
timestamp: new Date().toISOString()
};
sendErrorToServer(errorData);
}
}
// Vue错误处理器
Vue.config.errorHandler = (err, vm, info) => {
const errorData = {
message: err.message,
stack: err.stack,
component: vm?.$options?.name,
lifecycleHook: info,
timestamp: new Date().toISOString()
};
sendErrorToServer(errorData);
};
3. 网络请求错误监控
// 拦截fetch请求
const originalFetch = window.fetch;
window.fetch = async function(...args) {
try {
const response = await originalFetch(...args);
if (!response.ok) {
const errorData = {
type: 'fetch_error',
url: args[0],
status: response.status,
timestamp: new Date().toISOString()
};
sendErrorToServer(errorData);
}
return response;
} catch (error) {
const errorData = {
type: 'fetch_exception',
url: args[0],
message: error.message,
stack: error.stack,
timestamp: new Date().toISOString()
};
sendErrorToServer(errorData);
throw error;
}
};
二、错误定位方法
1. 基础定位流程
- 查看错误类型:区分是JS运行时错误、资源加载错误还是API请求错误
- 检查错误堆栈:优先查看
stack属性中的调用链信息 - 定位源代码:根据错误信息中的文件名、行号和列号定位问题代码
- 重现问题:尝试在开发环境复现相同错误
2. 具体案例分析
案例1:未定义变量错误
// 错误日志示例
{
"message": "Uncaught ReferenceError: userInfo is not defined",
"source": "https://example.com/static/js/main.js",
"line": 42,
"column": 15,
"stack": "ReferenceError: userInfo is not defined\n at getUserProfile (main.js:42:15)\n at initUser (main.js:38:3)\n at onPageLoad (main.js:12:5)",
"timestamp": "2025-05-04T09:30:15.123Z"
}
定位步骤:
- 查看
main.js第42行第15列 - 检查
getUserProfile函数中对userInfo的使用 - 确认变量是否正确定义或导入
案例2:API请求失败
javascriptCopy Code
// 错误日志示例
{
"type": "fetch_error",
"url": "/api/orders/123",
"status": 500,
"timestamp": "2025-05-04T10:15:22.456Z",
"requestHeaders": {
"Content-Type": "application/json",
"Authorization": "Bearer xxx"
},
"responseText": "Internal Server Error"
}
定位步骤:
- 检查后端日志中对应时间点的
/api/orders/123请求 - 确认请求参数是否正确
- 如果是500错误,查看后端异常堆栈
案例3:跨域错误
javascriptCopy Code
// 错误日志示例
{
"message": "Access to fetch at 'https://api.example.com/data' from origin 'https://app.example.com' has been blocked by CORS policy",
"stack": "Error: Failed to fetch\n at fetchData (main.js:87:15)",
"timestamp": "2025-05-04T11:20:33.789Z"
}
定位步骤:
- 检查请求URL是否正确
- 确认后端是否配置了正确的CORS头
- 对于复杂请求,检查预检请求(OPTIONS)是否通过
三、高级错误分析技巧
-
用户行为回溯:记录错误发生前的用户操作路径
-
环境信息收集:
- 浏览器类型和版本
- 操作系统
- 设备信息
- 网络状态
-
性能关联分析:将错误与页面加载性能数据关联分析
-
错误聚合:对相似错误进行分组统计,识别高频问题
四、最佳实践建议
- 错误分级:根据影响程度将错误分为致命、严重、警告等级别
- 采样上报:对高频非关键错误进行采样上报,避免数据过载
- 敏感信息过滤:避免记录用户敏感数据到日志中
- 实时报警:对关键错误设置实时报警机制
- 定期分析:每周/月进行错误趋势分析,识别系统性问题