npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hectormartin42/nestjs-seq-logger

v1.0.1

Published

NestJS module for logging to Seq using structured logging with CLEF format

Readme

@hectormartin42/nestjs-seq-logger

A powerful NestJS module for structured logging to Seq using the CLEF (Compact Log Event Format) format. Built with resilient design principles - logging failures will never break your application.

🚀 Features

  • Easy NestJS Integration - Drop-in replacement for default logger
  • Structured Logging - CLEF format with rich metadata
  • Automatic Batching - Efficient log transmission every 5 seconds
  • Resilient Design - Silent failure handling, won't crash your app
  • Configurable Levels - Filter logs by importance
  • Distributed Tracing - Full support for trace/span correlation
  • Environment Flexible - Works in development and production
  • Zero Dependencies - Only requires axios for HTTP requests

📦 Installation & Setup

Step 1: Install the Package

# NPM
npm install @hectormartin42/nestjs-seq-logger

# Yarn
yarn add @hectormartin42/nestjs-seq-logger

# PNPM
pnpm add @hectormartin42/nestjs-seq-logger

Step 2: Install Required Peer Dependencies

# If you don't have these already in your NestJS project
npm install @nestjs/common @nestjs/core reflect-metadata rxjs

Step 3: Set Up Seq Server

Option A: Docker (Recommended for Development)

# Quick start with Docker
docker run --name seq -d --restart unless-stopped \
  -e ACCEPT_EULA=Y \
  -p 5341:80 \
  datalust/seq:latest

# Access Seq at: http://localhost:5341

Option B: Docker Compose

Create docker-compose.yml:

version: '3.8'
services:
  seq:
    image: datalust/seq:latest
    container_name: seq-logger
    environment:
      - ACCEPT_EULA=Y
      - SEQ_FIRSTRUN_ADMINPASSWORDHASH=# Optional: set admin password
    ports:
      - "5341:80"
    volumes:
      - seq-data:/data
    restart: unless-stopped

volumes:
  seq-data:

Run with: docker-compose up -d

Option C: Production Seq Server

For production, use Seq Cloud or install Seq on your server following official docs.

Step 4: Configure Environment Variables

Add to your .env file:

# Required
SEQ_URL=http://localhost:5341

# Optional (recommended for production)
SEQ_API_KEY=your-api-key-here
APP_NAME=my-nestjs-app
SEQ_WORKSPACE=development

🔧 NestJS Integration

Basic Setup (app.module.ts)

import { Module } from '@nestjs/common';
import { SeqLoggerModule } from '@hectormartin42/nestjs-seq-logger';

@Module({
  imports: [
    // Basic configuration
    SeqLoggerModule.forRoot({
      seqUrl: 'http://localhost:5341',
      apiKey: 'your-api-key', // Optional
      application: 'my-app',
      workspace: 'development',
      minimumLevel: 'information'
    }),
  ],
  // ... your other modules
})
export class AppModule {}

Environment Variables Setup (Recommended)

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { SeqLoggerModule } from '@hectormartin42/nestjs-seq-logger';

@Module({
  imports: [
    ConfigModule.forRoot(),
    
    // Using environment variables
    SeqLoggerModule.forRoot({
      seqUrl: process.env.SEQ_URL,
      apiKey: process.env.SEQ_API_KEY,
      application: process.env.APP_NAME || 'my-app',
      workspace: process.env.SEQ_WORKSPACE || 'development',
      minimumLevel: 'information'
    }),
  ],
})
export class AppModule {}

Advanced Async Configuration

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { SeqLoggerModule } from '@hectormartin42/nestjs-seq-logger';

@Module({
  imports: [
    ConfigModule.forRoot(),
    
    // Async configuration with ConfigService
    SeqLoggerModule.forRootAsync({
      useFactory: async (configService: ConfigService) => ({
        seqUrl: configService.get('SEQ_URL'),
        apiKey: configService.get('SEQ_API_KEY'),
        application: configService.get('APP_NAME', 'my-app'),
        workspace: configService.get('SEQ_WORKSPACE', 'development'),
        minimumLevel: configService.get('LOG_LEVEL', 'information'),
      }),
      inject: [ConfigService],
    }),
  ],
})
export class AppModule {}

Replace Default NestJS Logger (Optional)

In your main.ts:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SeqLoggerService } from '@hectormartin42/nestjs-seq-logger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  
  // Replace default logger with Seq logger
  const seqLogger = app.get(SeqLoggerService);
  app.useLogger(seqLogger);
  
  await app.listen(3000);
  
  // This will now log to Seq!
  seqLogger.log('Application started successfully', 'Bootstrap', {
    port: 3000,
    environment: process.env.NODE_ENV
  });
}
bootstrap();

📝 Usage Examples

Basic Service Usage

import { Injectable } from '@nestjs/common';
import { SeqLoggerService } from '@hectormartin42/nestjs-seq-logger';

@Injectable()
export class UserService {
  constructor(private readonly logger: SeqLoggerService) {}

  async createUser(userData: CreateUserDto) {
    const startTime = Date.now();
    
    this.logger.log('Creating new user', 'UserService', {
      email: userData.email,
      role: userData.role,
      timestamp: new Date().toISOString()
    });

    try {
      const user = await this.userRepository.save(userData);
      
      this.logger.log('User created successfully', 'UserService', {
        userId: user.id,
        email: user.email,
        duration: `${Date.now() - startTime}ms`
      });

      return user;
    } catch (error) {
      this.logger.error('Failed to create user', error, 'UserService', {
        email: userData.email,
        errorCode: error.code,
        duration: `${Date.now() - startTime}ms`
      });
      throw error;
    }
  }
}

HTTP Controller Example

import { Controller, Post, Body, Get, Param } from '@nestjs/common';
import { SeqLoggerService } from '@hectormartin42/nestjs-seq-logger';

@Controller('users')
export class UserController {
  constructor(
    private readonly userService: UserService,
    private readonly logger: SeqLoggerService
  ) {}

  @Post()
  async createUser(@Body() userData: CreateUserDto) {
    const correlationId = crypto.randomUUID();
    
    this.logger.log('HTTP request received', 'UserController', {
      method: 'POST',
      endpoint: '/users',
      correlationId,
      userAgent: 'browser-info'
    });

    try {
      const result = await this.userService.createUser(userData);
      
      this.logger.log('HTTP request completed', 'UserController', {
        method: 'POST',
        endpoint: '/users',
        correlationId,
        statusCode: 201,
        userId: result.id
      });

      return result;
    } catch (error) {
      this.logger.error('HTTP request failed', error, 'UserController', {
        method: 'POST',
        endpoint: '/users',
        correlationId,
        statusCode: error.status || 500
      });
      throw error;
    }
  }
}

Database Service with Detailed Logging

@Injectable()
export class DatabaseService {
  constructor(private readonly logger: SeqLoggerService) {}

  async executeQuery(sql: string, params: any[] = []) {
    const queryId = crypto.randomUUID();
    const startTime = performance.now();

    this.logger.debug('Executing database query', 'DatabaseService', {
      queryId,
      sql: sql.substring(0, 100) + '...', // Truncate for security
      paramCount: params.length
    });

    try {
      const result = await this.connection.query(sql, params);
      const duration = performance.now() - startTime;

      this.logger.log('Query executed successfully', 'DatabaseService', {
        queryId,
        rowCount: result.length,
        duration: `${duration.toFixed(2)}ms`,
        performanceLevel: duration > 1000 ? 'slow' : 'fast'
      });

      return result;
    } catch (error) {
      const duration = performance.now() - startTime;
      
      this.logger.error('Query execution failed', error, 'DatabaseService', {
        queryId,
        duration: `${duration.toFixed(2)}ms`,
        errorCode: error.code,
        sqlState: error.sqlState
      });
      throw error;
    }
  }
}

⚙️ Configuration Reference

Configuration Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | seqUrl | string | process.env.SEQ_URL | Seq server URL (required) | | apiKey | string | process.env.SEQ_API_KEY | API key for authentication | | application | string | process.env.APP_NAME \|\| 'nestjs-app' | Application name in logs | | workspace | string | process.env.SEQ_WORKSPACE | Workspace/environment identifier | | minimumLevel | LogLevel | 'information' | Minimum log level to send |

Log Levels (in order of severity)

| Level | Numeric Value | When to Use | |-------|---------------|-------------| | verbose | 0 | Extremely detailed debugging info | | debug | 1 | Development debugging information | | information | 2 | General application flow | | warning | 3 | Potentially harmful situations | | error | 4 | Error events that don't stop execution | | fatal | 5 | Critical errors that may cause termination |

Environment Variables

# Required
SEQ_URL=http://localhost:5341              # Seq server endpoint

# Optional
SEQ_API_KEY=abcdef123456                   # Authentication (recommended for production)
APP_NAME=my-nestjs-application             # Application name in logs
SEQ_WORKSPACE=development                   # Environment identifier
LOG_LEVEL=information                      # Minimum log level

🎯 Advanced Features

Distributed Tracing Support

@Injectable()
export class OrderService {
  constructor(private readonly logger: SeqLoggerService) {}

  async processOrder(orderId: string, traceId: string) {
    const spanId = crypto.randomUUID();
    
    // Log with tracing information
    this.logger.traceEvent('Order processing started', 'OrderService', {
      traceId,
      spanId,
      spanKind: 'Internal',
      startTime: new Date().toISOString(),
      orderId,
      operation: 'processOrder'
    });

    try {
      // Call external payment service
      await this.callPaymentService(orderId, traceId, spanId);
      
      this.logger.traceEvent('Order processed successfully', 'OrderService', {
        traceId,
        spanId,
        orderId,
        status: 'completed'
      });
    } catch (error) {
      this.logger.error('Order processing failed', error, 'OrderService', {
        traceId,
        spanId,
        orderId
      });
      throw error;
    }
  }

  private async callPaymentService(orderId: string, parentTraceId: string, parentSpanId: string) {
    const spanId = crypto.randomUUID();
    
    this.logger.traceEvent('Calling payment service', 'OrderService', {
      traceId: parentTraceId,
      spanId,
      parentId: parentSpanId,
      spanKind: 'Client',
      orderId,
      service: 'payment-api'
    });

    // Make HTTP call...
  }
}

Custom Object Serialization

The logger safely handles complex objects:

this.logger.log('Complex operation completed', 'MyService', {
  user: {
    id: 123,
    email: '[email protected]',
    preferences: {
      theme: 'dark',
      notifications: true,
      nested: {
        deep: {
          value: 'safely serialized'
        }
      }
    }
  },
  request: req, // HTTP request objects are safely handled
  response: res, // HTTP response objects are safely handled
  metadata: {
    timestamp: new Date(),
    version: '1.0.0',
    environment: process.env.NODE_ENV
  }
});

🛠️ Development vs Production

Development Configuration

// app.module.ts (development)
SeqLoggerModule.forRoot({
  seqUrl: 'http://localhost:5341',
  application: 'my-app-dev',
  workspace: 'development',
  minimumLevel: 'debug' // Show debug logs in development
})
# .env.development
SEQ_URL=http://localhost:5341
APP_NAME=my-app-dev
SEQ_WORKSPACE=development
LOG_LEVEL=debug

Production Configuration

// app.module.ts (production)
SeqLoggerModule.forRoot({
  seqUrl: process.env.SEQ_URL, // External Seq instance
  apiKey: process.env.SEQ_API_KEY, // Required for production
  application: process.env.APP_NAME,
  workspace: 'production',
  minimumLevel: 'information' // Filter out debug logs
})
# .env.production
SEQ_URL=https://your-seq-server.com
SEQ_API_KEY=your-production-api-key
APP_NAME=my-app
SEQ_WORKSPACE=production
LOG_LEVEL=information

🔍 Troubleshooting

Common Issues & Solutions

❌ "Cannot connect to Seq server"

Seq logger could not connect to http://localhost:5341. Logs will not be sent to Seq.

Solutions:

  1. Verify Seq is running: curl http://localhost:5341/api
  2. Check Docker container: docker ps | grep seq
  3. Verify SEQ_URL environment variable
  4. Check firewall/network connectivity

❌ Module dependency errors

Cannot resolve dependency SeqLoggerService

Solutions:

  1. Install peer dependencies: npm install @nestjs/common @nestjs/core reflect-metadata rxjs
  2. Ensure module is imported in AppModule
  3. Check TypeScript decorator configuration

❌ API authentication failed

Error sending logs to Seq: 401 Unauthorized

Solutions:

  1. Verify API key in Seq admin panel
  2. Check API key permissions
  3. Ensure correct SEQ_API_KEY environment variable

❌ Logs not appearing in Seq

Check:

  1. Log level configuration (logs below minimumLevel are filtered)
  2. Seq ingestion endpoint accessibility
  3. Console for connection errors
  4. Seq server health and storage space

Debug Mode

Enable verbose logging to troubleshoot:

SeqLoggerModule.forRoot({
  seqUrl: 'http://localhost:5341',
  minimumLevel: 'verbose', // Shows all logs
  // ... other options
})

Health Check

Add a health check endpoint:

@Controller('health')
export class HealthController {
  constructor(private readonly logger: SeqLoggerService) {}

  @Get('seq')
  async checkSeqConnection() {
    this.logger.log('Health check performed', 'HealthController', {
      endpoint: '/health/seq',
      timestamp: new Date().toISOString()
    });
    
    return { status: 'ok', seqLogging: 'enabled' };
  }
}

📚 API Reference

SeqLoggerService Methods

// Basic logging
log(message: any, context?: string, data?: any): void
error(message: any, trace?: string | Error, context?: string, data?: any): void
warn(message: any, context?: string, data?: any): void
debug(message: any, context?: string, data?: any): void
verbose(message: any, context?: string, data?: any): void
fatal(message: any, context?: string, data?: any): void

// Distributed tracing
traceEvent(message: any, context?: string, traceData?: TraceData): void

// Utility methods
objectToJson(obj: any, maxDepth?: number): any

TraceData Interface

interface TraceData {
  traceId?: string;
  spanId?: string;
  parentId?: string;
  spanKind?: 'Client' | 'Server' | 'Internal' | 'Producer' | 'Consumer';
  startTime?: string;
  [key: string]: any; // Additional custom properties
}

Usage Examples by Method

// Information level
logger.log('User logged in', 'AuthService', { 
  userId: 123, 
  email: '[email protected]' 
});

// Warning level
logger.warn('API rate limit approaching', 'ApiService', { 
  currentRequests: 95, 
  limit: 100 
});

// Error level (with stack trace)
logger.error('Database connection failed', error, 'DatabaseService', { 
  connectionString: 'masked',
  retryAttempt: 3
});

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

// Verbose level
logger.verbose('Query executed', 'DatabaseService', { 
  query: 'SELECT * FROM users', 
  executionTime: '45ms' 
});

// Fatal level
logger.fatal('Application startup failed', 'Bootstrap', { 
  error: 'Port 3000 already in use' 
});

// Distributed tracing
logger.traceEvent('HTTP request processed', 'ApiController', {
  traceId: '1234567890abcdef',
  spanId: 'abcdef1234567890',
  parentId: '0987654321fedcba',
  spanKind: 'Server',
  startTime: '2024-01-01T12:00:00.000Z',
  httpMethod: 'POST',
  httpUrl: '/api/users',
  httpStatusCode: 201,
  userId: 123
});

🎨 Complete Working Example

Full Application Setup

// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { SeqLoggerModule } from '@hectormartin42/nestjs-seq-logger';
import { UserModule } from './user/user.module';

@Module({
  imports: [
    ConfigModule.forRoot(),
    SeqLoggerModule.forRoot({
      seqUrl: process.env.SEQ_URL,
      apiKey: process.env.SEQ_API_KEY,
      application: process.env.APP_NAME || 'my-app',
      workspace: process.env.SEQ_WORKSPACE || 'development',
      minimumLevel: 'information'
    }),
    UserModule,
  ],
})
export class AppModule {}

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SeqLoggerService } from '@hectormartin42/nestjs-seq-logger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  
  const seqLogger = app.get(SeqLoggerService);
  app.useLogger(seqLogger);
  
  await app.listen(3000);
  
  seqLogger.log('Application started', 'Bootstrap', {
    port: 3000,
    environment: process.env.NODE_ENV,
    timestamp: new Date().toISOString()
  });
}
bootstrap();

// user.service.ts
import { Injectable } from '@nestjs/common';
import { SeqLoggerService } from '@hectormartin42/nestjs-seq-logger';

@Injectable()
export class UserService {
  constructor(private readonly logger: SeqLoggerService) {}

  async findAll() {
    this.logger.log('Fetching all users', 'UserService');
    
    try {
      // Simulate database call
      const users = await this.mockDatabaseCall();
      
      this.logger.log('Users fetched successfully', 'UserService', {
        count: users.length
      });
      
      return users;
    } catch (error) {
      this.logger.error('Failed to fetch users', error, 'UserService');
      throw error;
    }
  }

  private async mockDatabaseCall() {
    // Simulate async operation
    return new Promise(resolve => 
      setTimeout(() => resolve([{ id: 1, name: 'John' }]), 100)
    );
  }
}

🤝 Contributing

  1. Fork the repository
  2. Create your feature branch: git checkout -b feature/amazing-feature
  3. Commit your changes: git commit -m 'Add amazing feature'
  4. Push to the branch: git push origin feature/amazing-feature
  5. Open a Pull Request

📄 License

MIT License - see the LICENSE file for details.


🔗 Links


Made with ❤️ for the NestJS community