Monitoring & Analytics
Implement monitoring and analytics for production JavaScript applications. This is a foundational concept in programming and web interactivity that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world JavaScript experience. Take your time with each section and practice the examples
Error Tracking
Implement comprehensive error tracking and monitoring for production applications.. This is an essential concept that every JavaScript developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Sentry Integration
// Sentry setup
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: 'YOUR_SENTRY_DSN',
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
});
// Error boundary
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
Sentry.captureException(error, {
contexts: {
react: {
componentStack: errorInfo.componentStack
}
}
});
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}Performance Monitoring
// Performance monitoring
class PerformanceMonitor {
constructor() {
this.metrics = new Map();
this.observers = [];
}
startTiming(name) {
this.metrics.set(name, performance.now());
}
endTiming(name) {
const startTime = this.metrics.get(name);
if (startTime) {
const duration = performance.now() - startTime;
this.recordMetric(name, duration);
this.metrics.delete(name);
}
}
recordMetric(name, value) {
const metric = {
name,
value,
timestamp: Date.now()
};
this.observers.forEach(observer => {
observer(metric);
});
}
addObserver(observer) {
this.observers.push(observer);
}
getMetrics() {
return Array.from(this.metrics.entries());
}
}User Analytics
// Analytics tracking
class Analytics {
constructor(config) {
this.config = config;
this.events = [];
this.sessionId = this.generateSessionId();
}
track(event, properties = {}) {
const eventData = {
event,
properties: {
...properties,
sessionId: this.sessionId,
timestamp: Date.now(),
url: window.location.href,
userAgent: navigator.userAgent
}
};
this.events.push(eventData);
this.sendEvent(eventData);
}
pageView(page) {
this.track('page_view', { page });
}
userAction(action, element) {
this.track('user_action', { action, element });
}
error(error, context) {
this.track('error', { error: error.message, context });
}
sendEvent(eventData) {
if (this.config.endpoint) {
fetch(this.config.endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(eventData)
}).catch(console.error);
}
}
generateSessionId() {
return 'session_' + Math.random().toString(36).substr(2, 9);
}
}Health Checks
// Health check system
class HealthChecker {
constructor() {
this.checks = new Map();
this.status = 'unknown';
}
addCheck(name, checkFunction) {
this.checks.set(name, checkFunction);
}
async runChecks() {
const results = {};
let allHealthy = true;
for (const [name, check] of this.checks) {
try {
const result = await check();
results[name] = {
status: 'healthy',
result
};
} catch (error) {
results[name] = {
status: 'unhealthy',
error: error.message
};
allHealthy = false;
}
}
this.status = allHealthy ? 'healthy' : 'unhealthy';
return {
status: this.status,
checks: results,
timestamp: new Date().toISOString()
};
}
getStatus() {
return {
status: this.status,
timestamp: new Date().toISOString()
};
}
}Mini-Project: Monitoring Dashboard
// Complete monitoring dashboard
class MonitoringDashboard {
constructor() {
this.performanceMonitor = new PerformanceMonitor();
this.analytics = new Analytics({ endpoint: '/api/analytics' });
this.healthChecker = new HealthChecker();
this.setupHealthChecks();
this.setupPerformanceTracking();
this.renderDashboard();
}
setupHealthChecks() {
this.healthChecker.addCheck('api', async () => {
const response = await fetch('/api/health');
return response.ok;
});
this.healthChecker.addCheck('database', async () => {
// Simulate database check
return true;
});
}
setupPerformanceTracking() {
this.performanceMonitor.addObserver((metric) => {
this.analytics.track('performance_metric', metric);
});
}
renderDashboard() {
const dashboard = document.createElement('div');
dashboard.id = 'monitoring-dashboard';
dashboard.innerHTML = `
<div class="dashboard">
<h2>Application Monitoring</h2>
<div id="health-status">Checking health...</div>
<div id="performance-metrics">Performance metrics will appear here</div>
<div id="error-log">Error log will appear here</div>
</div>
`;
document.body.appendChild(dashboard);
this.startMonitoring();
}
async startMonitoring() {
// Health checks every 30 seconds
setInterval(async () => {
const health = await this.healthChecker.runChecks();
this.updateHealthStatus(health);
}, 30000);
// Performance monitoring
this.performanceMonitor.startTiming('page_load');
window.addEventListener('load', () => {
this.performanceMonitor.endTiming('page_load');
});
}
updateHealthStatus(health) {
const statusElement = document.getElementById('health-status');
statusElement.innerHTML = `
<div class="health-status ${health.status}">
<h3>Health Status: ${health.status.toUpperCase()}</h3>
<div class="checks">
${Object.entries(health.checks).map(([name, check]) => `
<div class="check ${check.status}">
${name}: ${check.status}
</div>
`).join('')}
</div>
</div>
`;
}
}