Architecture
MagicLogger is built on four foundational pillars that work together to deliver unmatched performance and developer experience.
Zero-Cost Abstractions
No heap allocations, no promises, direct call paths
Progressive Enhancement
Features are opt-in and tree-shakeable
Transport Agnosticism
Unified interface for any destination
Compatibility
Drop-in replacement for popular loggers
Core Components
The building blocks that power MagicLogger
Logger Class
The main orchestration point that manages the entire logging lifecycle
Key Features:
- ▸Entry creation and routing
- ▸Transport management
- ▸Context and tag handling
- ▸Lifecycle management
class Logger {
private readonly id: string;
private readonly transports: Transport[];
private readonly contextManager: ContextManager;
private readonly tagManager: TagManager;
private asyncBuffer?: AsyncBuffer;
constructor(options: LoggerOptions = {}) {
this.id = options.id || this.generateId();
this.contextManager = new ContextManager(options.context);
this.tagManager = new TagManager(options.tags);
this.transports = this.initializeTransports(options.transports);
if (options.async?.enabled) {
this.asyncBuffer = new AsyncBuffer({
size: options.async.bufferSize || 10000,
onFlush: entries => this.flushEntries(entries)
});
}
}
info(message: string, meta?: any): void {
this.log('info', message, meta);
}
private log(level: LogLevel, message: string, meta?: any): void {
const entry = this.createEntry(level, message, meta);
if (this.asyncBuffer && meta?.async !== false) {
this.asyncBuffer.add(entry);
} else {
this.dispatchSync(entry);
}
}
}
Performance Architecture
How MagicLogger achieves 850k+ ops/sec
Memory Management
Object pooling, ring buffers, and string interning minimize allocations
class LogEntryPool {
private pool: LogEntry[] = [];
private maxSize = 1000;
acquire(): LogEntry {
if (this.pool.length > 0) {
return this.pool.pop()!;
}
return this.createNew();
}
release(entry: LogEntry): void {
if (this.pool.length < this.maxSize) {
this.reset(entry);
this.pool.push(entry);
}
}
}
Ring Buffer
Lock-free circular buffer for async logging without blocking
class RingBuffer<T> {
private buffer: Array<T | undefined>;
private writePos = 0;
private readPos = 0;
push(item: T): boolean {
if (this.size === this.capacity) {
// Overwrite oldest
this.readPos = (this.readPos + 1) % this.capacity;
}
this.buffer[this.writePos] = item;
this.writePos = (this.writePos + 1) % this.capacity;
return true;
}
}
Monomorphic Functions
JIT-optimized code paths with consistent object shapes
// ❌ Polymorphic - slow
function format(entry: LogEntry | string | Error) {
if (typeof entry === 'string') return entry;
if (entry instanceof Error) return entry.message;
return JSON.stringify(entry);
}
// ✅ Monomorphic - fast
function formatLogEntry(entry: LogEntry): string {
return JSON.stringify(entry);
}
function formatString(str: string): string {
return str;
}
Transport System
Send logs anywhere with a unified interface
Console Transport
High-performance console output with color support
Example Usage:
new ConsoleTransport({
level: 'debug',
useColors: true,
showTimestamp: true,
prefix: 'APP'
})
Transport Data Flow
Implementation Guide
Best practices and patterns for production use
🏗️ Project Structure
// Optimal import strategy
import { Logger } from 'magiclogger/core';
import { ConsoleTransport } from 'magiclogger/console';
import { HTTPTransport } from 'magiclogger/http';
// Only imports what you need (tree-shaking)
const logger = new Logger({
transports: [
new ConsoleTransport({ level: 'debug' }),
new HTTPTransport({ url: '/api/logs' })
]
});
🎯 Context Strategy
// Application-wide context
const logger = new Logger({
context: {
service: 'api',
version: process.env.VERSION,
environment: process.env.NODE_ENV
}
});
// Request-scoped context
app.use((req, res, next) => {
req.logger = logger.child({
context: {
requestId: req.id,
userId: req.user?.id,
method: req.method,
path: req.path
}
});
next();
});
⚡ Performance Tips
// Use async for high-frequency logs
const logger = new Logger({
async: {
enabled: true,
buffer: { size: 100000 },
flushInterval: 1000
}
});
// Bypass async for critical logs
logger.error('Critical error', {
async: false, // Force sync
alert: true
});
// Batch network transports
new HTTPTransport({
batch: {
maxSize: 100,
maxTime: 5000,
maxBytes: 1048576 // 1MB
}
});
🛡️ Error Handling
// Transport error handling
const httpTransport = new HTTPTransport({
url: 'https://logs.example.com',
fallback: new FileTransport({
filepath: './fallback.log'
}),
dlq: {
enabled: true,
filepath: './dlq.log'
}
});
// Listen for transport events
httpTransport.on('error', (error, entry) => {
console.error('Transport failed:', error);
});
httpTransport.on('fallback', ({ count }) => {
console.log(`Failed over for ${count} logs`);
});
Ready to dive deeper?
Explore the complete documentation and start building