Monitors applications with Sentry including error tracking, performance monitoring, and alerting. Use when tracking errors, monitoring performance, setting up alerts, or debugging production issues.
Monitors applications with Sentry including error tracking, performance monitoring, and alerting. Use when tracking errors, monitoring performance, setting up alerts, or debugging production issues.
/plugin marketplace add mgd34msu/goodvibes-plugin/plugin install goodvibes@goodvibes-marketThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Application monitoring platform for error tracking and performance monitoring.
Install (Next.js):
npx @sentry/wizard@latest -i nextjs
Manual install:
npm install @sentry/nextjs
# .env.local
SENTRY_DSN=https://xxx@xxx.ingest.sentry.io/xxx
SENTRY_AUTH_TOKEN=sntrys_...
SENTRY_ORG=your-org
SENTRY_PROJECT=your-project
// sentry.client.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
// Performance Monitoring
tracesSampleRate: 1.0, // 100% in dev, lower in prod
// Session Replay
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
integrations: [
Sentry.replayIntegration({
maskAllText: true,
blockAllMedia: true,
}),
],
// Release tracking
release: process.env.NEXT_PUBLIC_SENTRY_RELEASE,
// Ignore specific errors
ignoreErrors: [
'ResizeObserver loop limit exceeded',
'Non-Error promise rejection',
],
// Filter breadcrumbs
beforeBreadcrumb(breadcrumb) {
if (breadcrumb.category === 'console') {
return null; // Don't capture console logs
}
return breadcrumb;
},
});
// sentry.server.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
// Additional server-side options
profilesSampleRate: 1.0,
});
// sentry.edge.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
});
// next.config.js
const { withSentryConfig } = require('@sentry/nextjs');
const nextConfig = {
// Your Next.js config
};
module.exports = withSentryConfig(nextConfig, {
// Sentry webpack plugin options
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
// Upload source maps
silent: true,
widenClientFileUpload: true,
hideSourceMaps: true,
// Disable Sentry during builds
disableLogger: true,
});
Sentry automatically captures:
import * as Sentry from '@sentry/nextjs';
// Capture exception
try {
riskyOperation();
} catch (error) {
Sentry.captureException(error);
}
// Capture message
Sentry.captureMessage('Something happened');
// With severity
Sentry.captureMessage('Warning message', 'warning');
Sentry.captureMessage('Info message', 'info');
// Set user context
Sentry.setUser({
id: user.id,
email: user.email,
username: user.username,
});
// Clear user on logout
Sentry.setUser(null);
// Add tags
Sentry.setTag('feature', 'checkout');
Sentry.setTag('plan', 'premium');
// Add extra data
Sentry.setExtra('cart_items', cartItems);
// Set context
Sentry.setContext('order', {
orderId: order.id,
total: order.total,
items: order.items.length,
});
// Configure scope for specific capture
Sentry.withScope((scope) => {
scope.setTag('section', 'payments');
scope.setLevel('error');
scope.setExtra('paymentData', paymentData);
Sentry.captureException(error);
});
'use client';
import * as Sentry from '@sentry/nextjs';
import { Component, ReactNode } from 'react';
interface Props {
children: ReactNode;
fallback: ReactNode;
}
interface State {
hasError: boolean;
}
export class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
Sentry.withScope((scope) => {
scope.setExtra('componentStack', errorInfo.componentStack);
Sentry.captureException(error);
});
}
render() {
if (this.state.hasError) {
return this.props.fallback;
}
return this.props.children;
}
}
import * as Sentry from '@sentry/nextjs';
<Sentry.ErrorBoundary
fallback={<p>Something went wrong</p>}
showDialog
>
<App />
</Sentry.ErrorBoundary>
// app/api/example/route.ts
import * as Sentry from '@sentry/nextjs';
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
try {
const data = await request.json();
// Process data
return NextResponse.json({ success: true });
} catch (error) {
Sentry.captureException(error, {
extra: {
endpoint: '/api/example',
method: 'POST',
},
});
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
import { wrapApiHandlerWithSentry } from '@sentry/nextjs';
async function handler(req: NextRequest) {
// Your API logic
}
export const POST = wrapApiHandlerWithSentry(handler, '/api/example');
import * as Sentry from '@sentry/nextjs';
async function processOrder(orderId: string) {
return Sentry.startSpan(
{
name: 'Process Order',
op: 'order.process',
},
async (span) => {
span.setAttribute('order_id', orderId);
// Nested span
await Sentry.startSpan(
{
name: 'Validate Order',
op: 'order.validate',
},
async () => {
await validateOrder(orderId);
}
);
// Another nested span
await Sentry.startSpan(
{
name: 'Charge Payment',
op: 'payment.charge',
},
async () => {
await chargePayment(orderId);
}
);
return { success: true };
}
);
}
// Measure async operation
const result = await Sentry.startSpan(
{ name: 'Database Query', op: 'db.query' },
async () => {
return await db.query.users.findMany();
}
);
// app/actions.ts
'use server';
import * as Sentry from '@sentry/nextjs';
export async function submitForm(formData: FormData) {
return Sentry.withServerActionInstrumentation(
'submitForm',
{},
async () => {
try {
// Process form
const result = await processForm(formData);
return { success: true, data: result };
} catch (error) {
Sentry.captureException(error);
return { success: false, error: 'Form submission failed' };
}
}
);
}
// sentry.client.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
integrations: [
Sentry.replayIntegration({
// Capture 10% of sessions
maskAllText: true,
blockAllMedia: true,
}),
],
// Sample rates
replaysSessionSampleRate: 0.1, // 10% of sessions
replaysOnErrorSampleRate: 1.0, // 100% of sessions with errors
});
// next.config.js
module.exports = withSentryConfig(nextConfig, {
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
// Hide source maps from client
hideSourceMaps: true,
// Automatically delete source maps after upload
deleteFilesAfterUpload: ['**/*.map'],
});
npx @sentry/cli sourcemaps upload ./dist \
--org your-org \
--project your-project \
--auth-token $SENTRY_AUTH_TOKEN
Configure in Sentry dashboard:
Sentry.init({
dsn: process.env.SENTRY_DSN,
beforeSend(event, hint) {
// Filter out known issues
if (event.exception?.values?.[0]?.type === 'NetworkError') {
return null; // Don't send
}
// Modify event
if (event.user) {
delete event.user.email; // Remove PII
}
return event;
},
beforeSendTransaction(transaction) {
// Filter transactions
if (transaction.transaction === '/health') {
return null;
}
return transaction;
},
});
// Set release in config
Sentry.init({
dsn: process.env.SENTRY_DSN,
release: process.env.VERCEL_GIT_COMMIT_SHA,
});
// Or dynamically
Sentry.init({
dsn: process.env.SENTRY_DSN,
release: `${process.env.npm_package_name}@${process.env.npm_package_version}`,
});
| Mistake | Fix |
|---|---|
| Exposing DSN client-side | DSN is safe to expose |
| 100% sample rate in prod | Use lower rates |
| Missing source maps | Configure upload in build |
| No user context | Set user on login |
| Capturing too much | Filter with beforeSend |
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.