JSPM

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

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

Package Exports

  • @arv-bedrock/logger

Readme

NestJS Trace Logger

A lightweight request tracing and logging middleware for NestJS microservices with beautiful colored console output using Winston.

Features

  • Simple middleware-based setup
  • Request tracing with unique IDs
  • Colored console output using Winston
  • Automatic request/response logging
  • Error tracking with stack traces
  • Performance monitoring
  • Structured JSON logging
  • Loki-compatible output format

Installation

npm install @your-org/nest-trace-logger

Usage

Add the middleware in your main.ts:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { TraceLoggerMiddleware } from '@your-org/nest-trace-logger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  
  // Initialize with custom configuration
  const logger = TraceLoggerMiddleware.getInstance({
    serviceName: 'your-service-name',
    level: 'info',
    timestampFormat: 'YYYY-MM-DD HH:mm:ss'
  });
  
  // Use as global middleware
  app.use(logger.use.bind(logger));
  
  // Use logger directly for application logs
  logger.info('Application starting');
  
  await app.listen(3000);
}
bootstrap();

Usage with NestJS

  1. Configure the middleware in your AppModule:
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { TraceLoggerMiddleware } from '@your-org/nest-trace-logger';

@Module({
  imports: [],
  controllers: [],
  providers: [],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    // Configure the logger
    TraceLoggerMiddleware.configure({
      serviceName: 'your-service-name',
      level: 'info',
      timestampFormat: 'YYYY-MM-DD HH:mm:ss'
    });
    
    // Apply the middleware to all routes
    consumer
      .apply(TraceLoggerMiddleware)
      .forRoutes('*');
  }
}
  1. To use the logger in your services or controllers:
import { Injectable } from '@nestjs/common';
import { TraceLoggerMiddleware } from '@your-org/nest-trace-logger';

@Injectable()
export class YourService {
  private logger = TraceLoggerMiddleware.getInstance();

  async someMethod() {
    this.logger.info('Custom log message', { 
      customField: 'value'
    });
  }
}

Microservice Support

This library supports distributed tracing across microservices. Here's how to use it:

HTTP Module Example

// app.module.ts
import { Module } from '@nestjs/common';
import { HttpModule } from '@nestjs/axios';
import { TraceLoggerMiddleware } from '@your-org/nest-trace-logger';

@Module({
  imports: [
    HttpModule.registerAsync({
      useFactory: () => ({
        // Add trace ID to outgoing requests
        baseURL: 'http://other-service',
        headers: {
          [TraceLoggerMiddleware.TRACE_ID_HEADER]: TraceLoggerMiddleware.getCurrentTraceId()
        }
      })
    })
  ]
})
export class AppModule {}

// users.service.ts
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';
import { TraceLoggerMiddleware } from '@your-org/nest-trace-logger';

@Injectable()
export class UsersService {
  private readonly logger = TraceLoggerMiddleware.getInstance({
    serviceName: 'users-service'
  });

  constructor(private readonly httpService: HttpService) {}

  async getOrders(userId: string) {
    try {
      // Trace ID will be automatically propagated
      const response = await firstValueFrom(
        this.httpService.get(`/orders/${userId}`)
      );
      return response.data;
    } catch (error) {
      this.logger.error('Failed to fetch orders', {
        userId,
        targetService: 'orders-service',
        error
      });
      throw error;
    }
  }
}

Key Features for Microservices

  1. Automatic Trace ID Propagation: Trace IDs are automatically passed between services via headers
  2. Service Attribution: Logs include source and target service names
  3. Distributed Tracing: Track requests across multiple services
  4. Error Handling: Captures errors with service context

Headers

The following headers are used for tracing:

  • x-trace-id: Unique identifier for the request chain
  • x-source-service: Name of the calling service

Configuration

The middleware accepts these configuration options:

interface LoggerConfig {
  serviceName?: string;        // Default: process.env.SERVICE_NAME || 'unknown-service'
  level?: string;             // Default: 'info'
  timestampFormat?: string;   // Default: 'YYYY-MM-DD HH:mm:ss'
}

Log Format

All logs are output with color-coded levels and structured data:

2025-02-11 20:42:18 [your-service-name] INFO: Incoming request
{
  "traceId": "123e4567-e89b-12d3-a456-426614174000",
  "path": "/api/users",
  "method": "GET",
  "params": {},
  "query": {"page": "1"},
  "headers": {
    "user-agent": "curl/7.64.1"
  }
}

Request Tracing

The middleware automatically:

  • Generates a unique trace ID for each request
  • Adds the trace ID to response headers (x-trace-id)
  • Makes trace ID available in request object (req.traceId)
  • Includes trace ID in all log entries

Log Types

  1. Request Logs:

    {
      traceId: string;
      path: string;
      method: string;
      params: object;
      query: object;
      body: object;
      headers: object;
    }
  2. Response Logs:

    {
      traceId: string;
      path: string;
      method: string;
      statusCode: number;
      duration: number;
    }
  3. Error Logs:

    {
      traceId: string;
      path: string;
      method: string;
      statusCode: number;
      duration: number;
      error: {
        message: string;
        stack: string;
        code: string | number;
        status: number;
      }
    }

Direct Logger Usage

You can use the logger directly for custom logging:

const logger = TraceLoggerMiddleware.getInstance();

// Info level
logger.info('Processing payment', { 
  traceId: '123',
  userId: '456',
  amount: 100 
});

// Error level
logger.error('Payment failed', { 
  traceId: '123',
  error: new Error('Insufficient funds')
});

// Warning level
logger.warn('High CPU usage', { 
  usage: '85%' 
});

// Debug level
logger.debug('Cache miss', { 
  key: 'user:123' 
});

Best Practices

  1. Set a meaningful service name:

    const logger = TraceLoggerMiddleware.getInstance({
      serviceName: 'payment-service'
    });
  2. Use environment variables:

    export SERVICE_NAME=payment-service
  3. Include trace IDs in custom logs:

    logger.info('Custom event', { traceId: req.traceId });
  4. Set appropriate log levels:

    const logger = TraceLoggerMiddleware.getInstance({
      level: process.env.NODE_ENV === 'production' ? 'info' : 'debug'
    });