Structured logging with multiple outputs and performance timing for TypeScript applications
npm install @groundbrick/loggerA structured logging and error handling library for the microframework ecosystem.
- Structured Logging: JSON and pretty-print formats
- Multiple Outputs: Console, file, and custom handlers
- Log Levels: Debug, info, warn, error with filtering
- Child Loggers: Contextual logging with inheritance
- Persistent Metadata: Attach data to all logs from a logger instance
- Performance Timing: Built-in timer functionality
- Error Handling: Comprehensive error logging with stack traces
- File Rotation: Automatic log file rotation with size limits
- TypeScript: Full type safety and IntelliSense support
``bash`
npm install @groundbrick/logger
`typescript
import { createLogger } from '@groundbrick/logger';
const logger = createLogger();
logger.info('Application started');
logger.warn('This is a warning', { userId: '123' });
logger.error('Something went wrong', new Error('Database connection failed'));
`
`typescript
import { createLogger } from '@groundbrick/logger';
const logger = createLogger({
level: 'debug',
format: 'json',
context: 'my-service',
outputs: [
{ type: 'console' },
{
type: 'file',
options: {
filePath: './logs/app.log',
maxSize: 10 1024 1024, // 10MB
maxFiles: 5
}
}
]
});
`
You can configure the logger using environment variables:
`bash`
LOG_LEVEL=debug
LOG_FORMAT=json
NODE_ENV=production
`typescript`
logger.debug('Debug information', { query: 'SELECT * FROM users' });
logger.info('User logged in', { userId: '123', ip: '192.168.1.1' });
logger.warn('Rate limit approaching', { requests: 95, limit: 100 });
logger.error('Database error', error, { operation: 'user-fetch' });
`typescript
const dbLogger = logger.child('database');
const userLogger = dbLogger.child('users');
userLogger.info('Fetching user'); // Context: "database:users"
`
`typescript
logger.addMetadata('version', '1.0.0');
logger.addMetadata('environment', 'production');
// All subsequent logs will include this metadata
logger.info('This log includes version and environment');
`
`typescript
const endTimer = logger.startTimer('database-query');
// Perform some operation
await db.query('SELECT * FROM users');
endTimer(); // Logs: "Timer database-query completed" with duration
`
`typescript`
const logger = createLogger({
outputs: [
{
type: 'custom',
options: {
customHandler: async (entry) => {
// Send to external service
await sendToLogService(entry);
}
}
}
]
});
`typescript`
const logger = createLogger({
outputs: [
{
type: 'file',
options: {
filePath: './logs/app.log',
maxSize: 5 1024 1024, // 5MB per file
maxFiles: 10 // Keep 10 files max
}
}
]
});
Each log entry follows this structure:
`typescript`
interface LogEntry {
timestamp: string;
level: 'debug' | 'info' | 'warn' | 'error';
message: string;
context?: string;
metadata?: Record
error?: {
name: string;
message: string;
stack?: string;
code?: string | number;
};
request?: {
id?: string;
method?: string;
url?: string;
userAgent?: string;
ip?: string;
};
performance?: {
duration?: number;
memory?: NodeJS.MemoryUsage;
};
}
``
2024-01-15T10:30:00.000Z INFO [my-service] User logged in
{
"userId": "123",
"ip": "192.168.1.1"
}
`json`
{
"timestamp": "2024-01-15T10:30:00.000Z",
"level": "info",
"message": "User logged in",
"context": "my-service",
"metadata": {
"userId": "123",
"ip": "192.168.1.1"
},
"performance": {
"memory": { ... }
}
}
This logger is designed to integrate seamlessly with other microframework packages:
`typescript
// In repository layer
import { createLogger } from '@groundbrick/logger';
export class BaseRepository {
protected logger = createLogger().child('repository');
}
// In service layer
export class BaseService {
protected logger = createLogger().child('service');
}
`
`typescript`
interface Logger {
debug(message: string, metadata?: Record
info(message: string, metadata?: Record
warn(message: string, metadata?: Record
error(message: string, error?: Error, metadata?: Record
child(context: string): Logger;
setLevel(level: LogLevel): void;
addMetadata(key: string, value: any): void;
startTimer(label: string): () => void;
}
`typescript``
interface LoggerConfig {
level: 'debug' | 'info' | 'warn' | 'error';
format: 'json' | 'pretty';
includeTimestamp: boolean;
includeStack: boolean;
context?: string;
outputs: LogOutput[];
}
MIT