JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 301
  • Score
    100M100P100Q89364F
  • License MIT

Request tracing and logging middleware for NestJS microservices with Winston colored output

Package Exports

  • @arv-bedrock/logger

Readme

Bedrock Logger

A powerful Nest.js logger middleware that supports both structured JSON logging (Loki-optimized) and pretty console output.

Features

  • Request/Response logging with detailed information
  • Error tracking and logging
  • TypeScript support
  • Nest middleware compatible
  • Request ID propagation across services
  • Support for both Loki (JSON) and Pretty formats

Installation

npm i @arv-bedrock/logger

Usage

import { Logger, LoggerInterceptor, LoggerOptions, LogLevel, setupHttpInterceptor } from '@arv-bedrock/logger';
import { HttpService } from '@nestjs/axios';

const app = await NestFactory.create(AppModule);
// Create logger instance
// Add logger into file main.ts
const options: LoggerOptions = {
  level: LogLevel.INFO,      // Minimum log level
  format: 'loki',           // 'loki' or 'pretty'
  timestamp: true,          // Include timestamps
  serviceName: 'smart-utilities'   // Service name for identification
};

const logger = new Logger(options);

// Create and use the logger interceptor
const interceptor = new LoggerInterceptor(logger);
app.use(interceptor.logRequest.bind(interceptor));
// **(optional) If you use httpService from @nestjs/axios add this code it will intercept your axios request and response
const httpService = app.get(HttpService);
setupHttpInterceptor(logger, httpService);


// Direct logging
logger.debug('Debug message');
logger.info('Info message');
logger.warn('Warning message');
logger.error('Error message', new Error('Something went wrong'));

Configuration

LoggerOptions

interface LoggerOptions {
  level?: LogLevel;      // DEBUG, INFO, WARN, ERROR (default: INFO)
  timestamp?: boolean;   // Include timestamps (default: true)
  format?: 'loki' | 'pretty';  // Log format (default: 'loki')
  serviceName?: string;  // Service name for identification
  maxBodySize?: number;  // Maximum response body size in bytes (default: 1MB)
}

Request ID Tracking

The logger automatically handles request IDs for tracing requests across services:

  1. Checks for existing 'x-request-id' in request headers
  2. If not found, generates a new UUID
  3. Adds request ID to response headers
  4. Uses the same ID throughout request/response logging

Example of request ID header:

X-Request-ID: de021845-08ec-4158-8e83-d8f1022931a5

Log Formats

Loki Format (Default)

Outputs structured JSON logs optimized for Grafana Loki ingestion:

{
  "labels": {
    "level": "INFO",
    "service": "smart-utilities",
    "timestamp": "2025-03-08T17:53:27.164Z",
    "request_id": "de021845-08ec-4158-8e83-d8f1022931a5",
    "method": "GET",
    "path": "/api/example"
  },
  "message": "Incoming GET /api/example",
  "data": {
    "requestId": "de021845-08ec-4158-8e83-d8f1022931a5",
    "method": "GET",
    "path": "/api/example",
    "params": {},
    "query": {},
    "headers": {},
    "timestamp": 1741456407164,
    "type": "request"
  }
}

Pretty Format

Human-readable colored output for local development:

[2025-03-08T17:53:27.164Z] [smart-utilities] [INFO] [de021845-08ec] Incoming GET /api/example

Response Body Handling

The logger intelligently handles response bodies:

  1. Size Limit:

    • By default, response bodies larger than 1MB are excluded from logs
    • Configurable via maxBodySize option (in bytes)
    • When body is excluded, logs will show: [Content Excluded: <size> bytes]
  2. Binary Content:

    • Automatically excludes binary content types (images, PDFs, etc.)
    • Supported binary types:
      • application/octet-stream
      • application/pdf
      • application/vnd.ms-excel
      • application/zip
      • image/*
      • audio/*
      • video/*

Example configuration with custom body size limit:

const logger = new Logger({
  maxBodySize: 512 * 1024,  // Set 512KB limit
  format: 'pretty',
  serviceName: 'my-service'
});

Querying Logs in Grafana Loki

Basic Queries

  1. Filter by status code:
{serviceName="smart-utilities"} | json | data_statusCode = 200
  1. Filter by request method and path:
{serviceName="smart-utilities"} | json | data_method = "GET" and data_path = "/api/example"
  1. Search in time range:
{serviceName="smart-utilities"} | json 
| data_timestamp > unix_timestamp("2025-03-08T17:53:27.164Z") 
| data_timestamp < unix_timestamp("2025-03-08T17:53:28.519Z")

Trace Queries

Follow request across services:

{app=~".*"} | json | request_id = "de021845-08ec-4158-8e83-d8f1022931a5"

Advanced JSON Queries

Query nested JSON response data:

{serviceName="smart-utilities"} | json | data_body := unwrap data.body | json data_body 
| paymentStatus[*].label = "รอการถอดถอนมาตร"

Error Handling

The logger automatically handles errors and prevents duplicate error logs. Each error is logged only once with:

  • Error message and type
  • Stack trace
  • Request context
  • Response status code

License

MIT