Opinionated backend development standards for Node.js + Express + TypeScript microservices. Covers layered architecture, BaseController pattern, dependency injection, Prisma repositories, Zod validation, unifiedConfig, Sentry error tracking, async safety, and testing discipline.
71
71%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
Complete guide to error tracking and performance monitoring with Sentry v8.
MANDATORY: All errors MUST be captured to Sentry. No exceptions.
ALL ERRORS MUST BE CAPTURED - Use Sentry v8 with comprehensive error tracking across all services.
Location: src/instrument.ts (MUST be first import in server.ts and all cron jobs)
Template for Microservices:
import * as Sentry from '@sentry/node';
import * as fs from 'fs';
import * as path from 'path';
import * as ini from 'ini';
const sentryConfigPath = path.join(__dirname, '../sentry.ini');
const sentryConfig = ini.parse(fs.readFileSync(sentryConfigPath, 'utf-8'));
Sentry.init({
dsn: sentryConfig.sentry?.dsn,
environment: process.env.NODE_ENV || 'development',
tracesSampleRate: parseFloat(sentryConfig.sentry?.tracesSampleRate || '0.1'),
profilesSampleRate: parseFloat(sentryConfig.sentry?.profilesSampleRate || '0.1'),
integrations: [
...Sentry.getDefaultIntegrations({}),
Sentry.extraErrorDataIntegration({ depth: 5 }),
Sentry.localVariablesIntegration(),
Sentry.requestDataIntegration({
include: {
cookies: false,
data: true,
headers: true,
ip: true,
query_string: true,
url: true,
user: { id: true, email: true, username: true },
},
}),
Sentry.consoleIntegration(),
Sentry.contextLinesIntegration(),
Sentry.prismaIntegration(),
],
beforeSend(event, hint) {
// Filter health checks
if (event.request?.url?.includes('/healthcheck')) {
return null;
}
// Scrub sensitive headers
if (event.request?.headers) {
delete event.request.headers['authorization'];
delete event.request.headers['cookie'];
}
// Mask emails for PII
if (event.user?.email) {
event.user.email = event.user.email.replace(/^(.{2}).*(@.*)$/, '$1***$2');
}
return event;
},
ignoreErrors: [
/^Invalid JWT/,
/^JWT expired/,
'NetworkError',
],
});
// Set service context
Sentry.setTags({
service: 'form',
version: '1.0.1',
});
Sentry.setContext('runtime', {
node_version: process.version,
platform: process.platform,
});Critical Points:
// Use BaseController.handleError
protected handleError(error: unknown, res: Response, context: string, statusCode = 500): void {
Sentry.withScope((scope) => {
scope.setTag('controller', this.constructor.name);
scope.setTag('operation', context);
scope.setUser({ id: res.locals?.claims?.userId });
Sentry.captureException(error);
});
res.status(statusCode).json({
success: false,
error: { message: error instanceof Error ? error.message : 'Error occurred' }
});
}import { SentryHelper } from '../utils/sentryHelper';
try {
await businessOperation();
} catch (error) {
SentryHelper.captureOperationError(error, {
operationType: 'POST_CREATION',
entityId: 123,
userId: 'user-123',
operation: 'createPost',
});
throw error;
}try {
await someOperation();
} catch (error) {
Sentry.captureException(error, {
tags: {
service: 'form',
operation: 'someOperation'
},
extra: {
userId: currentUser.id,
entityId: 123
}
});
throw error;
}import { DatabasePerformanceMonitor } from '../utils/databasePerformance';
const result = await DatabasePerformanceMonitor.withPerformanceTracking(
'findMany',
'UserProfile',
async () => {
return await PrismaService.main.userProfile.findMany({ take: 5 });
}
);router.post('/operation', async (req, res) => {
return await Sentry.startSpan({
name: 'operation.execute',
op: 'http.server',
attributes: {
'http.method': 'POST',
'http.route': '/operation'
}
}, async () => {
const result = await performOperation();
res.json(result);
});
});#!/usr/bin/env node
import '../instrument'; // FIRST LINE after shebang
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 {
// Cron job logic here
} catch (error) {
Sentry.captureException(error, {
tags: {
'cron.job': 'job-name',
'error.type': 'execution_error'
}
});
console.error('[Cron] Error:', error);
process.exit(1);
}
});
}
main().then(() => {
console.log('[Cron] Completed successfully');
process.exit(0);
}).catch((error) => {
console.error('[Cron] Fatal error:', error);
process.exit(1);
});Sentry.withScope((scope) => {
// User context
scope.setUser({
id: user.id,
email: user.email,
username: user.username
});
// Tags for filtering
scope.setTag('service', 'form');
scope.setTag('endpoint', req.path);
scope.setTag('method', req.method);
// Structured context
scope.setContext('operation', {
type: 'workflow.complete',
workflowId: 123,
stepId: 456
});
// Breadcrumbs for timeline
scope.addBreadcrumb({
category: 'workflow',
message: 'Starting step completion',
level: 'info',
data: { stepId: 456 }
});
Sentry.captureException(error);
});// ❌ Swallowing errors
try {
await riskyOperation();
} catch (error) {
// Silent failure
}
// ❌ Generic error messages
throw new Error('Error occurred');
// ❌ Exposing sensitive data
Sentry.captureException(error, {
extra: { password: user.password } // NEVER
});
// ❌ Missing async error handling
async function bad() {
fetchData().then(data => processResult(data)); // Unhandled
}
// ✅ Proper async handling
async function good() {
try {
const data = await fetchData();
processResult(data);
} catch (error) {
Sentry.captureException(error);
throw error;
}
}Related Files: