Releases: fullstack-build/tslog
Release list
v5.1.0
Added
- Named sub-loggers on
tslog/lite—LiteLoggergainsname/nameSeparatoroptions andgetSubLogger()/child(). The label is partially applied withFunction.prototype.bind, so a sub-logger's level methods are still the bound nativeconsole.*functions and the devtools file:line badge keeps pointing at the caller. Every%in a label is escaped so a (possibly runtime-derived) name can never act as a console format specifier and consume a logged value. Sub-loggers nest to any depth, join names with the parent'snameSeparator(default":"), and inheritminLeveland the sink unless overridden; an unresolvableminLeveloverride inherits the parent's level, matching the fullLogger. Known trade-off (documented): on a named lite logger the label occupies the console's format-string slot, so printf-style specifiers in messages print literally. - Bundle-size budget for
tslog/lite—check-bundle-sizenow probes the lite subpath (~0.8 KB gzip measured, 1 KB budget).
v5.0.2
- Readable default styling on light devtools themes — the default pretty styles color timestamps, log positions, and logger names
white, which the browser CSS path rendered as a near-white hex: invisible on light consoles (the Safari/Chrome default theme). Foregroundwhite/whiteBrightnow contribute nocolor:declaration, so that text keeps the console's own default color and is readable in both light and dark themes. Terminal ANSI output is unchanged; background tokens keep their palette hex.
v5.0.1
A patch release that makes source-mapped error positions work out of the box with modern bundler output (Turbopack/Next.js dev, Rollup, Webpack) — verified end-to-end against live Next.js 16 (next dev --turbopack) and TanStack Start (Vite) dev servers — and fixes the default browser console output (error styling, stack parsing, log positions), verified in real Chromium, Firefox, and WebKit. No API or settings changes.
v5.0.0
[5.0.0] - 2026-07-14
A ground-up rewrite. tslog is now ESM-only, zero-dependency, Node >=20, and built with TypeScript 7 / ES2022. Settings are grouped, JSON output is fields-first, and the logger gains a middleware pipeline, async transports, JSONPath masking, OpenTelemetry/pino/GenAI presets, ready-made file/http/ringbuffer/worker transports, and tree-shakeable subpath modules. v5 also adds first-class support for agents and LLMs — fields-first calls, agent/session correlation, and OTel-GenAI attributes; OpenClaw uses tslog for its agent logging. This is a breaking release — see MIGRATION_v4_to_v5.md for the upgrade path.
Added
- Grouped settings — related options now live under
pretty,json,mask,stack, andmetagroups instead of a flat list ofprettyLog*/maskValues*keys. Sub-loggers merge groups rather than overwrite them. - Fields-first JSON output — every level method is overloaded pino-style:
info(fields, message?, ...args)as well asinfo(message, ...args). A single object spreads its fields to the top level, a leading object plus string spreads fields and setsmessage, and positional args land undermessage/"1"/… Runtime metadata moves under_logMetacarrying av: 5schema marker. All JSON keys are configurable via thejsongroup. - Middleware pipeline —
logger.use(middleware)runs functions over each log context to mutatelogObj/metaor drop the log entirely (returnnull/false). - Async transports with
attachTransport()returning a detach function,logger.flush(), andSymbol.asyncDispose/Symbol.disposesupport (await using). Each transport may declare its ownminLevelandformat("pretty","json", or a custom formatter). - Advanced masking —
mask.paths(JSONPath-ish patterns such asuser.passwordor*.token),mask.regex, and amask.censorof"remove","hash", a string, or a function (withmask.hashLabel). - Presets —
tslog/presets/pino(pinoFormat,pinoTransport,toPinoLevel),tslog/otel(otelFormat,toOtelRecord,levelToSeverityNumber,OtelSeverityNumber,otelTraceContext,stringifyOtelRecord), andtslog/presets/genai(genai,genaiAttributes,genaiSummaryemitting OTelgen_ai.*fields). - Built-in transports —
tslog/transports/file(fileTransport, non-blocking, flush/dispose),tslog/transports/http(httpTransport, batched),tslog/transports/ringbuffer(ringBufferTransportwith.dump()/.clear()), andtslog/transports/worker(workerTransport, Node-only off-thread sink I/O). - Standard serializers —
tslog/serializersexportsstdSerializers(err,req,res,user), the individual serializers, and aserialize(map)middleware helper. - Context propagation —
runInContext(ctx, fn)uses AsyncLocalStorage to attach context fields to_logMetawhenmeta.attachContextis enabled. Auto-resolves on Node/Deno/Bun; on Cloudflare Workers inject one via thecontextStoragesetting (graceful no-op in browsers, with a one-time development warning). - Custom levels via the
customLevelssetting andlog(levelId, levelName, ...args). - New API surface —
child()(alias ofgetSubLogger()),isLevelEnabled(),getContext(),addLevel(),logger.if(condition),Logger.fromEnv(),defineConfig(), andTslogConfigError(thrown whenstrictConfigis on). - Subpath modules (all tree-shakeable) —
tslog/lite(minimal console wrappers preserving native line numbers),tslog/cli(also thetslogbin, an NDJSON pretty-printer for stdin),tslog/testing(createTestLogger,mockLogger),tslog/throttle(rate-limit middleware),tslog/pretty/box(box,tree), andtslog/console(wrapConsole,restoreConsole,isConsoleWrapped). - Env-aware colorization — when
typeis omitted, output isprettyeverywhere (server, CI, browser, React Native); only the coloring adapts to the environment: colored on an interactive TTY (CSS in the browser) and uncolored when stdout is piped/redirected/CI, so no ANSI escapes leak into files or log collectors. Structured JSON is opt-in viatype: "json",TSLOG_TYPE=json, or a JSON transport.NO_COLORstrips colors without switching the format;FORCE_COLORforces styled pretty. Applies to bothnew Logger()and the ready-madelog. - React Native support — detected via
navigator.product(_logMeta.runtime: "react-native", Hermes engine version when available), Hermes/JSC stack frames parsed with a hybrid parser, pretty output by default. - Real hostname in server JSON logs —
_logMeta.hostnameresolves fromHOSTNAME/HOST/COMPUTERNAME, then the OS hostname (Deno.hostname()/node:osviaprocess.getBuiltinModule), instead of defaulting to"unknown". - Tree-shakeable exports —
sideEffects: false(audited) with per-runtime conditional exports. tslog/slim— the smallest structured-JSON build (~9KB gzip vs ~19KB for the full browser entry, budget-checked in CI): the same pipeline minus masking, pretty output, and stack capture;masksettings andtype: "pretty"throw instead of silently degrading.- Buffered stdout sink (Node) — the Node entry writes
type: "json"lines through a batchedprocess.stdout.write(one write per event-loop turn, early flush past ~8KB) instead of per-lineconsole.log; drained bylogger.flush(),await using, and guardedbeforeExit/exithooks (a bareprocess.exit()loses nothing). Browser/universal entries keepconsole.log. - Time seam — an injectable top-level
clock: () => Date(deterministic tests, offset/monotonic stamping; inherited by sub-loggers, hostile clocks ignored) andjson.time: "iso" | "epoch" | false | fncontrolling the top-level timestamp representation (_logMeta.datestays UTC ISO). - Deterministic test output —
createTestLogger(settings, { now, normalize }):nowfreezes only that logger's clock (no fake-timer sledgehammer),normalize: trueyields snapshot-stable records/lines; plus a standalonenormalizeMeta(recordOrLine)scrubber (all intslog/testing). - Real OTLP/JSON in
tslog/otel—otlpFormat/toOtlpJson/toOtlpLogRecord/toOtlpAnyValue/stringifyOtlpRequestemit the collector wire format (camelCase proto3 fields, typed attributes,resourceLogs[].scopeLogs[].logRecords[]envelope,exception.*semconv mapping for logged errors), andotlpBatchBodypairs with the http transport's newencodeBodyoption to POST merged batches straight to/v1/logs. httpTransport({ encodeBody })— custom body encoder for endpoints whose payload is neither NDJSON nor a JSON array (used by the OTLP pairing above).- Conditional logging —
logger.if(condition)returns the logger when the condition is truthy and a no-op stand-in when falsy, so a per-call guard reads as a fluent chain (log.if(!ok).warn("failed", { id })). UseisLevelEnabled()to skip expensive payload construction. - Browser-native pretty objects —
pretty.passObjectsNativelyhands non-Errorarguments to the console by reference (on by default in real browsers), so DevTools renders collapsible, interactive trees; pair withpretty.levelMethodfor native warn/error stack groups. Setfalsefor log-time snapshots or text-matchable console output. - Source-mapped error positions — on Node, Bun, and Deno, logged
Errorstack frames resolve through discoverable source maps back to original.tsfile/line/column (automatic outside production; override withTSLOG_SOURCE_MAPS=on/off).
Changed
- ESM-only and Node >=20; the project now targets TypeScript 7 / ES2022.
- JSON output on Node no longer goes through
console.log(see the buffered stdout sink above) — code interceptingconsole.logmust spy onprocess.stdout.writeor usetype: "hidden"plus a transport. tslog/otelresource precedence — intoOtelRecord,resourceattributes now win over colliding per-record fields (resource identity semantics); in the OTLP shape they live in the envelope, separate from record attributes.- The default JSON shape is fields-first with
_logMeta.v: 5;name/parentNamesappear only when set (no"[undefined]"noise). - Masking is off by default —
mask.keysstarts empty; enable it explicitly.
Removed
- The CommonJS build and
require("tslog")— the package is ESM-only. - The
overwrite.*hooks (mask,toLogObj,addMeta,formatMeta,formatLogObj,transportFormatted,transportJSON,addPlaceholders) — use middleware and per-transportformatinstead. - Flat settings keys —
prettyLogTemplate/prettyError*/prettyLog*,stylePrettyLogs,maskValuesOfKeys/maskValuesRegEx/maskPlaceholder,metaProperty, andstackDepthLevel(now thecallerFrameconstructor parameter). hideLogPositionForProduction— superseded by thestackgroup and env-aware defaults.- The
loggerEnvironment/createLoggerEnvironmentsingleton — each entry point exports its own environment factory (createNodeEnvironment,createBrowserEnvironment,createUniversalEnvironment/selectEnvironment). - The nested
{"0": message}JSON shape.
v5 RC
- fix(tests): switch worker.runner until() to time-based 10s timeout for CI stability 51cc454
- ci: expand Node test matrix to 20/22/24/26/latest; bump harnesses to 22 e367fb9
- Merge branch 'development' into v5 24a9988
- fix(tests): clear NO_COLOR in vitest setup and explicitly enable pretty.style for CSS tests bc17e21
- fix(tests): restore CI on Node 20 for lifecycle and worker.runner suites fd1ccc3
- Document v5 late features across CHANGELOG, migration guide, and release notes f761374
- Update README and release notes for v5.0.0: add TypeScript types and enhance logging features e45130b
- Enable pretty.passObjectsNatively by default in browsers fbf4af3
- Fix doc inaccuracies found by the pre-release audit e6a7f99
- Fix the Deno test runner so its tests actually run e71bcd9
- Add logger.if() conditional logging gate ebcaf3c
- Add pretty.passObjectsNatively to pass raw objects to the console 8234681
- Bump docs deps: astro 7, starlight 0.41, vite 8 6e262a5
- Keep fullFilePath absolute after a source-map remap d496454
- Improve source-map resolution: binary search, fullFilePath consistency, per-call enablement a2304ec
- Resolve error stack positions through source maps on Node, Bun, and Deno 1c10154
- Remove global Window.chrome type declaration cd077d0
- Redesign the docs site with a dark theme e39c30d
- Reflow README and migration guide for narrower content columns 8323373
- Remove the stale examples/ tree fac0648
- Rename _meta to _logMeta 352d03f
- Fix browser stack parser for Windows Vite /@fs/ drive-letter paths 3ac1900
- Default to pretty output everywhere and make JSON opt-in 49e9588
- Publish the v4-to-v5 migration guide as a docs site page 5b88479
- Highlight first-class agent and LLM support and OpenClaw usage ac89125
- Set 4.11.0 changelog release date 1b0ebf6
- Fix stale doc claims and expand llms.txt API coverage b244db9
- Report a structured droppedCount on http transport buffer drops 52163ba
- Fix doubled host in browser stack fullFilePath ef25020
- Extract the shared provider implementation into env/providerBase a3eaf14
- Trim padding tests, convert testable coverage ignores into real tests, and drop dead branches 8cacdfb
- Fix polyfill %i/%f parsing, flushSync double-write, and inert coverage tests 7c6ebb4
- Cover Sentry Logs in the Sentry integration docs 0003b76
- Add migration guides and Sentry/Better Stack integration docs c8c1da1
- Reach 100% test coverage across the source tree d19d43b
- Fix worker transport dispose after a failed spawn 02558e4
- Wire the Node environment provider onto core/meta.ts af3c293
- Remove dead v4 modules and reconcile coverage config 5159f5c
- Document the buffered sink, time seam, and preset output changes 2c2cdc8
- Isolate the transport format step and default hidden transports to JSON 844462a
- Serialize errors in pino's wire shape in the pino preset 501f3ed
- Emit real OTLP/JSON from the otel preset 6dfa49c
- Add an injectable clock and configurable JSON time output 665fece
- Batch Node JSON output through a buffered stdout sink 744633f
- Add a build-picker guide to the README fee348a
- Enforce gzip budgets for the slim and full browser bundles d996dae
- Add tslog/slim, a structured JSON logger at half the size 1de26d9
- Inject masking, JSON rendering and validation through the entries 6039f91
- Sync the browser spec with the (string, object) spread shape 9aa649b
- Point the legacy module field at the universal entry e4f7d51
- Treat NO_COLOR as a color switch, not a format switch 97661b7
- Let apps inject AsyncLocalStorage for context propagation cdf2bd4
- Resolve the real OS hostname for server JSON logs 90f1431
- Detect React Native and parse Hermes and JSC stack frames 3391032
- Add bindings and typed custom level methods 99993e6
- Stop the worker transport from pinning or starving the process 383a422
- Bound and retry HTTP log delivery f8176bc
- Contain file-transport failures and drain on process exit c06d798
- Make flush() cover async transport writes and scope disposal 8e1801a
- Point npm run bench at the actual benchmark script 2c8cec8
- Trim per-log overhead and use native inspect in ESM 1af363e
- Precompile the JSON line and spread message-first fields 5ac53df
- Validate settings keys against the grouped shape 9e1c01c
- Document v5 and add a migration guide f6b06e3
- Rewrite the test suite for the v5 API 564be4a
- Drop the CJS build and publish ESM only 76f4538
- Add tree-shakeable subpath modules d6ab74f
- Restructure the logger into core, env and render modules 647c704
- Sync AGENTS.md version from package.json on release 5479add
- Share agent guidance and keep personal overrides local 8ec821a
- Document new 4.11.0 settings and tidy release notes 0e43385
- Pin graphql and bson dev deps to versions that support Node 20 e2916f9
- Bump codecov-action to v5 and pass upload token a68a229
- Add regression tests for logging GraphQLError and BSON ObjectId c2b56b3
- Update changelog for 4.10.1, 4.10.2, and 4.11.0 6e953aa
- Add AI/agentic docs and ship them with the package 2ea3598
- Add runtime features: unified stack detection, named log levels, config validation fd6a0e4
- Fix bigint, invalid date, local timezone, worker styling and meta types 4733bdd
- Rename CI build job to test-node and bump actions to Node 24 f0e3b76
- Run browser tests as a per-engine CI matrix and gate development PRs 4ced09d
- Run browser tests on Firefox and WebKit and port core suites to the browser 725dfdd
- Optionally pass default meta to custom addMeta handler c373203
- Expose DefaultLogLevels enum for default log levels e899630
- Merge PR #330: add prettyLogLevelMethod for routing log levels 32a9a0a
- Merge PR #310: add missing fileNameWithLine style and dedup type 4c3b66a
- Add regression tests for inspect option handling 77eb8ad
- Merge PR #331: make _extend mutate the context in place 9f267c2
- Merge PR #335: fix cannot convert object to primitive value 619d6d7
- Harden transport and masking, reach full test coverage 643844b
- fix cannot convert object to primitive value 1457c86
- Refine docs styling and page title 20c00cd
- Replace docsify with Starlight for docs site 2b49f8f
- Replace eslint and prettier with biome b5369aa
- update dependencies and fix vulnerabilities f8940e6
- merge remote master 5ecd602
- Fix stale references and typos in readme b9dadb7
- fix deno regex masking test bypassing mask pipeline f98c1ea
- Run CI on development branch 9f30c84
- Add cross-runtime test suite for node, browser, deno, bun, and workers 3e49aea
- replace simple-git-hooks with husky v9 24f755a
- Replace Jest and Puppeteer with Vitest and Playwright f0a3d17
- fix: make _extend method use shallow copy 31b518e
- prettyLogLevelMethod bba5ad3
- 4.10.0 (#320) (#321) 6b98e17
- Add CI-specific launch arguments for Puppeteer cc6cc05
- Add missing fileNameWithLine 9aab33b
v4.11.0
- Set 4.11.0 changelog release date 1b0ebf6
- Sync AGENTS.md version from package.json on release 5479add
- Share agent guidance and keep personal overrides local 8ec821a
- Document new 4.11.0 settings and tidy release notes 0e43385
- Pin graphql and bson dev deps to versions that support Node 20 e2916f9
- Bump codecov-action to v5 and pass upload token a68a229
- Add regression tests for logging GraphQLError and BSON ObjectId c2b56b3
- Update changelog for 4.10.1, 4.10.2, and 4.11.0 6e953aa
- Add AI/agentic docs and ship them with the package 2ea3598
- Add runtime features: unified stack detection, named log levels, config validation fd6a0e4
- Fix bigint, invalid date, local timezone, worker styling and meta types 4733bdd
- Rename CI build job to test-node and bump actions to Node 24 f0e3b76
- Run browser tests as a per-engine CI matrix and gate development PRs 4ced09d
- Run browser tests on Firefox and WebKit and port core suites to the browser 725dfdd
- Optionally pass default meta to custom addMeta handler c373203
- Expose DefaultLogLevels enum for default log levels e899630
- Merge PR #330: add prettyLogLevelMethod for routing log levels 32a9a0a
- Merge PR #310: add missing fileNameWithLine style and dedup type 4c3b66a
- Add regression tests for inspect option handling 77eb8ad
- Merge PR #331: make _extend mutate the context in place 9f267c2
- Merge PR #335: fix cannot convert object to primitive value 619d6d7
- Harden transport and masking, reach full test coverage 643844b
- fix cannot convert object to primitive value 1457c86
- Refine docs styling and page title 20c00cd
- Replace docsify with Starlight for docs site 2b49f8f
- Replace eslint and prettier with biome b5369aa
- update dependencies and fix vulnerabilities f8940e6
- merge remote master 5ecd602
- Fix stale references and typos in readme b9dadb7
- fix deno regex masking test bypassing mask pipeline f98c1ea
- Run CI on development branch 9f30c84
- Add cross-runtime test suite for node, browser, deno, bun, and workers 3e49aea
- replace simple-git-hooks with husky v9 24f755a
- Replace Jest and Puppeteer with Vitest and Playwright f0a3d17
- fix: make _extend method use shallow copy 31b518e
- prettyLogLevelMethod bba5ad3
- 4.10.0 (#320) (#321) 6b98e17
- Add CI-specific launch arguments for Puppeteer cc6cc05
- Add missing fileNameWithLine 9aab33b
v4.10.2
v4.10.0
Changelog
[4.10.0] - 2025-09-25
Breaking
- Custom
transportFormattedoverrides now receivelogMetaas the fourth argument; pass five parameters to also receivesettings, otherwise adjust implementations that previously readsettingsfrom the fourth position. - Deprecated runtime entry points under
src/runtime/**and related browser mappings have been removed; use the primaryLoggerexport instead of importing runtime-specific helpers. - Logger metadata now exposes lowercase runtime identifiers (for example
node,browser,deno,bun,worker) and normalized versions without the leadingv; adjust consumers that compared againstNodejsor relied on the old format.
Added
- Introduced universal runtime detection that recognises Node.js, browsers, web workers, Deno, and Bun, enriching metadata with runtime versions and hostnames when available.
- Documented first-class Deno and Bun usage, refreshed examples under
examples/server, and aligned development scripts (npm run dev-ts*). - Pretty transports now detect when the browser console supports CSS, rendering styled output with
%ctokens and gracefully falling back when styling is unavailable. - Error formatting captures chained
Error.causeentries (up to depth five) and includes them in both pretty error blocks and JSON error objects.
Changed
- The core logger automatically locates the first user stack frame instead of relying on hard-coded depths, producing stable file and line metadata across bundlers; manual
stackDepthLeveloverrides continue to work. - Placeholder formatting now routes through a shared
buildPrettyMetautility, improving consistency for custom templates and nested style tokens. - Masking internals normalise and cache case-insensitive keys, reducing repeated allocations and keeping behaviour consistent when toggling mask options.
- Browser styling defaults keep ANSI colouring enabled unless explicitly disabled, letting CSS-capable consoles honour
stylePrettyLogswithout runtime-specific tweaks.
Fixed
- Runtime error detection now treats objects with an
Error-suffixed name as errors, ensuring they are formatted via the error transport. - Browser stack parsing guards against malformed frames, avoiding crashes when devtools emit unexpected stack entries.
- Logging no longer fails when
process.cwd()throws (for example under restricted permissions); environment helpers fall back to cached working directories and hostname detection across Node, Deno, and Bun.