@lytics/kero
v1.0.0
Published
Zero-dependency TypeScript logger with structured logging, multiple transports, and beautiful output
Readme
@lytics/kero
Zero-dependency TypeScript logger with structured logging, multiple transports, and beautiful output.
Inspired by Pino, built for modern TypeScript applications.
Features
- 🚀 Zero runtime dependencies - Only uses Node.js built-ins
- 📊 Structured logging - First-class support for objects and metadata
- 🎨 Beautiful output - Pretty console output for development, JSON for production
- ⚡ Fast & lightweight - Minimal overhead, maximum performance
- 🔧 TypeScript-first - Full type safety out of the box
- 🎯 Child loggers - Inherit configuration and add contextual data
- ⏱️ Built-in timers - Measure operation duration easily
- 🌈 Icons support - Visual scanning with Unicode or emoji icons
- 📦 ESM & CJS - Works with both module systems
- 🎭 Multiple presets - Development, production, and test configurations
Installation
pnpm add @lytics/keroQuick Start
import { kero } from '@lytics/kero';
// Basic logging
kero.info('Server started');
kero.success('Deployment complete');
kero.debug({ port: 3000 }, 'Listening');
kero.error(new Error('Failed'), 'Request failed');Creating a Logger
import { createLogger } from '@lytics/kero';
const logger = createLogger({
level: 'debug', // Minimum level: trace, debug, info, warn, error, fatal
format: 'pretty', // Output format: 'pretty' or 'json'
});Presets
import { createLogger } from '@lytics/kero';
// Development: pretty output, debug level
const devLogger = createLogger({ preset: 'development' });
// Production: JSON output, info level
const prodLogger = createLogger({ preset: 'production' });
// Test: JSON output, warn level (minimal noise)
const testLogger = createLogger({ preset: 'test' });Child Loggers
Child loggers inherit parent configuration and add context:
const logger = createLogger({ level: 'info' });
const reqLogger = logger.child({ requestId: 'abc-123' });
reqLogger.info('Processing'); // Includes requestId in outputStructured Logging
Pass an object as the first argument for structured data:
logger.info({ userId: 42, action: 'login' }, 'User authenticated');
// JSON: {"level":30,"time":1732505525000,"userId":42,"action":"login","msg":"User authenticated"}
// Pretty: [14:32:05] INFO User authenticated {"userId":42,"action":"login"}Error Logging
Pass an Error as the first argument:
try {
riskyOperation();
} catch (err) {
logger.error(err, 'Operation failed');
}Timing
Measure operation duration:
const done = logger.startTimer('database-query');
await db.query(sql);
done(); // Logs: "database-query completed (42ms)"Log Levels
From lowest to highest priority:
| Level | Value | Description |
|---------|-------|--------------------------|
| trace | 10 | Detailed tracing |
| debug | 20 | Debug information |
| info | 30 | Normal operations |
| warn | 40 | Warning conditions |
| error | 50 | Error conditions |
| fatal | 60 | System is unusable |
Output Formats
Pretty (Development)
[14:32:05] INFO Server started
[14:32:05] DEBUG Listening {"port":3000}
[14:32:06] INFO (abc-123) ProcessingPretty with Icons
Enable icons for visual scanning:
import { createLogger, PrettyFormatter } from '@lytics/kero';
// Unicode icons (default when icons=true) - works everywhere
const logger = createLogger({
formatter: new PrettyFormatter({ icons: true }),
});
// Or explicitly: icons: 'unicode' or icons: 'emoji'Unicode icons (terminal-safe):
[14:32:05] » TRACE Detailed info
[14:32:05] ○ DEBUG Listening {"port":3000}
[14:32:05] ● INFO Server started
[14:32:05] ✔ INFO Deployment complete (success)
[14:32:06] ▲ WARN Memory usage high
[14:32:07] ✖ ERROR Request failed| Level | Unicode | Emoji |
|-----------|---------|-------|
| trace | » | 🔍 |
| debug | ○ | 🐛 |
| info | ● | ℹ️ |
| success | ✔ | ✅ |
| warn | ▲ | ⚠️ |
| error | ✖ | ❌ |
| fatal | ✘ | 💀 |
JSON (Production)
{"level":30,"time":1732505525000,"msg":"Server started"}
{"level":20,"time":1732505525001,"port":3000,"msg":"Listening"}
{"level":30,"time":1732505526000,"requestId":"abc-123","msg":"Processing"}Custom Formatters
Implement the Formatter interface:
import { createLogger, Formatter, LogEntry } from '@lytics/kero';
const myFormatter: Formatter = {
format(entry: LogEntry): string {
return `[${entry.level}] ${entry.msg}`;
}
};
const logger = createLogger({ formatter: myFormatter });Custom Transports
Implement the Transport interface:
import { createLogger, Transport, LogEntry } from '@lytics/kero';
const myTransport: Transport = {
write(entry: LogEntry, formatted: string): void {
// Send to your logging service
fetch('/logs', { method: 'POST', body: formatted });
}
};
const logger = createLogger({ transports: [myTransport] });API Reference
createLogger(config?)
Creates a new logger instance.
Options:
level: Minimum log level (default:'info')format: Output format'pretty'|'json'(default:'pretty')formatter: Custom formatter instancetransports: Array of transports (default:[ConsoleTransport])context: Default context for all log entriespreset: Preset name'development'|'production'|'test'
kero
Default logger instance with development preset.
Logger Methods
trace(msg)/trace(obj, msg)- Log at trace leveldebug(msg)/debug(obj, msg)- Log at debug levelinfo(msg)/info(obj, msg)- Log at info levelsuccess(msg)/success(obj, msg)- Log success at info level (with ✔ icon)warn(msg)/warn(obj, msg)- Log at warn levelerror(msg)/error(err, msg)/error(obj, msg)- Log at error levelfatal(msg)/fatal(err, msg)/fatal(obj, msg)- Log at fatal levelchild(context)- Create child logger with added contextstartTimer(label)- Start a timer, returns function to stop and logisLevelEnabled(level)- Check if level would be loggedlevel- Get current log level
Zero Dependencies
This package has zero runtime dependencies. It uses only Node.js built-ins:
process.stdout/process.stderrfor outputprocess.envfor color detection
Why Kero?
Kero (ケロケロ) is the Japanese onomatopoeia for a frog's croak - the sound frogs make. Just like how a frog's call cuts through the noise to be heard clearly, kero helps your logs stand out with beautiful, structured output that's easy to read and understand.
Comparison with Other Loggers
| Feature | Kero | Pino | Winston | Bunyan | |---------|------|------|---------|--------| | Zero dependencies | ✅ | ❌ | ❌ | ❌ | | TypeScript-first | ✅ | ❌ | ❌ | ❌ | | Pretty console output | ✅ | ⚠️ (separate package) | ✅ | ⚠️ (via CLI) | | Structured logging | ✅ | ✅ | ✅ | ✅ | | Child loggers | ✅ | ✅ | ✅ | ✅ | | Built-in timers | ✅ | ❌ | ✅ | ❌ | | Package size | ~15KB | ~100KB | ~300KB | ~200KB |
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
MIT © Lytics
