Overview

Flexible and extensible logging system for Vercube applications

The Logger module provides a powerful, flexible logging system for Vercube applications. Built around a provider-based architecture, it allows you to log messages at different levels (debug, info, warn, error) and output them to multiple destinations simultaneously through pluggable drivers.

Installation

$ pnpm add @vercube/logger

Quick Start

Register Logger in Container

Set up the logger in your DI container and configure providers. This is typically done once during application bootstrap.

src/container.ts
import { Container } from '@vercube/di';
import { Logger, BaseLogger, ConsoleProvider } from '@vercube/logger';

export function setupContainer(container: Container): void {
  // Bind BaseLogger implementation to Logger interface
  container.bind(Logger, BaseLogger);
  
  // Configure the logger
  container.get(Logger).configure({
    logLevel: 'info',
    providers: [
      {
        name: 'console',
        provider: ConsoleProvider,
        logLevel: 'debug'  // This provider logs everything
      }
    ]
  });
}

Inject Logger into Services

Use dependency injection to access the logger in your services. Log important operations and errors for debugging.

src/services/UserService.ts
import { Inject } from '@vercube/di';
import { Logger } from '@vercube/logger';

export class UserService {
  @Inject(Logger)
  private logger!: Logger;
  
  async createUser(data: CreateUserDto) {
    this.logger.debug('Creating user with data:', data);
    
    try {
      const user = await this.database.createUser(data);
      this.logger.info('User created successfully', { userId: user.id });
      return user;
    } catch (error) {
      this.logger.error('Failed to create user', error);
      throw error;
    }
  }
  
  async findUser(id: string) {
    this.logger.debug(`Looking up user: ${id}`);
    const user = await this.database.findUser(id);
    
    if (!user) {
      this.logger.warn(`User not found: ${id}`);
      return null;
    }
    
    return user;
  }
}

Use Logger in Controllers

Inject the logger into controllers to track incoming requests. This helps with monitoring and debugging API endpoints.

src/controllers/UserController.ts
import { Controller, Get, Post } from '@vercube/core';
import { Inject } from '@vercube/di';
import { Logger } from '@vercube/logger';

@Controller('/users')
export class UserController {
  @Inject(Logger)
  private logger!: Logger;
  
  @Inject(UserService)
  private userService!: UserService;
  
  @Post('/')
  async create(req: Request) {
    this.logger.info('POST /users - Creating new user');
    
    const data = await req.json();
    const user = await this.userService.createUser(data);
    
    return Response.json(user);
  }
  
  @Get('/:id')
  async findOne(req: Request, params: { id: string }) {
    this.logger.debug(`GET /users/${params.id}`);
    
    const user = await this.userService.findUser(params.id);
    
    if (!user) {
      return new Response('Not found', { status: 404 });
    }
    
    return Response.json(user);
  }
}

Core Concepts

Logger

The Logger is the main interface for logging messages throughout your application. It provides four logging methods corresponding to different severity levels:

  • debug() - Detailed information useful for debugging
  • info() - General operational information
  • warn() - Warnings about potentially harmful situations
  • error() - Error messages for serious problems

Providers

Providers (also called drivers) are responsible for processing and outputting log messages. Each provider can output logs to a different destination (console, file, external service, etc.) with its own formatting and configuration.

Log Levels

Vercube supports four hierarchical log levels:

debug (1) → info (2) → warn (3) → error (4)

When you set a log level, only messages at that level or higher are processed:

  • Set to debug - All messages are logged
  • Set to info - Info, warn, and error are logged
  • Set to warn - Only warn and error are logged
  • Set to error - Only error messages are logged

IOC Container Integration

The Logger integrates seamlessly with Vercube's dependency injection system. You register it in the IOC container and inject it wherever needed using the @Inject decorator.

Configuration

Basic Configuration

Configure the logger when setting up your application:

container.get(Logger).configure({
  // Global log level - applies to all providers unless overridden
  logLevel: 'info',
  
  // List of providers to use
  providers: [
    {
      name: 'console',
      provider: ConsoleProvider,
      // Optional: Override global log level for this provider
      logLevel: 'debug'
    }
  ]
});

Multiple Providers

You can use multiple providers simultaneously to output logs to different destinations:

import { ConsoleProvider, JSONProvider } from '@vercube/logger';

container.get(Logger).configure({
  logLevel: 'info',
  providers: [
    // Console output for development
    {
      name: 'console',
      provider: ConsoleProvider,
      logLevel: 'debug'  // Show everything in console
    },
    // JSON output for log aggregation
    {
      name: 'json',
      provider: JSONProvider,
      logLevel: 'warn'  // Only log warnings and errors to JSON
    }
  ]
});

Environment-Specific Configuration

Configure different logging behavior for different environments:

const isDevelopment = process.env.NODE_ENV === 'development';
const isProduction = process.env.NODE_ENV === 'production';

container.get(Logger).configure({
  logLevel: isDevelopment ? 'debug' : 'info',
  providers: isDevelopment
    ? [
        // Development: colorful console output
        {
          name: 'console',
          provider: ConsoleProvider,
          logLevel: 'debug'
        }
      ]
    : [
        // Production: structured JSON for log aggregation
        {
          name: 'json',
          provider: JSONProvider,
          logLevel: 'info'
        }
      ]
});

Per-Provider Log Levels

Each provider can have its own log level, independent of the global setting:

container.get(Logger).configure({
  logLevel: 'warn',  // Global: only warnings and errors
  providers: [
    {
      name: 'console',
      provider: ConsoleProvider,
      logLevel: 'debug'  // Console shows everything
    },
    {
      name: 'file',
      provider: FileProvider,
      logLevel: 'error'  // File only records errors
    }
  ]
});
Previous

Drivers

Built-in log providers and guide to creating custom drivers

Next