Skip to content

shinijs/logger

@shinijs/logger

Pino-based structured logger for NestJS applications with file rotation and pretty printing

CI Documentation

📚 Full Documentation | API Reference | Examples

Features

  • Pino-based - Fast, low-overhead structured logging
  • NestJS Integration - Seamless integration with NestJS ecosystem
  • Pretty Printing - Beautiful console output in development
  • File Rotation - Automatic daily log file rotation
  • Configurable - Environment-based configuration
  • TypeScript - Full type safety
  • Context Support - Scoped logging with context

Installation

pnpm add @shinijs/logger pino pino-pretty pino-roll

Peer Dependencies

This package requires the following peer dependencies to be installed in your project:

Package Version Required
@nestjs/common ^11.0.0 Yes
@nestjs/config ^4.0.0 Yes
pino ^10.0.0 Yes
pino-pretty ^13.0.0 Yes
pino-roll ^4.0.0 Yes
reflect-metadata ^0.2.0 Yes

Install all peer dependencies:

pnpm add @nestjs/common@^11.0.0 @nestjs/config@^4.0.0 pino@^10.0.0 pino-pretty@^13.0.0 pino-roll@^4.0.0 reflect-metadata@^0.2.0

Note: If you're already using NestJS, you likely have @nestjs/common, @nestjs/config, and reflect-metadata installed. You only need to ensure pino, pino-pretty, and pino-roll are present.

Quick Start

1. Import the Module

import { LoggerModule } from '@shinijs/logger';

@Module({
  imports: [LoggerModule],
  // ...
})
export class AppModule {}

2. Use the Logger

import { CustomLogger } from '@shinijs/logger';

@Injectable()
export class YourService {
  constructor(private readonly logger: CustomLogger) {
    this.logger.setContext('YourService');
  }

  doSomething() {
    this.logger.log('Doing something');
    this.logger.error('Something went wrong', { error: 'details' });
  }
}

Configuration

Set environment variables:

# Log level: trace, debug, info, warn, error, fatal
LOG_LEVEL=info

# Pretty print in development
LOG_PRETTY_PRINT=true

# File logging
LOG_FILE_ENABLED=true
LOG_FILE_PATH=./logs

API Reference

CustomLogger

Main logger service implementing NestJS LoggerService.

Methods:

// Set logging context
setContext(context: string): void

// Log levels
log(message: string, metadata?: object): void
error(message: string, metadata?: object): void
warn(message: string, metadata?: object): void
debug(message: string, metadata?: object): void
verbose(message: string, metadata?: object): void

LoggerFactory

Factory for creating context-bound loggers. The ContextBoundLogger implements NestJS LoggerService for full compatibility.

import { LoggerFactory } from '@shinijs/logger';

@Injectable()
export class MyService {
  private readonly logger = LoggerFactory.createLogger('MyService');

  doWork() {
    this.logger.log('Working...');
    // ContextBoundLogger implements LoggerService, so it works with NestJS's standard logger interface
  }
}

Examples

Basic Logging

import { CustomLogger } from '@shinijs/logger';

@Injectable()
export class UserService {
  constructor(private readonly logger: CustomLogger) {
    this.logger.setContext('UserService');
  }

  async createUser(data: CreateUserDto) {
    this.logger.log('Creating user', { email: data.email });

    try {
      const user = await this.userRepository.create(data);
      this.logger.log('User created successfully', { userId: user.id });
      return user;
    } catch (error) {
      this.logger.error('Failed to create user', { error, email: data.email });
      throw error;
    }
  }
}

Using Logger Factory

import { LoggerFactory } from '@shinijs/logger';

export class SomeClass {
  private readonly logger = LoggerFactory.createLogger('SomeClass');

  process() {
    this.logger.debug('Processing started');
    // ... your logic
    this.logger.debug('Processing completed');
  }
}

Structured Logging

this.logger.log('Request processed', {
  method: 'POST',
  path: '/api/users',
  statusCode: 201,
  duration: 45,
  userId: '123',
});

Integrating with Rate Limit Module

Use the logger with @shinijs/rate-limit for consistent logging:

import { Module, Global } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { LoggerModule, LoggerFactory } from '@shinijs/logger';
import { RateLimitModule } from '@shinijs/rate-limit';

// Token for RateLimit logger provider
export const RATE_LIMIT_LOGGER_TOKEN = Symbol('RATE_LIMIT_LOGGER');

// Create a global module to provide the logger token
@Global()
@Module({
  providers: [
    {
      provide: RATE_LIMIT_LOGGER_TOKEN,
      useFactory: (loggerFactory: LoggerFactory) => {
        return loggerFactory.createLogger('RateLimit');
      },
      inject: [LoggerFactory],
    },
  ],
  exports: [RATE_LIMIT_LOGGER_TOKEN],
})
class RateLimitLoggerModule {}

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    LoggerModule,
    RateLimitLoggerModule,
    RateLimitModule.forRoot({
      loggerToken: RATE_LIMIT_LOGGER_TOKEN,
    }),
  ],
})
export class AppModule {}

Configuration Options

Environment Variables

Variable Description Default
LOG_LEVEL Minimum log level info
LOG_PRETTY_PRINT Enable pretty console output false
LOG_FILE_ENABLED Enable file logging false
LOG_FILE_PATH Directory for log files ./logs
LOG_FILE_ROTATION_ENABLED Enable automatic log file rotation true*
LOG_FILE_ROTATION_FREQUENCY Rotation frequency: daily, hourly, custom daily
LOG_FILE_ROTATION_PATTERN Date pattern for rotated filenames YYYY-MM-DD
LOG_FILE_MAX_FILES Number of log files to retain 7
LOG_FILE_SIZE_LIMIT Maximum file size before rotation 10M

* Rotation is enabled by default when LOG_FILE_ENABLED=true. Set to false to use a single log file without rotation.

Log Levels

From lowest to highest priority:

  • trace - Very detailed debugging
  • debug - Debugging information
  • info - Informational messages (default)
  • warn - Warning messages
  • error - Error messages
  • fatal - Fatal errors

File Logging

When file logging is enabled, logs are written to files in the specified directory with automatic rotation and cleanup.

Basic Configuration

LOG_FILE_ENABLED=true
LOG_FILE_PATH=./logs

Key Features:

  • File logging works simultaneously with pretty printing - you can have both console output and file logging in development
  • Directory is created automatically if it doesn't exist
  • Automatic log file rotation enabled by default
  • Old log files are automatically cleaned up based on retention policy

Log Rotation

Log rotation is enabled by default when file logging is enabled. This prevents log files from growing indefinitely and helps manage disk space.

Daily Rotation (Default)

LOG_FILE_ENABLED=true
LOG_FILE_PATH=./logs
LOG_FILE_ROTATION_FREQUENCY=daily
LOG_FILE_MAX_FILES=7

File naming pattern: app-YYYY-MM-DD.log

Example files:

logs/
├── app-2024-01-15.log  (today)
├── app-2024-01-14.log
├── app-2024-01-13.log
├── app-2024-01-12.log
├── app-2024-01-11.log
├── app-2024-01-10.log
└── app-2024-01-09.log  (oldest, will be deleted when new day starts)

Automatic cleanup: When the 8th day arrives, the oldest file (app-2024-01-09.log) is automatically deleted, keeping only the most recent 7 days of logs.

Hourly Rotation

For high-traffic applications or more granular log management:

LOG_FILE_ENABLED=true
LOG_FILE_PATH=./logs
LOG_FILE_ROTATION_FREQUENCY=hourly
LOG_FILE_ROTATION_PATTERN=YYYY-MM-DD-HH
LOG_FILE_MAX_FILES=24

File naming pattern: app-YYYY-MM-DD-HH.log

Example files:

logs/
├── app-2024-01-15-14.log  (current hour)
├── app-2024-01-15-13.log
├── app-2024-01-15-12.log
└── ... (keeps last 24 hours)

Size-Based Rotation

Rotate logs when they reach a specific size:

LOG_FILE_ENABLED=true
LOG_FILE_PATH=./logs
LOG_FILE_SIZE_LIMIT=50M  # Rotate when file reaches 50MB

Supported size units: K (kilobytes), M (megabytes), G (gigabytes)

Disabled Rotation

To use a single log file without rotation (legacy behavior):

LOG_FILE_ENABLED=true
LOG_FILE_PATH=./logs
LOG_FILE_ROTATION_ENABLED=false

File naming: app.log (single file, grows indefinitely)

Use case: Suitable when you have external log management tools or limited logging needs.

Rotation Configuration Reference

Setting Options Description
Frequency daily, hourly, custom How often to create new log files
Pattern Date format string Filename pattern (e.g., YYYY-MM-DD, YYYY-MM-DD-HH)
Max Files Number (e.g., 7, 24, 30) Number of log files to keep before deleting oldest
Size Limit Size string (e.g., 10M, 50M, 1G) Maximum file size before rotation

Complete Example

Production configuration with daily rotation and 30-day retention:

# Basic logging
LOG_LEVEL=info
LOG_PRETTY_PRINT=false

# File logging with rotation
LOG_FILE_ENABLED=true
LOG_FILE_PATH=/var/log/myapp

# Rotation settings
LOG_FILE_ROTATION_ENABLED=true
LOG_FILE_ROTATION_FREQUENCY=daily
LOG_FILE_ROTATION_PATTERN=YYYY-MM-DD
LOG_FILE_MAX_FILES=30
LOG_FILE_SIZE_LIMIT=100M

This configuration will:

  • Create daily log files: app-2024-01-15.log, app-2024-01-14.log, etc.
  • Keep the last 30 days of logs
  • Rotate early if a file exceeds 100MB
  • Automatically delete logs older than 30 days

Development vs Production

Development (with LOG_PRETTY_PRINT=true):

14:23:45 INFO  [UserService] Creating user
14:23:45 INFO  [UserService] User created successfully

Production (JSON output):

{"level":30,"time":1699999999,"context":"UserService","msg":"Creating user","email":"user@example.com"}
{"level":30,"time":1700000000,"context":"UserService","msg":"User created successfully","userId":"123"}

Testing

# Unit tests
pnpm test

# Watch mode
pnpm test:watch

# Coverage
pnpm test:cov

Documentation

📚 Full Documentation is available with:

  • Complete API reference
  • Configuration guide
  • Usage examples
  • Best practices
  • Advanced patterns

Contributing

Contributions are welcome! Please read our Contributing Guide and Code of Conduct before submitting pull requests.

Quick Start for Contributors

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests and linting (pnpm test && pnpm lint:check)
  5. Commit your changes (git commit -m 'feat: add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

For detailed guidelines, see CONTRIBUTING.md.

License

MIT © Shironex

About

Pino-based structured logger for NestJS applications with file rotation and pretty printing

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •