|$ curl https://forge-ai.dev/api/markdown?path=docs/js/monitoring
$cat docs/javascript-monitoring-&-logging.md
updated Recently·16 min read·published

JavaScript Monitoring & Logging

JavaScriptMonitoringDebuggingAdvanced🎯Free Tools
Why Monitor JavaScript?

JavaScript monitoring captures errors, performance metrics, and user behavior in production. Unlike backend monitoring, frontend monitoring must account for diverse browser environments, network conditions, device capabilities, and user interactions. A comprehensive monitoring strategy includes error tracking, performance monitoring, logging, and user session replay.

Without monitoring, bugs that only occur in production (specific browser versions, network conditions, or user flows) go undetected. Monitoring provides the observability needed to debug issues you cannot reproduce locally and to measure the real-world performance impact of your code changes.

Error Tracking

Error tracking aggregates and deduplicates JavaScript errors from production users. Services like Sentry, Datadog RUM, and Rollbar capture stack traces, browser metadata, user context, and breadcrumbs leading up to the error. Source maps are uploaded to translate minified stack traces back to original source.

sentry-setup.js
JavaScript
1// Sentry initialization
2import * as Sentry from '@sentry/react';
3
4Sentry.init({
5 dsn: 'https://your-dsn@sentry.io/project-id',
6 environment: process.env.NODE_ENV,
7 release: process.env.COMMIT_SHA,
8 tracesSampleRate: 0.1, // Performance tracing (10% of transactions)
9 replaysSessionSampleRate: 0.1, // Session replay (10%)
10 replaysOnErrorSampleRate: 1.0, // Always capture replay on error
11});
12
13// Manual error capture
14try {
15 riskyOperation();
16} catch (error) {
17 Sentry.captureException(error, {
18 tags: { component: 'CheckoutForm' },
19 extra: { cartTotal: 149.99, userId: 'usr_123' },
20 });
21}
22
23// Breadcrumbs — user actions leading to error
24Sentry.addBreadcrumb({
25 category: 'ui',
26 message: 'User clicked "Submit Order"',
27 level: 'info',
28});
29
30// Set user context for grouping
31Sentry.setUser({ id: userId, email: userEmail });
Performance Monitoring

Core Web Vitals are the primary performance metrics: Largest Contentful Paint (LCP), First Input Delay (FID) / Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS). The Performance API and web-vitals library provide programmatic access to these metrics for custom monitoring.

web-vitals.js
JavaScript
1// Web Vitals — metric reporting
2import { onLCP, onFID, onCLS, onINP, onTTFB } from 'web-vitals';
3
4function sendToAnalytics(metric) {
5 const body = {
6 name: metric.name,
7 value: metric.value,
8 rating: metric.rating, // 'good' | 'needs-improvement' | 'poor'
9 delta: metric.delta,
10 id: metric.id, // Unique ID for dedup
11 navigationType: metric.navigationType,
12 };
13
14 // Send to your analytics provider
15 navigator.sendBeacon('/api/vitals', JSON.stringify(body));
16}
17
18onLCP(sendToAnalytics);
19onFID(sendToAnalytics);
20onCLS(sendToAnalytics);
21onINP(sendToAnalytics);
22onTTFB(sendToAnalytics);
23
24// Custom performance marks for SPA navigation
25function trackPageLoad(pageName) {
26 performance.mark(`${pageName}-start`);
27 // ... page renders ...
28 performance.mark(`${pageName}-end`);
29 performance.measure(
30 `${pageName}-load`,
31 `${pageName}-start`,
32 `${pageName}-end`
33 );
34 const entries = performance.getEntriesByName(`${pageName}-load`);
35 console.log(`${pageName} loaded in ${entries[0].duration}ms`);
36}
37
38// Long task monitoring
39const observer = new PerformanceObserver((list) => {
40 for (const entry of list.getEntries()) {
41 if (entry.duration > 50) {
42 console.warn('Long task detected:', entry.duration, 'ms');
43 reportLongTask(entry);
44 }
45 }
46});
47observer.observe({ type: 'longtask', buffered: true });
Structured Logging

Structured logging outputs JSON-formatted log entries with consistent fields, making them queryable in log management systems (Datadog, Grafana, ELK). In the browser, use structured log levels and include context like timestamps, user IDs, and action names. In Node.js, structured logging is essential for production observability.

logger.js
JavaScript
1// Structured logger utility
2const LOG_LEVELS = {
3 debug: 0, info: 1, warn: 2, error: 3,
4};
5
6class Logger {
7 constructor(context = {}) {
8 this.context = context;
9 }
10
11 _log(level, message, data = {}) {
12 if (LOG_LEVELS[level] < LOG_LEVELS[this.context.level || 'info']) {
13 return;
14 }
15 const entry = {
16 timestamp: new Date().toISOString(),
17 level,
18 message,
19 ...this.context,
20 ...data,
21 };
22 // In production, batch and send to logging endpoint
23 if (level === 'error') {
24 console.error(JSON.stringify(entry));
25 } else if (level === 'warn') {
26 console.warn(JSON.stringify(entry));
27 } else {
28 console.log(JSON.stringify(entry));
29 }
30 // Network batching for production
31 this._buffer.push(entry);
32 }
33
34 child(childContext) {
35 return new Logger({ ...this.context, ...childContext });
36 }
37}
38
39const logger = new Logger({ service: 'web-app', version: '1.2.0' });
40logger.info('User action', { action: 'checkout_start', cartValue: 59.99 });
41logger.error('Payment failed', { error: 'card_declined', code: 'declined_01' });
Key Takeaways
  • Error tracking with source maps is essential for debugging minified production code
  • Monitor Core Web Vitals (LCP, INP, CLS) for real-user performance data
  • Use structured logging with consistent fields for queryability
  • Session replay captures the user's viewport leading up to an error
  • Set up performance budgets and alerts to catch regressions before they reach users

Community

Get help on Slack, Discord or VIP

Stuck on a guide? Join the community and ask.