Monitoring React Applications in Production

Loading

Effective production monitoring for React applications requires a comprehensive approach that covers performance, errors, user experience, and business metrics. Here’s a complete guide to implementing professional-grade monitoring:

Core Monitoring Components

1. Error Tracking

// Using Sentry
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';

Sentry.init({
  dsn: process.env.REACT_APP_SENTRY_DSN,
  integrations: [new BrowserTracing()],
  tracesSampleRate: 0.2,
  environment: process.env.NODE_ENV,
  release: process.env.REACT_APP_VERSION,
  beforeSend(event) {
    // Filter out sensitive data
    if (event.request?.url) {
      event.request.url = event.request.url.replace(/password=[^&]*/, 'password=[REDACTED]');
    }
    return event;
  }
});

// Error boundary component
const ErrorBoundary = ({ children }) => (
  <Sentry.ErrorBoundary 
    fallback={<ErrorScreen />}
    onError={(error, componentStack) => {
      // Custom error handling
    }}
  >
    {children}
  </Sentry.ErrorBoundary>
);

2. Performance Monitoring

// Using web-vitals library
import { getCLS, getFID, getLCP, getTTFB, getFCP } from 'web-vitals';

function sendToAnalytics(metric) {
  const body = JSON.stringify(metric);
  navigator.sendBeacon('/analytics', body);

  // Also send to your monitoring service
  if (window.monitoringTool) {
    window.monitoringTool.trackPerformance(metric);
  }
}

getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);
getFCP(sendToAnalytics);
getTTFB(sendToAnalytics);

Advanced Monitoring Setup

3. Real User Monitoring (RUM)

// Custom performance metrics collector
const startTime = performance.now();
let routeChangeStartTime;

export const initRouteMonitoring = (history) => {
  history.listen(() => {
    const now = performance.now();
    const routeLoadTime = now - routeChangeStartTime;

    trackMetric('route_change_time', routeLoadTime);
    routeChangeStartTime = now;
  });
};

export const trackPageLoad = () => {
  const loadTime = performance.now() - startTime;
  trackMetric('page_load_time', loadTime);

  // Capture resource timing
  const resources = performance.getEntriesByType('resource');
  trackMetric('resource_load_stats', resources);
};

4. Custom Business Metrics

// E-commerce tracking example
export const trackProductView = (product) => {
  trackEvent('product_view', {
    product_id: product.id,
    category: product.category,
    price: product.price
  });
};

export const trackCheckoutStep = (step) => {
  trackEvent('checkout_progress', {
    step,
    cart_value: getCartTotal()
  });
};

Backend Integration

5. Node.js Monitoring Setup

// Express middleware for frontend monitoring
app.use((req, res, next) => {
  const start = Date.now();
  const { originalUrl, method } = req;

  res.on('finish', () => {
    const duration = Date.now() - start;
    trackApiMetric({
      route: originalUrl,
      method,
      status: res.statusCode,
      duration,
      userAgent: req.headers['user-agent']
    });
  });

  next();
});

6. Distributed Tracing

// OpenTelemetry setup
import { WebTracerProvider } from '@opentelemetry/web';
import { SimpleSpanProcessor } from '@opentelemetry/tracing';
import { ZipkinExporter } from '@opentelemetry/exporter-zipkin';

const provider = new WebTracerProvider();
const exporter = new ZipkinExporter({
  url: 'https://your-collector.com/api/v2/spans'
});

provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.register();

Dashboard and Alerting

7. Grafana Dashboard Configuration

# Sample dashboard JSON for React metrics
{
  "panels": [
    {
      "title": "Page Load Time",
      "type": "graph",
      "datasource": "Prometheus",
      "targets": [
        {
          "expr": "avg(frontend_page_load_time_seconds)",
          "legendFormat": "Avg Load Time"
        }
      ],
      "thresholds": [
        {
          "value": 2.5,
          "color": "red",
          "op": "gt"
        }
      ]
    },
    {
      "title": "JS Errors",
      "type": "stat",
      "datasource": "Sentry",
      "targets": [
        {
          "query": "count:error{environment:production}"
        }
      ],
      "alert": {
        "conditions": [
          {
            "evaluator": {
              "params": [10],
              "type": "gt"
            }
          }
        ]
      }
    }
  ]
}

8. Alerting Rules

# Prometheus alerting rules
groups:
- name: frontend.rules
  rules:
  - alert: HighErrorRate
    expr: rate(frontend_errors_total[5m]) > 0.1
    for: 10m
    labels:
      severity: critical
    annotations:
      summary: "High error rate detected in frontend"
      description: "Error rate of {{ $value }} exceeds threshold"

  - alert: SlowPageLoad
    expr: frontend_page_load_time_seconds > 3
    for: 30m
    labels:
      severity: warning
    annotations:
      summary: "Slow page load detected"
      description: "Average load time of {{ $value }} seconds"

Synthetic Monitoring

9. Playwright Test Scripts

// smoke-test.spec.js
const { test, expect } = require('@playwright/test');

test('Homepage load', async ({ page }) => {
  const response = await page.goto('https://your-app.com');
  expect(response.status()).toBe(200);

  await expect(page.locator('text=Welcome to our app')).toBeVisible();
  const perf = await page.evaluate(() => 
    JSON.parse(JSON.stringify(performance.timing))
  );

  console.log('Page load time:', perf.loadEventEnd - perf.navigationStart);
});

test('Checkout flow', async ({ page }) => {
  await page.goto('https://your-app.com/products/1');
  await page.click('text=Add to Cart');
  await page.click('text=Checkout');

  // Measure checkout rendering time
  const start = Date.now();
  await expect(page.locator('text=Payment Method')).toBeVisible();
  const renderTime = Date.now() - start;

  trackMetric('checkout_render_time', renderTime);
});

Log Management

10. Structured Frontend Logging

// Enhanced logger with context
class FrontendLogger {
  constructor() {
    this.context = {
      appVersion: process.env.REACT_APP_VERSION,
      userId: null,
      sessionId: this.generateSessionId()
    };
  }

  log(level, message, metadata = {}) {
    const logEntry = {
      timestamp: new Date().toISOString(),
      level,
      message,
      ...this.context,
      ...metadata,
      userAgent: navigator.userAgent,
      url: window.location.href
    };

    // Send to log service
    fetch('/logs', {
      method: 'POST',
      body: JSON.stringify(logEntry),
      headers: { 'Content-Type': 'application/json' }
    }).catch(() => {
      // Fallback to console if network fails
      console[level](logEntry);
    });
  }

  generateSessionId() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
      const r = Math.random() * 16 | 0;
      const v = c === 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  }
}

// Usage
const logger = new FrontendLogger();
logger.log('error', 'Cart validation failed', { cartId: '123' });

Monitoring Strategy Checklist

  1. Error Tracking
  • [ ] Implement error boundaries
  • [ ] Track unhandled exceptions
  • [ ] Monitor API failures
  1. Performance Monitoring
  • [ ] Track Core Web Vitals
  • [ ] Measure route change times
  • [ ] Monitor resource loading
  1. User Experience
  • [ ] Track key user journeys
  • [ ] Measure interaction delays
  • [ ] Monitor abandoned flows
  1. Business Metrics
  • [ ] Track conversions
  • [ ] Monitor engagement metrics
  • [ ] Measure feature adoption
  1. Infrastructure
  • [ ] Monitor CDN performance
  • [ ] Track asset caching
  • [ ] Measure third-party script impact
  1. Alerting
  • [ ] Set up error rate alerts
  • [ ] Configure performance degradation alerts
  • [ ] Implement business metric thresholds
  1. Synthetic Monitoring
  • [ ] Set up smoke tests
  • [ ] Monitor critical user journeys
  • [ ] Test from multiple locations
  1. Log Management
  • [ ] Implement structured logging
  • [ ] Centralize frontend logs
  • [ ] Correlate with backend logs

Tooling Recommendations

  1. Error Tracking
  • Sentry
  • Rollbar
  • Bugsnag
  1. Performance Monitoring
  • New Relic Browser
  • Datadog RUM
  • Google Analytics 4
  1. Synthetic Monitoring
  • Checkly
  • Pingdom
  • UptimeRobot
  1. Log Management
  • ELK Stack
  • Splunk
  • Grafana Loki
  1. Dashboarding
  • Grafana
  • Datadog
  • Kibana

Leave a Reply

Your email address will not be published. Required fields are marked *