Sentry
"Sentry: error tracking, performance monitoring, session replay, source maps, breadcrumbs, Next.js/React SDK, alerts"
Sentry is an application monitoring platform focused on error tracking and performance monitoring. The guiding principles are:
## Key Points
- **Capture every error with context** — stack traces alone are insufficient; breadcrumbs, user context, and environment data turn noise into actionable insight.
- **Performance is a feature** — track transaction durations, web vitals, and database queries to find bottlenecks before users complain.
- **Source maps are non-negotiable** — minified stack traces are useless; always upload source maps in CI so production errors point to original source lines.
- **Alert on impact, not volume** — configure alerts based on issue frequency, affected users, or regression detection rather than raw error counts.
- **Release tracking closes the loop** — tie errors to specific deploys so you know exactly which commit introduced a regression.
1. **Set `tracesSampleRate` low in production** — 0.1 to 0.2 is typical; 1.0 will blow through quotas and add overhead.
2. **Use `beforeSend` to scrub PII** — strip emails, tokens, and passwords from error payloads before they leave the client.
3. **Tag errors by feature area** — use `Sentry.setTag("feature", "checkout")` so you can filter dashboards per team.
4. **Configure alert rules for regressions** — Sentry can detect when a previously resolved issue reappears after a deploy.
5. **Use the tunnel route in Next.js** — the `/monitoring` tunnel bypasses ad-blockers that strip Sentry requests.
6. **Upload source maps in CI, not at build time** — keeps your build fast and ensures maps are always tied to a release.
7. **Set meaningful release names** — use short git SHAs or semantic versions so the Releases dashboard is navigable.skilldb get monitoring-services-skills/SentryFull skill: 258 linesSentry Monitoring Skill
Core Philosophy
Sentry is an application monitoring platform focused on error tracking and performance monitoring. The guiding principles are:
- Capture every error with context — stack traces alone are insufficient; breadcrumbs, user context, and environment data turn noise into actionable insight.
- Performance is a feature — track transaction durations, web vitals, and database queries to find bottlenecks before users complain.
- Source maps are non-negotiable — minified stack traces are useless; always upload source maps in CI so production errors point to original source lines.
- Alert on impact, not volume — configure alerts based on issue frequency, affected users, or regression detection rather than raw error counts.
- Release tracking closes the loop — tie errors to specific deploys so you know exactly which commit introduced a regression.
Setup
Next.js SDK Installation
// Install dependencies
// npm install @sentry/nextjs
// sentry.client.config.ts
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NODE_ENV,
release: process.env.SENTRY_RELEASE,
tracesSampleRate: process.env.NODE_ENV === "production" ? 0.2 : 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
integrations: [
Sentry.replayIntegration({
maskAllText: false,
blockAllMedia: false,
}),
Sentry.browserTracingIntegration(),
],
ignoreErrors: [
"ResizeObserver loop limit exceeded",
"Network request failed",
/Loading chunk \d+ failed/,
],
});
Server-Side Configuration
// sentry.server.config.ts
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
release: process.env.SENTRY_RELEASE,
tracesSampleRate: 0.2,
profilesSampleRate: 0.1,
integrations: [
Sentry.prismaIntegration(),
],
beforeSend(event) {
if (event.exception?.values?.[0]?.type === "HealthCheckError") {
return null; // Drop health check noise
}
return event;
},
});
Next.js Config Integration
// next.config.ts
import { withSentryConfig } from "@sentry/nextjs";
const nextConfig = {
// your existing config
};
export default withSentryConfig(nextConfig, {
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
silent: true,
hideSourceMaps: true,
widenClientFileUpload: true,
tunnelRoute: "/monitoring", // Bypass ad-blockers
});
Key Techniques
Structured Error Boundaries
// components/SentryErrorBoundary.tsx
import * as Sentry from "@sentry/nextjs";
import { Component, type ErrorInfo, type ReactNode } from "react";
interface Props {
fallback: ReactNode;
children: ReactNode;
context?: string;
}
interface State {
hasError: boolean;
eventId: string | null;
}
export class SentryErrorBoundary extends Component<Props, State> {
state: State = { hasError: false, eventId: null };
static getDerivedStateFromError(): Partial<State> {
return { hasError: true };
}
componentDidCatch(error: Error, info: ErrorInfo) {
const eventId = Sentry.captureException(error, {
contexts: {
react: { componentStack: info.componentStack },
feature: { area: this.props.context ?? "unknown" },
},
});
this.setState({ eventId });
}
render() {
if (this.state.hasError) {
return this.props.fallback;
}
return this.props.children;
}
}
Custom Breadcrumbs and Context
// lib/sentry-helpers.ts
import * as Sentry from "@sentry/nextjs";
export function trackUserAction(action: string, data?: Record<string, unknown>) {
Sentry.addBreadcrumb({
category: "user-action",
message: action,
data,
level: "info",
});
}
export function setUserContext(user: { id: string; email: string; plan: string }) {
Sentry.setUser({ id: user.id, email: user.email });
Sentry.setTag("plan", user.plan);
Sentry.setContext("subscription", { plan: user.plan });
}
export function captureBusinessError(
message: string,
metadata: Record<string, unknown>
) {
Sentry.captureMessage(message, {
level: "warning",
tags: { domain: "business-logic" },
extra: metadata,
});
}
Performance Transactions
// lib/sentry-perf.ts
import * as Sentry from "@sentry/nextjs";
export async function tracedOperation<T>(
name: string,
op: string,
fn: () => Promise<T>
): Promise<T> {
return Sentry.startSpan(
{ name, op, attributes: { "code.function": name } },
async (span) => {
try {
const result = await fn();
span.setStatus({ code: 1, message: "ok" });
return result;
} catch (error) {
span.setStatus({ code: 2, message: "error" });
Sentry.captureException(error);
throw error;
}
}
);
}
// Usage in an API route
export async function POST(request: Request) {
return tracedOperation("create-order", "http.server", async () => {
const body = await request.json();
const order = await tracedOperation("db.insert-order", "db.query", () =>
db.order.create({ data: body })
);
await tracedOperation("email.send-confirmation", "queue.publish", () =>
emailQueue.send({ orderId: order.id })
);
return Response.json(order);
});
}
Source Map Upload in CI
// scripts/sentry-release.ts
import { execSync } from "child_process";
const version = process.env.GITHUB_SHA?.slice(0, 7) ?? "local";
const org = process.env.SENTRY_ORG!;
const project = process.env.SENTRY_PROJECT!;
function run(cmd: string) {
execSync(cmd, { stdio: "inherit" });
}
run(`sentry-cli releases new ${version} --org ${org} --project ${project}`);
run(`sentry-cli releases files ${version} upload-sourcemaps .next --org ${org} --project ${project}`);
run(`sentry-cli releases set-commits ${version} --auto --org ${org} --project ${project}`);
run(`sentry-cli releases finalize ${version} --org ${org} --project ${project}`);
run(`sentry-cli releases deploys ${version} new -e production --org ${org} --project ${project}`);
Best Practices
- Set
tracesSampleRatelow in production — 0.1 to 0.2 is typical; 1.0 will blow through quotas and add overhead. - Use
beforeSendto scrub PII — strip emails, tokens, and passwords from error payloads before they leave the client. - Tag errors by feature area — use
Sentry.setTag("feature", "checkout")so you can filter dashboards per team. - Configure alert rules for regressions — Sentry can detect when a previously resolved issue reappears after a deploy.
- Use the tunnel route in Next.js — the
/monitoringtunnel bypasses ad-blockers that strip Sentry requests. - Upload source maps in CI, not at build time — keeps your build fast and ensures maps are always tied to a release.
- Set meaningful release names — use short git SHAs or semantic versions so the Releases dashboard is navigable.
- Add breadcrumbs at key user flows — login, checkout, file upload; these provide the "what happened before the crash" timeline.
Anti-Patterns
- Catching and swallowing errors —
try { ... } catch (e) { console.log(e) }hides failures from Sentry entirely. Re-throw or callcaptureException. - Sample rate of 1.0 in production — generates massive data volumes, inflates costs, and can degrade app performance.
- Ignoring source maps — reading minified stack traces wastes hours of debugging time; always upload maps.
- Alerting on every single error — leads to alert fatigue. Alert on frequency spikes, new issues, or regressions instead.
- Storing secrets in Sentry context — never attach API keys, passwords, or tokens to error events. Use
beforeSendto filter. - Skipping
environmentconfiguration — without it, staging and production errors mix together, making triage impossible. - Not setting user context — without
Sentry.setUser(), you cannot tell how many unique users are affected by an issue.
Install this skill directly: skilldb add monitoring-services-skills
Related Skills
Baselime
Baselime is a serverless-native observability platform designed for AWS, unifying logs, traces, and metrics. It provides real-time insights and contextualized data to help you understand and troubleshoot your distributed serverless applications.
BetterStack
"BetterStack (formerly Better Uptime + Logtail): uptime monitoring, log management, status pages, incident management, alerting"
Checkly
"Checkly: synthetic monitoring, API checks, browser checks, Playwright-based E2E monitoring, monitoring-as-code CLI"
Cronitor
Cronitor is a robust monitoring service designed to ensure your background jobs (cron jobs, scheduled tasks, async workers) and APIs run reliably. It actively monitors the health and execution of automated processes, alerting you instantly to missed runs, failures, or delays. Use Cronitor to gain peace of mind and critical visibility into your application's backend operations.
Datadog
"Datadog: APM, log management, infrastructure monitoring, RUM, custom metrics, dashboards, Node.js tracing"
Grafana Cloud
Grafana Cloud is a fully managed observability platform that unifies metrics (Prometheus/Graphite), logs (Loki), and traces (Tempo) within a single Grafana interface. Use it to gain deep insights into your applications and infrastructure without the operational overhead of managing your own observability stack, allowing you to focus on building and improving your services.