Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Add Sentry v8 error tracking and performance monitoring to your project services. Use this skill when adding error handling, creating new controllers, instrumenting cron jobs, or tracking database performance. ALL ERRORS MUST BE CAPTURED TO SENTRY - no exceptions.
.claude/skills/microck-error-tracking/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 152% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 67% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 45% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 64% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 53% | 0% |
This skill enforces comprehensive Sentry error tracking and performance monitoring across all your project services following Sentry v8 patterns.
ALL ERRORS MUST BE CAPTURED TO SENTRY - No exceptions. Never use console.error alone.
typescript// ✅ CORRECT - Use BaseController import { BaseController } from '../controllers/BaseController'; export class MyController extends BaseController { async myMethod() { try { // ... your code } catch (error) { this.handleError(error, 'myMethod'); // Automatically sends to Sentry } } }
typescriptimport * as Sentry from '@sentry/node'; router.get('/route', async (req, res) => { try { // ... your code } catch (error) { Sentry.captureException(error, { tags: { route: '/route', method: 'GET' }, extra: { userId: req.user?.id } }); res.status(500).json({ error: 'Internal server error' }); } });
typescriptimport { WorkflowSentryHelper } from '../workflow/utils/sentryHelper'; // ✅ CORRECT - Use WorkflowSentryHelper WorkflowSentryHelper.captureWorkflowError(error, { workflowCode: 'DHS_CLOSEOUT', instanceId: 123, stepId: 456, userId: 'user-123', operation: 'stepCompletion', metadata: { additionalInfo: 'value' } });
typescript#!/usr/bin/env node // FIRST LINE after shebang - CRITICAL! import '../instrument'; import * as Sentry from '@sentry/node'; async function main() { return await Sentry.startSpan({ name: 'cron.job-name', op: 'cron', attributes: { 'cron.job': 'job-name', 'cron.startTime': new Date().toISOString(), } }, async () => { try { // Your cron job logic } catch (error) { Sentry.captureException(error, { tags: { 'cron.job': 'job-name', 'error.type': 'execution_error' } }); console.error('[Job] Error:', error); process.exit(1); } }); } main() .then(() => { console.log('[Job] Completed successfully'); process.exit(0); }) .catch((error) => { console.error('[Job] Fatal error:', error); process.exit(1); });
typescriptimport { DatabasePerformanceMonitor } from '../utils/databasePerformance'; // ✅ CORRECT - Wrap database operations const result = await DatabasePerformanceMonitor.withPerformanceTracking( 'findMany', 'UserProfile', async () => { return await PrismaService.main.userProfile.findMany({ take: 5, }); } );
typescriptimport * as Sentry from '@sentry/node'; const result = await Sentry.startSpan({ name: 'operation.name', op: 'operation.type', attributes: { 'custom.attribute': 'value' } }, async () => { // Your async operation return await someAsyncOperation(); });
Use appropriate severity levels:
typescriptimport * as Sentry from '@sentry/node'; Sentry.withScope((scope) => { // ALWAYS include these if available scope.setUser({ id: userId }); scope.setTag('service', 'form'); // or 'email', 'users', etc. scope.setTag('environment', process.env.NODE_ENV); // Add operation-specific context scope.setContext('operation', { type: 'workflow.start', workflowCode: 'DHS_CLOSEOUT', entityId: 123 }); Sentry.captureException(error); });
Location: ./blog-api/src/instrument.ts
typescriptimport * as Sentry from '@sentry/node'; import { nodeProfilingIntegration } from '@sentry/profiling-node'; Sentry.init({ dsn: process.env.SENTRY_DSN, environment: process.env.NODE_ENV || 'development', integrations: [ nodeProfilingIntegration(), ], tracesSampleRate: 0.1, profilesSampleRate: 0.1, });
Key Helpers:
WorkflowSentryHelper - Workflow-specific errorsDatabasePerformanceMonitor - DB query trackingBaseController - Controller error handlingLocation: ./notifications/src/instrument.ts
typescriptimport * as Sentry from '@sentry/node'; import { nodeProfilingIntegration } from '@sentry/profiling-node'; Sentry.init({ dsn: process.env.SENTRY_DSN, environment: process.env.NODE_ENV || 'development', integrations: [ nodeProfilingIntegration(), ], tracesSampleRate: 0.1, profilesSampleRate: 0.1, });
Key Helpers:
EmailSentryHelper - Email-specific errorsBaseController - Controller error handlingini[sentry] dsn = your-sentry-dsn environment = development tracesSampleRate = 0.1 profilesSampleRate = 0.1 [databaseMonitoring] enableDbTracing = true slowQueryThreshold = 100 logDbQueries = false dbErrorCapture = true enableN1Detection = true
bash# Test basic error capture curl http://localhost:3002/blog-api/api/sentry/test-error # Test workflow error curl http://localhost:3002/blog-api/api/sentry/test-workflow-error # Test database performance curl http://localhost:3002/blog-api/api/sentry/test-database-performance # Test error boundary curl http://localhost:3002/blog-api/api/sentry/test-error-boundary
bash# Test basic error capture curl http://localhost:3003/notifications/api/sentry/test-error # Test email-specific error curl http://localhost:3003/notifications/api/sentry/test-email-error # Test performance tracking curl http://localhost:3003/notifications/api/sentry/test-performance
typescriptimport * as Sentry from '@sentry/node'; // Automatic transaction tracking for Express routes app.use(Sentry.Handlers.requestHandler()); app.use(Sentry.Handlers.tracingHandler()); // Manual transaction for custom operations const transaction = Sentry.startTransaction({ op: 'operation.type', name: 'Operation Name', }); try { // Your operation } finally { transaction.finish(); }
❌ NEVER use console.error without Sentry ❌ NEVER swallow errors silently ❌ NEVER expose sensitive data in error context ❌ NEVER use generic error messages without context ❌ NEVER skip error handling in async operations ❌ NEVER forget to import instrument.ts as first line in cron jobs
When adding Sentry to new code:
/blog-api/src/instrument.ts - Sentry initialization/blog-api/src/workflow/utils/sentryHelper.ts - Workflow errors/blog-api/src/utils/databasePerformance.ts - DB monitoring/blog-api/src/controllers/BaseController.ts - Controller base/notifications/src/instrument.ts - Sentry initialization/notifications/src/utils/EmailSentryHelper.ts - Email errors/notifications/src/controllers/BaseController.ts - Controller base/blog-api/config.ini - Form service config/notifications/config.ini - Email service config/sentry.ini - Shared Sentry config/dev/active/email-sentry-integration//blog-api/docs/sentry-integration.md/notifications/docs/sentry-integration.md| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 14,412 | 8,288 | -42% | 1 | 1 | 0% | 2,608 | 4,175 | +60% | 0 | 0 | — |
case-02 | fail→pass | 8,587 | 8,536 | -1% | 1 | 1 | 0% | 1,679 | 4,236 | +152% | 0 | 0 | — |
case-03 | fail→pass | 12,126 | 7,015 | -42% | 1 | 1 | 0% | 2,352 | 3,937 | +67% | 0 | 0 | — |
case-04 | fail→pass | 13,589 | 6,368 | -53% | 1 | 1 | 0% | 2,572 | 3,718 | +45% | 0 | 0 | — |
case-05 | fail→pass | 12,016 | 5,975 | -50% | 1 | 1 | 0% | 2,248 | 3,685 | +64% | 0 | 0 | — |
case-06 | pass→pass | 9,554 | 6,690 | -30% | 1 | 1 | 0% | 1,621 | 3,811 | +135% | 0 | 0 | — |
case-07 | pass→pass | 9,710 | 6,162 | -37% | 1 | 1 | 0% | 1,732 | 3,747 | +116% | 0 | 0 | — |
case-08 | pass→pass | 11,823 | 8,552 | -28% | 1 | 1 | 0% | 2,287 | 4,203 | +84% | 0 | 0 | — |
case-09 | pass→pass | 14,275 | 6,065 | -58% | 1 | 1 | 0% | 2,670 | 3,724 | +39% | 0 | 0 | — |
case-10 | pass→pass | 10,441 | 8,479 | -19% | 1 | 1 | 0% | 1,956 | 3,969 | +103% | 0 | 0 | — |
case-11 | fail→fail | 15,822 | 12,196 | -23% | 1 | 1 | 0% | 2,918 | 4,802 | +65% | 0 | 0 | — |
case-12 | fail→pass | 10,732 | 2,677 | -75% | 1 | 1 | 0% | 1,953 | 2,990 | +53% | 0 | 0 | — |
case-13 | fail→pass | 12,672 | 4,834 | -62% | 1 | 1 | 0% | 2,220 | 3,391 | +53% | 0 | 0 | — |
case-14 | fail→fail | 12,056 | 1,952 | -84% | 1 | 1 | 0% | 1,991 | 2,765 | +39% | 0 | 0 | — |
case-15 | pass→pass | 4,935 | 2,155 | -56% | 1 | 1 | 0% | 789 | 2,862 | +263% | 0 | 0 | — |
case-21 | pass→pass | 9,657 | 8,248 | -15% | 1 | 1 | 0% | 1,935 | 4,043 | +109% | 0 | 0 | — |
case-16 | pass→pass | 11,452 | 3,892 | -66% | 1 | 1 | 0% | 1,703 | 3,079 | +81% | 0 | 0 | — |
case-17 | pass→pass | 10,500 | 3,980 | -62% | 1 | 1 | 0% | 1,576 | 3,249 | +106% | 0 | 0 | — |
case-18 | fail→pass | 7,729 | 2,339 | -70% | 1 | 1 | 0% | 1,242 | 2,980 | +140% | 0 | 0 | — |
case-19 | fail→pass | 9,944 | 2,176 | -78% | 1 | 1 | 0% | 1,639 | 2,885 | +76% | 0 | 0 | — |
case-20 | pass→fail | 10,130 | 7,876 | -22% | 1 | 1 | 0% | 1,829 | 3,889 | +113% | 0 | 0 | — |
case-22 | pass→pass | 11,011 | 10,361 | -6% | 1 | 1 | 0% | 2,173 | 4,482 | +106% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.