@hamak/logging
v0.5.1
Published
Pluggable logging system with API, SPI, and implementation
Readme
Pluggable Logging System
A comprehensive, pluggable logging system for the app-framework monorepo.
Packages
@hamak/logging-api- Public interfaces and types@hamak/logging-spi- Service Provider Interfaces for extensions@hamak/logging-impl- Core implementation
Quick Start
import { createLoggingPlugin } from '@hamak/logging-impl';
import { LogLevel } from '@hamak/logging-api';
// Create logging plugin with default configuration
const loggingPlugin = createLoggingPlugin();
// Or with custom configuration
const loggingPlugin = createLoggingPlugin({
globalLevel: LogLevel.DEBUG,
interceptConsole: true, // Default: true
devFormatter: true, // Default: true in development
pluginLevels: {
'my-plugin': LogLevel.TRACE
}
});
// Use in microkernel
const host = createHost({
plugins: [loggingPlugin, myPlugin]
});Features
✅ Context-Aware Logging
export const myPlugin: PluginModule = {
initialize(ctx) {
const logManager = ctx.resolve(LOG_MANAGER_TOKEN);
const logger = logManager.createLogger({ plugin: 'my-plugin' });
logger.info('Plugin initializing');
// Output: ℹ️ INFO [my-plugin] Plugin initializing
const childLogger = logger.child({ module: 'auth' });
childLogger.warn('Authentication failed');
// Output: ⚠️ WARN [my-plugin] {auth} Authentication failed
}
};✅ Console Interception (Default: Enabled)
All console.log/warn/error calls automatically route through the logging system!
// With interception enabled (default)
console.log('Hello world');
// → Routes through logger.info('Hello world')
console.warn('Warning message');
// → Routes through logger.warn('Warning message')
console.error('Error occurred', new Error('details'));
// → Routes through logger.error('Error occurred', error)Disable if needed:
const loggingPlugin = createLoggingPlugin({
interceptConsole: false // Disable console interception
});✅ Performance Timing
logger.time('database-query');
await db.query('SELECT * FROM users');
logger.timeEnd('database-query');
// Output: 🐛 DEBUG {module} database-query ⏱ 45ms #performance✅ Structured Metadata
logger.info('User logged in', {
userId: '123',
timestamp: Date.now(),
tags: ['auth', 'user-event']
});✅ Multiple Log Levels
logger.trace('Very detailed debug info');
logger.debug('Debug information');
logger.info('General information');
logger.warn('Warning message');
logger.error('Error occurred', error);
logger.fatal('Fatal error', error);✅ Rich Development Output
In development mode, logs include:
- 🎨 Colors - Different colors per log level
- 🎭 Emojis - Visual indicators for each level
- 📍 Context - Plugin/module/component hierarchy
- ⏱️ Performance - Duration tracking
- 🏷️ Tags - Categorization and filtering
✅ JSON Output for Production
In production mode, logs are structured JSON:
{
"timestamp": 1699564800000,
"level": "INFO",
"message": "User logged in",
"context": {
"plugin": "auth",
"module": "login"
},
"metadata": {
"userId": "123",
"tags": ["auth", "user-event"]
}
}Configuration Options
interface LoggingPluginConfig {
/** Global minimum log level */
globalLevel?: LogLevel;
/** Plugin-specific log levels */
pluginLevels?: Record<string, LogLevel>;
/** Module-specific log levels */
moduleLevels?: Record<string, LogLevel>;
/** Buffer size before forcing flush */
bufferSize?: number; // Default: 1000
/** Automatic flush interval in milliseconds */
flushInterval?: number; // Default: 5000
/** Use rich development formatter */
devFormatter?: boolean; // Default: true in development
/** Intercept console.log/warn/error (ENABLED BY DEFAULT) */
interceptConsole?: boolean; // Default: true
}Advanced Usage
Custom Transports
import { ILogTransport, LogEntry } from '@hamak/logging-api';
class MyCustomTransport implements ILogTransport {
readonly id = 'my-transport';
readonly name = 'My Custom Transport';
log(entry: LogEntry): void {
// Send to custom destination
fetch('/api/logs', {
method: 'POST',
body: JSON.stringify(entry)
});
}
}
// Register in plugin initialization
logManager.registerTransport(new MyCustomTransport(), {
id: 'my-transport',
enabled: true,
minLevel: LogLevel.WARN
});Filtering Logs
// Only log errors from 'payment' plugin
logManager.registerTransport(transport, {
id: 'payment-errors',
minLevel: LogLevel.ERROR,
plugins: ['payment']
});
// Only log entries with specific tags
logManager.registerTransport(transport, {
id: 'analytics',
filter: (entry) => entry.metadata?.tags?.includes('analytics')
});Accessing Log Manager
export const myPlugin: PluginModule = {
initialize(ctx) {
const logManager = ctx.resolve(LOG_MANAGER_TOKEN);
// Create logger
const logger = logManager.createLogger({ plugin: 'my-plugin' });
// Change log levels at runtime
logManager.setPluginLevel('my-plugin', LogLevel.TRACE);
logManager.setGlobalLevel(LogLevel.WARN);
// Flush logs manually
await logManager.flush();
}
};Architecture
- SPI/API/IMPL Pattern - Clean separation of concerns
- Dependency Injection - Loggers injected via microkernel DI
- Pluggable Transports - Multiple output destinations
- Event-Based - Integrates with microkernel event system
- Performance Optimized - Buffering, batching, lazy formatting
- Type-Safe - Full TypeScript support
Examples
See apps/demo/src/ for complete integration examples.
Documentation
License
MIT
