@shinijs/logger
v1.2.0
Published
Pino-based structured logger for NestJS applications with file rotation and pretty printing
Maintainers
Readme
@shinijs/logger
Pino-based structured logger for NestJS applications with file rotation and pretty printing
📚 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-rollPeer 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.0Note: 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=./logsAPI 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): voidLoggerFactory
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 debuggingdebug- Debugging informationinfo- Informational messages (default)warn- Warning messageserror- Error messagesfatal- 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=./logsKey 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=7File 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=24File 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 50MBSupported 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=falseFile 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=100MThis 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 successfullyProduction (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:covDocumentation
📚 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
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests and linting (
pnpm test && pnpm lint:check) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
For detailed guidelines, see CONTRIBUTING.md.
License
MIT © Shironex
