LogTide

Express SDK

@logtide/express provides Express.js middleware for automatic request/response logging, per-request scoping, and W3C Trace Context propagation.

Installation

npm install @logtide/express

This installs @logtide/core as a dependency automatically.

Quick Start

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

const app = express();

// Add LogTide middleware (initializes LogTide automatically)
app.use(logtide({
  dsn: 'https://[email protected]',
  service: 'api-server',
  environment: 'production',
}));

app.get('/users/:id', (req, res) => {
  // Access the request-scoped context
  req.logtideScope.setTag('userId', req.params.id);

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

  res.json({ id: req.params.id, name: 'Alice' });
});

app.listen(3000);

Middleware Options

The middleware accepts all ClientOptions from @logtide/core:

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

Request Scoping

The middleware creates a new scope for each request. Context set within a request is automatically included in all events captured during that request.

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

app.use((req, res, next) => {
  // Set user context for the request
  req.logtideScope.setExtra('userId', req.user?.id);
  req.logtideScope.setExtra('email', req.user?.email);

  // Set custom tags
  req.logtideScope.setTag('tenant', req.headers['x-tenant-id']);

  next();
});

app.get('/orders', (req, res) => {
  // This log automatically includes the user and tenant tag
  hub.captureLog('info', 'Fetching orders');
  res.json([]);
});

Trace Propagation

The middleware extracts incoming traceparent headers and continues the trace, or starts a new one. The trace ID is available on the request.

app.get('/api/data', (req, res) => {
  // Access the trace ID for the current request
  const traceId = req.logtideTraceId;

  // Pass it to downstream services
  const response = await fetch('https://service-b.internal/data', {
    headers: {
      // traceparent is automatically injected if tracePropagationTargets match
    },
  });

  // Include trace ID in response for client-side correlation
  res.set('X-Trace-Id', traceId);
  res.json(await response.json());
});

Error Handling

The middleware automatically captures errors when responses have 5xx status codes. You can add your own error handler to customize the response:

app.get('/users/:id', async (req, res) => {
  const user = await getUser(req.params.id);
  if (!user) throw new NotFoundError('User not found');
  res.json(user);
});

// Your error handler — 5xx errors are already captured by LogTide
app.use((err, req, res, next) => {
  res.status(err.status || 500).json({
    error: err.message,
    traceId: req.logtideTraceId,
  });
});

API Reference

Export Description
logtide(options)Middleware factory — initializes LogTide, creates scopes, extracts traces, captures 5xx errors
req.logtideScopePer-request scope for setting tags, user, extras
req.logtideTraceIdCurrent trace ID for the request

See the JavaScript SDK core docs for the full @logtide/core API (scopes, breadcrumbs, spans, configuration).