Files
myeasycms-v2/docs/monitoring/overview.mdoc
Giancarlo Buomprisco 7ebff31475 Next.js Supabase V3 (#463)
Version 3 of the kit:
- Radix UI replaced with Base UI (using the Shadcn UI patterns)
- next-intl replaces react-i18next
- enhanceAction deprecated; usage moved to next-safe-action
- main layout now wrapped with [locale] path segment
- Teams only mode
- Layout updates
- Zod v4
- Next.js 16.2
- Typescript 6
- All other dependencies updated
- Removed deprecated Edge CSRF
- Dynamic Github Action runner
2026-03-24 13:40:38 +08:00

348 lines
10 KiB
Plaintext

---
title: "Monitoring and Error Tracking in Makerkit"
status: "published"
label: "How Monitoring Works"
order: 0
description: "Set up error tracking and performance monitoring in your Next.js Supabase SaaS app with Sentry, PostHog, or SigNoz."
---
{% sequence title="Steps to configure monitoring" description="Learn how to configure monitoring in the Next.js Supabase Starter Kit." %}
[Understanding the monitoring architecture](#understanding-the-monitoring-architecture)
[Supported monitoring providers](#supported-monitoring-providers)
[Configuring your monitoring provider](#configuring-your-monitoring-provider)
[What gets monitored automatically](#what-gets-monitored-automatically)
[Manually capturing exceptions](#manually-capturing-exceptions)
[Identifying users in error reports](#identifying-users-in-error-reports)
{% /sequence %}
## Understanding the Monitoring Architecture
Makerkit's monitoring system uses a **provider-based architecture** that lets you swap monitoring services without changing your application code. The system lives in the `@kit/monitoring` package and handles:
- **Error tracking**: Capture client-side and server-side exceptions
- **Performance monitoring**: Track server response times via OpenTelemetry instrumentation
- **User identification**: Associate errors with specific users for debugging
The architecture follows a registry pattern. When you set `NEXT_PUBLIC_MONITORING_PROVIDER`, Makerkit loads the appropriate service implementation at runtime:
```
MonitoringProvider (React context)
Registry lookup
┌───────┴───────┐
│ sentry │
│ posthog │
│ signoz │
└───────────────┘
```
This means your components interact with a consistent `MonitoringService` interface regardless of which provider you choose.
## Supported Monitoring Providers
Makerkit provides first-class support for these monitoring providers:
| Provider | Error Tracking | Performance | Self-Hostable | Notes |
|----------|---------------|-------------|---------------|-------|
| [Sentry](/docs/next-supabase-turbo/monitoring/sentry) | Yes | Yes | Yes | Built-in, recommended for most apps |
| [PostHog](/docs/next-supabase-turbo/monitoring/posthog) | Yes | No | Yes | Plugin, doubles as analytics |
| [SigNoz](/docs/next-supabase-turbo/monitoring/signoz) | Yes | Yes | Yes | Plugin, OpenTelemetry-native |
**Sentry** is included out of the box. PostHog and SigNoz require installing plugins via the Makerkit CLI.
{% alert type="default" title="Custom providers" %}
You can add support for any monitoring service by implementing the `MonitoringService` interface and registering it in the provider registry. See [Adding a custom monitoring provider](#adding-a-custom-monitoring-provider) below.
{% /alert %}
## Configuring Your Monitoring Provider
Set these environment variables to enable monitoring:
```bash title=".env.local"
# Required: Choose your provider (sentry, posthog, or signoz)
NEXT_PUBLIC_MONITORING_PROVIDER=sentry
# Provider-specific configuration
# See the individual provider docs for required variables
```
The `NEXT_PUBLIC_MONITORING_PROVIDER` variable determines which service handles your errors. Leave it empty to disable monitoring entirely (errors still log to console in development).
## What Gets Monitored Automatically
Once configured, Makerkit captures errors without additional code:
### Client-side exceptions
The `MonitoringProvider` component wraps your app and captures uncaught exceptions in React components. This includes:
- Runtime errors in components
- Unhandled promise rejections
- Errors thrown during rendering
### Server-side exceptions
Next.js 15+ includes an instrumentation hook that captures server errors automatically. Makerkit hooks into this via `instrumentation.ts`:
```typescript title="apps/web/instrumentation.ts"
import { type Instrumentation } from 'next';
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,
headers: request.headers,
method: request.method,
routePath: context.routePath,
},
);
};
```
This captures errors from Server Components, Server Actions, Route Handlers, and Middleware.
## Manually Capturing Exceptions
For expected errors (like validation failures or API errors), capture them explicitly:
### In Server Actions or Route Handlers
```typescript
import { getServerMonitoringService } from '@kit/monitoring/server';
export async function createProject(data: FormData) {
try {
// ... your logic
} catch (error) {
const monitoring = await getServerMonitoringService();
await monitoring.ready();
monitoring.captureException(error, {
action: 'createProject',
userId: user.id,
});
throw error; // Re-throw or handle as needed
}
}
```
### In React Components
Use the `useMonitoring` hook for client-side error capture:
```tsx
'use client';
import { useMonitoring } from '@kit/monitoring/hooks';
export function DataLoader() {
const monitoring = useMonitoring();
async function loadData() {
try {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`Failed to load data: ${response.status}`);
}
return response.json();
} catch (error) {
monitoring.captureException(error, {
component: 'DataLoader',
});
throw error;
}
}
// ...
}
```
### The `useCaptureException` Hook
For error boundaries or components that receive errors as props:
```tsx
'use client';
import { useCaptureException } from '@kit/monitoring/hooks';
export function ErrorDisplay({ error }: { error: Error }) {
// Automatically captures the error when the component mounts
useCaptureException(error);
return (
<div>
<h2>Something went wrong</h2>
<p>{error.message}</p>
</div>
);
}
```
## Identifying Users in Error Reports
Associate errors with users to debug issues faster. Makerkit's monitoring providers support user identification:
```typescript
const monitoring = useMonitoring();
// After user signs in
monitoring.identifyUser({
id: user.id,
email: user.email,
// Additional fields depend on your provider
});
```
Makerkit automatically identifies users when they sign in if you've configured the analytics/events system. The `user.signedIn` event triggers user identification in both analytics and monitoring.
## Adding a Custom Monitoring Provider
To add a provider not included in Makerkit:
### 1. Implement the MonitoringService interface
```typescript title="packages/monitoring/my-provider/src/my-provider.service.ts"
import { MonitoringService } from '@kit/monitoring-core';
export class MyProviderMonitoringService implements MonitoringService {
private readyPromise: Promise<void>;
private readyResolver?: () => void;
constructor() {
this.readyPromise = new Promise((resolve) => {
this.readyResolver = resolve;
});
this.initialize();
}
async ready() {
return this.readyPromise;
}
captureException(error: Error, extra?: Record<string, unknown>) {
// Send to your monitoring service
myProviderSDK.captureException(error, { extra });
}
captureEvent(event: string, extra?: Record<string, unknown>) {
myProviderSDK.captureEvent(event, extra);
}
identifyUser(user: { id: string }) {
myProviderSDK.setUser(user);
}
private initialize() {
// Initialize your SDK
myProviderSDK.init({ dsn: process.env.MY_PROVIDER_DSN });
this.readyResolver?.();
}
}
```
### 2. Register the provider
Add your provider to the monitoring registries:
```typescript title="packages/monitoring/api/src/get-monitoring-provider.ts"
const MONITORING_PROVIDERS = [
'sentry',
'my-provider', // Add your provider
'',
] as const;
```
```typescript title="packages/monitoring/api/src/services/get-server-monitoring-service.ts"
serverMonitoringRegistry.register('my-provider', async () => {
const { MyProviderMonitoringService } = await import('@kit/my-provider');
return new MyProviderMonitoringService();
});
```
```typescript title="packages/monitoring/api/src/components/provider.tsx"
monitoringProviderRegistry.register('my-provider', async () => {
const { MyProviderProvider } = await import('@kit/my-provider/provider');
return {
default: function MyProviderWrapper({ children }: React.PropsWithChildren) {
return <MyProviderProvider>{children}</MyProviderProvider>;
},
};
});
```
{% alert type="default" title="Telegram notifications" %}
We wrote a tutorial showing how to add Telegram notifications for error monitoring: [Send SaaS errors to Telegram](/blog/tutorials/telegram-saas-error-monitoring).
{% /alert %}
## Best Practices
### Do capture context with errors
```typescript
// Good: Includes debugging context
monitoring.captureException(error, {
userId: user.id,
accountId: account.id,
action: 'updateBillingPlan',
planId: newPlanId,
});
// Less useful: No context
monitoring.captureException(error);
```
### Don't capture expected validation errors
```typescript
// Avoid: This clutters your error dashboard
if (!isValidEmail(email)) {
monitoring.captureException(new Error('Invalid email'));
return { error: 'Invalid email' };
}
// Better: Only capture unexpected failures
try {
await sendEmail(email);
} catch (error) {
monitoring.captureException(error, {
extra: { email: maskEmail(email) },
});
}
```
## Next Steps
Choose a monitoring provider and follow its setup guide:
- [Configure Sentry](/docs/next-supabase-turbo/monitoring/sentry) (recommended for most apps)
- [Configure PostHog](/docs/next-supabase-turbo/monitoring/posthog) (if you already use PostHog for analytics)
- [Configure SigNoz](/docs/next-supabase-turbo/monitoring/signoz) (self-hosted, OpenTelemetry-native)