loggily 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +67 -22
  2. package/package.json +37 -21
  3. package/src/context.ts +26 -11
  4. package/src/core.ts +118 -72
  5. package/src/file-writer.ts +12 -6
  6. package/src/index.browser.ts +9 -1
  7. package/src/index.ts +9 -1
  8. package/src/tracing.ts +11 -3
  9. package/src/worker.ts +119 -132
  10. package/.github/workflows/docs.yml +0 -58
  11. package/.github/workflows/release.yml +0 -31
  12. package/.github/workflows/test.yml +0 -20
  13. package/CHANGELOG.md +0 -45
  14. package/CLAUDE.md +0 -299
  15. package/CONTRIBUTING.md +0 -58
  16. package/benchmarks/overhead.ts +0 -267
  17. package/bun.lock +0 -479
  18. package/docs/api-reference.md +0 -400
  19. package/docs/benchmarks.md +0 -106
  20. package/docs/comparison.md +0 -315
  21. package/docs/conditional-logging-research.md +0 -159
  22. package/docs/guide.md +0 -205
  23. package/docs/migration-from-debug.md +0 -310
  24. package/docs/migration-from-pino.md +0 -178
  25. package/docs/migration-from-winston.md +0 -179
  26. package/docs/site/.vitepress/config.ts +0 -67
  27. package/docs/site/api/configuration.md +0 -94
  28. package/docs/site/api/index.md +0 -61
  29. package/docs/site/api/logger.md +0 -99
  30. package/docs/site/api/worker.md +0 -120
  31. package/docs/site/api/writers.md +0 -69
  32. package/docs/site/guide/getting-started.md +0 -143
  33. package/docs/site/guide/journey.md +0 -203
  34. package/docs/site/guide/migration-from-debug.md +0 -24
  35. package/docs/site/guide/spans.md +0 -139
  36. package/docs/site/guide/why.md +0 -55
  37. package/docs/site/guide/workers.md +0 -113
  38. package/docs/site/guide/zero-overhead.md +0 -87
  39. package/docs/site/index.md +0 -54
  40. package/tests/features.test.ts +0 -552
  41. package/tests/logger.test.ts +0 -944
  42. package/tests/tracing.test.ts +0 -618
  43. package/tests/universal.test.ts +0 -107
  44. package/tests/worker.test.ts +0 -590
  45. package/tsconfig.json +0 -20
  46. package/vitest.config.ts +0 -10
@@ -1,67 +0,0 @@
1
- import { defineConfig } from "vitepress"
2
-
3
- export default defineConfig({
4
- title: "loggily",
5
- description: "Clarity without the clutter. Ergonomic unified logs, spans, and debugs for modern TypeScript.",
6
- base: "/loggily/",
7
-
8
- themeConfig: {
9
- siteTitle: "loggily",
10
-
11
- nav: [
12
- { text: "Guide", link: "/guide/journey" },
13
- { text: "API", link: "/api/" },
14
- { text: "GitHub", link: "https://github.com/beorn/loggily" },
15
- ],
16
-
17
- sidebar: {
18
- "/guide/": [
19
- {
20
- text: "Introduction",
21
- items: [
22
- { text: "The Journey", link: "/guide/journey" },
23
- { text: "Getting Started", link: "/guide/getting-started" },
24
- { text: "Why loggily?", link: "/guide/why" },
25
- ],
26
- },
27
- {
28
- text: "Features",
29
- items: [
30
- { text: "Zero-Overhead Logging", link: "/guide/zero-overhead" },
31
- { text: "Spans", link: "/guide/spans" },
32
- { text: "Worker Threads", link: "/guide/workers" },
33
- ],
34
- },
35
- {
36
- text: "Migration",
37
- items: [{ text: "From debug", link: "/guide/migration-from-debug" }],
38
- },
39
- ],
40
- "/api/": [
41
- {
42
- text: "API Reference",
43
- items: [
44
- { text: "Overview", link: "/api/" },
45
- { text: "Logger", link: "/api/logger" },
46
- { text: "Configuration", link: "/api/configuration" },
47
- { text: "Writers", link: "/api/writers" },
48
- { text: "Worker Thread", link: "/api/worker" },
49
- ],
50
- },
51
- ],
52
- },
53
-
54
- socialLinks: [{ icon: "github", link: "https://github.com/beorn/loggily" }],
55
-
56
- outline: { level: [2, 3] },
57
-
58
- search: {
59
- provider: "local",
60
- },
61
-
62
- footer: {
63
- message: "Released under the MIT License.",
64
- copyright: "Copyright © 2026 Bjørn Stabell",
65
- },
66
- },
67
- })
@@ -1,94 +0,0 @@
1
- # Configuration
2
-
3
- ## Log Level
4
-
5
- ```typescript
6
- setLogLevel(level: LogLevel): void
7
- getLogLevel(): LogLevel
8
- ```
9
-
10
- Default: `"info"`. Override with `LOG_LEVEL` env var.
11
-
12
- ```typescript
13
- setLogLevel("debug") // debug, info, warn, error
14
- setLogLevel("error") // error only
15
- setLogLevel("silent") // nothing
16
- ```
17
-
18
- ## Log Format
19
-
20
- ```typescript
21
- setLogFormat(format: LogFormat): void
22
- getLogFormat(): LogFormat
23
- ```
24
-
25
- Default: `"console"`. Override with `LOG_FORMAT` env var. Also auto-enabled by `NODE_ENV=production`.
26
-
27
- ```typescript
28
- setLogFormat("json") // {"time":"...","level":"info","name":"myapp","msg":"..."}
29
- setLogFormat("console") // 14:32:15 INFO myapp message
30
- ```
31
-
32
- ## Span Control
33
-
34
- ```typescript
35
- enableSpans(): void
36
- disableSpans(): void
37
- spansAreEnabled(): boolean
38
- ```
39
-
40
- ## Trace Filter
41
-
42
- ```typescript
43
- setTraceFilter(namespaces: string[] | null): void
44
- getTraceFilter(): string[] | null
45
- ```
46
-
47
- Only emit spans matching these namespace prefixes.
48
-
49
- ```typescript
50
- setTraceFilter(["myapp:db"]) // Only db spans
51
- setTraceFilter(null) // All spans
52
- ```
53
-
54
- ## Debug Filter
55
-
56
- ```typescript
57
- setDebugFilter(namespaces: string[] | null): void
58
- getDebugFilter(): string[] | null
59
- ```
60
-
61
- Filter log output by namespace. Supports negative patterns.
62
-
63
- ```typescript
64
- setDebugFilter(["myapp"]) // Only myapp and children
65
- setDebugFilter(["myapp", "-myapp:sql"]) // Exclude sql
66
- setDebugFilter(null) // All namespaces
67
- ```
68
-
69
- Auto-lowers log level to `debug` when set.
70
-
71
- ## Output Mode
72
-
73
- ```typescript
74
- setOutputMode(mode: OutputMode): void
75
- getOutputMode(): OutputMode
76
- setSuppressConsole(value: boolean): void
77
- ```
78
-
79
- | Mode | Console | Writers |
80
- | ---------------- | ------- | ------- |
81
- | `"console"` | Yes | Yes |
82
- | `"stderr"` | stderr | Yes |
83
- | `"writers-only"` | No | Yes |
84
-
85
- ## Environment Variables
86
-
87
- | Variable | Values | Default |
88
- | -------------- | --------------------------------------- | --------- |
89
- | `LOG_LEVEL` | trace, debug, info, warn, error, silent | `info` |
90
- | `LOG_FORMAT` | console, json | `console` |
91
- | `DEBUG` | `*`, namespace prefixes, `-prefix` | (none) |
92
- | `TRACE` | `1`, `true`, namespace prefixes | (none) |
93
- | `TRACE_FORMAT` | json | (none) |
94
- | `NODE_ENV` | production | (none) |
@@ -1,61 +0,0 @@
1
- # API Reference
2
-
3
- See the [full API reference](https://github.com/beorn/loggily/blob/main/docs/api-reference.md) for complete documentation.
4
-
5
- ## Exports from `loggily`
6
-
7
- ### Core
8
-
9
- | Export | Description |
10
- | -------------------------------------------------------- | ---------------------------------------- |
11
- | `createLogger(name, props?)` | Create a conditional logger |
12
- | `setLogLevel(level)` / `getLogLevel()` | Log level control |
13
- | `setLogFormat(format)` / `getLogFormat()` | Output format (`"console"` or `"json"`) |
14
- | `enableSpans()` / `disableSpans()` / `spansAreEnabled()` | Span output control |
15
- | `setTraceFilter(ns)` / `getTraceFilter()` | Namespace-based span filtering |
16
- | `setDebugFilter(ns)` / `getDebugFilter()` | Namespace-based log filtering |
17
- | `setOutputMode(mode)` / `getOutputMode()` | Output destination |
18
- | `setSuppressConsole(bool)` | Suppress console (writers still receive) |
19
-
20
- ### Writers
21
-
22
- | Export | Description |
23
- | ------------------------------- | --------------------------------- |
24
- | `addWriter(fn)` | Subscribe to all formatted output |
25
- | `createFileWriter(path, opts?)` | Buffered file writer |
26
-
27
- ### Testing
28
-
29
- | Export | Description |
30
- | ----------------------------------------------- | ------------------------------ |
31
- | `startCollecting()` / `stopCollecting()` | Collect span data for analysis |
32
- | `getCollectedSpans()` / `clearCollectedSpans()` | Access collected spans |
33
- | `resetIds()` | Reset span/trace ID counters |
34
-
35
- ### Types
36
-
37
- | Export | Description |
38
- | ------------------- | ----------------------------------------- |
39
- | `Logger` | Full logger interface |
40
- | `SpanLogger` | Logger + Disposable + SpanData |
41
- | `ConditionalLogger` | Logger with optional methods |
42
- | `SpanData` | Span timing and attributes |
43
- | `LogLevel` | `"trace" \| "debug" \| ... \| "silent"` |
44
- | `LogFormat` | `"console" \| "json"` |
45
- | `LazyMessage` | `string \| (() => string)` |
46
- | `OutputMode` | `"console" \| "stderr" \| "writers-only"` |
47
- | `FileWriter` | `{ write, flush, close }` |
48
-
49
- ## Exports from `loggily/worker`
50
-
51
- | Export | Description |
52
- | --------------------------------------------- | --------------------------------- |
53
- | `createWorkerLogger(postMessage, ns, props?)` | Logger for worker threads |
54
- | `createWorkerLogHandler(opts?)` | Main thread handler |
55
- | `createWorkerConsoleHandler(opts?)` | Console message handler |
56
- | `forwardConsole(postMessage, ns?)` | Forward console.\* from worker |
57
- | `restoreConsole()` | Restore original console methods |
58
- | `isWorkerMessage(msg)` | Type guard for any worker message |
59
- | `isWorkerConsoleMessage(msg)` | Type guard for console messages |
60
- | `isWorkerLogMessage(msg)` | Type guard for log messages |
61
- | `isWorkerSpanMessage(msg)` | Type guard for span messages |
@@ -1,99 +0,0 @@
1
- # Logger
2
-
3
- ## createLogger
4
-
5
- ```typescript
6
- function createLogger(name: string, props?: Record<string, unknown>): ConditionalLogger
7
- ```
8
-
9
- Create a conditional logger. Disabled log levels return `undefined` -- use `?.` for zero-overhead.
10
-
11
- ```typescript
12
- const log = createLogger("myapp", { version: "2.1" })
13
- log.info?.("started")
14
- ```
15
-
16
- ## Logger Methods
17
-
18
- ### Logging
19
-
20
- All accept `LazyMessage` (string or `() => string`) and optional data:
21
-
22
- ```typescript
23
- log.trace?.("verbose", { detail: "..." })
24
- log.debug?.("debugging", { state: "..." })
25
- log.info?.("normal operation")
26
- log.warn?.("recoverable issue")
27
- log.error?.(new Error("failed"))
28
- log.error?.("manual error", { code: "ETIMEOUT" })
29
- ```
30
-
31
- ### Child Creation
32
-
33
- ```typescript
34
- // Extend namespace, inherit props
35
- const db = log.logger("db", { pool: "primary" })
36
- // namespace: "myapp:db", props: { version: "2.1", pool: "primary" }
37
-
38
- // Add context to every message (same namespace)
39
- const req = log.child({ requestId: "abc" })
40
-
41
- // Create timed span
42
- {
43
- using span = log.span("import")
44
- span.spanData.count = 42
45
- }
46
- ```
47
-
48
- ### Manual Span End
49
-
50
- ```typescript
51
- const span = log.span("op")
52
- try {
53
- /* ... */
54
- } finally {
55
- span.end()
56
- }
57
- ```
58
-
59
- ## ConditionalLogger
60
-
61
- The return type of `createLogger()`. Log methods are possibly `undefined`:
62
-
63
- ```typescript
64
- interface ConditionalLogger {
65
- readonly name: string
66
- readonly props: Readonly<Record<string, unknown>>
67
- trace?: (msg: LazyMessage, data?: Record<string, unknown>) => void
68
- debug?: (msg: LazyMessage, data?: Record<string, unknown>) => void
69
- info?: (msg: LazyMessage, data?: Record<string, unknown>) => void
70
- warn?: (msg: LazyMessage, data?: Record<string, unknown>) => void
71
- error?: (msg: LazyMessage | Error, data?: Record<string, unknown>) => void
72
- logger(ns?: string, props?: Record<string, unknown>): Logger
73
- span(ns?: string, props?: Record<string, unknown>): SpanLogger
74
- child(context: Record<string, unknown>): Logger
75
- end(): void
76
- }
77
- ```
78
-
79
- ## SpanLogger
80
-
81
- Logger + timing + Disposable:
82
-
83
- ```typescript
84
- interface SpanLogger extends Logger, Disposable {
85
- readonly spanData: SpanData & { [key: string]: unknown }
86
- }
87
- ```
88
-
89
- ### SpanData
90
-
91
- | Property | Type | Writable | Description |
92
- | ----------- | ---------------- | -------- | --------------------------- |
93
- | `id` | `string` | No | `sp_1`, `sp_2`, ... |
94
- | `traceId` | `string` | No | Shared across nested spans |
95
- | `parentId` | `string \| null` | No | Parent span ID |
96
- | `startTime` | `number` | No | Start timestamp |
97
- | `endTime` | `number \| null` | No | End timestamp |
98
- | `duration` | `number` | No | Live computed duration |
99
- | `[custom]` | `unknown` | **Yes** | `span.spanData.key = value` |
@@ -1,120 +0,0 @@
1
- # Worker Thread API
2
-
3
- Import from `loggily/worker`.
4
-
5
- ## Worker Side
6
-
7
- ### createWorkerLogger
8
-
9
- ```typescript
10
- function createWorkerLogger(
11
- postMessage: (msg: WorkerMessage) => void,
12
- namespace: string,
13
- props?: Record<string, unknown>,
14
- options?: { parentSpanId?: string; traceId?: string },
15
- ): Logger
16
- ```
17
-
18
- Create a logger that forwards all output to the main thread via `postMessage`.
19
-
20
- ```typescript
21
- const log = createWorkerLogger(postMessage, "myapp:worker")
22
- log.info?.("processing", { file: "data.csv" })
23
-
24
- {
25
- using span = log.span("parse")
26
- span.spanData.lines = 100
27
- }
28
- ```
29
-
30
- ### forwardConsole
31
-
32
- ```typescript
33
- function forwardConsole(postMessage: (msg: WorkerConsoleMessage) => void, namespace?: string): void
34
- ```
35
-
36
- Monkey-patch `console.*` to forward output via `postMessage`.
37
-
38
- ```typescript
39
- forwardConsole(postMessage, "myapp:worker")
40
- console.log("this is forwarded")
41
- ```
42
-
43
- ### restoreConsole
44
-
45
- ```typescript
46
- function restoreConsole(): void
47
- ```
48
-
49
- Restore original `console.*` methods.
50
-
51
- ## Main Thread Side
52
-
53
- ### createWorkerLogHandler
54
-
55
- ```typescript
56
- function createWorkerLogHandler(options?: { enableSpans?: boolean }): (message: WorkerMessage) => void
57
- ```
58
-
59
- Handle all worker messages (logs, spans, console). Creates loggers per namespace automatically.
60
-
61
- ```typescript
62
- const handle = createWorkerLogHandler({ enableSpans: true })
63
- worker.onmessage = (e) => handle(e.data)
64
- ```
65
-
66
- ### createWorkerConsoleHandler
67
-
68
- ```typescript
69
- function createWorkerConsoleHandler(options?: {
70
- defaultNamespace?: string
71
- logger?: Logger
72
- }): (message: WorkerConsoleMessage) => void
73
- ```
74
-
75
- Handle only console forwarding messages.
76
-
77
- ## Type Guards
78
-
79
- ```typescript
80
- isWorkerMessage(msg: unknown): msg is WorkerMessage
81
- isWorkerConsoleMessage(msg: unknown): msg is WorkerConsoleMessage
82
- isWorkerLogMessage(msg: unknown): msg is WorkerLogMessage
83
- isWorkerSpanMessage(msg: unknown): msg is WorkerSpanMessage
84
- ```
85
-
86
- ## Message Types
87
-
88
- ```typescript
89
- interface WorkerConsoleMessage {
90
- type: "console"
91
- level: "log" | "debug" | "info" | "warn" | "error" | "trace"
92
- namespace?: string
93
- args: unknown[]
94
- timestamp: number
95
- }
96
-
97
- interface WorkerLogMessage {
98
- type: "log"
99
- level: "trace" | "debug" | "info" | "warn" | "error"
100
- namespace: string
101
- message: string
102
- data?: Record<string, unknown>
103
- timestamp: number
104
- }
105
-
106
- interface WorkerSpanMessage {
107
- type: "span"
108
- event: "start" | "end"
109
- namespace: string
110
- spanId: string
111
- traceId: string
112
- parentId: string | null
113
- startTime: number
114
- endTime?: number
115
- duration?: number
116
- props: Record<string, unknown>
117
- spanData: Record<string, unknown>
118
- timestamp: number
119
- }
120
- ```
@@ -1,69 +0,0 @@
1
- # Writers
2
-
3
- ## addWriter
4
-
5
- ```typescript
6
- function addWriter(writer: (formatted: string, level: string) => void): () => void
7
- ```
8
-
9
- Subscribe to all formatted log output. Returns an unsubscribe function.
10
-
11
- ```typescript
12
- const lines: string[] = []
13
- const unsub = addWriter((formatted, level) => {
14
- lines.push(formatted)
15
- })
16
-
17
- // Later:
18
- unsub()
19
- ```
20
-
21
- Writers receive output regardless of `setOutputMode()` or `setSuppressConsole()` settings.
22
-
23
- ## createFileWriter
24
-
25
- ```typescript
26
- function createFileWriter(path: string, options?: FileWriterOptions): FileWriter
27
- ```
28
-
29
- Create a buffered file writer that flushes automatically.
30
-
31
- ### Options
32
-
33
- | Option | Type | Default | Description |
34
- | --------------- | -------- | ------- | -------------------------------------- |
35
- | `bufferSize` | `number` | 4096 | Flush when buffer exceeds this (bytes) |
36
- | `flushInterval` | `number` | 100 | Flush every N milliseconds |
37
-
38
- ### FileWriter Methods
39
-
40
- | Method | Description |
41
- | ------------- | ------------------------------------- |
42
- | `write(line)` | Append line to buffer (adds `\n`) |
43
- | `flush()` | Write buffer to disk immediately |
44
- | `close()` | Flush remaining buffer and close file |
45
-
46
- ### Example
47
-
48
- ```typescript
49
- import { createFileWriter, addWriter } from "loggily"
50
-
51
- const writer = createFileWriter("/tmp/app.log", {
52
- bufferSize: 8192,
53
- flushInterval: 200,
54
- })
55
-
56
- const unsub = addWriter((formatted) => writer.write(formatted))
57
-
58
- // On shutdown:
59
- unsub()
60
- writer.close()
61
- ```
62
-
63
- ### Safety
64
-
65
- - The flush interval timer is `unref()`'d so it won't keep the process alive
66
- - A `process.on("exit")` handler flushes remaining buffer on shutdown
67
- - `close()` removes the exit handler and clears the interval
68
- - Multiple `close()` calls are safe (idempotent)
69
- - `write()` after `close()` is silently ignored
@@ -1,143 +0,0 @@
1
- # Getting Started
2
-
3
- ## Installation
4
-
5
- ```bash
6
- bun add loggily # or: npm install loggily
7
- ```
8
-
9
- ## Create a Logger
10
-
11
- ```typescript
12
- import { createLogger } from "loggily"
13
-
14
- const log = createLogger("myapp")
15
- ```
16
-
17
- The string argument is the **namespace** -- it appears in every log message and is used for filtering.
18
-
19
- ## Log Messages
20
-
21
- Every log method accepts a message string and optional structured data:
22
-
23
- ```typescript
24
- log.info?.("server started", { port: 3000 })
25
- log.debug?.("cache hit", { key: "user:42", ttl: 300 })
26
- log.warn?.("rate limited", { remaining: 0, resetIn: 60 })
27
- log.error?.(new Error("connection lost"))
28
- ```
29
-
30
- Notice the `?.` -- this is intentional. When a log level is disabled, the method returns `undefined`, and optional chaining skips the entire call including argument evaluation. This is the core performance feature of loggily.
31
-
32
- ## Log Levels
33
-
34
- From most to least verbose:
35
-
36
- | Level | Purpose | Default |
37
- | -------- | --------------------- | ------- |
38
- | `trace` | Hot path debugging | Off |
39
- | `debug` | Development debugging | Off |
40
- | `info` | Normal operation | **On** |
41
- | `warn` | Recoverable issues | On |
42
- | `error` | Failures | On |
43
- | `silent` | Disable all output | -- |
44
-
45
- Control via environment variable or programmatically:
46
-
47
- ```bash
48
- LOG_LEVEL=debug bun run app # Enable debug and above
49
- LOG_LEVEL=error bun run app # Only errors
50
- ```
51
-
52
- ```typescript
53
- import { setLogLevel } from "loggily"
54
- setLogLevel("debug")
55
- ```
56
-
57
- ## Child Loggers
58
-
59
- Build a namespace hierarchy with `.logger()`:
60
-
61
- ```typescript
62
- const log = createLogger("myapp")
63
- const db = log.logger("db") // namespace: "myapp:db"
64
- const cache = log.logger("cache") // namespace: "myapp:cache"
65
-
66
- db.info?.("connected", { host: "localhost" })
67
- // 14:32:15 INFO myapp:db connected {host: "localhost"}
68
- ```
69
-
70
- Props are inherited by children:
71
-
72
- ```typescript
73
- const log = createLogger("myapp", { version: "2.1" })
74
- const db = log.logger("db")
75
- // db.props includes { version: "2.1" }
76
- ```
77
-
78
- ## Context Loggers
79
-
80
- Add structured context that appears in every message:
81
-
82
- ```typescript
83
- const reqLog = log.child({ requestId: "abc-123" })
84
- reqLog.info?.("handling request")
85
- // 14:32:15 INFO myapp handling request {requestId: "abc-123"}
86
- ```
87
-
88
- ## Spans
89
-
90
- Time any operation with `using`:
91
-
92
- ```typescript
93
- {
94
- using span = log.span("import", { file: "data.csv" })
95
- span.info?.("parsing")
96
- const rows = await importFile()
97
- span.spanData.rowCount = rows.length
98
- }
99
- // SPAN myapp:import (1234ms) {rowCount: 500, file: "data.csv"}
100
- ```
101
-
102
- Spans are disabled by default. Enable with:
103
-
104
- ```bash
105
- TRACE=1 bun run app # All spans
106
- TRACE=myapp:import bun run app # Specific namespace
107
- ```
108
-
109
- See [Spans](/guide/spans) for the full guide.
110
-
111
- ## Namespace Filtering
112
-
113
- Filter output by namespace, just like the `debug` package:
114
-
115
- ```bash
116
- DEBUG=myapp bun run app # Only myapp and children
117
- DEBUG='myapp,-myapp:noisy' bun run app # Exclude noisy sub-namespace
118
- DEBUG='*' bun run app # Everything
119
- ```
120
-
121
- ## Output Format
122
-
123
- Pretty console in development, JSON in production:
124
-
125
- ```bash
126
- # Development (default)
127
- bun run app
128
- # 14:32:15 INFO myapp server started {port: 3000}
129
-
130
- # Production (automatic)
131
- NODE_ENV=production bun run app
132
- # {"time":"2026-01-15T14:32:15.123Z","level":"info","name":"myapp","msg":"server started","port":3000}
133
-
134
- # Explicit
135
- LOG_FORMAT=json bun run app
136
- ```
137
-
138
- ## Next Steps
139
-
140
- - [Zero-Overhead Logging](/guide/zero-overhead) -- How optional chaining works and benchmarks
141
- - [Spans](/guide/spans) -- Timing, nesting, trace IDs
142
- - [Worker Threads](/guide/workers) -- Forward logs from workers
143
- - [API Reference](/api/) -- Complete API documentation