Privacy-focused error tracking and performance monitoring using Sentry. Opt-in design with automatic data sanitization to protect sensitive information.
Core Purpose
- Provide opt-in error tracking
- Sanitize sensitive data automatically
- Capture performance metrics
- Enable debugging with breadcrumbs
Configuration
Environment Variables
Variable | Default | Description |
---|---|---|
MONITORING_ENABLED |
false |
Enable/disable monitoring |
SENTRY_DSN |
- | Sentry project DSN* |
SENTRY_ENVIRONMENT |
NODE_ENV |
Environment name |
SENTRY_TRACES_SAMPLE_RATE |
0.1 |
Performance sampling |
*Required when monitoring is enabled
Key Functions
Check Status
export function isMonitoringEnabled(): boolean {
return process.env.MONITORING_ENABLED === 'true' && !!process.env.SENTRY_DSN;
}
Setup Express
// Before routes
setupExpressRequestHandler(app);
// After routes
setupExpressErrorHandler(app);
app.use(createErrorHandler());
Capture Errors
export function captureException(
error: Error,
context?: Record<string, unknown>
): void {
if (!isMonitoringEnabled()) return;
Sentry.captureException(error, {
extra: sanitizeData(context || {})
});
}
Add Breadcrumbs
export function addBreadcrumb(
message: string,
category: string,
data?: Record<string, unknown>
): void {
if (!isMonitoringEnabled()) return;
Sentry.addBreadcrumb({
message,
category,
level: 'info',
data: sanitizeData(data || {})
});
}
Integration in Application
Express Setup
import {
setupExpressRequestHandler,
setupExpressErrorHandler,
createErrorHandler,
logMonitoringStatus
} from './utils/monitoring.js';
const app = express();
// Log status
logMonitoringStatus();
// Setup request handler (first)
setupExpressRequestHandler(app);
// Routes
app.use('/api', apiRoutes);
// Setup error handlers (last)
setupExpressErrorHandler(app);
app.use(createErrorHandler());
Service Integration
export class ScanService {
async scanContent(content: string) {
addBreadcrumb('Scan requested', 'scan', {
contentSize: content.length
});
try {
const result = await this.client.scan(content);
return result;
} catch (error) {
captureException(error, {
service: 'ScanService',
operation: 'scanContent'
});
throw error;
}
}
}
Data Sanitization
Automatic removal of sensitive data:
const sensitiveKeys = [
'token', 'key', 'secret', 'password',
'auth', 'api', 'credential', 'private'
];
// Example sanitization
{
userId: '12345',
apiKey: 'secret-key', // → '[REDACTED]'
password: 'pass123' // → '[REDACTED]'
}
Privacy Features
What IS Captured
- Error messages and stack traces
- HTTP method, path, query params
- Custom breadcrumbs and context
- Application metadata
What is NOT Captured
- Request/response bodies
- HTTP headers (auth headers)
- API keys or credentials
- Personal information
- File contents
Error Response
When monitoring is enabled:
{
"error": "Internal server error",
"errorId": "abc123def456",
"timestamp": "2024-01-15T10:30:00.000Z"
}
Best Practices
Meaningful Breadcrumbs
// Good
addBreadcrumb('Payment processed', 'payment', {
amount: payment.amount,
method: payment.method
});
// Bad
addBreadcrumb('Action', 'generic');
Structured Context
// Good
captureException(error, {
component: 'PaymentService',
operation: 'processPayment',
paymentId: payment.id
});
Environment Sampling
# Production - conservative
SENTRY_TRACES_SAMPLE_RATE=0.01 # 1%
# Staging - moderate
SENTRY_TRACES_SAMPLE_RATE=0.1 # 10%
# Development - full
SENTRY_TRACES_SAMPLE_RATE=1.0 # 100%
Performance Monitoring
Custom sampling logic:
tracesSampler(context) {
// Skip health checks
if (context.request?.url?.includes('/health')) {
return 0;
}
// Lower rate for SSE
if (context.request?.url?.includes('/sse')) {
return 0.01; // 1%
}
return 0.1; // Default 10%
}
Related Modules
- Instrument - Sentry initialization
- Logger - Logging integration
- Main Application - Express setup
- Configuration - Environment config