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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@shinijs/logger

v1.2.0

Published

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

Readme

@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":"[email protected]"}
{"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