logquill 0.4.0 → 1.0.0

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.
package/dist/index.d.cts CHANGED
@@ -1,17 +1,149 @@
1
- import { P as Plugin, L as LogRecord, a as Level, T as Transport, b as LevelInput, F as Formatter } from './logger-D1_THnBJ.cjs';
2
- export { C as CollectingTransport, c as FunctionPlugin, J as JSONFormatter, d as Logger, e as LoggerOptions, M as MiddlewareFunc, S as SpanOptions, f as createRecord, l as levelName, p as parseLevel, u as utcTimestamp } from './logger-D1_THnBJ.cjs';
1
+ import { P as Plugin, L as LogRecord, a as Level, b as Logger, T as Transport, c as LevelInput, F as Formatter } from './logger-CRdmCDfC.cjs';
2
+ export { B as BackpressurePolicy, C as CollectingTransport, D as DispatchQueue, d as DispatchQueueOptions, e as FlushableTransport, f as FunctionPlugin, J as JSONFormatter, g as LoggerOptions, M as MiddlewareFunc, S as SpanOptions, h as Task, i as createRecord, j as hasFlush, l as levelName, p as parseLevel, u as utcTimestamp } from './logger-CRdmCDfC.cjs';
3
3
 
4
4
  /**
5
5
  * Injects fixed key/value pairs into every record's `meta`.
6
6
  * A value already present in a record's own `meta` wins over the fixed context.
7
7
  */
8
8
  declare class ContextPlugin implements Plugin {
9
+ /** Fixed key/value pairs merged into every record's `meta`. */
9
10
  readonly context: Record<string, unknown>;
10
11
  constructor(context: Record<string, unknown>);
11
12
  beforeLog(record: LogRecord): LogRecord;
12
13
  }
13
14
 
15
+ /**
16
+ * The merged key/value pairs bound by every `bindContext()` block currently
17
+ * active in this execution context, or `{}` outside any block. Backed by
18
+ * `AsyncLocalStorage` (not a plain module variable) so concurrent async
19
+ * operations sharing one `Logger` don't see each other's bound context —
20
+ * the Node equivalent of Python's `contextvars`-based `current_context()`.
21
+ */
22
+ declare function currentContext(): Record<string, unknown>;
23
+ /**
24
+ * Runs `fn` with `values` merged into the request-scoped context for the
25
+ * rest of its execution — every `Logger` call underneath it, through any
26
+ * number of function calls and `await`s deep, picks them up in `meta`
27
+ * automatically, without threading them through every signature by hand:
28
+ *
29
+ * ```ts
30
+ * await bindContext({ requestId: "abc123" }, async () => {
31
+ * await handleRequest(); // any logging in here, or in what it calls,
32
+ * // gets meta.requestId = "abc123" for free
33
+ * });
34
+ * ```
35
+ *
36
+ * Calls nest by merging: an inner `bindContext`'s value wins over an outer
37
+ * one on key collision, the same way an explicit call-site `meta` value
38
+ * always wins over anything bound here. `fn`'s return value (including a
39
+ * `Promise`, whose continuations stay inside the bound context across any
40
+ * `await`) is returned unchanged.
41
+ */
42
+ declare function bindContext<T>(values: Record<string, unknown>, fn: () => T): T;
43
+
44
+ /** Derives the key a record is rate-limited under. Any hashable value works — it's used as a `Map` key. */
45
+ type RateLimitKeyFunc = (record: LogRecord) => unknown;
46
+ /** Options for {@link RateLimitPlugin}. */
47
+ interface RateLimitPluginOptions {
48
+ /** Groups records into independent windows. Default: `(logger, level)`. */
49
+ keyFunc?: RateLimitKeyFunc;
50
+ /** Distinct keys tracked at once before the least-recently-seen one is evicted. Default 1000. */
51
+ maxKeys?: number;
52
+ /** Injectable clock (seconds), for deterministic window-rollover tests. Defaults to `performance.now() / 1000` — monotonic, so a wall-clock adjustment can't shrink or extend a window. */
53
+ clock?: () => number;
54
+ }
55
+ /**
56
+ * Drops records once a key — by default `(logger, level)` — exceeds
57
+ * `maxRecords` within a rolling `perSeconds` window, capping a noisy loop
58
+ * (a retry that logs the same error every iteration, a hot path that logs
59
+ * once per request) without silencing the logger's other messages.
60
+ *
61
+ * Each key gets its own fixed window: the count for a key resets
62
+ * `perSeconds` after that *key's own* first record in the current window,
63
+ * not a shared global clock, so unrelated keys never reset in lockstep.
64
+ *
65
+ * Pass `keyFunc` to rate-limit on something other than `(logger, level)` —
66
+ * e.g. per error message, or per a `meta` field identifying the caller.
67
+ *
68
+ * Bounded by `maxKeys` distinct keys tracked at once; past that, the
69
+ * least-recently-seen key's window is evicted to make room for a new one —
70
+ * the same bounded-memory trade-off `SamplingPlugin` makes for trace
71
+ * buffering, since an unbounded key space (e.g. rate-limiting per user id)
72
+ * would otherwise grow memory without limit.
73
+ */
74
+ declare class RateLimitPlugin implements Plugin {
75
+ /** Records allowed per key within a `perSeconds` window before further records for that key are dropped. */
76
+ readonly maxRecords: number;
77
+ /** Length, in seconds, of each key's rolling window. */
78
+ readonly perSeconds: number;
79
+ /** Distinct keys tracked at once before the least-recently-seen one is evicted. */
80
+ readonly maxKeys: number;
81
+ private readonly keyFunc;
82
+ private readonly clock;
83
+ private readonly windows;
84
+ constructor(maxRecords: number, perSeconds: number, options?: RateLimitPluginOptions);
85
+ beforeLog(record: LogRecord): LogRecord | null;
86
+ private evictOldest;
87
+ }
88
+
89
+ /** Maps a pino numeric level to a LogQuill level. */
90
+ type PinoLevelMap = Readonly<Record<number, Level>>;
91
+ /** pino's default numeric levels (`trace`=10 … `fatal`=60), mapped onto the matching LogQuill level. */
92
+ declare const DEFAULT_PINO_LEVEL_MAP: PinoLevelMap;
93
+ /** Options for {@link LogQuillPinoDestination}. */
94
+ interface LogQuillPinoDestinationOptions {
95
+ /** Overrides `DEFAULT_PINO_LEVEL_MAP` — useful for a pino instance configured with custom levels. An unmapped level falls back to `INFO`. */
96
+ levelMap?: PinoLevelMap;
97
+ }
98
+ /**
99
+ * A pino `destination` — pass an instance directly as `pino(destination)`
100
+ * to have pino's own NDJSON output parsed back into LogQuill calls, so an
101
+ * existing `pino()` call site keeps working exactly as it does today while
102
+ * its records also flow through every LogQuill `Transport`/`Plugin`
103
+ * attached to the given `Logger` — handy for migrating incrementally
104
+ * rather than in one PR.
105
+ *
106
+ * ```ts
107
+ * import pino from "pino";
108
+ * import { Logger, LogQuillPinoDestination } from "logquill";
109
+ *
110
+ * const logquill = new Logger("app");
111
+ * const log = pino(new LogQuillPinoDestination(logquill));
112
+ *
113
+ * log.info({ userId: 42 }, "still works exactly as before");
114
+ * ```
115
+ *
116
+ * No `pino` import needed here — a destination only has to be duck-type
117
+ * compatible with a Node `Writable`'s `.write(chunk)`, so unlike the
118
+ * `winston-transport`-based bridge, this needs no dependency on `pino`
119
+ * itself and ships from the main entry point.
120
+ *
121
+ * pino batches writes over a fast, buffered stream, so a single `write()`
122
+ * call can carry more than one NDJSON line; each complete line is parsed
123
+ * and dispatched independently, and a line that fails to parse as JSON is
124
+ * skipped rather than crashing the destination.
125
+ */
126
+ declare class LogQuillPinoDestination {
127
+ /**
128
+ * Pino only recognizes a bare object passed as its sole argument
129
+ * (`pino(destination)`, without a separate options argument) as a
130
+ * destination stream, rather than an options object, if it looks
131
+ * stream-like — checking for `.writable`/`._writableState`, the same
132
+ * duck-typing `stream.Writable` itself satisfies. Without this, `pino()`
133
+ * would silently fall back to writing to `process.stdout` instead.
134
+ */
135
+ readonly writable = true;
136
+ private readonly target;
137
+ private readonly levelMap;
138
+ constructor(logquillLogger: Logger, options?: LogQuillPinoDestinationOptions);
139
+ /** Node `Writable`-compatible write hook — splits `chunk` into NDJSON lines and dispatches each as a `Logger` call. */
140
+ write(chunk: string): boolean;
141
+ private writeLine;
142
+ }
143
+
144
+ /** Options for {@link RunPlugin}. */
14
145
  interface RunPluginOptions {
146
+ /** Adopt an id handed in from elsewhere (e.g. an upstream call) instead of generating a fresh `randomUUID()`. */
15
147
  runId?: string;
16
148
  }
17
149
  /**
@@ -34,6 +166,7 @@ interface RunPluginOptions {
34
166
  * this instance's own counter.
35
167
  */
36
168
  declare class RunPlugin implements Plugin {
169
+ /** Id stamped onto `meta.runId` for every record this instance processes. */
37
170
  readonly runId: string;
38
171
  private step;
39
172
  constructor(options?: RunPluginOptions);
@@ -71,6 +204,7 @@ declare function parseTraceHeader(header: string): string | undefined;
71
204
  * deliberate: `Plugin.beforeLog` is synchronous, so this has to be too.
72
205
  */
73
206
  declare function defaultResolveActiveOtelTraceId(): string | undefined;
207
+ /** Options for {@link TraceContextPlugin}. */
74
208
  interface TraceContextPluginOptions {
75
209
  /** `meta` key the trace id is written to. Default `"traceId"`. */
76
210
  traceKey?: string;
@@ -102,6 +236,7 @@ interface TraceContextPluginOptions {
102
236
  * header: falls through to generating a new trace id.
103
237
  */
104
238
  declare class TraceContextPlugin implements Plugin {
239
+ /** `meta` key the trace id is written to. */
105
240
  readonly traceKey: string;
106
241
  private readonly explicitTraceparent;
107
242
  private readonly resolveActiveOtelTraceId;
@@ -110,14 +245,106 @@ declare class TraceContextPlugin implements Plugin {
110
245
  private resolveTraceId;
111
246
  }
112
247
 
248
+ /** The subset of an OTel `SpanContext` this processor reads. */
249
+ interface OtelSpanContextLike {
250
+ /** 16-hex-char span id. */
251
+ spanId: string;
252
+ }
253
+ /** The subset of an OTel `SpanStatus` this processor reads. */
254
+ interface OtelStatusLike {
255
+ /** Numeric status code — compared against OTel's `SpanStatusCode.ERROR` (`2`). */
256
+ code: number;
257
+ /** Present when the span ended with an error status; used as the `.error()` message. */
258
+ message?: string;
259
+ }
260
+ /**
261
+ * The subset of an OTel `Span`/`ReadableSpan`'s shape this processor reads,
262
+ * duck-typed so this package never declares a real dependency on
263
+ * `@opentelemetry/api`/`@opentelemetry/sdk-trace-base` — the same approach
264
+ * `TraceContextPlugin` uses for its own OTel lookup. Matches what any
265
+ * standard `@opentelemetry/sdk-trace-base`-backed tracer provider actually
266
+ * passes to a registered `SpanProcessor`.
267
+ */
268
+ interface OtelSpanLike {
269
+ /** Span name — becomes the `.action()`/`.observation()`/`.error()` message. */
270
+ name: string;
271
+ /** Returns this span's own id (and trace id), matching an OTel `Span`'s `spanContext()`. */
272
+ spanContext(): OtelSpanContextLike;
273
+ /** Present on `@opentelemetry/sdk-trace-base` >=1.9's `Span`. */
274
+ parentSpanContext?: OtelSpanContextLike;
275
+ /** Pre-1.9 `@opentelemetry/sdk-trace-base` shape (superseded by `parentSpanContext`) — read as a fallback when that isn't present. */
276
+ parentSpanId?: string;
277
+ /** Span attributes, copied verbatim onto `meta[attributesKey]` when non-empty. */
278
+ attributes: Record<string, unknown>;
279
+ /** This span's OTel status — an error status routes the end record through `.error()` instead of `.observation()`. */
280
+ status: OtelStatusLike;
281
+ /** Wall-clock duration as an OTel `HrTime` tuple, only meaningful once the span has ended. */
282
+ duration: readonly [seconds: number, nanoseconds: number];
283
+ }
284
+ /** Options for {@link OtelSpanProcessor}. */
285
+ interface OtelSpanProcessorOptions {
286
+ /** `meta` key non-empty span attributes are copied onto. Default `"attributes"`. */
287
+ attributesKey?: string;
288
+ }
289
+ /**
290
+ * Bridges an OpenTelemetry-native integration — the Vercel AI SDK's
291
+ * `experimental_telemetry` is the main JS example — into LogQuill without
292
+ * forcing it through the callback-handler-object model `LangChainAdapter`
293
+ * uses. Register an instance the same way any other span processor is
294
+ * registered:
295
+ *
296
+ * ```ts
297
+ * import { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
298
+ * import { OtelSpanProcessor } from "logquill";
299
+ *
300
+ * const provider = new BasicTracerProvider();
301
+ * provider.addSpanProcessor(new OtelSpanProcessor(log.child("agent")));
302
+ * ```
303
+ *
304
+ * Every span the SDK creates becomes one `.action()` call on start and one
305
+ * `.observation()` (or `.error()`, if the span ended with an error status)
306
+ * call on end — the same two-call shape `LangChainAdapter` uses for
307
+ * `handleToolStart`/`handleToolEnd`. Both carry the span's own `spanId`/
308
+ * `parentSpanId` — OTel span ids are already the same 16-hex-char shape
309
+ * LogQuill's own `spanId` uses, so no translation is needed — and the end
310
+ * call additionally carries `meta.durationMs`. Non-empty span attributes are
311
+ * copied onto `meta[attributesKey]` verbatim, unrenamed — mapping onto the
312
+ * OTel `gen_ai.*` semantic conventions is deliberately out of scope here
313
+ * (see the v2.0 `OTLPTransport`/`gen_ai.*` plan).
314
+ *
315
+ * Never imports `@opentelemetry/api` or `@opentelemetry/sdk-trace-base` —
316
+ * duck-typed against the shape a `Span`/`ReadableSpan` actually has, so
317
+ * `import { Logger } from "logquill"` still never requires either package
318
+ * to be installed.
319
+ */
320
+ declare class OtelSpanProcessor {
321
+ private readonly log;
322
+ private readonly attributesKey;
323
+ constructor(log: Logger, options?: OtelSpanProcessorOptions);
324
+ /** Called by the tracer provider when a span starts — emits `.action()`. */
325
+ onStart(span: OtelSpanLike): void;
326
+ /** Called by the tracer provider when a span ends — emits `.observation()`, or `.error()` if the span's status is an error. */
327
+ onEnd(span: OtelSpanLike): void;
328
+ /** No internal buffering to flush — every span is forwarded to the `Logger` immediately. */
329
+ forceFlush(): Promise<void>;
330
+ /** No resources of its own to release; flush/close the wrapped `Logger` separately. */
331
+ shutdown(): Promise<void>;
332
+ private baseMeta;
333
+ }
334
+
335
+ /** `meta` keys (case-insensitive) `RedactPlugin` replaces by default. */
113
336
  declare const DEFAULT_REDACTED_KEYS: readonly string[];
337
+ /** Options for {@link RedactPlugin}. */
114
338
  interface RedactPluginOptions {
339
+ /** Keys (case-insensitive) to redact. Default `DEFAULT_REDACTED_KEYS`. */
115
340
  keys?: readonly string[];
341
+ /** Placeholder a matched value is replaced with. Default `"***"`. */
116
342
  replacement?: string;
117
343
  }
118
344
  /** Replaces sensitive `meta` values, matched by key (case-insensitive), with a placeholder. */
119
345
  declare class RedactPlugin implements Plugin {
120
346
  private readonly keys;
347
+ /** Placeholder a matched value is replaced with. */
121
348
  readonly replacement: string;
122
349
  constructor(options?: RedactPluginOptions);
123
350
  beforeLog(record: LogRecord): LogRecord;
@@ -130,8 +357,11 @@ declare class RedactPlugin implements Plugin {
130
357
  * for anything stricter.
131
358
  */
132
359
  declare const DEFAULT_PII_PATTERNS: Readonly<Record<string, RegExp>>;
360
+ /** Options for {@link PIIRedactPlugin}. */
133
361
  interface PIIRedactPluginOptions {
362
+ /** Named patterns to scan for. Default `DEFAULT_PII_PATTERNS`. */
134
363
  patterns?: Readonly<Record<string, RegExp>>;
364
+ /** Placeholder a matched substring is replaced with. Default `"***"`. */
135
365
  replacement?: string;
136
366
  }
137
367
  /**
@@ -155,7 +385,9 @@ interface PIIRedactPluginOptions {
155
385
  * throwing.
156
386
  */
157
387
  declare class PIIRedactPlugin implements Plugin {
388
+ /** Named patterns scanned for in every string `meta` value. */
158
389
  readonly patterns: Readonly<Record<string, RegExp>>;
390
+ /** Placeholder a matched substring is replaced with. */
159
391
  readonly replacement: string;
160
392
  constructor(options?: PIIRedactPluginOptions);
161
393
  beforeLog(record: LogRecord): LogRecord;
@@ -163,7 +395,9 @@ declare class PIIRedactPlugin implements Plugin {
163
395
  private redactText;
164
396
  }
165
397
 
398
+ /** Options for {@link SamplingPlugin}. */
166
399
  interface SamplingPluginOptions {
400
+ /** Source of randomness for the rate check. Defaults to `Math.random`; override with a seeded/fake generator for deterministic tests. */
167
401
  rng?: () => number;
168
402
  /** `meta` key holding the trace/run id used to group buffered records. Default `"traceId"`. */
169
403
  traceKey?: string;
@@ -207,11 +441,17 @@ interface SamplingPluginOptions {
207
441
  * or high-cardinality trace grow memory without limit.
208
442
  */
209
443
  declare class SamplingPlugin implements Plugin {
444
+ /** Fraction of non-elevated records kept, in `[0, 1]`. */
210
445
  readonly rate: number;
446
+ /** `meta` key holding the trace/run id used to group buffered records. */
211
447
  readonly traceKey: string;
448
+ /** A record at or above this level elevates its whole trace. */
212
449
  readonly elevateAt: Level;
450
+ /** Transports buffered records are flushed straight to on elevation; `undefined` disables tail-based elevation. */
213
451
  readonly transports: Transport[] | undefined;
452
+ /** Total buffered records allowed across every trace before the oldest trace is evicted. */
214
453
  readonly maxBufferedRecords: number;
454
+ /** Distinct trace ids held at once before the oldest is evicted. */
215
455
  readonly maxTraces: number;
216
456
  private readonly rng;
217
457
  private readonly buffer;
@@ -224,8 +464,11 @@ declare class SamplingPlugin implements Plugin {
224
464
  private evictOldestTrace;
225
465
  }
226
466
 
467
+ /** The hash chain's starting value — a record's `prevHash` when it's the first record in the chain. */
227
468
  declare const GENESIS_HASH: string;
469
+ /** Options for {@link TamperEvidentPlugin}. */
228
470
  interface TamperEvidentPluginOptions {
471
+ /** Starting hash the chain builds from. Default `GENESIS_HASH`. Override to continue a chain started elsewhere (e.g. a previous process). */
229
472
  genesisHash?: string;
230
473
  }
231
474
  /**
@@ -258,6 +501,7 @@ declare class TamperEvidentPlugin implements Plugin {
258
501
  static verifyChain(records: Iterable<Pick<LogRecord, "timestamp" | "level" | "logger" | "message" | "meta">>, options?: TamperEvidentPluginOptions): boolean;
259
502
  }
260
503
 
504
+ /** Options for {@link AlertingPlugin} and every concrete alert plugin that extends it. */
261
505
  interface AlertingPluginOptions {
262
506
  /** A record at or above this level fires an alert. Default `Level.ERROR`. */
263
507
  threshold?: LevelInput;
@@ -280,9 +524,10 @@ interface AlertingPluginOptions {
280
524
  * default: level + logger + message) fires `sendAlert` right away, without
281
525
  * awaiting it — so the log call that triggered it is never blocked on a
282
526
  * webhook, SMTP handshake, or any other I/O, even if the destination is
283
- * slow or unreachable. This stands in for the shared async dispatch queue
284
- * a later phase will introduce; once that queue exists, `AlertingPlugin`
285
- * can route through it instead of firing its own unawaited call per alert.
527
+ * slow or unreachable. This stands in for `Logger`'s own async dispatch
528
+ * queue, which doesn't yet handle alert delivery; `AlertingPlugin` could
529
+ * route through it instead of firing its own unawaited call per alert
530
+ * once it does.
286
531
  *
287
532
  * Any further record matching the same dedupe key within
288
533
  * `dedupeWindowMs` of the first is *not* sent again — it just increments a
@@ -298,8 +543,11 @@ interface AlertingPluginOptions {
298
543
  * that throws.
299
544
  */
300
545
  declare abstract class AlertingPlugin implements Plugin {
546
+ /** A record at or above this level fires an alert. */
301
547
  readonly threshold: Level;
548
+ /** How long a dedupe window stays open before a collapsed follow-up alert (if any) fires. */
302
549
  readonly dedupeWindowMs: number;
550
+ /** Distinct concurrent dedupe keys tracked at once; beyond this, new keys are dropped rather than tracked. */
303
551
  readonly maxTrackedKeys: number;
304
552
  private readonly dedupeKeyFn;
305
553
  private readonly windows;
@@ -321,7 +569,9 @@ declare abstract class AlertingPlugin implements Plugin {
321
569
 
322
570
  /** Posts one alert body to a Slack incoming webhook URL. Swap in a fake for tests. */
323
571
  type SlackSender = (webhookUrl: string, body: string) => Promise<void> | void;
572
+ /** Options for {@link SlackAlertPlugin}. */
324
573
  interface SlackAlertPluginOptions extends AlertingPluginOptions {
574
+ /** Posts one alert. Defaults to a `fetch` POST; override for a fake or an alternate backend. */
325
575
  sender?: SlackSender;
326
576
  }
327
577
  /**
@@ -332,6 +582,7 @@ interface SlackAlertPluginOptions extends AlertingPluginOptions {
332
582
  * fake for tests or an alternate backend.
333
583
  */
334
584
  declare class SlackAlertPlugin extends AlertingPlugin {
585
+ /** Slack "Incoming Webhook" URL every alert is posted to. */
335
586
  readonly webhookUrl: string;
336
587
  private readonly sender;
337
588
  constructor(webhookUrl: string, options?: SlackAlertPluginOptions);
@@ -340,7 +591,9 @@ declare class SlackAlertPlugin extends AlertingPlugin {
340
591
 
341
592
  /** POSTs one PagerDuty Events API v2 payload. Swap in a fake for tests. */
342
593
  type PagerDutySender = (body: string) => Promise<void> | void;
594
+ /** Options for {@link PagerDutyAlertPlugin}. */
343
595
  interface PagerDutyAlertPluginOptions extends AlertingPluginOptions {
596
+ /** Posts one Events API v2 payload. Defaults to a `fetch` POST; override for a fake or an alternate backend. */
344
597
  sender?: PagerDutySender;
345
598
  }
346
599
  /**
@@ -352,22 +605,29 @@ interface PagerDutyAlertPluginOptions extends AlertingPluginOptions {
352
605
  * swap in a fake for tests or an alternate backend.
353
606
  */
354
607
  declare class PagerDutyAlertPlugin extends AlertingPlugin {
608
+ /** PagerDuty Events API v2 integration key every alert is sent under. */
355
609
  readonly routingKey: string;
356
610
  private readonly sender;
357
611
  constructor(routingKey: string, options?: PagerDutyAlertPluginOptions);
358
612
  protected sendAlert(record: LogRecord, occurrences: number): Promise<void>;
359
613
  }
360
614
 
615
+ /** One email alert, as built from a deduplicated record before being handed to `nodemailer` (or an injected `sender`). */
361
616
  interface EmailMessage {
617
+ /** Envelope `From` address. */
362
618
  from: string;
619
+ /** Envelope `To` addresses. */
363
620
  to: string[];
621
+ /** Subject line — the record's level and logger, with an occurrence count appended on a deduped follow-up. */
364
622
  subject: string;
623
+ /** Plain-text body: the message, occurrence count, timestamp, and JSON-serialized `meta`. */
365
624
  text: string;
366
625
  }
367
626
  /** Sends one email message. Swap in a fake for tests. */
368
627
  type EmailSender = (message: EmailMessage) => Promise<void> | void;
369
628
  /** The subset of a `nodemailer` transporter that `EmailAlertPlugin` needs. */
370
629
  interface NodemailerTransporterLike {
630
+ /** Sends one message; matches `nodemailer`'s own `Transporter.sendMail`. */
371
631
  sendMail(message: {
372
632
  from: string;
373
633
  to: string;
@@ -375,12 +635,19 @@ interface NodemailerTransporterLike {
375
635
  text: string;
376
636
  }): Promise<unknown>;
377
637
  }
638
+ /** Options for {@link EmailAlertPlugin}. */
378
639
  interface EmailAlertPluginOptions extends AlertingPluginOptions {
640
+ /** SMTP server hostname. */
379
641
  smtpHost: string;
642
+ /** SMTP server port. */
380
643
  smtpPort: number;
644
+ /** Envelope `From` address for every alert. */
381
645
  fromAddr: string;
646
+ /** Envelope `To` addresses for every alert. */
382
647
  toAddrs: string[];
648
+ /** SMTP auth username. Only used if `password` is also set. */
383
649
  username?: string;
650
+ /** SMTP auth password. Only used if `username` is also set. */
384
651
  password?: string;
385
652
  /** `false` for an SMTP server that doesn't support STARTTLS (e.g. a local relay). Default `true`. */
386
653
  useTls?: boolean;
@@ -395,9 +662,13 @@ interface EmailAlertPluginOptions extends AlertingPluginOptions {
395
662
  * `username`/`password` are only used if both are set.
396
663
  */
397
664
  declare class EmailAlertPlugin extends AlertingPlugin {
665
+ /** SMTP server hostname. */
398
666
  readonly smtpHost: string;
667
+ /** SMTP server port. */
399
668
  readonly smtpPort: number;
669
+ /** Envelope `From` address for every alert. */
400
670
  readonly fromAddr: string;
671
+ /** Envelope `To` addresses for every alert. */
401
672
  readonly toAddrs: string[];
402
673
  private readonly username;
403
674
  private readonly password;
@@ -409,7 +680,9 @@ declare class EmailAlertPlugin extends AlertingPlugin {
409
680
  private importTransporter;
410
681
  }
411
682
 
683
+ /** Options for {@link BatchingTransport} and every concrete batching transport that extends it. */
412
684
  interface BatchingTransportOptions {
685
+ /** Turns a `LogRecord` into the string this transport writes. Defaults to `JSONFormatter`. */
413
686
  formatter?: Formatter;
414
687
  /** Flush once the buffer holds this many items. Default 100. */
415
688
  maxRecords?: number;
@@ -427,7 +700,9 @@ interface BatchingTransportOptions {
427
700
  * matching `HTTPTransport`'s contract.
428
701
  */
429
702
  declare abstract class BatchingTransport<T = LogRecord> extends Transport {
703
+ /** Buffer is flushed once it holds this many items. */
430
704
  readonly maxRecords: number;
705
+ /** Buffer is flushed once its estimated byte size reaches this many bytes. */
431
706
  readonly maxBytes: number;
432
707
  private buffer;
433
708
  private bufferBytes;
@@ -436,6 +711,7 @@ declare abstract class BatchingTransport<T = LogRecord> extends Transport {
436
711
  protected toItem(formatted: string, record: LogRecord): T;
437
712
  /** Estimated byte size of one buffered item, used for the `maxBytes` bound. */
438
713
  protected sizeOf(item: T): number;
714
+ /** Buffers the record, flushing the batch once `maxRecords`/`maxBytes` is reached. */
439
715
  write(formatted: string, record: LogRecord): void;
440
716
  /** Send the current batch now, even if it hasn't reached a bound. */
441
717
  flush(): void;
@@ -446,17 +722,26 @@ declare abstract class BatchingTransport<T = LogRecord> extends Transport {
446
722
 
447
723
  /** One row of the fixed `logs` table schema shared across every SQL transport. */
448
724
  interface SQLLogRow {
725
+ /** `record.timestamp`, as ISO8601. */
449
726
  timestamp: string;
727
+ /** `record.level`. */
450
728
  level: string;
729
+ /** `record.logger`. */
451
730
  logger: string;
731
+ /** `record.message`. */
452
732
  message: string;
453
733
  /** `record.meta`, JSON-serialized — every SQL dialect can store this as TEXT/JSON/JSONB. */
454
734
  meta: string;
735
+ /** `record.meta.runId`, if present. */
455
736
  runId: string | null;
737
+ /** `record.meta.spanId`, if present. */
456
738
  spanId: string | null;
739
+ /** `record.meta.parentSpanId`, if present. */
457
740
  parentSpanId: string | null;
741
+ /** `record.meta.traceId`, if present. */
458
742
  traceId: string | null;
459
743
  }
744
+ /** Options for {@link BaseSQLTransport} and every concrete SQL transport that extends it. */
460
745
  interface BaseSQLTransportOptions extends BatchingTransportOptions {
461
746
  /** Table to write into. Default `"logs"`. */
462
747
  tableName?: string;
@@ -474,7 +759,9 @@ interface BaseSQLTransportOptions extends BatchingTransportOptions {
474
759
  * Inserts are always batched — never one query per log call.
475
760
  */
476
761
  declare abstract class BaseSQLTransport extends BatchingTransport<SQLLogRow> {
762
+ /** Table records are inserted into. */
477
763
  readonly tableName: string;
764
+ /** Whether `createTableSQL()` runs before the first insert. Dev/test convenience only. */
478
765
  readonly ensureSchema: boolean;
479
766
  private schemaEnsured;
480
767
  constructor(options?: BaseSQLTransportOptions);
@@ -496,12 +783,16 @@ declare abstract class BaseSQLTransport extends BatchingTransport<SQLLogRow> {
496
783
 
497
784
  /** The subset of a `better-sqlite3` prepared statement that `SQLiteTransport` needs. */
498
785
  interface SQLiteStatementLike {
786
+ /** Executes the prepared statement with `params` bound positionally. */
499
787
  run(...params: unknown[]): unknown;
500
788
  }
501
789
  /** The subset of a `better-sqlite3` `Database` that `SQLiteTransport` needs. Inject a fake in tests. */
502
790
  interface SQLiteClientLike {
791
+ /** Runs one or more SQL statements with no return value, e.g. `createTableSQL()`. */
503
792
  exec(sql: string): unknown;
793
+ /** Compiles `sql` into a reusable, repeatedly-`run`-able statement. */
504
794
  prepare(sql: string): SQLiteStatementLike;
795
+ /** Wraps `fn` so every call runs inside a single SQLite transaction. */
505
796
  transaction<Args extends unknown[]>(fn: (...args: Args) => void): (...args: Args) => void;
506
797
  }
507
798
  interface SQLiteTransportOptions extends BaseSQLTransportOptions {
@@ -532,6 +823,7 @@ declare class SQLiteTransport extends BaseSQLTransport {
532
823
 
533
824
  /** The subset of a `pg` `Pool`/`Client` that `PostgresTransport` needs. Inject a fake in tests. */
534
825
  interface PgClientLike {
826
+ /** Runs a parameterized query, matching `pg`'s own `Pool`/`Client.query(text, values)`. */
535
827
  query(text: string, values: unknown[]): Promise<unknown>;
536
828
  }
537
829
  interface PostgresTransportOptions extends BaseSQLTransportOptions {
@@ -567,6 +859,7 @@ declare class PostgresTransport extends BaseSQLTransport {
567
859
 
568
860
  /** The subset of a `mysql2/promise` connection/pool that `MySQLTransport` needs. Inject a fake in tests. */
569
861
  interface MySQLClientLike {
862
+ /** Runs a parameterized query, matching `mysql2`'s own `Connection`/`Pool.execute(sql, values)`. */
570
863
  execute(sql: string, values: unknown[]): Promise<unknown>;
571
864
  }
572
865
  interface MySQLTransportOptions extends BaseSQLTransportOptions {
@@ -603,15 +896,20 @@ declare class MySQLTransport extends BaseSQLTransport {
603
896
 
604
897
  /** The subset of a `mongodb` `Collection` that `MongoDBTransport` needs. Inject a fake in tests. */
605
898
  interface MongoCollectionLike {
899
+ /** Inserts every document in one call, matching `mongodb`'s own `Collection.insertMany()`. */
606
900
  insertMany(docs: readonly unknown[]): Promise<unknown>;
607
901
  }
608
902
  /** The subset of a `mongodb` `MongoClient` that `MongoDBTransport` needs to lazily connect. */
609
903
  interface MongoClientLike {
904
+ /** Opens the connection, matching `mongodb`'s own `MongoClient.connect()`. */
610
905
  connect(): Promise<unknown>;
906
+ /** Returns a database handle, from which a collection is looked up by name. */
611
907
  db(name: string): {
908
+ /** Returns a collection handle for `name`, matching `mongodb`'s own `Db.collection()`. */
612
909
  collection(name: string): MongoCollectionLike;
613
910
  };
614
911
  }
912
+ /** Options for {@link MongoDBTransport}. */
615
913
  interface MongoDBTransportOptions extends BatchingTransportOptions {
616
914
  /** Pre-built collection, e.g. for tests, or an already-connected app. Skips the `mongodb` auto-import entirely. */
617
915
  collection?: MongoCollectionLike;
@@ -645,14 +943,23 @@ declare class MongoDBTransport extends BatchingTransport {
645
943
 
646
944
  /** One item written to DynamoDB: `runId` is the partition key, `timestamp` is the sort key. */
647
945
  interface DynamoLogItem {
946
+ /** Partition key: `record.meta.runId`, else `record.meta.traceId`, else the logger name. */
648
947
  runId: string;
948
+ /** Sort key: `record.timestamp`, as ISO8601. */
649
949
  timestamp: string;
950
+ /** `record.level`. */
650
951
  level: string;
952
+ /** `record.logger`. */
651
953
  logger: string;
954
+ /** `record.message`. */
652
955
  message: string;
956
+ /** `record.meta`, stored as-is (DynamoDB items are schemaless). */
653
957
  meta: Record<string, unknown>;
958
+ /** `record.meta.spanId`, if present. */
654
959
  spanId?: string;
960
+ /** `record.meta.parentSpanId`, if present. */
655
961
  parentSpanId?: string;
962
+ /** `record.meta.traceId`, if present. */
656
963
  traceId?: string;
657
964
  }
658
965
  /**
@@ -665,8 +972,10 @@ interface DynamoLogItem {
665
972
  * `@aws-sdk/client-dynamodb` wrapper by not injecting a `client`.
666
973
  */
667
974
  interface DynamoClientLike {
975
+ /** Writes one chunk of items (already capped at `DYNAMO_BATCH_LIMIT`) to `tableName` via a `BatchWriteItem`-equivalent call. */
668
976
  batchWriteItems(tableName: string, items: readonly DynamoLogItem[]): Promise<unknown>;
669
977
  }
978
+ /** Options for {@link DynamoDBTransport}. */
670
979
  interface DynamoDBTransportOptions extends BatchingTransportOptions {
671
980
  /** Pre-built client, e.g. for tests, or a custom wrapper. Skips the `@aws-sdk/client-dynamodb` auto-import entirely. */
672
981
  client?: DynamoClientLike;
@@ -707,8 +1016,10 @@ declare class DynamoDBTransport extends BatchingTransport {
707
1016
 
708
1017
  /** The subset of a `redis` (node-redis v4) client that `RedisTransport` needs. Inject a fake in tests. */
709
1018
  interface RedisClientLike {
1019
+ /** Appends one entry to `stream`, matching `node-redis`'s own `client.xAdd()`. */
710
1020
  xAdd(stream: string, id: string, fields: Record<string, string>): Promise<unknown>;
711
1021
  }
1022
+ /** Options for {@link RedisTransport}. */
712
1023
  interface RedisTransportOptions extends BatchingTransportOptions {
713
1024
  /** Pre-built, already-connected client, e.g. for tests. Skips the `redis` auto-import entirely. */
714
1025
  client?: RedisClientLike;
@@ -718,9 +1029,9 @@ interface RedisTransportOptions extends BatchingTransportOptions {
718
1029
  stream?: string;
719
1030
  }
720
1031
  /**
721
- * Sink for Redis, via Redis Streams (`XADD`) — as CLAUDE.md's spec puts it,
722
- * "a fast local buffer, a different use case from durable storage, not a
723
- * replacement for the others." Reach for this when you want a low-latency
1032
+ * Sink for Redis, via Redis Streams (`XADD`) — a fast local buffer, a
1033
+ * different use case from durable storage, not a replacement for the
1034
+ * others. Reach for this when you want a low-latency
724
1035
  * local tail (e.g. feeding a `redis-cli XREAD`-based live viewer) rather than
725
1036
  * a system of record.
726
1037
  *
@@ -747,6 +1058,7 @@ declare class RedisTransport extends BatchingTransport {
747
1058
  protected sendBatch(batch: readonly LogRecord[]): Promise<void>;
748
1059
  }
749
1060
 
1061
+ /** Options for {@link BaseQueueTransport} and every concrete queue transport that extends it. */
750
1062
  interface BaseQueueTransportOptions extends BatchingTransportOptions {
751
1063
  /**
752
1064
  * Destination name on the backend — a Kafka topic, a RabbitMQ queue name,
@@ -765,6 +1077,7 @@ interface BaseQueueTransportOptions extends BatchingTransportOptions {
765
1077
  * `publishBatch()` against its own driver's publish API.
766
1078
  */
767
1079
  declare abstract class BaseQueueTransport extends BatchingTransport {
1080
+ /** Destination name on the backend — a Kafka topic, a RabbitMQ queue name, an SQS queue URL, or a GCP Pub/Sub topic. */
768
1081
  readonly topic: string;
769
1082
  constructor(options: BaseQueueTransportOptions);
770
1083
  protected sendBatch(batch: readonly LogRecord[]): Promise<void>;
@@ -776,6 +1089,7 @@ declare abstract class BaseQueueTransport extends BatchingTransport {
776
1089
  interface KafkaProducerLike {
777
1090
  /** Optional: some injected producers (or fakes) are already connected. */
778
1091
  connect?(): Promise<void>;
1092
+ /** Publishes one batch of messages to a topic, matching `kafkajs`'s own `Producer.send()`. */
779
1093
  send(record: {
780
1094
  topic: string;
781
1095
  messages: {
@@ -822,6 +1136,7 @@ declare class KafkaTransport extends BaseQueueTransport {
822
1136
  interface AmqpChannelLike {
823
1137
  /** Optional: only called once, and only when provided, to ensure the queue exists. */
824
1138
  assertQueue?(queue: string, options?: unknown): Promise<unknown>;
1139
+ /** Publishes one message directly to `queue`, matching `amqplib`'s own `Channel.sendToQueue()`. */
825
1140
  sendToQueue(queue: string, content: Buffer, options?: unknown): boolean;
826
1141
  }
827
1142
  interface RabbitMQTransportOptions extends BaseQueueTransportOptions {
@@ -869,6 +1184,7 @@ declare class RabbitMQTransport extends BaseQueueTransport {
869
1184
  * a fake in tests, or wrap a real `SQSClient` to match this shape.
870
1185
  */
871
1186
  interface SQSClientLike {
1187
+ /** Sends one chunk of entries (already capped at SQS's 10-message `SendMessageBatch` limit) to `queueUrl`. */
872
1188
  sendMessageBatch(queueUrl: string, entries: {
873
1189
  id: string;
874
1190
  body: string;
@@ -907,6 +1223,7 @@ declare class SQSTransport extends BaseQueueTransport {
907
1223
  * needs. Inject a fake in tests, or an already-resolved `Topic` instance.
908
1224
  */
909
1225
  interface PubSubTopicLike {
1226
+ /** Publishes one message, matching `@google-cloud/pubsub`'s own `Topic.publishMessage()`. */
910
1227
  publishMessage(message: {
911
1228
  data: Buffer;
912
1229
  }): Promise<string>;
@@ -941,7 +1258,9 @@ declare class PubSubTransport extends BaseQueueTransport {
941
1258
 
942
1259
  /** One CloudWatch Logs event: epoch-milliseconds timestamp plus a single log line. */
943
1260
  interface CloudWatchLogEvent {
1261
+ /** Epoch-milliseconds timestamp. */
944
1262
  timestamp: number;
1263
+ /** Formatted log line. */
945
1264
  message: string;
946
1265
  }
947
1266
  /**
@@ -952,8 +1271,10 @@ interface CloudWatchLogEvent {
952
1271
  * small for tests; `importClient()` builds the real adapter around it.
953
1272
  */
954
1273
  interface CloudWatchClientLike {
1274
+ /** Sends one already timestamp-sorted batch of events to `logGroupName`/`logStreamName`. */
955
1275
  putLogEvents(logGroupName: string, logStreamName: string, events: readonly CloudWatchLogEvent[]): Promise<unknown>;
956
1276
  }
1277
+ /** Options for {@link CloudWatchTransport}. */
957
1278
  interface CloudWatchTransportOptions extends BatchingTransportOptions {
958
1279
  /** CloudWatch Logs log group to write into. */
959
1280
  logGroupName: string;
@@ -975,8 +1296,11 @@ interface CloudWatchTransportOptions extends BatchingTransportOptions {
975
1296
  * `CloudWatchLogsClient` wrapped to match `CloudWatchClientLike`).
976
1297
  */
977
1298
  declare class CloudWatchTransport extends BatchingTransport {
1299
+ /** CloudWatch Logs log group written into. */
978
1300
  readonly logGroupName: string;
1301
+ /** CloudWatch Logs log stream, within `logGroupName`, written into. */
979
1302
  readonly logStreamName: string;
1303
+ /** AWS region passed to the real SDK client; `undefined` when `client` is injected or the SDK's own credential-chain resolution is used. */
980
1304
  readonly region: string | undefined;
981
1305
  private readonly injectedClient;
982
1306
  private client;
@@ -989,8 +1313,11 @@ declare class CloudWatchTransport extends BatchingTransport {
989
1313
 
990
1314
  /** One GCP Cloud Logging entry, shaped for `Log#write`. */
991
1315
  interface CloudLoggingEntry {
1316
+ /** Cloud Logging `LogSeverity` value, mapped from the record's level. */
992
1317
  severity: string;
1318
+ /** ISO8601 timestamp. */
993
1319
  timestamp: string;
1320
+ /** The record, JSON-decoded, as Cloud Logging's structured payload. */
994
1321
  jsonPayload: Record<string, unknown>;
995
1322
  }
996
1323
  /**
@@ -999,8 +1326,10 @@ interface CloudLoggingEntry {
999
1326
  * `importClient()` builds the real adapter around `logging.log(name).write(entries)`.
1000
1327
  */
1001
1328
  interface CloudLoggingClientLike {
1329
+ /** Writes one batch of entries to the configured log. */
1002
1330
  writeLogEntries(entries: readonly CloudLoggingEntry[]): Promise<unknown>;
1003
1331
  }
1332
+ /** Options for {@link CloudLoggingTransport}. */
1004
1333
  interface CloudLoggingTransportOptions extends BatchingTransportOptions {
1005
1334
  /** GCP log name (the last segment of the log resource path). Default `"logquill"`. */
1006
1335
  logName?: string;
@@ -1019,7 +1348,9 @@ interface CloudLoggingTransportOptions extends BatchingTransportOptions {
1019
1348
  * `Log` wrapped to match `CloudLoggingClientLike`).
1020
1349
  */
1021
1350
  declare class CloudLoggingTransport extends BatchingTransport {
1351
+ /** GCP log name (the last segment of the log resource path). */
1022
1352
  readonly logName: string;
1353
+ /** GCP project ID passed to the real SDK client; `undefined` when `client` is injected or Application Default Credentials' project is used. */
1023
1354
  readonly projectId: string | undefined;
1024
1355
  private readonly injectedClient;
1025
1356
  private client;
@@ -1032,7 +1363,9 @@ declare class CloudLoggingTransport extends BatchingTransport {
1032
1363
 
1033
1364
  /** One Application Insights trace: a message plus its `SeverityLevel`. */
1034
1365
  interface AppInsightsTrace {
1366
+ /** Formatted log line. */
1035
1367
  message: string;
1368
+ /** Application Insights `SeverityLevel` value, mapped from the record's level. */
1036
1369
  severity: number;
1037
1370
  }
1038
1371
  /**
@@ -1048,8 +1381,10 @@ interface AppInsightsTrace {
1048
1381
  * batch call — Application Insights doesn't offer one.
1049
1382
  */
1050
1383
  interface AppInsightsClientLike {
1384
+ /** Tracks every trace in the batch, then flushes once at the end. */
1051
1385
  trackTraceBatch(traces: readonly AppInsightsTrace[]): Promise<unknown>;
1052
1386
  }
1387
+ /** Options for {@link AppInsightsTransport}. */
1053
1388
  interface AppInsightsTransportOptions extends BatchingTransportOptions {
1054
1389
  /** Azure Application Insights connection string. Passed to the real SDK client; ignored when `client` is injected. */
1055
1390
  connectionString?: string;
@@ -1068,6 +1403,7 @@ interface AppInsightsTransportOptions extends BatchingTransportOptions {
1068
1403
  * wrapped to match `AppInsightsClientLike`).
1069
1404
  */
1070
1405
  declare class AppInsightsTransport extends BatchingTransport {
1406
+ /** Azure Application Insights connection string passed to the real SDK client; `undefined` when `client` is injected. */
1071
1407
  readonly connectionString: string | undefined;
1072
1408
  private readonly injectedClient;
1073
1409
  private client;
@@ -1080,6 +1416,7 @@ declare class AppInsightsTransport extends BatchingTransport {
1080
1416
 
1081
1417
  /** Sends one batch of formatted lines to Datadog's Logs intake API at `url`. Swap in a fake for tests. */
1082
1418
  type DatadogSender = (url: string, apiKey: string, batch: readonly string[]) => Promise<void> | void;
1419
+ /** Options for {@link DatadogTransport}. */
1083
1420
  interface DatadogTransportOptions extends BatchingTransportOptions {
1084
1421
  /** Datadog API key, sent in the `DD-API-KEY` header. */
1085
1422
  apiKey: string;
@@ -1090,6 +1427,7 @@ interface DatadogTransportOptions extends BatchingTransportOptions {
1090
1427
  * region's intake host silently fails to deliver logs to your account.
1091
1428
  */
1092
1429
  site?: string;
1430
+ /** Delivers one batch. Defaults to a `fetch` POST; override for a fake or a different delivery mechanism. */
1093
1431
  sender?: DatadogSender;
1094
1432
  }
1095
1433
  /**
@@ -1098,8 +1436,11 @@ interface DatadogTransportOptions extends BatchingTransportOptions {
1098
1436
  * `sender` to swap in a fake for tests, or a different delivery mechanism.
1099
1437
  */
1100
1438
  declare class DatadogTransport extends BatchingTransport {
1439
+ /** Logs intake endpoint derived from `site`. */
1101
1440
  readonly url: string;
1441
+ /** Datadog API key sent in the `DD-API-KEY` header. */
1102
1442
  readonly apiKey: string;
1443
+ /** Datadog site (region) this transport sends to. */
1103
1444
  readonly site: string;
1104
1445
  private readonly sender;
1105
1446
  constructor(options: DatadogTransportOptions);
@@ -1108,6 +1449,7 @@ declare class DatadogTransport extends BatchingTransport {
1108
1449
 
1109
1450
  /** Sends one pre-built NDJSON `_bulk` body to `url` with the given headers. Swap in a fake for tests. */
1110
1451
  type ElasticsearchSender = (url: string, headers: Readonly<Record<string, string>>, body: string) => Promise<void> | void;
1452
+ /** Options for {@link ElasticsearchTransport}. */
1111
1453
  interface ElasticsearchTransportOptions extends BatchingTransportOptions {
1112
1454
  /** Cluster base URL, e.g. `"https://localhost:9200"`. */
1113
1455
  node: string;
@@ -1115,6 +1457,7 @@ interface ElasticsearchTransportOptions extends BatchingTransportOptions {
1115
1457
  index?: string;
1116
1458
  /** Elasticsearch API key (base64 `id:api_key`), sent as `Authorization: ApiKey <apiKey>`. Omit to send no auth header (e.g. behind a proxy that adds its own). */
1117
1459
  apiKey?: string;
1460
+ /** Delivers one NDJSON `_bulk` body. Defaults to a `fetch` POST; override for a fake or a different delivery mechanism. */
1118
1461
  sender?: ElasticsearchSender;
1119
1462
  }
1120
1463
  /**
@@ -1124,7 +1467,9 @@ interface ElasticsearchTransportOptions extends BatchingTransportOptions {
1124
1467
  * to swap in a fake for tests, or a different delivery mechanism.
1125
1468
  */
1126
1469
  declare class ElasticsearchTransport extends BatchingTransport {
1470
+ /** `_bulk` endpoint derived from the `node` option. */
1127
1471
  readonly url: string;
1472
+ /** Index written into. */
1128
1473
  readonly index: string;
1129
1474
  private readonly apiKey;
1130
1475
  private readonly sender;
@@ -1136,13 +1481,16 @@ declare class ElasticsearchTransport extends BatchingTransport {
1136
1481
  type NewRelicRegion = "US" | "EU";
1137
1482
  /** What `NewRelicSender` reports back about one delivery attempt, so the transport can drive its own 429 backoff logic. */
1138
1483
  interface NewRelicSenderResult {
1484
+ /** `true` for a 2xx response. */
1139
1485
  ok: boolean;
1486
+ /** HTTP status code of the response. */
1140
1487
  status: number;
1141
1488
  /** The raw `Retry-After` response header value, if present — either a number of seconds or an HTTP-date, per RFC 9110. */
1142
1489
  retryAfter: string | null;
1143
1490
  }
1144
1491
  /** Sends one gzip-compressed batch to New Relic's Log API at `url`. Swap in a fake for tests. */
1145
1492
  type NewRelicSender = (url: string, headers: Readonly<Record<string, string>>, body: Buffer) => Promise<NewRelicSenderResult> | NewRelicSenderResult;
1493
+ /** Options for {@link NewRelicTransport}. */
1146
1494
  interface NewRelicTransportOptions extends BatchingTransportOptions {
1147
1495
  /** New Relic license key, sent in the `Api-Key` header. */
1148
1496
  licenseKey: string;
@@ -1153,6 +1501,7 @@ interface NewRelicTransportOptions extends BatchingTransportOptions {
1153
1501
  * vice versa) is rejected. Default `"US"`.
1154
1502
  */
1155
1503
  region?: NewRelicRegion;
1504
+ /** Delivers one gzip-compressed batch. Defaults to a `fetch` POST; override for a fake or to intercept 429s in tests. */
1156
1505
  sender?: NewRelicSender;
1157
1506
  /** Injectable clock for the 429 backoff window, matching `SamplingPlugin`'s injectable `rng`. Default `Date.now`. */
1158
1507
  clock?: () => number;
@@ -1169,7 +1518,9 @@ interface NewRelicTransportOptions extends BatchingTransportOptions {
1169
1518
  * backoff tests without waiting on a real clock.
1170
1519
  */
1171
1520
  declare class NewRelicTransport extends BatchingTransport {
1521
+ /** Ingest endpoint derived from `region`. */
1172
1522
  readonly url: string;
1523
+ /** New Relic account region this transport sends to. */
1173
1524
  readonly region: NewRelicRegion;
1174
1525
  private readonly licenseKey;
1175
1526
  private readonly sender;
@@ -1181,12 +1532,18 @@ declare class NewRelicTransport extends BatchingTransport {
1181
1532
 
1182
1533
  /** The subset of `console` this transport needs — swap in a fake for tests. */
1183
1534
  interface ConsoleLike {
1535
+ /** Writes one already-formatted line, e.g. for a TRACE–WARN record. */
1184
1536
  log(message: string): void;
1537
+ /** Writes one already-formatted line, e.g. for an ERROR/FATAL record. */
1185
1538
  error(message: string): void;
1186
1539
  }
1540
+ /** Options for {@link ConsoleTransport}. */
1187
1541
  interface ConsoleTransportOptions {
1542
+ /** Turns a `LogRecord` into the string this transport writes. Defaults to `JSONFormatter`. */
1188
1543
  formatter?: Formatter;
1544
+ /** Wrap each line in an ANSI color escape for its level. Defaults to `true` unless the `NO_COLOR` env var is set. */
1189
1545
  colorize?: boolean;
1546
+ /** Sink to write through instead of the global `console` — swap in a fake for tests. */
1190
1547
  console?: ConsoleLike;
1191
1548
  }
1192
1549
  /**
@@ -1195,25 +1552,68 @@ interface ConsoleTransportOptions {
1195
1552
  * so this transport works unmodified in a browser bundle.
1196
1553
  */
1197
1554
  declare class ConsoleTransport extends Transport {
1555
+ /** Whether each line is wrapped in an ANSI color escape for its level. */
1198
1556
  colorize: boolean;
1199
1557
  private readonly out;
1200
1558
  constructor(options?: ConsoleTransportOptions);
1559
+ /** Writes `formatted` via `console.log`, or `console.error` for ERROR/FATAL records. */
1201
1560
  write(formatted: string, record: LogRecord): void;
1202
1561
  private applyColor;
1203
1562
  }
1204
1563
 
1564
+ /** Sends one batch of formatted lines to `url`. Swap in a fake for tests. */
1565
+ type BeaconSender = (url: string, batch: readonly string[]) => void;
1566
+ /** Options for {@link BeaconTransport}. */
1567
+ interface BeaconTransportOptions {
1568
+ /** Turns a `LogRecord` into the string this transport writes. Defaults to `JSONFormatter`. */
1569
+ formatter?: Formatter;
1570
+ /** Flush once the buffer holds this many lines. Default 20 — kept low since `sendBeacon` payloads are capped. */
1571
+ batchSize?: number;
1572
+ /** Delivers one batch. Defaults to `sendBeacon` with a `fetch(..., { keepalive: true })` fallback; override for a fake or a different backend. */
1573
+ sender?: BeaconSender;
1574
+ }
1575
+ /**
1576
+ * Batches formatted records and sends them via `navigator.sendBeacon`,
1577
+ * falling back to a `keepalive` `fetch` where `sendBeacon` isn't available.
1578
+ * Meant for the browser: unlike `HTTPTransport`, a beacon send can complete
1579
+ * even after the page that queued it starts unloading. Keep `batchSize`
1580
+ * small — `sendBeacon` payloads are capped (64KB in most browsers).
1581
+ */
1582
+ declare class BeaconTransport extends Transport {
1583
+ /** Endpoint each batch is sent to. */
1584
+ readonly url: string;
1585
+ /** Buffer is flushed once it holds this many lines. */
1586
+ readonly batchSize: number;
1587
+ private readonly sender;
1588
+ private batch;
1589
+ constructor(url: string, options?: BeaconTransportOptions);
1590
+ /** Buffers the formatted line, flushing the batch once `batchSize` is reached. */
1591
+ write(formatted: string): void;
1592
+ /** Send the current batch now, even if it hasn't reached `batchSize`. */
1593
+ flush(): void;
1594
+ close(): void;
1595
+ }
1596
+
1597
+ /** Options for {@link FileTransport}. */
1205
1598
  interface FileTransportOptions {
1599
+ /** Turns a `LogRecord` into the string this transport writes. Defaults to `JSONFormatter`. */
1206
1600
  formatter?: Formatter;
1601
+ /** Rotate once the file reaches this many bytes. `0` disables rotation. Default 10MB. */
1207
1602
  maxBytes?: number;
1603
+ /** How many rotated backups (`.1`, `.2`, ...) to keep. The oldest is deleted once exceeded. Default 5. */
1208
1604
  backupCount?: number;
1209
1605
  }
1210
1606
  /** Appends formatted records to a file, rotating when it exceeds `maxBytes`. */
1211
1607
  declare class FileTransport extends Transport {
1608
+ /** Path of the file records are appended to. */
1212
1609
  readonly path: string;
1610
+ /** File is rotated once it reaches this many bytes. `0` disables rotation. */
1213
1611
  readonly maxBytes: number;
1612
+ /** How many rotated backups (`.1`, `.2`, ...) are kept. */
1214
1613
  readonly backupCount: number;
1215
1614
  private fd;
1216
1615
  constructor(path: string, options?: FileTransportOptions);
1616
+ /** Appends one formatted line to the file, rotating first if `maxBytes` has been exceeded. */
1217
1617
  write(formatted: string): void;
1218
1618
  private rotate;
1219
1619
  close(): void;
@@ -1221,9 +1621,13 @@ declare class FileTransport extends Transport {
1221
1621
 
1222
1622
  /** Sends one batch of formatted lines to `url`. Swap in a fake for tests. */
1223
1623
  type Sender = (url: string, batch: readonly string[]) => Promise<void> | void;
1624
+ /** Options for {@link HTTPTransport}. */
1224
1625
  interface HTTPTransportOptions {
1626
+ /** Turns a `LogRecord` into the string this transport writes. Defaults to `JSONFormatter`. */
1225
1627
  formatter?: Formatter;
1628
+ /** Flush once the buffer holds this many lines. Default 50. */
1226
1629
  batchSize?: number;
1630
+ /** Delivers one batch. Defaults to a `fetch` POST of newline-delimited JSON; override for a fake or a different backend. */
1227
1631
  sender?: Sender;
1228
1632
  }
1229
1633
  /**
@@ -1231,17 +1635,75 @@ interface HTTPTransportOptions {
1231
1635
  * Pass `sender` to swap in a fake for tests, or a different backend.
1232
1636
  */
1233
1637
  declare class HTTPTransport extends Transport {
1638
+ /** Endpoint each batch is POSTed to. */
1234
1639
  readonly url: string;
1640
+ /** Buffer is flushed once it holds this many lines. */
1235
1641
  readonly batchSize: number;
1236
1642
  private readonly sender;
1237
1643
  private batch;
1238
1644
  constructor(url: string, options?: HTTPTransportOptions);
1645
+ /** Buffers the formatted line, flushing the batch once `batchSize` is reached. */
1239
1646
  write(formatted: string): void;
1240
1647
  /** Send the current batch now, even if it hasn't reached `batchSize`. */
1241
1648
  flush(): void;
1242
1649
  close(): void;
1243
1650
  }
1244
1651
 
1652
+ /**
1653
+ * Wraps a serverless handler so `logger.flush()` is awaited before the
1654
+ * wrapped function returns or throws. A serverless runtime can freeze or
1655
+ * recycle its execution environment the instant a handler settles, so
1656
+ * anything still sitting in the dispatch queue — or a batching transport's
1657
+ * own buffer — needs to be sent before that happens, not left for an
1658
+ * invocation that may not come for a while (or ever, if the environment is
1659
+ * torn down instead of frozen).
1660
+ *
1661
+ * The handler shape itself doesn't matter here — only that `fn` is an async
1662
+ * function whose settling is the runtime's cue to freeze — so the same
1663
+ * wrapper covers AWS Lambda, GCP Cloud Functions, and Azure Functions
1664
+ * equally; `withLambda`/`withCloudFunction`/`withAzureFunction` are the same
1665
+ * function under names that match each platform's docs.
1666
+ *
1667
+ * ```ts
1668
+ * export const handler = withLambda(logger, async (event) => {
1669
+ * logger.info("handling request", { requestId: event.requestId });
1670
+ * return { statusCode: 200 };
1671
+ * });
1672
+ * ```
1673
+ */
1674
+ declare function withFlush<Args extends unknown[], TResult>(logger: Logger, fn: (...args: Args) => Promise<TResult>): (...args: Args) => Promise<TResult>;
1675
+ /** `withFlush`, named for an AWS Lambda handler. */
1676
+ declare const withLambda: typeof withFlush;
1677
+ /** `withFlush`, named for a GCP Cloud Functions handler. */
1678
+ declare const withCloudFunction: typeof withFlush;
1679
+ /** `withFlush`, named for an Azure Functions handler. */
1680
+ declare const withAzureFunction: typeof withFlush;
1681
+
1682
+ /** Options for {@link installShutdownHandlers}. */
1683
+ interface ShutdownHandlerOptions {
1684
+ /** Signals to flush-and-close on (e.g. an orchestrator's SIGTERM). Default `["SIGTERM", "SIGINT"]`. */
1685
+ signals?: NodeJS.Signals[];
1686
+ }
1687
+ /**
1688
+ * Registers listeners so `logger.close()` runs once as the process ends —
1689
+ * on `beforeExit` (the event loop draining naturally) and on the given
1690
+ * `signals` (a container/orchestrator asking the process to stop) — so
1691
+ * whatever is still in the dispatch queue or a batching transport's buffer
1692
+ * isn't silently lost. Node-only (uses `process`); don't call this from a
1693
+ * browser bundle.
1694
+ *
1695
+ * Registering a listener for a signal like `SIGTERM` opts this process out
1696
+ * of Node's default "terminate immediately" behavior for it, so this
1697
+ * function calls `process.exit(0)` itself once `close()` settles — `
1698
+ * beforeExit` doesn't need that, since the process is already on its way
1699
+ * out there.
1700
+ *
1701
+ * Returns a function that removes the listeners again — call it in tests,
1702
+ * or if the caller wants to manage its own shutdown lifecycle instead.
1703
+ */
1704
+ declare function installShutdownHandlers(logger: Logger, options?: ShutdownHandlerOptions): () => void;
1705
+
1706
+ /** This package's version, matching `package.json`'s `version` field. */
1245
1707
  declare const VERSION = "0.3.0";
1246
1708
 
1247
- export { AlertingPlugin, type AlertingPluginOptions, type AmqpChannelLike, type AppInsightsClientLike, type AppInsightsTrace, AppInsightsTransport, type AppInsightsTransportOptions, BaseQueueTransport, type BaseQueueTransportOptions, BaseSQLTransport, type BaseSQLTransportOptions, BatchingTransport, type BatchingTransportOptions, type CloudLoggingClientLike, type CloudLoggingEntry, CloudLoggingTransport, type CloudLoggingTransportOptions, type CloudWatchClientLike, type CloudWatchLogEvent, CloudWatchTransport, type CloudWatchTransportOptions, type ConsoleLike, ConsoleTransport, type ConsoleTransportOptions, ContextPlugin, DEFAULT_PII_PATTERNS, DEFAULT_REDACTED_KEYS, type DatadogSender, DatadogTransport, type DatadogTransportOptions, type DynamoClientLike, DynamoDBTransport, type DynamoDBTransportOptions, type DynamoLogItem, type ElasticsearchSender, ElasticsearchTransport, type ElasticsearchTransportOptions, EmailAlertPlugin, type EmailAlertPluginOptions, type EmailMessage, type EmailSender, FileTransport, type FileTransportOptions, Formatter, GENESIS_HASH, HTTPTransport, type HTTPTransportOptions, type KafkaProducerLike, KafkaTransport, type KafkaTransportOptions, Level, LevelInput, LogRecord, type MongoClientLike, type MongoCollectionLike, MongoDBTransport, type MongoDBTransportOptions, type MySQLClientLike, MySQLTransport, type MySQLTransportOptions, type NewRelicRegion, type NewRelicSender, type NewRelicSenderResult, NewRelicTransport, type NewRelicTransportOptions, type NodemailerTransporterLike, PIIRedactPlugin, type PIIRedactPluginOptions, PagerDutyAlertPlugin, type PagerDutyAlertPluginOptions, type PagerDutySender, type PgClientLike, Plugin, PostgresTransport, type PostgresTransportOptions, type PubSubTopicLike, PubSubTransport, type PubSubTransportOptions, RabbitMQTransport, type RabbitMQTransportOptions, RedactPlugin, type RedactPluginOptions, type RedisClientLike, RedisTransport, type RedisTransportOptions, RunPlugin, type RunPluginOptions, type SQLLogRow, type SQLiteClientLike, type SQLiteStatementLike, SQLiteTransport, type SQLiteTransportOptions, type SQSClientLike, SQSTransport, type SQSTransportOptions, SamplingPlugin, type SamplingPluginOptions, type Sender, SlackAlertPlugin, type SlackAlertPluginOptions, type SlackSender, TamperEvidentPlugin, type TamperEvidentPluginOptions, TraceContextPlugin, type TraceContextPluginOptions, Transport, VERSION, defaultResolveActiveOtelTraceId, generateTraceId, getTraceparent, parseTraceHeader, setTraceparent };
1709
+ export { AlertingPlugin, type AlertingPluginOptions, type AmqpChannelLike, type AppInsightsClientLike, type AppInsightsTrace, AppInsightsTransport, type AppInsightsTransportOptions, BaseQueueTransport, type BaseQueueTransportOptions, BaseSQLTransport, type BaseSQLTransportOptions, BatchingTransport, type BatchingTransportOptions, type BeaconSender, BeaconTransport, type BeaconTransportOptions, type CloudLoggingClientLike, type CloudLoggingEntry, CloudLoggingTransport, type CloudLoggingTransportOptions, type CloudWatchClientLike, type CloudWatchLogEvent, CloudWatchTransport, type CloudWatchTransportOptions, type ConsoleLike, ConsoleTransport, type ConsoleTransportOptions, ContextPlugin, DEFAULT_PII_PATTERNS, DEFAULT_PINO_LEVEL_MAP, DEFAULT_REDACTED_KEYS, type DatadogSender, DatadogTransport, type DatadogTransportOptions, type DynamoClientLike, DynamoDBTransport, type DynamoDBTransportOptions, type DynamoLogItem, type ElasticsearchSender, ElasticsearchTransport, type ElasticsearchTransportOptions, EmailAlertPlugin, type EmailAlertPluginOptions, type EmailMessage, type EmailSender, FileTransport, type FileTransportOptions, Formatter, GENESIS_HASH, HTTPTransport, type HTTPTransportOptions, type KafkaProducerLike, KafkaTransport, type KafkaTransportOptions, Level, LevelInput, LogQuillPinoDestination, type LogQuillPinoDestinationOptions, LogRecord, Logger, type MongoClientLike, type MongoCollectionLike, MongoDBTransport, type MongoDBTransportOptions, type MySQLClientLike, MySQLTransport, type MySQLTransportOptions, type NewRelicRegion, type NewRelicSender, type NewRelicSenderResult, NewRelicTransport, type NewRelicTransportOptions, type NodemailerTransporterLike, type OtelSpanContextLike, type OtelSpanLike, OtelSpanProcessor, type OtelSpanProcessorOptions, type OtelStatusLike, PIIRedactPlugin, type PIIRedactPluginOptions, PagerDutyAlertPlugin, type PagerDutyAlertPluginOptions, type PagerDutySender, type PgClientLike, type PinoLevelMap, Plugin, PostgresTransport, type PostgresTransportOptions, type PubSubTopicLike, PubSubTransport, type PubSubTransportOptions, RabbitMQTransport, type RabbitMQTransportOptions, type RateLimitKeyFunc, RateLimitPlugin, type RateLimitPluginOptions, RedactPlugin, type RedactPluginOptions, type RedisClientLike, RedisTransport, type RedisTransportOptions, RunPlugin, type RunPluginOptions, type SQLLogRow, type SQLiteClientLike, type SQLiteStatementLike, SQLiteTransport, type SQLiteTransportOptions, type SQSClientLike, SQSTransport, type SQSTransportOptions, SamplingPlugin, type SamplingPluginOptions, type Sender, type ShutdownHandlerOptions, SlackAlertPlugin, type SlackAlertPluginOptions, type SlackSender, TamperEvidentPlugin, type TamperEvidentPluginOptions, TraceContextPlugin, type TraceContextPluginOptions, Transport, VERSION, bindContext, currentContext, defaultResolveActiveOtelTraceId, generateTraceId, getTraceparent, installShutdownHandlers, parseTraceHeader, setTraceparent, withAzureFunction, withCloudFunction, withFlush, withLambda };