Monitoring Overview

Capture exceptions, track performance, and identify users with a provider-agnostic monitoring system. Built-in Sentry support with extensible architecture.

The monitoring system provides exception tracking and performance monitoring through a provider-agnostic architecture. Sentry is supported out of the box, and you can add custom providers using the registry pattern.

Features

  • Exception capture - Automatic and manual error tracking
  • User identification - Associate errors with authenticated users
  • Performance monitoring - Next.js instrumentation hook integration
  • Client error boundary - Catch and report React errors
  • Server error capture - Track server-side exceptions automatically
  • Provider-agnostic - Switch providers without changing application code
  • Console fallback - Development-friendly logging when no provider is configured

How It Works

The monitoring system consists of three packages:

PackagePurpose
@kit/monitoring-coreBase interfaces and console service
@kit/monitoring/apiProvider registry, hooks, and components
@kit/sentrySentry implementation

Architecture

  1. MonitoringService - Abstract class that providers implement
  2. MonitoringProvider - React context provider that loads the active service
  3. Registry - Dynamic provider loading based on environment variable
  4. Instrumentation - Next.js integration for server-side error capture

Quick Start

Environment Configuration

Set the monitoring provider in your environment file:

apps/web/.env.local

NEXT_PUBLIC_MONITORING_PROVIDER=sentry
NEXT_PUBLIC_SENTRY_DSN=https://xxxxx@xxxxx.ingest.sentry.io/xxxxx

Leave NEXT_PUBLIC_MONITORING_PROVIDER empty to use the console fallback (useful for development).

Capture an Exception Manually

The useCaptureException hook automatically captures an error when the component mounts. This is ideal for error boundary patterns:

import { useCaptureException } from '@kit/monitoring/hooks';
function ErrorDisplay({ error }: { error: Error }) {
// Captures the error automatically on mount
useCaptureException(error);
return <div>Something went wrong</div>;
}

For more control (e.g., capturing errors from event handlers), use the useMonitoring hook:

import { useMonitoring } from '@kit/monitoring/hooks';
function MyComponent() {
const monitoring = useMonitoring();
const handleSubmit = async () => {
try {
await submitForm();
} catch (error) {
monitoring.captureException(error as Error, {
context: 'form_submission',
});
}
};
// ...
}

Server-Side Exception Capture

In Server Actions or API routes:

import { getServerMonitoringService } from '@kit/monitoring/server';
export async function processPayment() {
const monitoring = await getServerMonitoringService();
try {
// Process payment...
} catch (error) {
await monitoring.captureException(error as Error, {
context: 'payment_processing',
});
throw error;
}
}

Automatic Error Capture

Client-Side Errors

The MonitoringProvider component wraps your application and provides the monitoring context. Client-side errors in React components are automatically captured when using the error page pattern:

apps/web/app/[locale]/error.tsx

'use client';
import { useCaptureException } from '@kit/monitoring/hooks';
export default function ErrorPage({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
useCaptureException(error);
return (
<div>
<h2>Something went wrong</h2>
<button onClick={reset}>Try again</button>
</div>
);
}

Server-Side Errors

Server errors are captured automatically via the Next.js instrumentation hook in apps/web/instrumentation.ts:

apps/web/instrumentation.ts

import type { Instrumentation } from 'next';
export async function register() {
const { registerMonitoringInstrumentation } =
await import('@kit/monitoring/instrumentation');
await registerMonitoringInstrumentation();
}
export const onRequestError: Instrumentation.onRequestError = async (
err,
request,
context,
) => {
const { getServerMonitoringService } = await import('@kit/monitoring/server');
const service = await getServerMonitoringService();
await service.ready();
await service.captureException(err as Error, {}, {
path: request.path,
method: request.method,
routePath: context.routePath,
});
};

This captures all unhandled server errors with request context automatically.

User Identification

Associate errors with users for better debugging:

import { useMonitoring } from '@kit/monitoring/hooks';
function UserProvider({ user }) {
const monitoring = useMonitoring();
useEffect(() => {
if (user) {
monitoring.identifyUser({
id: user.id,
email: user.email,
});
}
}, [user, monitoring]);
return <>{children}</>;
}

Topics

  1. Sentry Configuration - Set up Sentry for production monitoring
  2. Custom Monitoring Provider - Integrate LogRocket, Bugsnag, Datadog, or other services

API Reference

MonitoringService

The interface that monitoring providers implement:

abstract class MonitoringService {
// Capture an exception
abstract captureException<Extra, Config>(
error: Error & { digest?: string },
extra?: Extra,
config?: Config,
): unknown;
// Track a custom event
abstract captureEvent<Extra>(
event: string,
extra?: Extra,
): unknown;
// Identify a user
abstract identifyUser<Info extends { id: string }>(
info: Info,
): unknown;
// Wait for the service to be ready
abstract ready(): Promise<unknown>;
}

Hooks

HookPurpose
useMonitoring()Access the full monitoring service
useCaptureException(error)Capture an error (fires once on mount)

Components

ComponentPurpose
MonitoringProviderContext provider that loads the active service
ErrorBoundaryReact error boundary with monitoring integration

Important Notes

  • Provider selection - Set NEXT_PUBLIC_MONITORING_PROVIDER to enable a provider
  • Console fallback - Without a provider, errors log to console (development-friendly)
  • Async ready - Call await service.ready() before capturing in server contexts
  • Error digests - Next.js error digests are preserved for correlation

Frequently Asked Questions

Do I need to configure monitoring for development?
No. Without NEXT_PUBLIC_MONITORING_PROVIDER set, the kit uses ConsoleMonitoringService which logs errors to the console. This is ideal for local development.
Are server-side errors captured automatically?
Yes. The instrumentation.ts file uses Next.js onRequestError hook to automatically capture all unhandled server errors with request context (path, method, route).
How do I associate errors with specific users?
Use monitoring.identifyUser({ id, email }) after authentication. Sentry and other providers will then attach user information to all subsequent error reports.
What is the difference between useCaptureException and useMonitoring?
useCaptureException(error) automatically captures an error on component mount, ideal for error boundaries. useMonitoring() gives you full access to the monitoring service for manual captures in event handlers.
Can I use a monitoring provider other than Sentry?
Yes. Implement the MonitoringService interface, register your provider in the monitoring registry, and add your provider name to the MONITORING_PROVIDERS array. See the Custom Monitoring Provider guide.

Next: Sentry Configuration →