error-handler.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // 客户端错误收集器
  2. (function() {
  3. // 保存原始控制台方法
  4. const originalConsoleError = console.error;
  5. // 重写console.error以捕获错误
  6. console.error = function(...args) {
  7. // 调用原始方法
  8. originalConsoleError.apply(console, args);
  9. // 提取错误信息
  10. const errorMessage = args.map(arg => {
  11. if (arg instanceof Error) {
  12. return arg.stack || arg.message;
  13. } else if (typeof arg === 'object') {
  14. try {
  15. return JSON.stringify(arg);
  16. } catch (e) {
  17. return String(arg);
  18. }
  19. } else {
  20. return String(arg);
  21. }
  22. }).join(' ');
  23. // 向服务器报告错误
  24. reportErrorToServer({
  25. message: errorMessage,
  26. source: 'console.error',
  27. type: 'console'
  28. });
  29. };
  30. // 全局错误处理
  31. window.addEventListener('error', function(event) {
  32. reportErrorToServer({
  33. message: event.message,
  34. source: event.filename,
  35. lineno: event.lineno,
  36. colno: event.colno,
  37. stack: event.error ? event.error.stack : null,
  38. type: 'uncaught'
  39. });
  40. });
  41. // Promise错误处理
  42. window.addEventListener('unhandledrejection', function(event) {
  43. const message = event.reason instanceof Error
  44. ? event.reason.message
  45. : String(event.reason);
  46. const stack = event.reason instanceof Error
  47. ? event.reason.stack
  48. : null;
  49. reportErrorToServer({
  50. message: message,
  51. stack: stack,
  52. type: 'promise'
  53. });
  54. });
  55. // 向服务器发送错误报告
  56. function reportErrorToServer(errorData) {
  57. // 添加额外信息
  58. const data = {
  59. ...errorData,
  60. userAgent: navigator.userAgent,
  61. page: window.location.href,
  62. timestamp: new Date().toISOString()
  63. };
  64. // 发送错误报告到服务器
  65. fetch('/api/client-error', {
  66. method: 'POST',
  67. headers: { 'Content-Type': 'application/json' },
  68. body: JSON.stringify(data),
  69. // 使用keepalive以确保在页面卸载时仍能发送
  70. keepalive: true
  71. }).catch(err => {
  72. // 不记录这个错误,避免无限循环
  73. });
  74. }
  75. })();