Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt

Use this file to discover all available pages before exploring further.

Spec: PF-07 — Error Handling & Monitoring
Last Updated: 2026-03-14
For operational procedures (alerting, dashboards, escalation), see MONITORING_RUNBOOK.md.

Structured Logger

All logging must use the platform logger. Never use console.log in production code.
import { logger } from '@/platform/monitoring';

// Info-level log with context
logger.info('Employee created', {
  module: 'hr',
  action: 'employee_create',
});

// Error-level log with error object
logger.error('Failed to save document', error, {
  module: 'pf',
  action: 'document_save_error',
});

// Set persistent context (e.g., after login)
logger.setContext({
  user_id: session.user.id,
  org_id: organizationId,
  correlation_id: crypto.randomUUID(),
});

// Clear context on logout
logger.clearContext();

Rules

  • NEVER log PHI/PII — only stable IDs (user_id, org_id, entity UUIDs)
  • Always include module (core prefix: pf, hr, fa, etc.) and action
  • Use logger.error() with an Error object for stack trace capture
  • Use sanitizeErrorMessage(error) for any user-facing error text

Error Boundaries

Wrap components in <ErrorBoundary> to prevent crashes from propagating.
import { ErrorBoundary } from '@/platform/monitoring';

// Feature-level boundary (recommended for route modules)
<ErrorBoundary level="feature">
  <MyFeatureModule />
</ErrorBoundary>

// Component-level boundary (for non-critical widgets)
<ErrorBoundary level="component" fallback={<p>Widget unavailable</p>}>
  <OptionalWidget />
</ErrorBoundary>

Levels

LevelUse CaseFallback
globalApp root (main.tsx, App.tsx)Full-page error screen
featureRoute modules (RouteLoader.tsx)Module-level error screen
componentIndividual widgetsCustom or default inline fallback

Suppressed Errors

The ErrorBoundary suppresses known non-actionable errors (WebSocket unavailable, insecure context) to prevent unnecessary UI crashes. See SUPPRESSED_PATTERNS in ErrorBoundary.tsx.

Performance Monitoring

Automatic Tracking

  • Web Vitals (LCP, INP, CLS): Tracked by Sentry via reactRouterV6BrowserTracingIntegration
  • Page load / DOM ready: Tracked by performanceMonitorpf_health_metrics

Custom Marks

import { performanceMonitor } from '@/platform/monitoring';

// Measure a specific operation
const markId = performanceMonitor.startMark('heavy-calculation');
// ... do work ...
performanceMonitor.endMark(markId);

API Metrics

API response times are tracked automatically via api-metrics.ts when enabled. Histograms are flushed to pf_health_metrics periodically.

Sentry Integration

Error Capture

Sentry captures unhandled errors automatically. For manual capture:
import * as Sentry from '@sentry/react';

// Capture an exception with context
Sentry.captureException(error, {
  tags: { module: 'hr', action: 'payroll_calc' },
});

// Capture a message
Sentry.captureMessage('Unexpected state', 'warning');

Session Replay

Session replays are recorded at 100% for error sessions. All text is masked and media is blocked for HIPAA compliance. No configuration needed — this is handled in sentry.ts.

PHI Safety

The beforeSend callback in sentry.ts scrubs potential PHI patterns (emails, phone numbers, SSNs, DOBs) from all events before they leave the browser. Only UUIDs are sent as user/org identifiers.

Correlation IDs

Auth state changes generate a correlation_id (via crypto.randomUUID()) that is set in the logger context. This enables tracing all logs from a single auth session. The correlation ID is automatically set in App.tsx for SIGNED_IN, TOKEN_REFRESHED, and SIGNED_OUT events.

Checklist for New Features

  • Use logger instead of console.*
  • Include module and action in all log context
  • Never log PHI/PII
  • Wrap route modules in <ErrorBoundary level="feature">
  • Use sanitizeErrorMessage() for user-facing errors
  • Add performanceMonitor.startMark()/endMark() for heavy operations