前端线上错误日志收集与定位指南

481 阅读3分钟

一、错误日志收集方案

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. 基础定位流程

  1. 查看错误类型‌:区分是JS运行时错误、资源加载错误还是API请求错误
  2. 检查错误堆栈‌:优先查看stack属性中的调用链信息
  3. 定位源代码‌:根据错误信息中的文件名、行号和列号定位问题代码
  4. 重现问题‌:尝试在开发环境复现相同错误

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"
}

定位步骤‌:

  1. 查看main.js第42行第15列
  2. 检查getUserProfile函数中对userInfo的使用
  3. 确认变量是否正确定义或导入

案例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"
}

定位步骤‌:

  1. 检查后端日志中对应时间点的/api/orders/123请求
  2. 确认请求参数是否正确
  3. 如果是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"
}

定位步骤‌:

  1. 检查请求URL是否正确
  2. 确认后端是否配置了正确的CORS头
  3. 对于复杂请求,检查预检请求(OPTIONS)是否通过

三、高级错误分析技巧

  1. 用户行为回溯‌:记录错误发生前的用户操作路径

  2. 环境信息收集‌:

    • 浏览器类型和版本
    • 操作系统
    • 设备信息
    • 网络状态
  3. 性能关联分析‌:将错误与页面加载性能数据关联分析

  4. 错误聚合‌:对相似错误进行分组统计,识别高频问题

四、最佳实践建议

  1. 错误分级‌:根据影响程度将错误分为致命、严重、警告等级别
  2. 采样上报‌:对高频非关键错误进行采样上报,避免数据过载
  3. 敏感信息过滤‌:避免记录用户敏感数据到日志中
  4. 实时报警‌:对关键错误设置实时报警机制
  5. 定期分析‌:每周/月进行错误趋势分析,识别系统性问题