@kitiumai/logger
v3.0.1
Published
Enterprise-ready centralized logging system with Loki integration
Maintainers
Keywords
Readme
Centralized Logging System
An enterprise-ready centralized logging system with structured logging and Grafana Loki integration for cloud-native applications.
What is @kitiumai/logger?
@kitiumai/logger is a comprehensive, enterprise-grade logging solution designed specifically for modern Node.js applications. It provides structured logging, distributed tracing, centralized log aggregation, and extensive middleware support for frameworks like Express.js, Next.js, and NestJS.
Key Capabilities
- 5 Logger Types: Console, File, In-Memory, and Central (Grafana Loki) logging
- Framework Integration: Native middleware for Express, Next.js, NestJS, and Fastify
- Distributed Tracing: Automatic trace ID/span ID propagation with OpenTelemetry support
- Security Features: Automatic PII detection and redaction
- Performance Monitoring: Request timing, memory tracking, and custom metrics
- Testing Support: Complete mock logger implementations for Jest/Vitest
- Type Safety: Full TypeScript support with comprehensive type definitions
Why Do You Need This Package?
In modern cloud-native applications, logging is critical for:
🔍 Observability & Debugging
- Distributed Tracing: Track requests across microservices with automatic trace/span ID correlation
- Context Propagation: Maintain user, session, and request context throughout async operations
- Performance Monitoring: Track response times, memory usage, and custom business metrics
🛡️ Security & Compliance
- PII Protection: Automatic detection and redaction of sensitive data (passwords, tokens, API keys)
- Audit Logging: Compliance-ready audit trails with structured, tamper-evident logs
- Security Monitoring: Integration with security information and event management (SIEM) systems
🚀 Production Reliability
- Centralized Aggregation: All logs in one place with Grafana Loki for easy querying and analysis
- Error Tracking: Structured error logging with stack traces and contextual metadata
- Health Monitoring: Built-in health checks and circuit breakers for resilient logging
🧪 Developer Experience
- Testing Support: Comprehensive mocking utilities eliminate the need to write custom mocks
- Type Safety: Full TypeScript support prevents logging-related runtime errors
- Framework Integration: Drop-in middleware for popular Node.js frameworks
Competitor Comparison
| Feature | @kitiumai/logger | Winston | Pino | Bunyan | Morgan | |---------|------------------|---------|------|--------|--------| | Logger Types | 5 (Console, File, Memory, Loki) | 4+ | 3 | 3 | 1 | | Loki Integration | ✅ Native | ❌ Manual | ❌ Manual | ❌ Manual | ❌ | | Framework Middleware | Express, Next.js, NestJS, Fastify | Basic Express | Basic Express | Basic Express | Express Only | | Distributed Tracing | ✅ OpenTelemetry | ❌ | ❌ | ❌ | ❌ | | PII Redaction | ✅ Automatic | ❌ | ❌ | ❌ | ❌ | | Testing Mocks | ✅ Complete | ❌ | ❌ | ❌ | ❌ | | TypeScript Support | ✅ Full | ⚠️ Partial | ⚠️ Partial | ⚠️ Partial | ❌ | | Performance Metrics | ✅ Built-in | ❌ | ❌ | ❌ | ❌ | | Health Checks | ✅ Built-in | ❌ | ❌ | ❌ | ❌ | | Bundle Size | 🟢 Small (Tree-shakeable) | 🟡 Medium | 🟢 Small | 🟡 Medium | 🟢 Small |
Unique Selling Proposition (USP)
🎯 Production-Ready Enterprise Features
Unlike basic logging libraries, @kitiumai/logger includes enterprise-grade features out-of-the-box:
- Cloud-Native Architecture: Native Grafana Loki integration for scalable log aggregation
- Security-First Design: Automatic PII detection and compliance-ready audit logging
- Framework Agnostic: Works seamlessly across Express, Next.js, NestJS, and Fastify
- Zero-Config Testing: Complete mock implementations eliminate testing friction
🚀 Developer Productivity
- One-Line Setup: Environment-based auto-configuration for development/staging/production
- Type-Safe APIs: Full TypeScript support prevents logging bugs at compile time
- Rich Context: Automatic propagation of trace IDs, user context, and session data
- Performance Insights: Built-in metrics collection and performance monitoring
🛡️ Compliance & Security
- GDPR/CCPA Ready: Automatic sensitive data redaction and privacy protection
- Audit Trails: Structured, immutable audit logs for regulatory compliance
- Security Monitoring: Integration points for SIEM systems and security alerting
Features
✅ Multiple Logger Types - Console, File, In-Memory, or Central (Loki) logging ✅ Structured Logging - JSON-formatted logs with contextual metadata ✅ Distributed Tracing - Automatic trace ID and span ID tracking ✅ Grafana Loki Integration - Cloud-native log aggregation and analysis ✅ TypeScript Support - Full type safety and excellent IDE support ✅ Express.js Middleware - Out-of-the-box HTTP request/response logging ✅ Error Tracking - Automatic error logging with stack traces ✅ Performance Metrics - Request duration and memory usage tracking ✅ Request Context - Async context for user, session, and request metadata ✅ Sensitive Data Filtering - Automatic redaction of passwords, tokens, and API keys ✅ Builder Pattern - Fluent API for easy logger configuration ✅ Log Levels - error, warn, info, http, debug ✅ Audit Logging - Compliance-ready audit trail support
Structured Logging Implementation ✨
This package implements a complete, production-ready structured logging system with all core features fully verified and documented. See STRUCTURED_LOGGING_IMPLEMENTATION.md for comprehensive verification of:
- ✅ Log Level Management - 5 custom log levels (error, warn, info, http, debug) with full configuration
- ✅ Centralized Log Aggregation - Winston + Grafana Loki integration with batching and reliability
- ✅ Log Formatting Standards - Structured JSON with contextual metadata, colored console output
- ✅ Request/Response Logging - 5+ Express middleware functions for comprehensive HTTP logging
- ✅ Performance Logging - Automatic duration tracking, memory monitoring, and metrics collection
- ✅ Distributed Tracing - Trace IDs, span IDs, request IDs, session tracking, and correlation
- ✅ Sensitive Data Protection - Recursive field redaction with configurable filter lists
- ✅ Error Handling - Stack traces, structured error logging, audit trail support
- ✅ Type Safety - Full TypeScript support with comprehensive type definitions
- ✅ Configuration - Environment-based setup with validation
Implementation Highlights
For Quick Reference:
- 📄 STRUCTURED_LOGGING_IMPLEMENTATION.md - Detailed feature verification with code examples
- 📊 5 Logger Types: Console, File, InMemory, Central (Loki)
- 🔒 Security: Automatic sensitive field redaction, Loki basic auth
- 📈 Performance: Batch logging, async context propagation, memory tracking
- 🏥 Health Checks: System monitoring, logger status, transport verification
Quick Start
Installation
npm install @kitiumai/logger
# or
yarn add @kitiumai/loggerBasic Setup
import { initializeLogger, getLoggerConfig, getLogger } from '@kitiumai/logger';
// Initialize logger with configuration
const config = getLoggerConfig();
const logger = initializeLogger(config);
// Use logger
getLogger().info('Application started');
getLogger().error('An error occurred', { userId: '123' }, error);One-line presets (happy path)
import { createLogger } from '@kitiumai/logger';
// Automatically applies environment defaults:
// - development: pretty console
// - staging: console + file
// - production: Loki + file, sampling, circuit breaker
const logger = createLogger('production');
logger.info('Bootstrap complete');You can also override any field without building a full config object:
const logger = createLogger('staging', {
samplingRate: 0.5,
loki: { enabled: true, batchSize: 200 },
});Express.js Integration
import express from 'express';
import {
initializeLogger,
getLoggerConfig,
tracingMiddleware,
errorLoggingMiddleware,
performanceMetricsMiddleware,Usage & Tree-Shaking
Subpath Imports (Recommended for Bundle Size)
The logger package provides modular subpath exports to help bundlers tree-shake unused code. Import only what you need:
// ✅ Minimal — only core logger functions
import { createLogger, getLogger } from '@kitiumai/logger';
// ✅ Middleware only — for Express/Next.js apps
import { tracingMiddleware, errorLoggingMiddleware } from '@kitiumai/logger/middleware';
// ✅ Utilities only — for timers, metrics, error handling
import { createTimer, loggerMetrics, retryWithBackoff } from '@kitiumai/logger/utils';Top-level Barrel (Works, But Larger)
If you import from the top-level barrel, modern bundlers (esbuild, Rollup, webpack with Terser) will still tree-shake unused exports:
// ⚠️ Works but includes all exports; bundler will tree-shake unused ones
import { createLogger, tracingMiddleware, createTimer } from '@kitiumai/logger';Build Optimization Tips
- Use subpath imports in production to guarantee minimal bundle surface across all bundlers.
- For middleware apps (Express, Next.js, NestJS), import middleware via
@kitiumai/logger/middlewareto avoid including core logger logic if you only wrap existing loggers. - For utility libraries, use
@kitiumai/logger/utilsto ship only the helpers (timers, metrics) without the full logger. - Verify bundling with esbuild:
esbuild --bundle --minify --analyze src/index.tsto see what's included.
The package provides ESM and CommonJS dual builds (dist/esm/ and dist/cjs/) with sideEffects: false, so tree-shaking works across all modern toolchains.
} from '@kitiumai/logger';
const app = express();
// Initialize logger const config = getLoggerConfig(); initializeLogger(config);
// Add logging middleware (order matters!) app.use(tracingMiddleware()); // Must be first app.use(performanceMetricsMiddleware());
// Your routes here app.get('/api/data', (req, res) => { getLogger().info('Fetching data'); res.json({ data: [] }); });
// Error handling middleware (must be last) app.use(errorLoggingMiddleware());
app.listen(3000, () => { getLogger().info('Server started on port 3000'); });
### Context bridges (Express, Next.js, OpenTelemetry)
```typescript
import { bridgeExpressRequest, bridgeOpenTelemetryContext } from '@kitiumai/logger';
// Express request handler
app.use((req, _res, next) => {
bridgeExpressRequest(req); // pulls traceparent/B3/user headers into contextManager
next();
});
// Inside any function running under OpenTelemetry span
bridgeOpenTelemetryContext();For framework-agnostic scenarios, use bridgeHeadersToContext to hydrate the async context from a raw headers object.
Logger Types
The logging system supports multiple logger types to suit different environments and use cases:
1. Console Logger (Development)
Simple console output for development and debugging:
import { LoggerBuilder } from '@kitiumai/logger';
const logger = LoggerBuilder.console('my-app');
logger.info('Application started');Best for: Local development, testing, quick debugging
2. In-Memory Logger (Testing/Debugging)
Stores logs in memory for inspection and testing:
import { LoggerBuilder, InMemoryLogger } from '@kitiumai/logger';
const logger = LoggerBuilder.inMemory('my-app') as InMemoryLogger;
logger.info('User login', { userId: '123' });
// Query logs
const logs = logger.getLogs();
const errorLogs = logger.getLogsByLevel('error');
const stats = logger.getStats();
// Export logs
const json = logger.export();Best for: Unit testing, debugging, log inspection, development
3. File Logger (Production/Staging)
Writes logs to disk with automatic rotation:
import { LoggerBuilder } from '@kitiumai/logger';
const logger = LoggerBuilder.file('my-app', './logs')
.withMaxFileSize('100m')
.withMaxFiles(14)
.withConsole(false) // Only file, no console
.build();
logger.info('Application started');Best for: Staging, production servers, on-premise deployments
4. Central Logger (Cloud-Native with Loki)
Sends logs to Grafana Loki for cloud-native environments:
import { LoggerBuilder, getLoggerConfig } from '@kitiumai/logger';
const config = getLoggerConfig();
const logger = LoggerBuilder.central(config);
logger.info('Application started');
// Logs are aggregated in Loki and queryable in GrafanaBest for: Microservices, Kubernetes, cloud deployments, centralized log analysis
Standard log schema and validation
All transports normalize entries to a common schema before emission. Required fields:
timestamp,level,messageservice,environment- Correlation fields:
traceId,spanId,requestId,sessionId,correlationId,userId - Optional
metadataand structurederrorpayloads
Schema enforcement is on by default (LOG_ENFORCE_SCHEMA=true) and fills missing fields from the async context. Set samplingRate (0–1) to curb noisy logs without changing code; logs are dropped probabilistically before formatting.
import { getLoggerConfig, initializeLogger } from '@kitiumai/logger';
const config = getLoggerConfig();
config.enforceSchema = true;
config.samplingRate = 0.25; // keep 25% of debug chatter
initializeLogger(config);If Loki becomes unhealthy, the built-in circuit breaker pauses the transport and keeps logging to console/file based on the configured fallback, then retries after the cool-down.
Using the Builder Pattern
The LoggerBuilder provides a fluent API for easy configuration:
import { LoggerBuilder, LoggerType } from '@kitiumai/logger';
// Console logger with all options
const logger = new LoggerBuilder()
.withType(LoggerType.CONSOLE)
.withServiceName('my-service')
.withColors(true)
.withTimestamps(true)
.build();
// File logger with rotation
const fileLogger = new LoggerBuilder()
.withType(LoggerType.FILE)
.withServiceName('my-app')
.withLogPath('./logs')
.withMaxFileSize('50m')
.withMaxFiles(7)
.withConsole(true) // Include console output
.build();
// In-memory logger with large capacity
const memLogger = new LoggerBuilder()
.withType(LoggerType.IN_MEMORY)
.withServiceName('test-app')
.withMaxInMemoryLogs(50000)
.build();Using the Factory Pattern
For dynamic logger creation:
import { LoggerFactory, LoggerType } from '@kitiumai/logger';
// Create logger dynamically
const logger = LoggerFactory.create({
type: LoggerType.CONSOLE,
serviceName: 'my-app',
});
// Create from string (useful for env variables)
const loggerType = process.env.LOGGER_TYPE || 'console';
const logger = LoggerFactory.createFromString(loggerType, {
type: LoggerType.CONSOLE,
serviceName: 'my-app',
});Configuration
Environment Variables
Create a .env file based on .env.example:
# Application
NODE_ENV=development
SERVICE_NAME=my-service
LOG_LEVEL=info
# Loki
LOKI_ENABLED=true
LOKI_HOST=localhost
LOKI_PORT=3100
LOKI_PROTOCOL=httpAvailable Configuration Options
| Variable | Default | Description |
| ------------------- | --------------- | -------------------------------------------------- |
| NODE_ENV | development | Environment (development, staging, production) |
| SERVICE_NAME | default-service | Service name for log labels |
| LOG_LEVEL | info | Minimum log level (error, warn, info, http, debug) |
| LOG_CONSOLE | true | Enable console output |
| LOG_FILE_ENABLED | false | Enable file logging |
| LOG_FILE_PATH | ./logs | Log file directory |
| LOG_MAX_FILE_SIZE | 100m | Max size per log file before rotation |
| LOG_MAX_FILES | 14 | Max number of rotated log files |
| LOKI_ENABLED | true | Enable Loki integration |
| LOKI_HOST | localhost | Loki server host |
| LOKI_PORT | 3100 | Loki server port |
| LOKI_PROTOCOL | http | Protocol (http or https) |
| LOKI_BATCH_SIZE | 100 | Number of logs to batch before sending |
| LOKI_INTERVAL | 5000 | Time in ms between batch sends |
| LOKI_USERNAME | - | Optional basic auth username |
| LOKI_PASSWORD | - | Optional basic auth password |
| LOKI_LABELS | - | Custom Loki labels (JSON or key=value) |
Usage Guide
Basic Logging
import { getLogger } from '@kitiumai/logger';
const logger = getLogger();
// Info level
logger.info('User logged in', { userId: '123' });
// Warning level
logger.warn('API rate limit approaching', { remaining: 10 });
// Error level with error object
logger.error('Database connection failed', { attempt: 1 }, error);
// Debug level
logger.debug('Processing request', { requestId: 'abc123' });
// HTTP level (for API requests)
logger.http('Request completed', { statusCode: 200, duration: 45 });Distributed Tracing
import { contextManager } from '@kitiumai/logger';
// Automatic in Express middleware, but can be used manually:
contextManager.run(
{
traceId: 'custom-trace-123',
userId: 'user-456',
},
() => {
// All logs in this scope will have traceId and userId
getLogger().info('Processing with context');
}
);Request Context Enhancement
import { addMetadata } from '@kitiumai/logger';
app.get('/api/users/:id', (req, res) => {
const userId = req.params.id;
// Add metadata that will be included in all logs for this request
addMetadata('userId', userId);
addMetadata('department', 'engineering');
getLogger().info('Fetching user');
// Log will include: traceId, userId, department, etc.
res.json({ id: userId });
});Error Handling with LoggableError
import { LoggableError } from '@kitiumai/logger';
// Create errors with structured metadata
const error = new LoggableError('User not found', 'USER_NOT_FOUND', {
userId: '123',
searchField: 'email',
});
// Log with appropriate level
error.log('warn');
// Manual handling
try {
throw error;
} catch (err) {
if (err instanceof LoggableError) {
err.log('error');
}
}Performance Timing
import { createTimer } from '@kitiumai/logger';
const timer = createTimer('Database query');
// Perform operation
const result = await database.query();
// End timer and log duration
timer.end({ recordCount: result.length });
// Logs: "Database query completed in 145ms" with metadataAsync Operations with Error Logging
import { withErrorLogging } from '@kitiumai/logger';
const result = await withErrorLogging(
async () => {
// Your async operation
return await fetchUserData(userId);
},
{
operation: 'Fetch user data',
metadata: { userId },
}
);
// Automatically logs errors and timingAudit Logging (Compliance)
import { auditLog } from '@kitiumai/logger';
// Log security/compliance-relevant events
auditLog('UPDATE', 'user_permissions', userId, {
oldRole: 'user',
newRole: 'admin',
reason: 'Team lead promotion',
});
// Logs:
// "Audit: UPDATE on user_permissions"
// with metadata for compliance analysisBatch Logging
import { BatchLogger } from '@kitiumai/logger';
const batch = new BatchLogger();
// Collect logs
batch
.info('Processing started', { itemCount: 100 })
.debug('Item 1 processed', { itemId: 1 })
.debug('Item 2 processed', { itemId: 2 })
.warn('Item 3 skipped', { itemId: 3, reason: 'invalid' });
// Flush all at once
await batch.flush();Testing & Mocking
The @kitiumai/logger package provides comprehensive mocking utilities for testing applications that use the logger. These mocks are compatible with both Jest and Vitest, eliminating the need for consumers to write their own mock implementations.
Quick Start
import {
createMockLogger,
createLoggerSpy,
createIsolatedMockLogger
} from '@kitiumai/logger';
describe('MyService', () => {
it('should log user actions', () => {
const mockLogger = createMockLogger();
const service = new MyService(mockLogger);
service.doSomething();
expect(mockLogger.calls).toHaveLength(1);
expect(mockLogger.getLastCall()?.message).toBe('Something happened');
});
});Mock Logger Classes and Functions
MockLogger
A complete implementation of the ILogger interface that captures all log calls.
Methods:
calls: Get all captured log calls (readonly)clear(): Clear all captured callsgetCallsByLevel(level: string): Get calls for a specific log levelgetLastCall(): Get the most recent log callhasLogs(level?: string): Check if any logs exist (optionally by level)findCallsByMessage(text: string): Find calls containing specific text
Example:
const logger = createMockLogger();
logger.info('User logged in', { userId: 123 });
logger.error('Database error', { code: 'CONNECTION_FAILED' }, new Error('Connection timeout'));
console.log(logger.calls.length); // 2
console.log(logger.getCallsByLevel('error')); // [error call]
console.log(logger.hasLogs('info')); // true
console.log(logger.findCallsByMessage('Database')); // [error call]createMockLogger()
Creates a new MockLogger instance.
const logger = createMockLogger();createMockLoggerWithContext(context)
Creates a mock logger with initial context.
const logger = createMockLoggerWithContext({
traceId: 'test-123',
userId: 'user-456'
});
logger.info('Test message');
// The call will include the contextcreateLoggerSpy()
Creates a spy object with additional utility methods.
const spy = createLoggerSpy();
// Use spy.logger for logging
spy.logger.info('Test message');
// Access utilities
console.log(spy.calls); // readonly array
spy.clear(); // clear calls
console.log(spy.hasLogs('info')); // truecreateIsolatedMockLogger()
Creates a logger with testing-specific assertion methods.
const { logger, reset, getLogs, assertNoErrors, assertLogged } = createIsolatedMockLogger();
logger.error('Something went wrong');
// These methods throw on failure
assertNoErrors(); // Throws: "Expected no error logs, but found 1"
assertLogged('went wrong'); // Passes
assertLogged('nonexistent'); // Throws: "Expected logger to have logged message containing 'nonexistent'"Testing Services with Dependencies
class UserService {
constructor(private logger: ILogger) {}
async createUser(userData: UserData): Promise<User> {
this.logger.info('Creating user', { email: userData.email });
try {
const user = await this.userRepository.create(userData);
this.logger.info('User created successfully', { userId: user.id });
return user;
} catch (error) {
this.logger.error('Failed to create user', { email: userData.email }, error);
throw error;
}
}
}
// Test
describe('UserService', () => {
let mockLogger: MockLogger;
let service: UserService;
beforeEach(() => {
mockLogger = createMockLogger();
service = new UserService(mockLogger);
});
it('should log successful user creation', async () => {
const userData = { email: '[email protected]', name: 'John Doe' };
await service.createUser(userData);
expect(mockLogger.calls).toHaveLength(2);
expect(mockLogger.findCallsByMessage('Creating user')).toHaveLength(1);
expect(mockLogger.findCallsByMessage('successfully')).toHaveLength(1);
});
it('should log errors during user creation', async () => {
// Mock repository to throw
mockUserRepository.create.mockRejectedValue(new Error('Database error'));
await expect(service.createUser(userData)).rejects.toThrow();
// Assert logging
expect(mockLogger.getCallsByLevel('error')).toHaveLength(1);
const errorCall = mockLogger.getLastCall();
expect(errorCall?.message).toBe('Failed to create user');
expect(errorCall?.error?.message).toBe('Database error');
});
});Testing Middleware
import { createMockLogger } from '@kitiumai/logger';
describe('Logging Middleware', () => {
it('should log HTTP requests', () => {
const mockLogger = createMockLogger();
const middleware = loggingMiddleware({ logger: mockLogger });
const mockReq = { method: 'GET', url: '/api/users' };
const mockRes = {};
const mockNext = jest.fn();
middleware(mockReq, mockRes, mockNext);
expect(mockLogger.hasLogs('http')).toBe(true);
expect(mockLogger.findCallsByMessage('GET /api/users')).toHaveLength(1);
});
});Testing with Context
describe('Context-aware logging', () => {
it('should include context in logs', async () => {
const logger = createMockLogger();
await logger.withContext({ traceId: 'req-123', userId: 'user-456' }, async () => {
logger.info('Processing request');
// Context is automatically included
const call = logger.getLastCall();
expect(call?.context?.traceId).toBe('req-123');
expect(call?.context?.userId).toBe('user-456');
});
});
});Best Practices
Use Appropriate Mock Type
createMockLogger(): Basic logging capturecreateLoggerSpy(): Additional utility methodscreateIsolatedMockLogger(): Built-in assertions for simple tests
Clear Between Tests
let mockLogger: MockLogger; beforeEach(() => { mockLogger = createMockLogger(); });Test Logging Behavior
// Good expect(logger.findCallsByMessage('User not found')).toHaveLength(1); expect(logger.getCallsByLevel('error')).toHaveLength(1); // Less useful expect(logger.calls.length).toBeGreaterThan(0);Test Error Logging
try { await riskyOperation(); } catch (error) { const errorLogs = logger.getCallsByLevel('error'); expect(errorLogs).toHaveLength(1); expect(errorLogs[0].error).toBe(error); }
Docker Setup (Loki + Grafana)
Start the Stack
# Copy environment variables
cp .env.example .env
# Start services
docker-compose up -d
# View logs
docker-compose logs -f lokiAccess Grafana
- URL: http://localhost:3000
- Username: admin
- Password: admin
Querying Logs in Grafana
# All logs from service
{service="my-service"}
# Logs by level
{service="my-service"} | json level="error"
# Logs with trace ID
{service="my-service"} | json | traceId="abc123"
# Performance metrics
{service="my-service"} | json duration > 1000
# Error logs
{service="my-service"} | json level="error"
# Logs for specific user
{service="my-service"} | json userId="user-123"Advanced Features
Custom Transports
import winston from 'winston';
import { CentralLogger } from '@kitiumai/logger';
const logger = new CentralLogger(config);
// The underlying winston logger is available
// logger.logger to add custom transportsRequest Body Logging with Filtering
import { bodyLoggingMiddleware } from '@kitiumai/logger';
// Log request bodies but filter sensitive fields
app.use(bodyLoggingMiddleware(['password', 'token', 'apiKey', 'ssn', 'creditCard']));User Context Middleware
import { userContextMiddleware } from '@kitiumai/logger';
// Automatically extract user ID from request
app.use(
userContextMiddleware((req) => {
// Custom extraction logic
return req.user?.id || req.get('x-user-id');
})
);Sanitizing Sensitive Data
import { sanitizeData } from '@kitiumai/logger';
const data = {
email: '[email protected]',
password: 'secret123',
apiKey: 'key-abc123',
};
const safe = sanitizeData(data, ['password', 'apiKey']);
// Result: { email: '[email protected]', password: '[REDACTED]', apiKey: '[REDACTED]' }API Reference
Core Logger APIs
createLogger(preset?, overrides?)
Create a logger instance with environment-based presets.
Parameters:
preset?: 'development' | 'staging' | 'production'- Environment presetoverrides?: Partial<LoggerConfig>- Configuration overrides
Returns: ILogger - Configured logger instance
Example:
const logger = createLogger('production', { samplingRate: 0.5 });initializeLogger(config)
Initialize the global logger instance.
Parameters:
config: LoggerConfig- Logger configuration
Returns: CentralLogger - Initialized logger
getLogger()
Get the current global logger instance.
Returns: ILogger - Current logger instance
Logger Types
ConsoleLogger
Development logger with colored console output.
FileLogger
File-based logger with rotation support.
InMemoryLogger
In-memory logger for testing and development.
CentralLogger
Production logger with Grafana Loki integration.
Middleware APIs
Express.js Middleware
import {
tracingMiddleware,
errorLoggingMiddleware,
performanceMetricsMiddleware,
userContextMiddleware,
bodyLoggingMiddleware
} from '@kitiumai/logger/middleware';tracingMiddleware()- Adds trace ID/span ID to requestserrorLoggingMiddleware()- Logs errors with stack tracesperformanceMetricsMiddleware()- Tracks request duration and memoryuserContextMiddleware(userExtractor?)- Extracts user context from requestsbodyLoggingMiddleware(options?)- Logs request/response bodies
Next.js Middleware
import {
withNextApiLogger,
withNextRouteLogger,
createNextFetchWrapper
} from '@kitiumai/logger/middleware/next';withNextApiLogger(handler)- Wraps API route handlerswithNextRouteLogger(handler)- Wraps App Router route handlerscreateNextFetchWrapper(options?)- Wraps outbound fetch calls
NestJS Middleware
import {
createNestLoggingMiddleware,
createNestExceptionFilter
} from '@kitiumai/logger/middleware/nest';createNestLoggingMiddleware()- Creates logging middlewarecreateNestExceptionFilter()- Creates exception filter
Context Management
bridgeExpressRequest(req)
Extract trace context from Express request headers.
bridgeOpenTelemetryContext()
Bridge OpenTelemetry context to logger context.
bridgeHeadersToContext(headers)
Extract context from raw headers object.
withLoggingContext(context, fn)
Run async function with additional context.
Utility APIs
createTimer(name?)
Create a performance timer.
Returns: Timer - Timer instance with .start(), .stop(), .duration() methods
LoggableError
Error class that includes logging context.
auditLog(action, details, user?)
Create structured audit log entry.
BatchLogger
Batch multiple log operations for performance.
withErrorLogging(fn, context?)
Wrap async function with automatic error logging.
withErrorLoggingSync(fn, context?)
Wrap sync function with automatic error logging.
Security & PII Protection
sanitizeObject(obj, fields?)
Recursively sanitize object fields.
redactValue(value, pattern?)
Redact sensitive values.
detectPIITypes(text)
Detect PII types in text.
isSensitiveField(fieldName)
Check if field name indicates sensitive data.
Metrics & Monitoring
loggerMetrics
Access to metrics registry.
Counter, Gauge, Histogram
Metrics collection classes.
performHealthCheck()
Check logger system health.
healthCheckMiddleware()
Express middleware for health checks.
Testing APIs
createMockLogger()
Create mock logger for testing.
Returns: MockLogger - Mock logger with .calls, .clear(), .getLastCall() methods
createLoggerSpy()
Create logger spy with additional utilities.
createIsolatedMockLogger()
Create logger with built-in assertions.
Configuration APIs
getLoggerConfig()
Get default logger configuration.
LogLevel
Enum: error, warn, info, http, debug
Logger Configuration Types
interface LoggerConfig {
level: LogLevel;
loki?: LokiConfig;
file?: FileConfig;
console?: ConsoleConfig;
samplingRate?: number;
batchSize?: number;
// ... more options
}Builder Pattern
LoggerBuilder
Fluent API for logger construction.
const logger = LoggerBuilder
.console('my-app')
.withLoki({ host: 'localhost', port: 3100 })
.withLevel('debug')
.build();Error Handling
retryWithBackoff(fn, config?)
Retry function with exponential backoff.
safeAsync(fn, fallback?)
Wrap async function with error handling.
CircuitBreaker
Circuit breaker for resilient operations.
Console Capture
captureConsole(options?)
Capture console.log/warn/error calls.
restoreConsole()
Restore original console methods.
Production Recommendations
1. Log Levels
NODE_ENV=production
LOG_LEVEL=info # Only error, warn, info
LOG_CONSOLE=false # Disable console in production
LOG_FILE_ENABLED=true # Enable file logging2. Loki Configuration
LOKI_ENABLED=true
LOKI_HOST=loki.company.com # Use managed Loki or secure endpoint
LOKI_PROTOCOL=https
LOKI_USERNAME=your-org
LOKI_PASSWORD=your-token
LOKI_LABELS={"region":"us-west-2","cluster":"prod"}3. Error Handling
// Ensure graceful shutdown
process.on('SIGTERM', async () => {
await logger.close(); // Flush Loki
process.exit(0);
});4. Resource Limits
- Set appropriate
LOKI_BATCH_SIZEfor your volume - Monitor memory usage with large batch sizes
- Use file rotation to prevent disk space issues
5. Monitoring
- Monitor Loki disk usage
- Set up Grafana alerts for errors
- Track logger performance with metrics
Performance Considerations
- Batching: Logs are batched before sending to Loki (default 100 logs or 5s)
- Async Context: Uses Node.js AsyncLocalStorage (minimal overhead)
- Memory: Each log entry is ~1KB; 100 batch size = ~100KB in memory
- Network: Batching reduces network calls; typical overhead <5ms per request
Troubleshooting
Logs not appearing in Loki
# Check Loki is running
docker-compose logs loki
# Verify connection
curl http://localhost:3100/loki/api/v1/status/ready
# Check logs
getLogger().info('test log');Memory issues
Reduce batch size:
LOKI_BATCH_SIZE=25 # From default 100High latency
Increase interval to reduce frequency:
LOKI_INTERVAL=10000 # From default 5000 (10 seconds)Missing trace IDs
Ensure middleware is first:
app.use(tracingMiddleware()); // Must be before other middlewareTypeScript Support
Fully typed interfaces are available:
import { LoggerConfig, LokiConfig, LogContext, StructuredLogEntry } from '@kitiumai/logger';
// All configurations are type-safeLicense
MIT
Contributing
Contributions are welcome! Please read our contributing guidelines.
Migration Guide
Complete guide for migrating from various logging solutions to @kitiumai/logger.
Quick Migration Steps
Install the Package
npm install @kitiumai/logger # or yarn add @kitiumai/logger # or pnpm add @kitiumai/loggerInitialize in Your App
import { LoggerBuilder, LoggerType } from '@kitiumai/logger'; // For development (console output) const logger = LoggerBuilder.console('my-app'); // For production (file-based) const logger = LoggerBuilder.file('my-app', './logs'); // For cloud (Loki integration) import { getLoggerConfig } from '@kitiumai/logger'; const config = getLoggerConfig(); const logger = LoggerBuilder.central(config);
Migration Strategies
Strategy 1: Gradual Migration (Recommended)
- Install the package
- Create a singleton logger instance
- Replace logging statements progressively
- Run tests after each file migration
- Commit changes
Strategy 2: Automated Migration
- Use the migration script:
npm run migrate - Review the generated changes
- Test thoroughly
- Commit changes
Strategy 3: Wrapper Pattern
// logger-adapter.ts
import { getLogger } from '@kitiumai/logger';
export const logger = {
log: (msg: string, meta?: any) => getLogger().info(msg, meta),
error: (msg: string, err?: Error) => getLogger().error(msg, {}, err),
warn: (msg: string, meta?: any) => getLogger().warn(msg, meta),
debug: (msg: string, meta?: any) => getLogger().debug(msg, meta),
};Before & After Examples
From console.log:
// Before
console.log('User logged in:', userId);
console.error('Database error:', err.message);
// After
logger.info('User logged in', { userId });
logger.error('Database error', { message: err.message }, err);From Winston Logger:
// Before
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [new winston.transports.Console()],
});
// After
import { LoggerBuilder } from '@kitiumai/logger';
const logger = LoggerBuilder.console('my-app');From Pino Logger:
// Before
import pino from 'pino';
const logger = pino({ level: 'info' });
logger.info({ userId: '123' }, 'User action');
// After
import { LoggerBuilder } from '@kitiumai/logger';
const logger = LoggerBuilder.console('my-app');
logger.info('User action', { userId: '123' });From Bunyan Logger:
// Before
import bunyan from 'bunyan';
const log = bunyan.createLogger({ name: 'myapp' });
log.info({ userId: '123', action: 'login' }, 'User logged in');
// After
import { LoggerBuilder } from '@kitiumai/logger';
const logger = LoggerBuilder.console('myapp');
logger.info('User logged in', { userId: '123', action: 'login' });Using the Migration Tool
Run the Interactive Tool:
npm run migrateThis tool will:
- Scan your project for logging statements
- Identify which loggers are used
- Generate a migration report with statistics
- Provide recommendations
Advanced Options:
# Scan specific directory
npm run migrate -- /path/to/project
# Generate a report file
npm run migrate -- --report migration-report.json
# CI/CD integration
npm run migrate -- --ciFramework Integration Examples
Express.js:
import express from 'express';
import {
LoggerBuilder,
tracingMiddleware,
errorLoggingMiddleware,
bodyLoggingMiddleware,
performanceMetricsMiddleware,
} from '@kitiumai/logger';
const app = express();
const logger = LoggerBuilder.console('my-api');
// Add logging middleware
app.use(tracingMiddleware());
app.use(bodyLoggingMiddleware());
app.use(performanceMetricsMiddleware());
// Routes
app.get('/api/users', (req, res) => {
logger.info('Fetching users');
res.json({ users: [] });
});
// Error handling
app.use(errorLoggingMiddleware());Next.js:
// lib/logger.ts
import { LoggerBuilder } from '@kitiumai/logger';
export const logger = LoggerBuilder.console('my-nextjs-app');
// pages/api/hello.ts
import { withNextApiLogger } from '@kitiumai/logger/middleware/next';
import { logger } from '@/lib/logger';
export default withNextApiLogger(async (req, res) => {
logger.info('API call', { path: req.url, method: req.method });
res.status(200).json({ message: 'Hello' });
});
// app/api/users/route.ts (App Router)
import { withNextRouteLogger } from '@kitiumai/logger/middleware/next';
import { logger } from '@/lib/logger';
export const GET = withNextRouteLogger(async (request) => {
logger.info('Fetching users (Next Route)', { path: request.nextUrl.pathname });
return Response.json({ users: [] });
});NestJS:
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import {
createNestLoggingMiddleware,
createNestExceptionFilter,
} from '@kitiumai/logger/middleware/nest';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(createNestLoggingMiddleware());
app.useGlobalFilters(createNestExceptionFilter());
await app.listen(3000);
}
bootstrap();Fastify:
import Fastify from 'fastify';
import { LoggerBuilder } from '@kitiumai/logger';
const kitiumLogger = LoggerBuilder.console('my-fastify-app');
const fastify = Fastify({ logger: { level: 'info' } });
fastify.get('/hello', async (request, reply) => {
kitiumLogger.info('Request received', {
url: request.url,
method: request.method,
});
return { hello: 'world' };
});Common Migration Patterns
Pattern 1: Contextual Logging
// Before (Winston)
const logger = winston.createLogger({
defaultMeta: { userId: user.id, requestId: req.id },
});
// After (Kitium)
await logger.withContext({ userId: user.id, requestId: req.id }, async () => {
logger.info('Processing user request');
logger.debug('Loading data');
// All logs include userId and requestId automatically
});Pattern 2: Error Handling
// Before
logger.error('Operation failed', {
error: err.message,
stack: err.stack,
context: { userId: '123' },
});
// After
logger.error('Operation failed', { userId: '123' }, err);Pattern 3: Performance Monitoring
import { createTimer } from '@kitiumai/logger';
const timer = createTimer('Database query');
// ... perform operation ...
const { duration, memoryUsed } = timer.end({
query: 'SELECT * FROM users',
});Pattern 4: Batch Logging
import { BatchLogger } from '@kitiumai/logger';
const batch = new BatchLogger();
batch.info('Step 1 complete');
batch.info('Step 2 complete');
batch.warn('Step 3 had warning');
batch.flush(); // Log all at onceMigration Checklist
- [ ] Install package:
npm install @kitiumai/logger - [ ] Run migration tool:
npm run migrate - [ ] Update imports in all files
- [ ] Replace logging calls
- [ ] Update error handling
- [ ] Test in development
- [ ] Run full test suite
- [ ] Update documentation
- [ ] Commit and deploy
Migration Troubleshooting
Issue: Type Errors with any type
- Solution: Use
unknowninstead and handle narrowing:
const meta: Record<string, unknown> = {};Issue: Missing Imports
- Solution: Check package installation and import paths:
// ✅ Correct
import { LoggerBuilder } from '@kitiumai/logger';Issue: Logger Not Initialized
- Solution: Initialize logger before using it:
import { LoggerBuilder } from '@kitiumai/logger';
const logger = LoggerBuilder.console('my-app');
export { logger };Issue: Console Output in Tests
- Solution: Use InMemoryLogger for testing:
import { LoggerBuilder, LoggerType } from '@kitiumai/logger';
const logger = LoggerBuilder.inMemory('test-app');Migration Scripts Documentation
This package includes scripts to help migrate existing projects to use @kitiumai/logger.
Available Scripts
1. Interactive Migration Tool (npm run migrate)
A Node.js script that analyzes your project and provides migration guidance.
Features:
- Scans project for existing logging patterns
- Detects console.log, Winston, Bunyan, Pino, and Debug usage
- Generates migration report with statistics
- Provides interactive migration guide
- Identifies files that need updates
Example Output:
🚀 Kitium Logger Migration Tool
📊 Logger Usage Summary:
console.log/error/warn/info/debug: 245 occurrences
Winston logger: 89 occurrences
Total logging statements found: 334
📁 Files that need migration:
src/index.ts
src/utils/helpers.ts
src/services/api.ts2. TypeScript Version
A TypeScript version of the migration script for advanced use cases.
ts-node scripts/migrate.tsHow to Use Migration Tool
Step 1: Run the Scanner
npm run migrateStep 2: Review the Report The tool will show:
- Total logging statements found
- Types of loggers detected
- Files that need updating
- Line numbers for each occurrence
Step 3: Follow the Guide The tool provides:
- Installation instructions
- Code examples for your use case
- Migration patterns
- Best practices
Step 4: Apply Changes Apply the suggested changes to your codebase
Step 5: Test & Verify
npm run test
npm run build
npm run lintMigration Script Options
Scan specific directory:
npm run migrate -- /path/to/projectGet help:
npm run migrate:helpGenerate migration script (optional): The tool can generate an automated migration script to replace common patterns.
Integration with CI/CD
Add to your pre-commit hook or CI pipeline:
npm run migrate -- --ci
npm run migrate -- --report migration-report.jsonPackage Assessment & Improvements
Overall Assessment: 7.5/10 - Solid Foundation with Notable Improvements Needed
✅ Strengths
Architecture & Design Patterns (9/10)
- Multiple logger implementations with strategy pattern
- Builder pattern for fluent configuration
- Factory pattern for logger instantiation
- Singleton pattern for global logger management
- Clear separation of concerns
Type Safety (9/10)
- Full TypeScript implementation
- Well-defined interfaces (ILogger, LogContext, LogEntry)
- No any types in critical paths
- Generic support for context management
- Proper enums for LogLevel and LoggerType
Context Propagation (8.5/10)
- AsyncLocalStorage-based context management
- Automatic trace/span ID generation (UUID)
- User and session tracking support
- Distributed tracing ready
- Context isolation per request
Multiple Output Targets (8/10)
- Console, File, InMemory, and Loki support
- Daily file rotation with configurable retention
- Loki integration for centralized logging
- Environment-based configuration
- Optional console transport with file logging
Express.js Integration (8/10)
- Tracing middleware with request/response timing
- Performance metrics middleware
- Error logging middleware
- Body logging with automatic sanitization
- User context extraction middleware
Security Features (7.5/10)
- Automatic sensitive field redaction
- Recursive sanitization for nested objects
- Loki basic auth support
- Audit logging support
- LoggableError for context-aware error handling
⚠️ Critical Issues
1. Testing & Quality (0% Coverage) 🔴 CRITICAL
- No unit tests in repository
- Target: >90% code coverage (Google/Netflix standard)
- Required: Comprehensive test suite for all logger implementations
2. Error Handling (4/10) 🔴 CRITICAL
- Missing try-catch blocks in middleware
- No retry logic with exponential backoff
- No circuit breaker pattern for Loki
- No graceful degradation strategy
- Fire-and-forget batching without recovery
3. Performance Issues (5/10) 🔴 CRITICAL
- Unbounded memory in InMemoryLogger (default 10,000 logs)
- Missing metrics/observability
- No memory limits or LRU eviction
- Slow request detection not configurable
4. Configuration Management (5/10) 🟠 MAJOR
- Hardcoded threshold values
- Missing validation of config values
- No hot reloading support
- No dynamic log level changes
5. Missing Production Features (4/10) 🔴 CRITICAL
- No structured logging enforcement
- No log sampling for high-volume services
- No log aggregation strategy
- No OpenTelemetry integration
🎯 Comparison with Industry Standards
| Aspect | Current | Google | Amazon | Netflix | | ---------------------- | -------- | -------- | -------- | -------- | | Test Coverage | 0% | >95% | >90% | >95% | | Error Handling | Basic | Advanced | Advanced | Advanced | | Circuit Breakers | ❌ | ✅ | ✅ | ✅ | | Metrics/Observability | 🟡 Basic | ✅ Full | ✅ Full | ✅ Full | | Performance Monitoring | Partial | Complete | Complete | Complete | | Distributed Tracing | Manual | OTEL | OTEL | OTEL |
📋 Top 10 Recommendations
🔴 CRITICAL (Must Have)
Add Comprehensive Unit Tests (40-60 hours)
- Jest setup with >90% coverage
- Test all logger implementations
- Mock Loki and file system
- Context propagation tests
Implement Error Handling & Recovery (20-30 hours)
- Add try-catch blocks in middleware
- Implement retry logic with exponential backoff
- Circuit breaker for Loki
- Graceful degradation
Add Observability/Metrics (15-25 hours)
- Prometheus metrics export
- Memory usage tracking
- Batch latency metrics
- Dropped logs counter
Fix Code Complexity Issues (10-15 hours)
- Refactor methods exceeding limits
- Extract helper functions
- Improve readability
🟠 MAJOR (High Value)
- Implement Configuration Validation (8-12 hours)
- Add OpenTelemetry Support (15-20 hours)
- Implement Structured Logging Standard (10-15 hours)
- Add Health Check Endpoints (5-8 hours)
🟡 MEDIUM (Nice to Have)
- Add Performance/Load Tests (12-18 hours)
- Improve Documentation (10-15 hours)
💡 Quick Win Implementations
These improvements can be done quickly to improve production readiness:
- Add error handling to middleware (1 hour)
- Add Prometheus metrics (3 hours)
- Add basic test file (2 hours)
- Add graceful shutdown (2 hours)
Production Readiness
Current Status: NOT READY for production without addressing critical issues
Recommended Timeline:
- Tests - 2 weeks
- Error handling - 1 week
- Metrics - 1 week
- Code quality refactoring - 1 week
Support
For issues or questions:
- Check the troubleshooting section
- Review example applications
- Review the Migration Guide above
- Check Loki documentation: https://grafana.com/docs/loki/latest/
- Review Winston documentation: https://github.com/winstonjs/winston
Built with ❤️ for enterprise logging
