LogContext
Este conteúdo não está disponível em sua língua ainda.
constLogContext:object
Defined in: src/LogContext.ts:89
The LogContext namespace exposes the MDC operations. The class-
style LogContext.run(...) shape follows the MDC pattern — a
scoped, thread-local-like map of diagnostic context that
propagates through every log line inside the callback — and keeps the
public API tight without exporting the underlying
AsyncLocalStorage instance.
Type Declaration
Section titled “Type Declaration”get():
LogContextData
Read the current context. Returns the frozen empty object when
called outside any run — never undefined, never null, so
callers can .entries() over it without guarding.
Returns
Section titled “Returns”isEmpty()
Section titled “isEmpty()”isEmpty(
context):boolean
Does this context carry nothing?
For the envelope builders, which ask once per tell and are the reason
this exists (#411). Object.keys(context).length === 0 answers the same
question and allocates an array to do it — on the overwhelmingly common
path, where no run is active at all, purely to discover that a frozen
empty object is empty.
The identity check is therefore a fast path in front of the general one,
not a replacement for it. LogContext.run({}, cb) installs a store that
is empty but is not EMPTY, and callers must keep omitting
context for it: attaching {} instead would route every such message
through LogContext.run(env.context, …) on delivery, adding an
AsyncLocalStorage frame per message where the point was to remove work.
Parameters
Section titled “Parameters”context
Section titled “context”Returns
Section titled “Returns”boolean
run<
T>(context,callback):T
Run callback with context as the current context. The previous context
(if any) is shadowed for the duration of the call and restored
automatically. Sync and async callback both work — AsyncLocalStorage
preserves the binding across awaits.
Type Parameters
Section titled “Type Parameters”T
Parameters
Section titled “Parameters”context
Section titled “context”callback
Section titled “callback”() => T
Returns
Section titled “Returns”T
runEach()
Section titled “runEach()”runEach<
TItem>(entries,callback):Promise<void>
Process entries sequentially, each under the context captured
when that entry was enqueued.
This is the batching counterpart to LogContext.runFresh.
runFresh is right when the deferred work belongs to nobody;
runEach is right when it belongs to someone specific per item —
a mailbox drained in one turn, a flush of buffered writes, a batch
of requests coalesced across tenants. Handling such a batch under
one ambient context attributes every item to whichever request
happened to trigger the flush.
The capture must happen at enqueue time, since that is the only moment the item’s own context is still current:
queue.push({ context: LogContext.get(), item: job }); // …later, in some other turn: await LogContext.runEach(queue.splice(0), (job) => this.handle(job));
Returns Promise<void> by design. Collecting results would
make this read like Promise.all and invite callers to treat it as
a concurrency helper, which it is not — the ordering and the
one-scope-per-item guarantee are the product, and the payload of
each call is a side effect (a log line, a downstream tell).
Anything worth returning is worth writing where the batch was
built.
Errors propagate immediately and abandon the remaining
entries. Swallowing them would be a supervision policy, and that
decision does not belong to a diagnostics primitive; a caller who
wants per-item isolation puts the try/catch inside callback, where
it still runs under the right context.
Type Parameters
Section titled “Type Parameters”TItem
Parameters
Section titled “Parameters”entries
Section titled “entries”Iterable<LogContextEntry<TItem>>
callback
Section titled “callback”(item) => unknown
Returns
Section titled “Returns”Promise<void>
runFresh()
Section titled “runFresh()”runFresh<
T>(callback):T
Run callback with the context explicitly emptied, shadowing whatever
was ambient. The inverse of LogContext.with: where with
inherits, this deliberately does not.
Reach for it at the seam where work stops belonging to the caller
that happened to start it — a background drain loop, a retry timer,
a queue consumer, anything kicked off with a bare un-awaited
promise. Without it, AsyncLocalStorage hands that work the
context of whichever turn created it, and every tell it makes
stamps that context onto the envelope; if the work then serves
another tenant, the first tenant’s identifiers travel with it.
Starting from empty is cheaper to reason about than remembering to
strip individual keys, and it fails safe: a field nobody set cannot
leak.
The framework applies it to its own seams of that shape (#718): a
dispatcher turn (ActorCell.runReported), a fired schedule
(Scheduler), and an inbound cluster frame that carries no context
(Cluster.onEnvelope). So the deferred work still needing this by hand
is the work you defer — an un-awaited promise, a buffer flushed later,
a raw setTimeout — not anything the framework hands you.
No store means no wrapper. With nothing ambient, get() already
returns EMPTY, so running callback bare is observably identical
to running it inside storage.run(EMPTY, …) — and it keeps the runtime’s
no-store fast path, which is what makes the framework’s own three seams
affordable. The cost of an active store is not the run call: it is that
every async resource created under one propagates it, so wrapping a turn
unconditionally taxed each await inside it. Measured on
benchmarks/single-node/tell-throughput.ts, an unconditional wrapper cost
3-8 % of tell throughput in a process with no MDC at all; this guard takes
that back, and a process that does open scopes pays only where there is
something to shadow.
Type Parameters
Section titled “Type Parameters”T
Parameters
Section titled “Parameters”callback
Section titled “callback”() => T
Returns
Section titled “Returns”T
snapshot()
Section titled “snapshot()”snapshot():
Record<string,string|number|boolean>
Capture the current context as a plain (mutable-by-the-caller)
object — useful when you need to pass the context through a
boundary that strips Readonly (e.g. a JSON serialiser).
Returns a fresh copy every call.
Returns
Section titled “Returns”Record<string, string | number | boolean>
with()
Section titled “with()”with<
T>(extra,callback):T
Run callback with extra fields merged into the current context.
Equivalent to run({ ...get(), ...extra }, callback) but a touch
shorter at call sites that just want to add a field.
Type Parameters
Section titled “Type Parameters”T
Parameters
Section titled “Parameters”callback
Section titled “callback”() => T
Returns
Section titled “Returns”T
