Express
Create an instrumentation.ts file:
import 'autotel/register'; // Must be first for ESM
import { init } from 'autotel';import pino from 'pino';
const logger = pino({ name: 'my-api' });
init({ service: 'my-api', logger, autoInstrumentations: ['express', 'http', 'pino'], endpoint: process.env.OTLP_ENDPOINT,});Run with the --import flag:
tsx --import ./instrumentation.ts src/index.tsTracing Route Handlers
Section titled “Tracing Route Handlers”import express from 'express';import { trace, type TraceContext } from 'autotel';
const app = express();
// Auto-traced: HTTP spans created by auto-instrumentation// Manual trace: business logic spansconst fetchUser = trace((ctx: TraceContext) => async (userId: string) => { ctx.setAttribute('db.userId', userId); return await db.users.findById(userId);});
app.get('/users/:userId', async (req, res) => { const user = await fetchUser(req.params.userId); res.json(user);});
app.get('/error', async () => { throw new Error('Test error'); // Automatically captured});Request-Scoped Logging
Section titled “Request-Scoped Logging”import { trace, getRequestLogger } from 'autotel';
app.get('/checkout', async (req, res) => { // If using autotel-hono or middleware that creates a span, // getRequestLogger() works without ctx const log = getRequestLogger();
log.set({ userId: req.body.userId }); const result = await processCheckout(req.body); log.set({ orderId: result.id }); log.emitNow(); // One wide event per request
res.json(result);});What Gets Traced
Section titled “What Gets Traced”With autoInstrumentations: ['express', 'http']:
- HTTP server spans — automatic per-request spans with method, path, status
- Express middleware — middleware execution time
- Your
trace()calls — business logic spans as children
Examples
Section titled “Examples”example-http— Express with Pino logger, manualtrace()in routes, error tracking.