@oxog/log
v1.0.1
Published
Blazing fast, plugin-based logging with @oxog ecosystem integration, colored output, and swappable transports
Maintainers
Readme
@oxog/log
Blazing fast, plugin-based logging for Node.js and browsers with micro-kernel architecture.
Part of the @oxog ecosystem.
Features
- Six Log Levels: trace, debug, info, warn, error, fatal
- Structured Logging: Attach metadata objects to log entries
- Child Loggers: Create scoped loggers with bound context
- Correlation ID: Track requests across async operations
- Source Location: Capture file and line number
- Performance Timing: Built-in time/timeEnd utilities
- Redaction: Mask sensitive fields from output
- Multiple Formats: JSON, Pretty, Auto (based on environment)
- Multiple Transports: Console, Stream, File, HTTP, localStorage
- Hybrid Sync/Async: Level-based synchronization with buffering
- Browser Support: Native DevTools integration
- Zero Config: Works out of the box with sensible defaults
- TypeScript First: Full type safety and IntelliSense support
Installation
npm install @oxog/logQuick Start
import { createLogger } from '@oxog/log';
const log = createLogger({ name: 'my-app' });
// Simple logging
log.info('Server started');
// Structured logging with data
log.info({ port: 3000, env: 'production' }, 'Listening');
// Child loggers with context
const dbLog = log.child({ module: 'database' });
dbLog.info('Connected to database');Log Levels
log.trace('Detailed debugging'); // 10
log.debug('Debug information'); // 20
log.info('Informational'); // 30
log.warn('Warning'); // 40
log.error('Error occurred'); // 50
log.fatal('Fatal error'); // 60Examples
Child Loggers
const dbLog = log.child({ module: 'database' });
dbLog.info('Connected');
const queryLog = dbLog.child({ operation: 'select' });
queryLog.debug('Executing query');Correlation ID
const reqLog = log.withCorrelation('req-abc-123');
reqLog.info('Request received');
reqLog.info('Processing');
reqLog.info('Response sent');Performance Timing
log.time('db-query');
await database.query('SELECT * FROM users');
log.timeEnd('db-query');
// Or use startTimer for more control
const end = log.startTimer('api-call');
await fetch('/api/data');
end();Redaction
const log = createLogger({
redact: ['password', 'token', 'creditCard']
});
log.info({ user: 'john', password: 'secret123' });
// Output: {"user":"john","password":"[REDACTED]"}Multiple Transports
import { createLogger, consoleTransport, fileTransport } from '@oxog/log';
const log = createLogger({
transports: [
consoleTransport({ colors: true }),
fileTransport({
path: './logs/app.log',
rotate: '1d',
maxFiles: 7
})
]
});Output Formats
// Structured JSON (production)
const jsonLog = createLogger({ format: 'json' });
// Human-readable (development)
const prettyLog = createLogger({ format: 'pretty' });
// Auto-detect based on environment
const autoLog = createLogger({ format: 'auto' });Error Handling
try {
const data = await fetchData();
} catch (error) {
log.error(error, 'Failed to fetch data');
}
log.fatal(new Error('Cannot start'), 'Server error');Level Filtering
const log = createLogger({ level: 'warn' });
log.info('This will NOT appear'); // Below minimum level
log.warn('This WILL appear');
// Dynamic level change
log.setLevel('debug');
log.info('Now this appears');Source Location
const log = createLogger({ source: true });
log.info('Debug me');
// Output: {"level":30,"file":"server.ts","line":42,"msg":"Debug me"}Plugin System
import { createLogger, redactPlugin, sourcePlugin } from '@oxog/log';
const log = createLogger({
plugins: [
redactPlugin(['apiKey', 'secret']),
sourcePlugin()
]
});Custom Plugin
import type { Plugin } from '@oxog/types';
const myPlugin: Plugin = {
name: 'myPlugin',
version: '1.0.0',
install(kernel) {
// Custom logic
}
};
log.use(myPlugin);Browser Usage
import { createLogger } from '@oxog/log';
const log = createLogger();
log.info('Hello from browser!');
log.warn('Careful!');
log.error('Something went wrong');
// Child loggers use console.group
const child = log.child({ component: 'Auth' });
child.info('Checking token');Transport Error Handling
// Listen for transport failures
log.on('error', ({ transport, error, entry }) => {
console.error(`Transport ${transport} failed:`, error.message);
// Optionally alert ops team or use fallback
});Sync vs Async Logging
const log = createLogger({
// fatal and error are sync by default (written before process exit)
sync: {
fatal: true, // default
error: true, // default
warn: false,
info: false,
debug: false,
trace: false,
}
});
// Fatal logs are written synchronously - safe before process.exit()
process.on('uncaughtException', (err) => {
log.fatal(err, 'Uncaught exception');
process.exit(1); // Log is guaranteed to be written
});Efficient Redaction
import { stringifyWithRedaction } from '@oxog/log';
// More efficient than redactFields + JSON.stringify for large objects
const json = stringifyWithRedaction(
largeObject,
['password', 'token', 'headers.authorization']
);Graceful Shutdown
// Flush buffered logs before shutdown
await log.flush();
// Cleanup and destroy (also flushes buffer)
await log.close();API Reference
createLogger(options?)
Creates a new logger instance.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| name | string | 'app' | Logger name |
| level | LogLevelName | 'info' | Minimum log level |
| format | 'json' \| 'pretty' \| 'auto' | 'auto' | Output format |
| transports | Transport[] | [consoleTransport()] | Output destinations |
| redact | string[] | [] | Fields to redact |
| source | boolean | false | Include source location |
| timestamp | boolean | true | Include timestamp |
| context | object | {} | Static context |
| plugins | Plugin[] | [] | Plugins to load |
Logger Methods
Logging
trace(msg)/trace(obj, msg)- Trace leveldebug(msg)/debug(obj, msg)- Debug levelinfo(msg)/info(obj, msg)- Info levelwarn(msg)/warn(obj, msg)- Warn levelerror(msg)/error(obj, msg)/error(err, msg)- Error levelfatal(msg)/fatal(obj, msg)/fatal(err, msg)- Fatal level
Context
child(context)- Create child logger with additional contextwithCorrelation(id)- Create logger with correlation ID
Timing
time(label)- Start a timertimeEnd(label)- End timer and log durationstartTimer(label)- Returns stop function
Plugin Management
use(plugin)- Register pluginunregister(name)- Unregister pluginhasPlugin(name)- Check if plugin existslistPlugins()- List all plugins
Lifecycle
flush()- Flush buffered logsclose()- Cleanup and close transports
Level Management
setLevel(level)- Set minimum levelgetLevel()- Get current levelisLevelEnabled(level)- Check if level is enabled
Documentation
For detailed documentation, see the docs folder:
- Specification - Full API specification
- Implementation - Implementation details
- Tasks - Development tasks
Contributing
Contributions are welcome! Please read our contributing guidelines before submitting a PR.
License
MIT - see LICENSE for details.
Author
Ersin Koc - @ersinkoc
