@remidosol/the-nestjs-logger v1.1.1
@remidosol/the-nestjs-logger
A flexible, multi-provider logging module for NestJS applications. This package offers a unified logging interface with support for Winston, Pino, and Bunyan loggers, simplifying the integration of comprehensive logging into your NestJS projects.
Table of Contents
- Features
- Installation
- Quick Start
- Detailed Configuration
- Usage Examples
- API Reference
- Best Practices
- Contributing
- License
- Support
- Acknowledgments
Features
🚀 Multiple Logger Providers
- Winston (full support)
- Pino (with pretty-print support)
- Bunyan (with streaming support)
📝 Advanced Configuration Options
- Type-safe configurations
- Environment-based setup
- Custom transport options
- Format customization
🔄 File Management
- Daily rotating file logs
- Size-based rotation
- Compression support
- Automatic cleanup
🌐 Network Support
- Syslog integration (UDP/TCP)
- HTTP transport
- Custom network protocols
- Remote logging
🎨 Output Formatting
- Colorized console output
- JSON formatting
- Custom formatters
- Pretty printing
🔍 Error Handling
- Detailed error tracking
- Stack trace formatting
- Error context preservation
- Custom error handlers
📊 Context & Metadata
- Request context logging
- Class context injection
- Custom metadata
- Global metadata
🔗 Request Tracking
- Correlation ID support
- Request ID tracking
- Transaction tracking
- Request context preservation
⚡ Performance
- Performance profiling
- Timing decorators
- Async tracking
- Resource monitoring
🔒 Security
- Transport-level security
- Sensitive data masking
- Configurable redaction
- Secure defaults
🌍 Module Integration
- Global module support
- Custom provider injection
- Module configuration
- Dynamic modules
Installation
Install the package using your preferred package manager:
# npm
npm install @remidosol/the-nestjs-logger
# yarn
yarn add @remidosol/the-nestjs-logger
# pnpm
pnpm add @remidosol/the-nestjs-loggerQuick Start
Integrate the logger into your NestJS application by configuring the TheLoggerModule with your preferred logger provider.
import { Module } from '@nestjs/common';
import { TheLoggerModule, WinstonLogLevel } from '@remidosol/the-nestjs-logger';
@Module({
imports: [
TheLoggerModule.forRoot({
provider: 'winston',
defaultLevel: WinstonLogLevel.Info,
consoleTransportOptions: [
{
level: WinstonLogLevel.Debug,
},
],
}),
],
})
export class AppModule {}Detailed Configuration
Winston Configuration
Configure the TheLoggerModule to use Winston with advanced transport options.
import { Module } from '@nestjs/common';
import { TheLoggerModule, WinstonLogLevel, SyslogTypeEnum } from '@remidosol/the-nestjs-logger';
import * as winston from 'winston';
@Module({
imports: [
TheLoggerModule.forRoot({
provider: 'winston',
global: true,
winstonOptions: {
defaultLevel: WinstonLogLevel.Info,
defaultMeta: {
service: 'my-service',
environment: process.env.NODE_ENV,
},
consoleTransportOptions: [
{
level: WinstonLogLevel.Debug,
format: winston.format.combine(
winston.format.timestamp(),
winston.format.colorize(),
winston.format.json()
),
},
],
syslogTransportOptions: [
{
host: 'localhost',
port: 514,
protocol: 'udp4',
type: SyslogTypeEnum.RFC5424,
facility: 'local0',
app_name: 'my-app',
},
],
dailyRotateFileTransportOptions: [
{
dirname: 'logs',
filename: 'error-%DATE%.log',
datePattern: 'YYYY-MM-DD-HH',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d',
level: 'error',
},
],
},
}),
],
})
export class AppModule {}Pino Configuration
Set up Pino as your logger provider with pretty-print support and sensitive data redaction.
import { Module } from '@nestjs/common';
import { TheLoggerModule } from '@remidosol/the-nestjs-logger';
@Module({
imports: [
TheLoggerModule.forRoot({
provider: 'pino',
pinoOptions: {
level: 'info',
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: true,
},
},
formatters: {
level: (label) => ({ level: label }),
},
redact: ['password', 'secret'],
},
}),
],
})
export class AppModule {}Bunyan Configuration
Configure Bunyan with multiple streams and rotating file support.
import { Module } from '@nestjs/common';
import { TheLoggerModule } from '@remidosol/the-nestjs-logger';
import * as bunyan from 'bunyan';
@Module({
imports: [
TheLoggerModule.forRoot({
provider: 'bunyan',
bunyanOptions: {
name: 'my-app',
level: 'info',
streams: [
{
stream: process.stdout,
level: 'debug',
},
{
type: 'rotating-file',
path: 'logs/app.log',
period: '1d',
count: 7,
},
],
serializers: bunyan.stdSerializers,
},
}),
],
})
export class AppModule {}Async Configuration
Load logger configurations asynchronously, such as from environment variables or external configuration services.
import { Module } from '@nestjs/common';
import { TheLoggerModule } from '@remidosol/the-nestjs-logger';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
TheLoggerModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
provider: 'winston',
winstonOptions: {
defaultLevel: configService.get<string>('LOG_LEVEL', 'info'),
consoleTransportOptions: [
{
level: configService.get<string>('CONSOLE_LOG_LEVEL', 'debug'),
},
],
syslogTransportOptions: [
{
host: configService.get<string>('SYSLOG_HOST', 'localhost'),
port: configService.get<number>('SYSLOG_PORT', 514),
},
],
},
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}Usage Examples
Basic Logging
Inject the abstract logger and utilize it within your services.
import { Injectable } from '@nestjs/common';
import { AbstractLogger } from '@remidosol/the-nestjs-logger';
@Injectable()
export class UserService {
constructor(private readonly logger: AbstractLogger) {}
async createUser(userData: any) {
this.logger.info('Creating new user', {
context: 'UserService',
props: { userData },
});
try {
// ... user creation logic
} catch (error) {
this.logger.error('Failed to create user', {
context: 'UserService',
error,
props: { userData },
});
throw error;
}
}
}Performance Profiling
Track performance metrics within your services.
import { Injectable } from '@nestjs/common';
import { AbstractLogger } from '@remidosol/the-nestjs-logger';
@Injectable()
export class PerformanceService {
constructor(private readonly logger: AbstractLogger) {}
async heavyOperation() {
const profileId = 'heavy-operation';
this.logger.debug('Starting heavy operation', { context: 'PerformanceService' }, profileId);
// Operation code here
this.logger.debug('Completed heavy operation', { context: 'PerformanceService' }, profileId);
}
}Error Handling
Log errors with detailed context and metadata.
import { Injectable } from '@nestjs/common';
import { AbstractLogger } from '@remidosol/the-nestjs-logger';
@Injectable()
export class ErrorHandlingService {
constructor(private readonly logger: AbstractLogger) {}
async riskyOperation() {
try {
throw new Error('Something went wrong');
} catch (error) {
this.logger.error('Operation failed', {
context: 'ErrorHandlingService',
error,
correlationId: 'abc-123',
props: {
additionalInfo: 'Some context',
timestamp: new Date(),
},
});
}
}
}API Reference
Log Levels
enum CommonLogLevel {
fatal = 'fatal',
error = 'error',
warn = 'warn',
info = 'info',
debug = 'debug',
trace = 'trace',
}LogData Interface
interface LogData {
organization?: string; // Organization name
context?: string; // Context name
app?: string; // Application name
sourceClass?: string; // Source class name
correlationId?: string; // Correlation ID
error?: Error; // Error object
props?: any; // Additional properties
}Available Methods
log
log(
level: CommonLogLevel,
message: string | Error,
data?: LogData,
profile?: string,
): void;Logs a message with the specified log level.
Parameters:
level: The severity level of the log (e.g.,info,error).message: The log message or anErrorobject.data: Optional additional metadata for the log.profile: Optional profiling identifier.
debug
debug(
message: string,
data?: LogData,
profile?: string,
): void;Logs a debug-level message.
Parameters:
message: The log message.data: Optional additional metadata.profile: Optional profiling identifier.
info
info(
message: string,
data?: LogData,
profile?: string,
): void;Logs an info-level message.
Parameters:
message: The log message.data: Optional additional metadata.profile: Optional profiling identifier.
warn
warn(
message: string | Error,
data?: LogData,
profile?: string,
): void;Logs a warning-level message.
Parameters:
message: The log message or anErrorobject.data: Optional additional metadata.profile: Optional profiling identifier.
error
error(
message: string | Error,
data?: LogData,
profile?: string,
): void;Logs an error-level message.
Parameters:
message: The log message or anErrorobject.data: Optional additional metadata.profile: Optional profiling identifier.
fatal
fatal(
message: string | Error,
data?: LogData,
profile?: string,
): void;Logs a fatal-level message.
Parameters:
message: The log message or anErrorobject.data: Optional additional metadata.profile: Optional profiling identifier.
Usage Example:
this.logger.info('User created successfully', {
context: 'UserService',
userId: '12345',
});Best Practices
Context Usage
- Always provide a context in
LogData. - Use meaningful context names.
- Maintain a consistent context hierarchy.
- Always provide a context in
Request Tracking
- Utilize correlation IDs for tracking requests across services.
- Ensure correlation IDs are propagated through asynchronous operations.
- Include request-specific metadata in logs.
Metadata Management
- Include relevant metadata in the
propsfield. - Structure metadata consistently for easier querying and analysis.
- Avoid logging sensitive information unless properly masked or redacted.
- Include relevant metadata in the
Log Levels
- Use appropriate log levels (
info,warn,error, etc.) based on the severity. - Be consistent with log level usage across the application.
- Document log level guidelines for team members.
- Use appropriate log levels (
Error Handling
- Log complete error contexts, including stack traces.
- Capture and log relevant error metadata.
- Implement custom error handlers if necessary to enrich error logs.
Performance
- Profile and monitor performance-intensive operations.
- Monitor log volume to prevent performance degradation.
- Implement log rotation and cleanup to manage log storage.
Contributing
Contributions are welcome! Please follow the guidelines below to contribute to this project.
Development Setup
# Clone the repository
git clone https://github.com/remidosol/nestjs-logger.git
cd nestjs-logger
# Install dependencies
npm install
# Run tests
npm run test:e2e
# Run linting
npm run lint
# Build the package
npm run buildCommit Guidelines
We follow Conventional Commits for this project. Each commit message should adhere to the following structure:
<type>(<scope>): <description>
[optional body]
[optional footer(s)]Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoring without adding features or fixing bugsperf: Performance improvementstest: Adding or updating testschore: Maintenance tasks (e.g., updating dependencies)
Example:
feat(auth): add JWT authentication support
Implemented JWT-based authentication to enhance security and scalability.
Added necessary guards and strategies.License
This project is licensed under the MIT License.
Support
- Create an Issue: GitHub Issues
- Email: ibrahim.aksut.dev@gmail.com
Acknowledgments
- NestJS Team: For providing an excellent framework.
- Winston Contributors: For the robust logging foundation.
- Pino Contributors: For high-performance logging solutions.
- Bunyan Contributors: For structured logging capabilities.
- All Open-Source Contributors: Your efforts make projects like this possible.