Skip to main content

Overview

The LogData interface represents the complete log data object for an HTTP request-response cycle. It contains all information about the request, response, timing, size metrics, and optional enrichment data like IP geolocation and error details.

Interface Definition

import { Timestamp, IpInfo, LogError, LogLevel } from '@httpledger/express';

interface LogData {
  method: string;
  url: string;
  statusCode: number;
  timeTaken: number;
  requestSize: number;
  responseSize: number;
  timestamp: Timestamp;
  headers: Record<string, string | string[] | undefined>;
  queryParams: Record<string, unknown>;
  body?: unknown;
  responseBody?: unknown;
  ipInfo?: IpInfo;
  error?: LogError;
  userAgent?: string;
  referer?: string;
  requestContentType?: string;
  responseContentType?: string;
  httpVersion?: string;
  requestId?: string;
  hostname?: string;
  logLevel?: LogLevel;
}

Properties

Required Properties

method
string
required
The HTTP method used for the request.Example: "GET", "POST", "PUT", "DELETE"
url
string
required
The full URL path of the request, including query string.Example: "/api/users/123?include=profile"
statusCode
number
required
The HTTP status code returned in the response.Example: 200, 404, 500
timeTaken
number
required
Time taken for the complete request-response cycle, measured in milliseconds.Example: 145.23
requestSize
number
required
Size of the request body in bytes.Example: 1024
responseSize
number
required
Size of the response body in bytes.Example: 2048
timestamp
Timestamp
required
Object containing ISO string timestamps for request start and response end times. See Timestamp for details.Example:
{
  "request": "2024-03-15T10:30:00.000Z",
  "response": "2024-03-15T10:30:00.145Z"
}
headers
Record<string, string | string[] | undefined>
required
Request headers as a key-value object. Headers excluded via excludedHeaders option will not be present.Example:
{
  "content-type": "application/json",
  "accept": "application/json",
  "user-agent": "Mozilla/5.0..."
}
queryParams
Record<string, unknown>
required
Query parameters from the request URL as a key-value object. Empty if logQueryParams is disabled.Example:
{
  "page": "1",
  "limit": "20",
  "sort": "createdAt"
}

Optional Properties

body
unknown
The request body. Only present when logBody option is enabled.Example:
{
  "name": "John Doe",
  "email": "[email protected]"
}
responseBody
unknown
The response body. Only present when logResponse option is enabled.Example:
{
  "id": 123,
  "name": "John Doe",
  "email": "[email protected]"
}
ipInfo
IpInfo
IP geolocation information. Only present when getIpInfo function is provided in options. See IpInfo for details.Example:
{
  "ip": "203.0.113.42",
  "country": "US",
  "region": "California",
  "city": "San Francisco",
  "timezone": "America/Los_Angeles"
}
error
LogError
Error information if the request resulted in an error. See LogError for details.Example:
{
  "name": "ValidationError",
  "message": "Invalid email format",
  "code": "INVALID_EMAIL",
  "stack": "Error: Invalid email format\n    at ..."
}
userAgent
string
The User-Agent header from the request.Example: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
referer
string
The Referer header from the request.Example: "https://example.com/dashboard"
requestContentType
string
The Content-Type header from the request.Example: "application/json", "multipart/form-data"
responseContentType
string
The Content-Type header from the response.Example: "application/json", "text/html"
httpVersion
string
The HTTP protocol version used for the request.Example: "1.1", "2.0"
requestId
string
Request ID from headers (e.g., x-request-id) or auto-generated if autoGenerateRequestId option is enabled.Example: "550e8400-e29b-41d4-a716-446655440000"
hostname
string
Hostname of the server handling the request.Example: "api.example.com"
logLevel
LogLevel
The log level for this request: 'info', 'warn', or 'error'. Determined by customLogLevel function or default logic. See LogLevel for details.Example: "info"

Usage Examples

Using LogData in onLog Callback

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

const options: ApiLoggerOptions = {
  onLog: async (logData: LogData) => {
    console.log(`${logData.method} ${logData.url} - ${logData.statusCode} (${logData.timeTaken}ms)`);
    
    // Log errors separately
    if (logData.error) {
      console.error('Request error:', logData.error.message);
    }
    
    // Track slow requests
    if (logData.timeTaken > 1000) {
      console.warn('Slow request detected:', {
        url: logData.url,
        duration: logData.timeTaken
      });
    }
  }
};

app.use(httpLedger(options));

Custom Log Level Based on LogData

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

const options: ApiLoggerOptions = {
  customLogLevel: (logData: LogData): LogLevel => {
    // Error level for server errors or exceptions
    if (logData.error || logData.statusCode >= 500) {
      return 'error';
    }
    
    // Warning level for client errors or slow requests
    if (logData.statusCode >= 400 || logData.timeTaken > 5000) {
      return 'warn';
    }
    
    // Info level for successful requests
    return 'info';
  }
};

Custom Formatter for LogData

import { LogData } from '@httpledger/express';

const options: ApiLoggerOptions = {
  customFormatter: (logData: LogData) => {
    return {
      // Simplified log format
      timestamp: logData.timestamp.request,
      request: `${logData.method} ${logData.url}`,
      status: logData.statusCode,
      duration_ms: logData.timeTaken,
      size_kb: {
        request: (logData.requestSize / 1024).toFixed(2),
        response: (logData.responseSize / 1024).toFixed(2)
      },
      client: {
        ip: logData.ipInfo?.ip,
        location: logData.ipInfo?.city,
        userAgent: logData.userAgent
      },
      error: logData.error?.message
    };
  }
};

Sending LogData to External Service

import { LogData } from '@httpledger/express';

const options: ApiLoggerOptions = {
  onLog: async (logData: LogData) => {
    // Send to analytics service
    await fetch('https://analytics.example.com/api/logs', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${process.env.ANALYTICS_TOKEN}`
      },
      body: JSON.stringify({
        timestamp: logData.timestamp.request,
        endpoint: logData.url,
        method: logData.method,
        statusCode: logData.statusCode,
        duration: logData.timeTaken,
        userAgent: logData.userAgent,
        country: logData.ipInfo?.country,
        error: logData.error?.message
      })
    });
  }
};

Complete Example

{
  "method": "POST",
  "url": "/api/users",
  "statusCode": 201,
  "timeTaken": 145.23,
  "requestSize": 256,
  "responseSize": 512,
  "timestamp": {
    "request": "2024-03-15T10:30:00.000Z",
    "response": "2024-03-15T10:30:00.145Z"
  },
  "headers": {
    "content-type": "application/json",
    "accept": "application/json",
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
  },
  "queryParams": {},
  "body": {
    "name": "John Doe",
    "email": "[email protected]"
  },
  "responseBody": {
    "id": 123,
    "name": "John Doe",
    "email": "[email protected]",
    "createdAt": "2024-03-15T10:30:00.145Z"
  },
  "ipInfo": {
    "ip": "203.0.113.42",
    "country": "US",
    "region": "California",
    "city": "San Francisco",
    "timezone": "America/Los_Angeles"
  },
  "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
  "requestContentType": "application/json",
  "responseContentType": "application/json",
  "httpVersion": "1.1",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "hostname": "api.example.com",
  "logLevel": "info"
}

See Also

Build docs developers (and LLMs) love