Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[4.4.0] - 2026-04-05
Added
- File rotation — New
rotationoption onFileTransportOptions- Size-based rotation:
maxSizein bytes (e.g.10 * 1024 * 1024for 10 MB) - Time-based rotation:
intervalaccepts'daily','hourly', or a number (ms) - Retention:
maxFilescaps the number of rotated files (default: 5); oldest are deleted - Compression:
compress: truegzip-compresses rotated files asynchronously (.gzsuffix) - Naming: numeric suffix —
app.log→app.log.1→app.log.2; current file stays at configured path - No entry loss: writes during rotation are buffered and flushed after the new file opens
- Byte counter seeded from existing file size on append mode — rotation triggers correctly on restart
- New export:
RotationOptionstype
- Size-based rotation:
[4.3.0] - 2026-03-30
Added
Platform worker adapter —
useWorker: truenow works on both browser and Node.js- Browser: Web Worker via Blob + Object URL (unchanged)
- Node.js:
worker_threadsvia dynamic import withparentPortshim - Unified
KonsoleWorkerinterface insrc/workerAdapter.ts - Messages sent before the Node.js worker is ready are buffered and flushed automatically
- Falls back gracefully to main-thread processing if no worker API is available
- New exports:
createPlatformWorker(),KonsoleWorkertype
Conditional
node/browserexports inpackage.jsonfor better bundler support
Changed
useWorker: trueis no longer browser-only — it is now supported in Node.js viaworker_threads- Removed the "Web Worker is not available" console warning in Node.js (worker is now created instead)
[4.2.0] - 2026-03-28
Added
Field redaction — New
redactoption onKonsoleOptionsandKonsoleChildOptions- Accepts dot-notation field paths:
redact: ['password', 'req.headers.authorization'] - Values replaced with
'[REDACTED]'before any output, transport, or buffer - Children inherit parent redact paths (security invariant — cannot opt out) and can add more
- Applied after bindings merge, before all consumers
- Original caller objects are never mutated
- New exports:
compileRedactPaths(),applyRedaction(),REDACTED
- Accepts dot-notation field paths:
Graceful shutdown — New static methods for clean process exit
Konsole.shutdown()— flushes and destroys all registered loggersKonsole.enableShutdownHook()— registersSIGTERM,SIGINT, andbeforeExithandlers (Node.js only, no-op in browser)
Browser runtime redaction toggle —
__Konsole.disableRedaction(true/false)viaexposeToWindow()- Temporarily bypass redaction in DevTools for debugging
- Not available in Node.js — server-side redaction is always enforced
[4.0.0] - 2026-03-19
Added
Configurable timestamps — New
timestampoption onKonsoleOptionsandKonsoleChildOptions- Preset formats:
'datetime'(default),'iso','time','date','unix','unixMs','none' - Custom function:
(date: Date, hrTime?: number) => string - Full options object:
{ format: TimestampFormat, highResolution: boolean } - New
TimestampFormatandTimestampOptionstypes exported
- Preset formats:
Full date in timestamps — Pretty, text, and browser formatters now show
YYYY-MM-DD HH:MM:SS.mmmby default (was time-onlyHH:MM:SS.mmm)Browser formatter timestamps —
BrowserFormatternow renders timestamps in DevTools output (previously omitted, relying on DevTools built-in timestamps)High-resolution timestamps —
{ highResolution: true }captures nanosecond-precision monotonic timingLogEntry.hrTimefield (nanoseconds viaprocess.hrtime.bigint()in Node.js,performance.now()in browsers)- Included in JSON output when present
- Custom timestamp functions receive
hrTimeas the second argument
Runtime timestamp control — New
setTimestamp()instance method- Accepts preset strings, custom functions, or
TimestampOptionsobjects - Recreates the internal formatter with the new format
- Accepts preset strings, custom functions, or
Browser runtime timestamp control —
exposeToWindow()now exposes:__Konsole.setTimestamp(format)— change all loggers__Konsole.getLogger(ns).setTimestamp(format)— change a specific logger__Konsole.getLogger(ns).setLevel(level)— change level from DevTools
Child logger timestamp override —
child(bindings, { timestamp })can override the parent's timestamp formatNew exports —
resolveTimestampConfig(),formatTimestamp(),getHrTime(),FormatterOptionsPerformance optimizations — on par with Pino on per-call overhead, faster on JSON serialization
bufferoption: defaults tofalsein Node.js (no circular buffer overhead),truein browsers- Disabled log levels add zero overhead
- Optimized argument parsing and field merging on the hot path
- Removed deprecated
logtypefield from entry construction
Benchmark suite —
npm run benchmarkcompares against Pino, Winston, and Bunyan- Throughput (ops/sec), latency (p50/p95/p99), bundle size, and memory usage
- Daily CI benchmark via GitHub Actions (
.github/workflows/benchmark.yml)
Changed
- Default timestamp format changed from time-only (
HH:MM:SS.mmm) todatetime(YYYY-MM-DD HH:MM:SS.mmm) for pretty, text, and browser formatters toTextLine()in file/stream transports now outputsYYYY-MM-DD HH:MM:SS.mmm(was time-only)createFormatter()andcreateAutoFormatter()accept an optionaltsFormatparameter- All formatter classes now accept
FormatterOptionswith an optionaltimestampFormatfield - Child loggers get their own formatter instance when overriding
timestamp(previously always shared with parent) - In Node.js,
bufferdefaults tofalse—getLogs()/viewLogs()return empty unlessbuffer: trueis set explicitly - Disabled log levels add zero per-call overhead in Node.js
Breaking Changes
- Default timestamp format changed — Pretty, Text, and Browser formatters now output
YYYY-MM-DD HH:MM:SS.mmm(wasHH:MM:SS.mmm). Restore old behavior withtimestamp: 'time'. - BrowserFormatter now renders timestamps — DevTools output includes a timestamp prefix. Use
timestamp: 'none'to omit. bufferdefaults tofalsein Node.js —getLogs(),viewLogs(), andgetStats()return empty unlessbuffer: trueis set. Browser default is unchanged (true).logtypefield removed from entries — The deprecatedLogEntry.logtypeis no longer set. Useentry.levelinstead (available since v3.0.0).toTextLine()output changed — File and stream transport text format now includes the full date (YYYY-MM-DD HH:MM:SS.mmm), matching the formatter default.
Migration from v3
// Restore v3 timestamp format
new Konsole({ timestamp: 'time' });
// Restore v3 buffer behavior in Node.js
new Konsole({ buffer: true });
// Replace logtype usage
entry.logtype // ❌ undefined in v4
entry.level // ✅ 'info', 'error', etc.[3.0.0] - 2025-03-14
Added
Node.js compatibility — Works in both browser and Node.js ≥ 18
- Replaced
windowusage withglobalThisthroughout fetchis detected viaglobalThis.fetch; passfetchImplfor Node.js < 18- Graceful warning when
useWorker: trueis set in Node.js (removed in v4.3.0 — now supported natively)
- Replaced
Numeric log levels — Six-level numeric system
- New methods:
trace()(10),debug()(20),fatal()(60) log()kept as an alias forinfo()(30)- New
levelconstructor option — minimum threshold; entries below are discarded entirely - New
setLevel()instance method for runtime changes LogEntrynow includeslevelandlevelValuefields
- New methods:
Structured logging — Consistent JSON schema
- Log entries now carry
msgandfields(structured key-value pairs) in addition tomessages - Fields spread into the top level of JSON output:
{ level, levelName, time, namespace, msg, ...fields } - Object-first calling convention:
logger.info({ msg: '...', key: val }) - String + fields object:
logger.info('msg', { key: val }) Erroras first argument:msg=err.message,fields.err= the Error
- Log entries now carry
Output formatters —
formatconstructor option ('auto' | 'pretty' | 'json' | 'text' | 'browser' | 'silent')PrettyFormatter— ANSI-colored human-readable output for TTY terminals; respectsNO_COLOR/FORCE_COLORJsonFormatter— Newline-delimited JSON for pipes, CI, and log aggregatorsTextFormatter— Plain text, no ANSI, for CI environmentsBrowserFormatter—%cCSS badge styling in browser DevToolsSilentFormatter— No output; entries still stored in buffer and forwarded to transportsautoselects the best formatter for the current environment automatically- Errors and fatals always route to
stderr; all other levels tostdout
Child loggers —
logger.child(bindings, options?)- Bindings automatically merged into every entry the child produces
- Bindings accumulate through nested children; call-site fields override on collision
- Optional
{ namespace, level }overrides per child - Children share parent's circular buffer and formatter
- Children are not registered in
Konsole.instances(ephemeral) child.addTransport()does not affect parent
Transport abstraction — New
Transportinterface withwrite,flush?,destroyHttpTransport— renamed fromTransport; updated payload to structured JSON schemaConsoleTransport— wraps a Formatter; useful withformat: 'silent'FileTransport— appends NDJSON/text to a file; Node.js only; buffers entries during async openStreamTransport— writes to anyWritableLike; duck-typed for compatibilityaddTransport()andtransportsoption now accept bothTransportinstances andTransportConfigobjects
Vitest test suite — 92 tests across 8 files covering all core components and transports
Changed
criteriais now deprecated — uselevelfor threshold filtering andformat: 'silent'to suppress outputTransportConfigno longer the only type accepted bytransports/addTransport()— bothTransportinstances andTransportConfigplain objects are acceptedLogEntry.logtypeis deprecated — useLogEntry.level- Rollup now externalizes all
node:built-ins to prevent browser stubs
Breaking Changes
LogEntryshape changed: addedmsg,fields,level,levelValue;logtypeis now@deprecated- Old
Transportclass is nowHttpTransport;src/Transport.tsis a deprecated re-export criteria: false(the old default) is superseded byformat: 'silent'
[2.0.0] - 2024-12-27
Added
Circular Buffer Storage — Memory-efficient log storage with configurable
maxLogslimit- Automatically evicts oldest logs when capacity is reached
- New
CircularBufferclass exported for custom use
Web Worker Support — Offload log processing to background thread
- Enable with
useWorker: trueoption - New
getLogsAsync()method for async log retrieval
- Enable with
Transport System — Send logs to external services
- Configurable
batchSize,flushInterval, retry with exponential backoff - Filter and transform per entry
- New
addTransport()andflushTransports()methods
- Configurable
Memory Statistics —
getStats()returns log count and buffer usageGlobal Transport —
Konsole.addGlobalTransport()static method
Changed
destroy()method is now async and returns a Promise- Log storage uses
CircularBufferinstead of a plain array
Fixed
viewLogs()no longer shows "Array(1)" — messages are correctly formatted
[1.0.0] - 2024-01-01
Added
- Initial release
- Namespaced logging with
Konsoleclass - Log levels:
log,error,warn,info - In-memory log storage with automatic cleanup
- Conditional logging with boolean and function criteria
viewLogs()for batch viewing of stored logsgetLogs()for programmatic accessclearLogs()to remove all stored logsKonsole.getLogger(),exposeToWindow(),enableGlobalPrint()- Configurable retention period and cleanup interval
- Full TypeScript support with exported types
- Zero dependencies
Security
- Window exposure is opt-in and can be conditionally enabled