Fastify Integration
The fastifyContext plugin registers as a Fastify plugin, hooking into the request lifecycle to propagate context to all downstream queries.
Setup
typescript
import Fastify from 'fastify';
import { PrismaClient } from '@prisma/client';
import { createMonitor, fastifyContext, prismaAdapter } from '@periodic/arsenic';
const app = Fastify({ logger: true });
const prisma = new PrismaClient();
const monitor = createMonitor({
slowQueryThresholdMs: 200,
exporter: (event) => {
if (event.severity === 'critical') sendToPagerDuty(event);
},
});
// Register BEFORE routes
await app.register(fastifyContext(monitor, {
attachUser: (req) => req.user?.id,
}));
prismaAdapter(monitor, prisma);
app.get('/api/users/:id', async (req, res) => {
const user = await prisma.user.findUnique({
where: { id: req.params.id },
});
return user;
});
await app.listen({ port: 3000, host: '0.0.0.0' });Register before routes
Use
await app.register() to ensure the plugin is fully initialized before routes are registered.With TypeScript typed request
typescript
import { FastifyRequest } from 'fastify';
interface JWTUser { id: string; email: string; role: string; }
declare module 'fastify' {
interface FastifyRequest {
user?: JWTUser;
}
}
await app.register(fastifyContext(monitor, {
attachUser: (req: FastifyRequest) => req.user?.id,
}));With multiple databases
typescript
import Redis from 'ioredis';
const pgMonitor = createMonitor({ slowQueryThresholdMs: 100, exporter: pgExporter });
const redisMonitor = createMonitor({ slowQueryThresholdMs: 50, exporter: redisExporter });
// One fastifyContext is enough — it covers all DB adapters
await app.register(fastifyContext(pgMonitor));
// Attach adapters with their own monitors
prismaAdapter(pgMonitor, prisma);
redisAdapter(redisMonitor, redis);