Skip to main content

Overview

The ApiLoggerOptions interface defines all configuration options available for customizing the behavior of the HTTP Ledger Express middleware. These options control what data is logged, how it’s processed, and when logging occurs.

Interface Definition

import { Request, Response } from 'express';
import { IpInfo, LogData, LogLevel } from '@httpledger/express';

interface ApiLoggerOptions {
  logBody?: boolean;
  logResponse?: boolean;
  logQueryParams?: boolean;
  excludedHeaders?: string[];
  getIpInfo?: (ip: string) => Promise<IpInfo>;
  onLog?: (logData: LogData) => void | Promise<void>;
  maskFields?: string[];
  customLogLevel?: (logData: LogData) => LogLevel;
  customFormatter?: (logData: LogData) => unknown;
  autoGenerateRequestId?: boolean;
  shouldLog?: (req: Request, res: Response) => boolean;
  logSampling?: number;
}

Properties

logBody
boolean
default:"false"
Whether to log the request body. When enabled, the request body will be included in the log data.
logResponse
boolean
default:"false"
Whether to log the response body. When enabled, the response body will be included in the log data.
logQueryParams
boolean
default:"true"
Whether to log query parameters from the request URL. When disabled, query parameters will be excluded from logs.
excludedHeaders
string[]
List of header names to exclude from logs. Header matching is case-insensitive. Useful for excluding sensitive headers like Authorization or Cookie.Example: ['authorization', 'cookie', 'x-api-key']
getIpInfo
(ip: string) => Promise<IpInfo>
Optional async function to enrich logs with IP geolocation information. Receives the client IP address and should return an IpInfo object.Example:
async (ip: string) => {
  const response = await fetch(`https://ipapi.co/${ip}/json/`);
  return response.json();
}
onLog
(logData: LogData) => void | Promise<void>
Optional callback function that receives the complete log data for each request. Can be used to send logs to external services, databases, or custom logging systems.Example:
async (logData: LogData) => {
  await sendToDatadog(logData);
}
maskFields
string[]
List of field names to mask in request/response bodies, headers, and query parameters. Masked fields will show [REDACTED] instead of their actual values.Example: ['password', 'creditCard', 'ssn']
customLogLevel
(logData: LogData) => LogLevel
Custom function to determine the log level based on the log data. Receives the complete LogData object and should return 'info', 'warn', or 'error'.Example:
(logData: LogData) => {
  if (logData.statusCode >= 500) return 'error';
  if (logData.statusCode >= 400) return 'warn';
  return 'info';
}
customFormatter
(logData: LogData) => unknown
Custom function to format or transform the log data before it’s logged. Receives the complete LogData object and can return any structure.Example:
(logData: LogData) => ({
  timestamp: logData.timestamp.request,
  request: `${logData.method} ${logData.url}`,
  status: logData.statusCode,
  duration: `${logData.timeTaken}ms`
})
autoGenerateRequestId
boolean
default:"false"
Whether to automatically generate a request ID if one is not present in the request headers. The generated ID will be a UUID v4.
shouldLog
(req: Request, res: Response) => boolean
Function to conditionally determine whether to log a specific request. Receives the Express request and response objects. Return false to skip logging.Example:
(req: Request, res: Response) => {
  // Don't log health check endpoints
  return req.path !== '/health';
}
logSampling
number
Sampling rate for logging requests, expressed as a decimal between 0 and 1. For example, 0.1 means log 10% of requests, 0.5 means log 50%.Example: 0.1 (log 10% of requests)

Usage Examples

Basic Configuration

import express from 'express';
import { httpLedger, ApiLoggerOptions } from '@httpledger/express';

const app = express();

const options: ApiLoggerOptions = {
  logBody: true,
  logResponse: true,
  excludedHeaders: ['authorization', 'cookie']
};

app.use(httpLedger(options));

Advanced Configuration with Custom Handlers

import { httpLedger, ApiLoggerOptions, LogData, IpInfo } from '@httpledger/express';

const options: ApiLoggerOptions = {
  logBody: true,
  logResponse: false,
  logQueryParams: true,
  excludedHeaders: ['authorization', 'x-api-key'],
  maskFields: ['password', 'creditCard', 'ssn'],
  autoGenerateRequestId: true,
  
  // Add IP geolocation
  getIpInfo: async (ip: string): Promise<IpInfo> => {
    try {
      const response = await fetch(`https://ipapi.co/${ip}/json/`);
      return await response.json();
    } catch (error) {
      return { ip };
    }
  },
  
  // Custom log handler
  onLog: async (logData: LogData) => {
    // Send to external logging service
    await fetch('https://logs.example.com/api/logs', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(logData)
    });
  },
  
  // Custom log level determination
  customLogLevel: (logData: LogData) => {
    if (logData.error) return 'error';
    if (logData.statusCode >= 500) return 'error';
    if (logData.statusCode >= 400) return 'warn';
    if (logData.timeTaken > 5000) return 'warn';
    return 'info';
  },
  
  // Conditional logging
  shouldLog: (req, res) => {
    // Skip health checks and metrics endpoints
    const skipPaths = ['/health', '/metrics', '/ping'];
    return !skipPaths.includes(req.path);
  },
  
  // Log only 25% of requests
  logSampling: 0.25
};

app.use(httpLedger(options));

Production-Ready Configuration

import { httpLedger, ApiLoggerOptions } from '@httpledger/express';
import { sendToDatadog } from './monitoring';

const options: ApiLoggerOptions = {
  logBody: process.env.NODE_ENV === 'development',
  logResponse: false,
  logQueryParams: true,
  excludedHeaders: [
    'authorization',
    'cookie',
    'x-api-key',
    'x-auth-token'
  ],
  maskFields: [
    'password',
    'token',
    'secret',
    'creditCard',
    'ssn',
    'apiKey'
  ],
  autoGenerateRequestId: true,
  onLog: async (logData) => {
    await sendToDatadog(logData);
  },
  customLogLevel: (logData) => {
    if (logData.statusCode >= 500) return 'error';
    if (logData.statusCode >= 400) return 'warn';
    return 'info';
  },
  shouldLog: (req) => {
    return !req.path.startsWith('/internal/');
  },
  // In production, sample 10% of successful requests
  logSampling: process.env.NODE_ENV === 'production' ? 0.1 : 1.0
};

app.use(httpLedger(options));

See Also

  • LogData - The complete log data structure
  • IpInfo - IP geolocation information structure
  • LogLevel - Available log levels

Build docs developers (and LLMs) love