Set up Overseer in your Express.js application
Express.js Integration
Set up Overseer in Express.js and Node.js applications.
Installation
npm install @codmir/overseeryarn add @codmir/overseerpnpm add @codmir/overseerbun add @codmir/overseerSetup
// server.ts
import express from 'express';
import { init, captureException, addBreadcrumb } from '@codmir/overseer';
// Initialize Overseer first
init({
dsn: process.env.OVERSEER_DSN,
service: 'express-api',
environment: process.env.NODE_ENV || 'development',
});
const app = express();
app.use(express.json());
// Request logging middleware
app.use((req, res, next) => {
addBreadcrumb({
type: 'http',
category: 'request',
message: `${req.method} ${req.path}`,
data: {
method: req.method,
url: req.url,
query: req.query,
},
level: 'info',
});
next();
});
// Your routes
app.get('/api/users', async (req, res, next) => {
try {
const users = await getUsers();
res.json(users);
} catch (error) {
next(error);
}
});
// Error handling middleware (must be last)
app.use((err, req, res, next) => {
captureException(err, {
extra: {
method: req.method,
url: req.url,
body: req.body,
query: req.query,
headers: req.headers,
},
});
res.status(500).json({
error: 'Internal Server Error',
message: process.env.NODE_ENV === 'development' ? err.message : undefined,
});
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});Request Context Middleware
Create a middleware to add request context:
// middleware/overseer.ts
import { setContext, addBreadcrumb } from '@codmir/overseer';
export function overseerMiddleware() {
return (req, res, next) => {
// Set request context
setContext('request', {
id: req.id,
method: req.method,
path: req.path,
ip: req.ip,
});
// Add request breadcrumb
addBreadcrumb({
type: 'http',
category: 'request.start',
message: `${req.method} ${req.path}`,
level: 'info',
});
// Track response
res.on('finish', () => {
addBreadcrumb({
type: 'http',
category: 'request.finish',
message: `${req.method} ${req.path} - ${res.statusCode}`,
data: { statusCode: res.statusCode },
level: res.statusCode >= 400 ? 'warning' : 'info',
});
});
next();
};
}
// Usage
app.use(overseerMiddleware());Async Error Handler
Wrap async routes to catch errors:
// utils/asyncHandler.ts
import { captureException } from '@codmir/overseer';
export function asyncHandler(fn) {
return (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch((error) => {
captureException(error, {
extra: {
route: req.route?.path,
method: req.method,
},
});
next(error);
});
};
}
// Usage
app.get('/api/data', asyncHandler(async (req, res) => {
const data = await fetchData();
res.json(data);
}));Environment Variables
# .env
OVERSEER_DSN=https://your-project.codmir.com/overseer
NODE_ENV=productionGraceful Shutdown
Flush pending events on shutdown:
import { flush } from '@codmir/overseer';
process.on('SIGTERM', async () => {
console.log('Shutting down...');
await flush(5000); // Wait up to 5 seconds
process.exit(0);
});