> ## Documentation Index
> Fetch the complete documentation index at: https://docs.simular.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# InitLogger

# Function: initLogger()

> **initLogger**(`cb?`, `spec?`): `void`

Defined in: [index.d.ts:1286](https://github.com/simular-ai/simulang-js-internal/blob/d2b85c3277cbb16ce50c0781e1db8ad2c8a5690e/index.d.ts#L1286)

Initialize the logger.

**You usually don't need to call this.** The package's `main` entry
(`wrapped.js`) calls `initLogger()` with no arguments on first
evaluation, so simply `import '@simular-ai/simulang-js'` is enough to
see `[level] message` records on stderr. Call this directly
only when you want to *override* that default — to forward records to
a JS callback, change the filter spec, or silence everything.

* **No callback** (`initLogger()` or `initLogger(null, spec)`): records
  are formatted as `[level] message` and written to stderr.
* **With a callback** (`initLogger(cb, spec)`): records are forwarded to
  the JS callback via a non-blocking, unref'd threadsafe function. Use
  this for GUI panels, file appenders, or routing through a logging
  library like pino. The unref'd dispatch means the logger does not keep
  the Node event loop alive on its own.

Omit `spec` to read `RUST_LOG` (falls back to `"simulang_rs=info,warn"`
when `RUST_LOG` is unset — info-level records from simulang's own
actions, warn-level from every other crate). Pass an explicit `spec`
to override `RUST_LOG`. Syntax is identical to `RUST_LOG`:

* `"info"` — global level
* `"simulang_rs=debug,warn"` — per-module override + default
* `"simulang_rs::windows=trace,simulang_rs::macos=debug,warn"` — multiple
* `"off"` — disable all logging

Safe to call repeatedly: each call atomically swaps the inner sink and
filter — useful for e.g. starting on stderr at boot and switching to a
renderer callback once the UI is ready.

**Don't log from inside the callback.** Whether directly (`console.log`
is fine — that's not a `log::*!` call) or transitively via another
`simulang-js` function whose Rust side emits a record, you'd feed the
relay another record, which queues another callback invocation, and so
on forever. The callback itself runs on the Node main thread; the
non-blocking dispatch from Rust is what creates the recursion risk.

## Parameters

### cb?

((`arg`) => `unknown`) | `null`

### spec?

`string` | `null`

## Returns

`void`
