Sentry Error Tracking: Catch Bugs Before Users Report Them
Welcome to TopperBlog! 👋
I'm a tech content creator passionate about helping developers level up their careers and master cutting-edge technologies.
🎯 What I Write About:
• AI/ML Engineering & LLMs
• Web3 & Blockchain Development
• System Design & Architecture
• Interview Preparation (FAANG)
• Freelancing & Remote Work
• Modern Tech Stacks (Next.js, React, Rust, TypeScript)
• Performance Optimization & Best Practices
💼 Mission: Sharing practical, actionable insights that accelerate your tech career and maximize your earning potential.
📚 15+ In-Depth Guides covering everything from earning $10k/month as a freelancer to cracking FAANG interviews.
🌐 Let's connect and grow together in this amazing tech journey!
#TechBlogger #SoftwareEngineering #CareerGrowth #WebDevelopment #AIEngineering
Sentry Error Tracking: Catch Bugs Before Users Report Them
The Bug We Couldn't Reproduce (Until We Fixed Our Logging)
Users complained about errors we couldn't see. Our logs were useless. Here's what changed everything.
Table of Contents
- Modern Logging 2026
- Architecture Design
- 5 Logging Patterns
- Error Tracking
- Performance Impact
- Security Considerations
- Troubleshooting
- FAQ
- Production Setup
Modern Logging in 2026
Good logs are your production debugger.
Logging Levels
// Standard log levels
enum LogLevel {
DEBUG = 0, // Development details
INFO = 1, // General info
WARN = 2, // Warnings
ERROR = 3, // Errors
FATAL = 4 // Critical failures
}
// Use appropriately
logger.debug('Variable value:', { value });
logger.info('User logged in', { userId });
logger.warn('API rate limit approaching', { usage: 90 });
logger.error('Payment failed', { error, orderId });
logger.fatal('Database connection lost', { error });
Structured vs Unstructured
// ❌ Bad: Unstructured
console.log('User John Doe logged in at ' + new Date());
// ✅ Good: Structured
logger.info('User logged in', {
userId: 'user_123',
username: 'johndoe',
timestamp: new Date().toISOString(),
ip: req.ip,
userAgent: req.get('user-agent')
});
Business Impact
Fast debugging = less downtime = happy users.
Architecture Design
Building observable systems.
Centralized Logging
// Send logs to central system
import { createLogger, transports } from 'winston';
const logger = createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.json(),
defaultMeta: {
service: 'api',
environment: process.env.NODE_ENV,
version: process.env.APP_VERSION
},
transports: [
// Console for local dev
new transports.Console(),
// File for production
new transports.File({ filename: 'error.log', level: 'error' }),
new transports.File({ filename: 'combined.log' }),
// HTTP transport to log aggregator
new transports.Http({
host: 'logs.example.com',
port: 443,
path: '/logs'
})
]
});
Correlation IDs
// Track requests across services
import { v4 as uuidv4 } from 'uuid';
app.use((req, res, next) => {
req.id = req.get('x-request-id') || uuidv4();
res.setHeader('x-request-id', req.id);
// Add to all logs
req.log = logger.child({ requestId: req.id });
next();
});
// Usage
app.get('/api/users', (req, res) => {
req.log.info('Fetching users');
// All logs include requestId
});
Pattern 1: Structured Logging
JSON Format
// Log as JSON objects
interface LogEntry {
timestamp: string;
level: string;
message: string;
context: {
requestId: string;
userId?: string;
[key: string]: any;
};
error?: {
message: string;
stack: string;
code?: string;
};
}
function log(entry: LogEntry) {
console.log(JSON.stringify({
...entry,
timestamp: new Date().toISOString()
}));
}
// Usage
log({
level: 'error',
message: 'Payment processing failed',
context: {
requestId: req.id,
userId: req.user.id,
orderId: order.id,
amount: order.total
},
error: {
message: err.message,
stack: err.stack,
code: err.code
}
});
Context Enrichment
// Add context automatically
class Logger {
private context: Record<string, any> = {};
child(context: Record<string, any>) {
const childLogger = new Logger();
childLogger.context = { ...this.context, ...context };
return childLogger;
}
info(message: string, data?: any) {
this.write('info', message, data);
}
private write(level: string, message: string, data?: any) {
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
level,
message,
...this.context,
...data
}));
}
}
Pattern 2: Error Tracking
Sentry Integration
// Initialize Sentry
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0
});
// Capture errors
app.use((err, req, res, next) => {
Sentry.captureException(err, {
user: {
id: req.user?.id,
email: req.user?.email
},
tags: {
path: req.path,
method: req.method
},
extra: {
body: req.body,
query: req.query
}
});
res.status(500).json({ error: 'Internal server error' });
});
Custom Error Context
// Add breadcrumbs
Sentry.addBreadcrumb({
category: 'payment',
message: 'Processing payment',
level: 'info',
data: {
amount: 99.99,
currency: 'USD'
}
});
try {
await processPayment();
} catch (error) {
Sentry.captureException(error);
throw error;
}
Pattern 3: Performance Logging
Request Timing
// Log request duration
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
logger.info('Request completed', {
method: req.method,
path: req.path,
status: res.statusCode,
duration,
requestId: req.id
});
// Alert on slow requests
if (duration > 5000) {
logger.warn('Slow request detected', {
method: req.method,
path: req.path,
duration,
requestId: req.id
});
}
});
next();
});
Database Query Logging
// Log slow queries
const db = knex({
// ...config
log: {
warn(message) {
logger.warn('Database warning', { message });
},
error(message) {
logger.error('Database error', { message });
},
debug(message) {
// Only in development
if (process.env.NODE_ENV === 'development') {
logger.debug('Database query', { message });
}
}
}
});
Pattern 4: Log Aggregation
Query Logs
// Search logs by fields
const errors = await logService.query({
level: 'error',
timeRange: {
start: new Date(Date.now() - 24 * 60 * 60 * 1000),
end: new Date()
},
filter: {
'context.userId': 'user_123'
}
});
// Aggregate metrics
const errorCount = await logService.aggregate({
field: 'level',
value: 'error',
groupBy: 'context.service',
timeRange: 'last_hour'
});
Alerts
// Alert on error spike
const alertRule = {
name: 'High Error Rate',
condition: {
metric: 'error_count',
threshold: 100,
window: '5m'
},
actions: [
{ type: 'email', to: 'team@example.com' },
{ type: 'slack', channel: '#alerts' },
{ type: 'pagerduty', severity: 'high' }
]
};
Pattern 5: Sensitive Data
Redaction
// Redact sensitive fields
const sensitiveFields = ['password', 'token', 'ssn', 'credit_card'];
function redact(obj: any): any {
if (typeof obj !== 'object' || obj === null) return obj;
const result = Array.isArray(obj) ? [] : {};
for (const [key, value] of Object.entries(obj)) {
if (sensitiveFields.includes(key.toLowerCase())) {
result[key] = '[REDACTED]';
} else if (typeof value === 'object') {
result[key] = redact(value);
} else {
result[key] = value;
}
}
return result;
}
// Usage
logger.info('User updated', redact(userData));
GDPR Compliance
// Delete user logs
async function deleteUserLogs(userId: string) {
await logService.delete({
'context.userId': userId
});
}
Performance Impact
| Method | Overhead | Throughput |
| console.log | ~5ms | 20K/s |
| Async file | ~1ms | 100K/s |
| Buffered | ~0.1ms | 1M/s |
| Async HTTP | ~2ms | 50K/s |
Security Considerations
Don't Log Secrets
// ❌ Never log these
- Passwords
- API keys
- Tokens
- Credit cards
- SSNs
- Private keys
// ✅ Safe to log
- User IDs
- Request IDs
- Timestamps
- Status codes
- Public data
Log Rotation
// Rotate logs daily
import { createLogger, transports } from 'winston';
import 'winston-daily-rotate-file';
const logger = createLogger({
transports: [
new transports.DailyRotateFile({
filename: 'app-%DATE%.log',
datePattern: 'YYYY-MM-DD',
maxSize: '20m',
maxFiles: '14d'
})
]
});
FAQ
Q1: How much to log?
Info+ in production, debug in development.
Q2: Where to store logs?
Centralized system (ELK, Loki, BetterStack).
Q3: Log retention period?
30-90 days typical, longer for compliance.
Q4: Performance impact?
Async logging has minimal impact (<1ms).
Q5: Cost at scale?
Plan for $100-1000/month for medium app.
Production Setup
Checklist
- [ ] Structured JSON logging
- [ ] Log levels configured
- [ ] Sensitive data redacted
- [ ] Correlation IDs added
- [ ] Error tracking setup
- [ ] Alerts configured
- [ ] Log rotation enabled
- [ ] Retention policy set
Conclusion
Great logging enables great debugging.
Key takeaways:
- Structure all logs
- Add context
- Track errors
- Monitor performance
- Protect sensitive data
Log smartly for fast debugging.
Resources:
- Logging Best Practices
- Error Tracking Guide
- Performance Monitoring
- Security Guidelines
Next Steps:
- Add structured logging
- Set up error tracking
- Configure alerts
- Test log queries
- Monitor production
Improve observability today.