integration
Fastify Logging Integration
Add structured logging to Fastify applications with plugin-based integration, lifecycle hooks, and trace propagation.
- Native Fastify plugin
- Lifecycle hook integration
- Request scoping
- Auto error capture
LogTide’s Fastify SDK provides a native plugin that hooks into Fastify’s lifecycle for automatic request tracing, per-request scoping, and distributed tracing.
Why use LogTide with Fastify?
- Native plugin architecture: Follows Fastify plugin conventions
- Lifecycle hooks: Automatic instrumentation via onRequest, onSend, onResponse, onError
- Per-request scoping: Isolated context per request through decorators
- Zero overhead: Asynchronous batching keeps Fastify fast
Prerequisites
- Node.js 18+
- Fastify 4.x or 5.x
- LogTide instance with a DSN
Installation
npm install @logtide/fastify
Quick Start
import Fastify from 'fastify';
import { hub } from '@logtide/core';
import { logtide } from '@logtide/fastify';
const fastify = Fastify();
// Register the plugin (initializes LogTide automatically)
await fastify.register(logtide, {
dsn: process.env.LOGTIDE_DSN,
service: 'api-server',
environment: process.env.NODE_ENV,
});
fastify.get('/users/:id', async (request) => {
request.logtideScope?.setTag('userId', request.params.id);
hub.captureLog('info', 'Fetching user', {
userId: request.params.id,
});
return { id: request.params.id };
});
await fastify.listen({ port: 3000 });
Plugin Options
await fastify.register(logtide, {
dsn: process.env.LOGTIDE_DSN,
service: 'api-server',
environment: process.env.NODE_ENV,
release: '1.0.0',
tracesSampleRate: 1.0,
});
Request Scoping
Each request gets an isolated scope:
fastify.addHook('onRequest', async (request) => {
request.logtideScope?.setExtra('userId', request.user?.id);
request.logtideScope?.setTag('tenant', String(request.headers['x-tenant-id']));
});
Lifecycle Integration
The plugin hooks into Fastify’s lifecycle automatically:
| Hook | Behavior |
|---|---|
onRequest | Creates scope, extracts traceparent, starts span |
onSend | Optionally captures the response body |
onResponse | Finishes the span with duration and status, logs 5xx responses as errors |
onError | Captures errors with request context |
Error Handling
fastify.setErrorHandler((error, request, reply) => {
// Error already captured by LogTide plugin
reply.status(error.statusCode || 500).send({
error: error.message,
traceId: request.logtideTraceId,
});
});
Next Steps
- JavaScript SDK - Core SDK reference
- Fastify SDK Reference - Full API documentation
- Docker Integration - Container deployments
Frequently Asked Questions
How do I integrate LogTide with a Fastify application?
Install @logtide/fastify and register the plugin with await fastify.register(logtide, { dsn, service, environment }). The plugin follows Fastify plugin conventions and hooks into the lifecycle automatically - no extra configuration is required to start tracing requests.
Which Fastify lifecycle hooks does LogTide use?
The plugin hooks into onRequest to create a scoped context and extract the traceparent header, onSend to optionally capture the response body, onResponse to finish the request span with duration and status code (5xx responses are also logged as errors), and onError to capture exceptions with full request context.
Does LogTide replace Fastify built-in pino logging?
LogTide operates alongside Fastify's built-in pino logger rather than replacing it. You can keep pino for local development output while LogTide ships structured logs to your self-hosted LogTide instance for centralised search and alerting.
How does per-request scoping work in the Fastify plugin?
Each request receives an isolated scope accessible via request.logtideScope. You can call setTag() and setExtra() on it inside routes or hooks, and those values are attached to the events LogTide captures with that request's scope (such as 5xx error logs and errors from the onError hook) - they do not leak into other concurrent requests.