yuulogger
v0.0.5
Published
NestJS Logging Library
Readme
YuuLogger
A powerful, flexible, and performance-oriented logging library for NestJS applications. YuuLogger enhances your application with advanced logging capabilities, performance profiling, and beautiful console output.
Features
- 🎨 Multiple Visual Themes - Colorized console output with different themes
- 📋 File Logging - Automatic daily log rotation and separation by log level
- 🔄 Multiple Transport Support - Console, file, and cloud logging services (Logtail)
- ⚙️ Fully Configurable - Customize log levels, themes, and more
- 📊 Performance Profiling - Track function performance, memory and CPU usage
- 🧩 Modular Design - Works with NestJS dependency injection
- 🔍 Interceptor Support - Built-in performance interceptor for HTTP request profiling
- 📏 Decorators - Measure function execution time with simple decorators
- 🎯 Highlighting Utilities - Format and highlight text in logs with theme colors
- 🔀 Framework Agnostic - Fully compatible with both Express and Fastify
- 📊 Structured Logging - JSON-formatted logs for better parsing and analysis
- ⚖️ Sampling Support - Configurable sampling rate for high-volume applications
- 📈 Metrics Endpoint - Built-in metrics endpoint including Prometheus format
Installation
npm install yuulogger --save
yarn install yuulogger
bun install -E yuuloggerQuick Start
Basic Setup
// app.module.ts
import { Module } from '@nestjs/common';
import { YuuLogModule } from 'yuulogger';
@Module({
imports: [
YuuLogModule.forRoot({
appName: 'MyApp',
logLevels: ['error', 'warn', 'info'],
loggerTheme: 'colorful',
enableFileLogging: true
})
],
})
export class AppModule {}Async Configuration (Recommended)
For production applications, use async configuration with environment variables:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { PerformanceInterceptor, YuuLogModule } from 'yuulogger';
import { EnvModule } from './env/env.module';
import { EnvService } from './env/env.service';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
EnvModule,
YuuLogModule.forRootAsync({
inject: [EnvService],
useFactory: (envService: EnvService) => ({
appName: envService.get('APP_NAME'),
loggerTheme: envService.get('LOGGER_THEME'),
logLevels: envService.get('LOG_LEVEL'),
enableFileLogging: envService.get('ENABLE_FILE_LOGGING'),
logtail: {
enabled: envService.get('ENABLE_LOGTAIL'),
sourceToken: envService.get('LOGTAIL_SOURCE_TOKEN'),
endpoint: envService.get('LOGTAIL_ENDPOINT'),
},
}),
}),
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: PerformanceInterceptor,
},
],
})
export class AppModule {}
### Use in main.ts
```typescript
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { YuuLogService, parseLogLevels } from 'yuulogger';
async function bootstrap() {
// Configure YuuLogger directly in the main.ts file
// This is useful when you need to configure the logger before the app starts
YuuLogService.configure({
appName: 'MyAPI',
logLevels: parseLogLevels(process.env.LOG_LEVELS || 'error,warn,info'),
loggerTheme: 'colorful',
enableFileLogging: true
});
// Use YuuLogger as the application logger
const app = await NestFactory.create(AppModule, {
logger: YuuLogService.getNestLogger()
});
// You can also get the logger instance for manual logging
const logger = YuuLogService.getLogger();
logger.log('Application starting...', 'Bootstrap');
// For advanced scenarios, you can also access the logger options
// and modify them after initialization
const options = YuuLogService.getOptions();
logger.debug(`Current log levels: ${options.logLevels.join(', ')}`);
await app.listen(3000);
logger.log(`Application is running on: http://localhost:3000`, 'Bootstrap');
}
bootstrap();You can also configure YuuLogger to work with the NestJS global prefix and version:
### Use in main.ts
```typescript
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { YuuLogService } from 'yuulogger';
async function bootstrap() {
// Create the app with YuuLogger
const app = await NestFactory.create(AppModule, {
logger: YuuLogService.getNestLogger()
});
const logger = YuuLogService.getLogger();
const port = process.env.PORT || 3000;
await app.listen(port);
logger.log(`Application is running on: http://localhost:${port}`, 'Bootstrap');
}
bootstrap();You can also configure YuuLogger to work with the NestJS global prefix and version:
// main.ts with global prefix and versioning
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { YuuLogService } from 'yuulogger';
import { ValidationPipe, VersioningType } from '@nestjs/common';
async function bootstrap() {
// Create the app with YuuLogger logger
const app = await NestFactory.create(AppModule, {
logger: YuuLogService.getNestLogger()
});
const logger = YuuLogService.getLogger();
// Set global prefix and versioning
app.setGlobalPrefix('api');
app.enableVersioning({
type: VersioningType.URI,
defaultVersion: '1',
});
app.useGlobalPipes(new ValidationPipe({
whitelist: true,
transform: true,
}));
const port = process.env.PORT || 3000;
await app.listen(port);
logger.log(`Application running on: http://localhost:${port}/api/v1`, 'Bootstrap');
}
bootstrap();
### Using in Services
```typescript
### Using in Services
```typescript
// users.service.ts
import { Injectable } from '@nestjs/common';
import { YuuLogService } from 'yuulogger';
@Injectable()
export class UsersService {
private readonly logger = YuuLogService.getLogger();
async createUser(userData: any) {
const profileId = this.logger.startProfile('Create User', 'UsersService');
try {
// Your business logic here
const user = await this.createUserInDatabase(userData);
this.logger.log(`User created successfully: ${user.id}`, 'UsersService');
return user;
} catch (error) {
this.logger.error(`Failed to create user: ${error.message}`, error.stack, 'UsersService');
throw error;
} finally {
this.logger.stopProfile(profileId);
}
}
}Configuration Options
The YuuLogModule can be configured with the following options:
interface YuuLogOptions {
// Application name that will appear in the logs
appName?: string; // default: "NestJS"
// Enabled log levels
logLevels?: LogLevel[]; // default: ["error", "warn", "info"]
// Visual theme for console logs
loggerTheme?: LoggerTheme; // default: "default"
// Enable file logging
enableFileLogging?: boolean; // default: false
// Logtail configuration
logtail?: {
sourceToken: string; // your Logtail token
endpoint: string; // Logtail endpoint
enabled: boolean; // enable/disable Logtail
};
// Log sampling configuration for high-volume environments
sampling?: {
// Percentage of general logs to capture (1.0 = 100%, 0.1 = 10%)
generalSamplingRate?: number; // default: 1.0
// Percentage of performance profiles to capture
profileSamplingRate?: number; // default: 1.0
// Whether to always log errors, regardless of sampling rate
alwaysLogErrors?: boolean; // default: true
};
}
// Available log levels
type LogLevel = "error" | "warn" | "info" | "verbose" | "debug";
// Available themes
type LoggerTheme = "default"
| "dark"
| "light"
| "colorful"
| "minimal"
| "pastel"
| "ocean"
| "sunset"
| "forest"
| "cyberpunk"
| "coffee"
| "royal"
| "midnight"
| "candy"
| "highContrast"
| "matrix";Async Configuration
For dynamic configuration (e.g., loading from environment variables):
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { YuuLogModule, parseLogLevels } from 'yuulogger';
@Module({
imports: [
ConfigModule.forRoot(),
YuuLogModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
appName: configService.get('APP_NAME'),
logLevels: parseLogLevels(configService.get('LOG_LEVELS')),
loggerTheme: configService.get('LOGGER_THEME'),
enableFileLogging: configService.get('ENABLE_FILE_LOGGING') === 'true',
logtail: {
sourceToken: configService.get('LOGTAIL_TOKEN'),
endpoint: configService.get('LOGTAIL_ENDPOINT'),
enabled: configService.get('LOGTAIL_ENABLED') === 'true',
},
sampling: {
generalSamplingRate: parseFloat(configService.get('GENERAL_SAMPLING_RATE') || '1.0'),
profileSamplingRate: parseFloat(configService.get('PROFILE_SAMPLING_RATE') || '1.0'),
alwaysLogErrors: configService.get('ALWAYS_LOG_ERRORS') === 'true',
},
}),
}),
],
})
export class AppModule {}Framework Compatibility
YuuLogger works seamlessly with both Express (default) and Fastify adapters in NestJS:
Express (Default)
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { YuuLogService } from 'yuulogger';
async function bootstrap() {
// Works with Express by default
const app = await NestFactory.create(AppModule, {
logger: YuuLogService.getNestLogger()
});
await app.listen(3000);
}
bootstrap();Fastify
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
import { YuuLogService } from 'yuulogger';
async function bootstrap() {
// Works with Fastify adapter
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
{
logger: YuuLogService.getNestLogger()
}
);
await app.listen(3000, '0.0.0.0'); // Fastify requires the host to be specified
}
bootstrap();Performance Profiling
Basic Profiling
import { YuuLogService } from 'yuulogger';
const logger = YuuLogService.getLogger();
async function complexOperation() {
// Start profiling
const profileId = logger.startProfile('Complex Operation');
// Perform some work
await someAsyncWork();
// Create a child profile for a nested operation
const childId = logger.startChildProfile(profileId, 'Nested Task');
await someNestedTask();
logger.stopProfile(childId);
// More work
await moreWork();
// Stop profiling and log results
logger.stopProfile(profileId);
}Using the Measure Decorator
import { Controller, Get } from '@nestjs/common';
import { Measure } from 'yuulogger';
@Controller('users')
export class UsersController {
@Get()
@Measure('Get Users Request')
async getUsers() {
// This method's execution time will be automatically measured
return { users: [] };
}
}Using the Performance Interceptor
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { PerformanceInterceptor } from 'yuulogger';
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: PerformanceInterceptor,
},
],
})
export class AppModule {}Structured Logging
YuuLogger provides structured logging capabilities that make logs easier to parse and analyze:
import { YuuLogService } from 'yuulogger';
import { Injectable } from '@nestjs/common';
@Injectable()
export class PaymentService {
private readonly logger = YuuLogService.getLogger();
async processPayment(userId: string, amount: number) {
// Start tracking performance
const startTime = Date.now();
try {
// Process payment logic
const result = await this.paymentProvider.charge(userId, amount);
// Log success with structured data
this.logger.structuredInfo(
'Payment processed successfully',
'PaymentService',
{
payment: { userId, amount, transactionId: result.id },
performance: { duration: Date.now() - startTime },
request: { ip: '192.168.1.1', userAgent: 'Chrome' }
}
);
return result;
} catch (error) {
// Log error with structured data
this.logger.structuredError(
'Payment processing failed',
'PaymentService',
{
message: error.message,
code: error.code,
stack: error.stack
},
{
payment: { userId, amount, status: 'failed' },
performance: { duration: Date.now() - startTime }
}
);
throw error;
}
}
}HTTP Logging
YuuLogger provides powerful HTTP logging through its interceptors and middleware:
HTTP Logger Interceptor
This interceptor logs detailed information about HTTP requests and responses:
import { Module, Controller, Get } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { HttpLoggerInterceptor } from 'yuulogger';
// Apply globally to all controllers
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: HttpLoggerInterceptor
}
]
})
export class AppModule {}
// Or apply to specific controllers or methods
@Controller('users')
@UseInterceptors(new HttpLoggerInterceptor({
logRequestHeaders: true,
excludePaths: ['/health', '/metrics']
}))
export class UsersController {
@Get()
findAll() {
return ['user1', 'user2'];
}
}LogHttp Decorator
For simpler usage, you can use the @LogHttp() decorator:
import { Controller, Get } from '@nestjs/common';
import { LogHttp } from 'yuulogger';
@Controller('products')
@LogHttp() // Apply to all endpoints in this controller
export class ProductsController {
@Get()
findAll() {
return ['product1', 'product2'];
}
@Get(':id')
@LogHttp({ logRequestHeaders: true }) // Override options for specific endpoint
findOne(id: string) {
return { id, name: 'Sample Product' };
}
}Metrics and Monitoring
YuuLogger includes built-in support for metrics collection and exposure:
Using the Metrics Controller
import { Module } from '@nestjs/common';
import { YuuLogModule, MetricsController } from 'yuulogger';
@Module({
imports: [YuuLogModule.forRoot()],
controllers: [MetricsController],
})
export class AppModule {}This exposes several endpoints:
/metrics/logs- Statistics about log counts by level/metrics/performance- Performance metrics for profiled operations/metrics/system- System information like memory and CPU usage/metrics/health- Simple health check endpoint/metrics/prometheus- Metrics in Prometheus format for integration with monitoring systems
Prometheus Integration
YuuLogger can export metrics in Prometheus format, making it easy to integrate with monitoring systems:
# HELP yuulog_logs_total Total número de logs generados por nivel
# TYPE yuulog_logs_total counter
yuulog_logs_total{level="error"} 5
yuulog_logs_total{level="warn"} 12
yuulog_logs_total{level="info"} 248
# HELP nodejs_memory_usage_bytes Uso de memoria por Node.js
# TYPE nodejs_memory_usage_bytes gauge
nodejs_memory_usage_bytes{type="rss"} 52428800
nodejs_memory_usage_bytes{type="heapTotal"} 34603008
nodejs_memory_usage_bytes{type="heapUsed"} 27721840
nodejs_memory_usage_bytes{type="external"} 1833162
# HELP yuulog_operation_duration_seconds Tiempo de operación en segundos
# TYPE yuulog_operation_duration_seconds histogram
yuulog_operation_duration_seconds{operation="UsersController.findAll"} 0.045
yuulog_operation_duration_seconds{operation="AuthService.validateUser"} 0.128You can scrape these metrics directly with Prometheus or use tools like Grafana for visualization.
Formatting and Highlighting Utilities
YuuLogger provides powerful utilities for formatting and highlighting text in your logs:
Highlighting Text
import { highlight, h, highlightMany, highlightUrl } from 'yuulogger';
// Basic highlighting using function
logger.log(`Status: ${highlight('active')}`); // 'active' will be colorized
// Template literal tag for highlighting (cleaner syntax)
logger.log(`Connected to ${h`database`} successfully`); // 'database' will be colorized
// Highlight multiple values
const roles = highlightMany(['admin', 'user', 'guest']);
logger.log(`Available roles: ${roles.join(', ')}`);
// Highlight URLs
logger.log(`API running at ${highlightUrl()}`); // Colorizes http://localhost:3000Formatting Utilities
import {
formatDuration,
formatMemorySize,
formatCpuUsage,
formatMemoryUsage
} from 'yuulogger';
// Format a duration
const duration = formatDuration(1500); // "1.50 s"
// Format memory size
const memory = formatMemorySize(1572864); // "1.50 MB"
// Format CPU usage
const cpuUsage = formatCpuUsage({user: 15200, system: 5500}); // "User: 15.20ms, System: 5.50ms"
// Format memory usage
const memUsage = formatMemoryUsage(process.memoryUsage()); // "RSS: 50.20 MB, Heap: 25.10 MB/35.50 MB"
// Use in logs
logger.log(`Operation completed in ${duration} using ${memory}`);Getting Theme Colors
import {
getCurrentTheme,
getThemeHighlightColor,
getLoggerOptions
} from 'yuulogger';
// Get current theme name
const theme = getCurrentTheme(); // e.g., "default", "dark", etc.
// Get highlight color for a specific theme
const color = getThemeHighlightColor('colorful');
// Get current logger configuration
const options = getLoggerOptions();Environment Variable Parsing
YuuLogger provides utilities to help parse environment variables for configuration:
Parsing Log Levels
The parseLogLevels utility handles parsing comma-separated log level strings from environment variables:
import { parseLogLevels, validLogLevels } from 'yuulogger';
// Using with environment variables
// If LOG_LEVELS=error,warn,info in your .env file:
const levels = parseLogLevels(process.env.LOG_LEVELS);
// Result: ['error', 'warn', 'info']
// Special 'all' value expands to all valid log levels
// If LOG_LEVELS=all in your .env file:
const allLevels = parseLogLevels(process.env.LOG_LEVELS);
// Result: ['error', 'warn', 'info', 'verbose', 'debug']
// Empty or invalid values default to 'all'
const defaultLevels = parseLogLevels('');
// Result: ['all']
// Valid log levels are accessible through validLogLevels
console.log(validLogLevels);
// Output: ['error', 'warn', 'info', 'verbose', 'debug', 'all']This is particularly useful with NestJS ConfigService:
import { ConfigService } from '@nestjs/config';
import { YuuLogModule, parseLogLevels } from 'yuulogger';
@Module({
imports: [
ConfigModule.forRoot(),
YuuLogModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
// Parse LOG_LEVELS=error,warn,info from environment
logLevels: parseLogLevels(config.get('LOG_LEVELS')),
// Other options...
}),
}),
],
})
export class AppModule {}API Reference
YuuLogService
The main service that provides logging functionality.
Basic Logging Methods
log(message, context?)- Log at 'info' levelerror(message, trace?, context?)- Log at 'error' levelwarn(message, context?)- Log at 'warn' leveldebug(message, context?)- Log at 'debug' levelverbose(message, context?)- Log at 'verbose' level
Structured Logging Methods
structured(level, message, context?, data?)- Create a structured log entrystructuredInfo(message, context?, data?)- Create an info structured logstructuredError(message, context?, errorInfo?, additionalData?)- Create an error structured log
Performance Measurement
startMeasure(operationName, metadata?)- Start measuring performancestopMeasure(operationName, logResults?)- Stop measuring and get metricsgetPerformanceStats(operationName)- Get performance statisticsclearPerformanceMetrics(operationName?)- Clear collected metrics
Advanced Profiling
startProfile(operationName, context?, metadata?)- Start a detailed profilestartChildProfile(parentId, operationName, metadata?)- Add nested profilingstopProfile(id, logResults?)- Stop profiling and calculate metricsgetActiveProfiles()- Get all active profileslogPerformanceReport(profile, title?)- Log a formatted report
Metrics and Statistics
getLogStats()- Get log count statistics and metricsresetLogCounters()- Reset log count statistics
Helper Methods
profileFunction(fn, operationName?)- Wrap a function with performance profilingprofileAsyncFunction(fn, operationName?)- Wrap an async functionprofileAsyncIterator(iterator, operationName)- Profile each iteration
Static Methods
getLogger()- Get a singleton instance of YuuLogServicegetNestLogger()- Get a NestJS compatible logger
Themes
YuuLogger supports multiple visual themes for console output:
Basic Themes
default- Standard theme with balanced colorsdark- Optimized for dark terminalslight- Optimized for light terminalscolorful- Vibrant colors for maximum visibilityminimal- Reduced use of colors for a cleaner look
Enhanced Themes
pastel- Soft, muted colors for a gentle appearanceocean- Cool blue tones inspired by the seasunset- Warm gradient colors resembling a sunsetforest- Natural green and earth tonescyberpunk- Neon colors on dark backgroundcoffee- Warm browns and subtle highlightsroyal- Rich purple and gold color schememidnight- Deep blues and subtle highlightscandy- Bright, fun colors with high contrasthighContrast- Maximum readability for accessibilitymatrix- Green text on black background
Example:
YuuLogModule.forRoot({
loggerTheme: 'colorful'
})Example:
YuuLogModule.forRoot({
loggerTheme: 'colorful'
})File Logging
When file logging is enabled, logs are stored in the following structure:
logs/application-YYYY-MM-DD.log- All logs at or above minimum levellogs/error-YYYY-MM-DD.log- Only error logs
Files automatically rotate daily and are limited to 20MB.
Contributing
We welcome contributions to YuuLogger! If you're interested in helping out, please read our Contributing Guide for details on:
- Submitting bug reports and feature requests
- Code style and development guidelines
- Pull request process
- Development setup instructions
- Testing guidelines
Your contributions help make YuuLogger better for everyone. Thank you!
License
This project is licensed under the MIT License - see the LICENSE file for details.
