LogTide

Fastify SDK

@logtide/fastify is a Fastify plugin that provides automatic request logging, per-request scoping, lifecycle hooks, and W3C Trace Context propagation.

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: 'https://[email protected]',
  service: 'api-server',
  environment: 'production',
});

fastify.get('/users/:id', async (request, reply) => {
  // Access request-scoped context
  request.logtideScope.setTag('userId', request.params.id);

  hub.captureLog('info', 'Fetching user', {
    userId: request.params.id,
  });

  return { id: request.params.id, name: 'Alice' };
});

await fastify.listen({ port: 3000 });

Plugin Options

The plugin accepts all ClientOptions from @logtide/core:

await fastify.register(logtide, {
  dsn: 'https://[email protected]',
  service: 'api-server',
  environment: 'production',
  release: '1.0.0',
  tracesSampleRate: 1.0,
  debug: false,
});

Plus three Fastify-specific capture options. They are all opt-in and attach their data to the request span (http.request_body, http.response_body, http.request_headers). Bodies are captured raw (no redaction) and truncated to 4096 characters — gate them to non-sensitive routes if needed.

await fastify.register(logtide, {
  dsn: 'https://[email protected]',
  service: 'api-server',

  // Capture options (all default to false)
  includeRequestBody: true,    // → span attribute  http.request_body
  includeResponseBody: true,   // → span attribute  http.response_body  (v0.9.0+)
  includeRequestHeaders: true, // → span attribute  http.request_headers
  // or capture only specific headers:
  // includeRequestHeaders: ['x-request-id', 'x-tenant-id'],
});

Sensitive headers (authorization, cookie, set-cookie, x-api-key …) are always stripped from includeRequestHeaders.

Request Scoping

Each request gets an isolated scope. Tags, user data, and extras set on the scope are included in all events captured during that request lifecycle.

import { hub } from '@logtide/core';

fastify.addHook('onRequest', async (request) => {
  request.logtideScope.setExtra('userId', request.user?.id);
  request.logtideScope.setTag('tenant', request.headers['x-tenant-id']);
});

fastify.get('/orders', async (request) => {
  // Logs include user + tenant automatically
  hub.captureLog('info', 'Listing orders');
  return { orders: [] };
});

Lifecycle Hooks

The plugin hooks into Fastify's request lifecycle to provide automatic instrumentation:

Hook Behavior
onRequestCreates request scope, extracts traceparent, starts span
onResponseLogs request completion with duration and status code
onErrorCaptures errors with full request context
onCloseFlushes pending events on server shutdown

Error Handling

// Errors thrown in route handlers are automatically captured
fastify.get('/users/:id', async (request) => {
  const user = await getUser(request.params.id);
  if (!user) {
    // This error is captured with the request scope context
    throw fastify.httpErrors.notFound('User not found');
  }
  return user;
});

// Custom error handler still works
fastify.setErrorHandler((error, request, reply) => {
  // Error was already captured by LogTide
  reply.status(error.statusCode || 500).send({
    error: error.message,
    traceId: request.logtideTraceId,
  });
});

API Reference

Export Description
logtideFastify plugin — register with fastify.register(logtide, options)
request.logtideScopePer-request scope for setting tags, user, extras
request.logtideTraceIdCurrent trace ID for the request

See the JavaScript SDK core docs for the full @logtide/core API.

Esc

Type to search across all documentation pages