Error monitoring solution
The Necessity of Engineering Standards
As frontend projects scale up, code complexity grows exponentially. Codebases lacking unified standards quickly devolve into unmaintainable "big balls of mud," with different developers writing in varied styles and employing disparate error-handling approaches. Engineering standards significantly enhance code maintainability and team collaboration efficiency by enforcing coding styles, unifying error-handling mechanisms, and establishing commit conventions.
Typical problem scenarios:
- Developer A uses try-catch for asynchronous error handling
- Developer B employs .catch for Promise errors
- Developer C neglects error handling altogether
- A single project exhibits four different indentation styles
// Anti-pattern: Mixed error handling approaches
function fetchData() {
try {
axios.get('/api').then(res => {
// Business logic
}).catch(e => console.log(e)) // Promise-style
} catch (e) { // try-catch style
alert('Request failed')
}
}
Error Monitoring System Architecture
A comprehensive error monitoring solution consists of three layers:
- Collection Layer: Covers runtime errors, resource loading errors, API request errors, console errors, etc.
- Transmission Layer: Implements different reporting strategies for production/development environments
- Analysis Layer: Error aggregation, source map parsing, affected user analysis
interface ErrorReport {
timestamp: number;
message: string;
stack?: string;
componentStack?: string; // React error boundaries
userAgent: string;
location: string;
customData?: Record<string, any>;
}
Code Standard Implementation Strategies
Advanced ESLint Configuration
Extending base rule sets requires consideration of the project's tech stack:
// .eslintrc.js
module.exports = {
extends: [
'airbnb',
'plugin:react-hooks/recommended',
'plugin:@typescript-eslint/recommended'
],
rules: {
'no-console': ['error', { allow: ['warn', 'error'] }],
'react/jsx-uses-react': 'off',
'react/react-in-jsx-scope': 'off',
'@typescript-eslint/no-floating-promises': 'error'
}
}
Key rule configurations:
no-floating-promises
: Enforces handling of Promise rejectionsrequire-await
: Prevents meaningless async declarationsno-misused-promises
: Avoids Promise misuse
Git Hooks Integration
Automated validation during commits via husky:
// package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
]
}
}
Error Classification and Capture Solutions
Synchronous Error Capture
Limitations of basic try-catch:
- Cannot catch syntax errors
- Errors in asynchronous code escape
- Negligible performance impact (~0.01ms per operation)
// Typical misuse case
try {
setTimeout(() => {
throw new Error('Async error'); // Won't be caught
}, 100);
} catch (e) {
console.log('Never executes');
}
Asynchronous Error Handling
Solutions for modern frontend asynchronous scenarios:
// Unified Promise error handling
const safeFetch = async (url: string) => {
try {
const resp = await fetch(url);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
return await resp.json();
} catch (error) {
// Unified reporting logic
reportError(error);
// Return safe value or rethrow
return null;
}
};
// React Suspense boundary
<ErrorBoundary fallback={<ErrorPage />}>
<Suspense fallback={<Loader />}>
<AsyncComponent />
</Suspense>
</ErrorBoundary>
Production Environment Error Reporting
Performance-Optimized Reporting Strategies
- Throttled Reporting: Avoid reporting duplicate error instances within 5 minutes
- Batched Queue Reporting: Collect errors before sending in bulk
- Local Caching: Temporarily store in IndexedDB when offline
class ErrorTracker {
constructor() {
this.queue = [];
this.debounceTimer = null;
this.MAX_RETRY = 3;
}
report(error) {
if (this.shouldFilter(error)) return;
this.queue.push(error);
clearTimeout(this.debounceTimer);
this.debounceTimer = setTimeout(() => this.flush(), 5000);
}
async flush() {
if (!navigator.onLine) {
await this.saveToIDB(this.queue);
return;
}
try {
await sendBeacon('/api/errors', { errors: this.queue });
this.queue = [];
} catch (e) {
if (this.retryCount < this.MAX_RETRY) {
setTimeout(() => this.flush(), 2000);
this.retryCount++;
}
}
}
}
SourceMap Mapping Solution
Production error stack trace resolution process:
- Upload sourcemaps to internal servers during build
- Record version numbers and build IDs during error reporting
- Backend services match version numbers with corresponding sourcemaps
- Reverse parsing using mozilla/source-map library
# Webpack configuration example
module.exports = {
devtool: 'hidden-source-map',
plugins: [
new SourceMapUploadPlugin({
url: 'https://internal.com/sourcemaps',
exclude: [/node_modules/]
})
]
}
Error Analysis Dimension Design
Effective error analysis should include multi-dimensional data:
-
User Dimension:
- Device type
- OS version
- Network environment
-
Business Dimension:
- Current route path
- User operation flow
- Feature module identifier
-
Technical Dimension:
- Error type (TypeError/ReferenceError etc.)
- Call stack depth
- Dependency library version
// Enhanced error reporting data example
{
"error": {
"type": "TypeError",
"message": "Cannot read property 'name' of null",
"stack": "..."
},
"context": {
"route": "/user/profile",
"reduxState": {
"auth": { "userId": 12345 }
},
"env": {
"sdkVersion": "2.3.4",
"browser": "Chrome/91.0.4472.124"
},
"breadcrumbs": [
{ "type": "click", "target": "#submit-btn", "timestamp": 1620000000000 },
{ "type": "api", "url": "/api/user", "status": 200 }
]
}
}
Monitoring System Integration Practices
Integration with Existing Systems
Deep customization example for Sentry integration:
import * as Sentry from '@sentry/react';
import { Integrations } from '@sentry/tracing';
Sentry.init({
dsn: 'https://example@sentry.io/123',
release: process.env.REACT_APP_VERSION,
integrations: [
new Integrations.BrowserTracing({
routingInstrumentation: Sentry.reactRouterV5Instrumentation(history)
}),
],
beforeSend(event) {
// Filter browser extension errors
if (event.stacktrace?.frames?.some(frame =>
frame.filename?.includes('chrome-extension://'))) {
return null;
}
return event;
}
});
// Custom tags
Sentry.configureScope(scope => {
scope.setTag('environment', process.env.NODE_ENV);
});
Performance Monitoring Integration
Correlating error and performance data:
// Using PerformanceObserver to monitor long tasks
const observer = new PerformanceObserver(list => {
const entries = list.getEntries();
entries.forEach(entry => {
if (entry.duration > 100) {
trackLongTask(entry);
}
});
});
observer.observe({ entryTypes: ['longtask'] });
// Resource loading monitoring
window.addEventListener('error', event => {
if (event.target instanceof HTMLLinkElement ||
event.target instanceof HTMLScriptElement) {
reportResourceError({
url: event.target.src || event.target.href,
element: event.target.tagName
});
}
}, true);
Continuous Optimization Mechanism
Establishing an error monitoring closed-loop process:
-
Tiered Alerts:
- P0 errors (core flow impact): Real-time SMS notifications
- P1 errors (major functionality issues): Hourly summary emails
- P2 errors (edge case problems): Daily reports
-
Resolution Tracking:
- [ ] #ERROR-123 Null pointer exception in cart page - Affected users: 2.3% (~1200 daily) - First occurrence: 2023-05-10 - Related commit: a1b2c3d (User service refactor) - Fix owner: @frontend_zhangwei
-
Trend Analysis:
- Establish error rate baselines (e.g., below 0.5% is normal)
- Monitor error growth trends
- Compare error rates before/after releases
// Error rate calculation example
function calculateErrorRate() {
const totalPageViews = analytics.getPageViews();
const errorCount = errorStore.getTotalErrors();
return {
rate: (errorCount / totalPageViews * 100).toFixed(2) + '%',
trend: compareWithLastPeriod(errorCount)
};
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn