Skip to content

Loggers

Z-M-Huang edited this page Apr 27, 2026 · 3 revisions

Loggers

Logger extensions are fan-out sinks for log records. Every logger receives every record; each decides whether to drop, format, or write it.

contractVersion: 1.0.0


Intent

Loggers externalize the session. A stdout logger prints for the local operator; a file logger persists to ~/.stud/logs/; a remote logger ships to an external service. Loggers are extensions because the set of destinations is open and deployment-specific.

Loggers do not own observability primitives — correlation IDs, spans, and audit events are core constructs (see Observability). Loggers are the sinks through which those records flow outward.


Contract shape

classDiagram
    class LoggerContract {
        kind : "Logger"
        contractVersion : SemVer
        requiredCoreVersion : SemVerRange
        configSchema : JSONSchema
        loadedCardinality : unlimited
        activeCardinality : unlimited
        stateSlot : optional
        validationSeverity : optional
        discoveryRules : DiscoveryRules
        reloadBehavior : in-turn
        accepts : LogKindFilter
    }
    class LogKindFilter {
        events : bool
        audit : bool
        diagnostics : bool
        minSeverity : trace | debug | info | warn | error
    }
    LoggerContract --> LogKindFilter
Loading

accepts lets a logger declare which record kinds it wants — a metrics sink might take events but skip audit; a compliance sink might take only audit.


Configuration schema

Every logger's configSchema must accept:

Field Meaning
enabled Whether this logger participates.
level Minimum severity to emit — trace, debug, info, warn, error. Default: info. Overridden by the --debug flag or logging.level: "debug" in settings.json.
redactSecrets Whether to apply the default redaction filter before writing. Default: true. Must remain true whenever level is debug or below — see Debug-level redaction.

Plus sink-specific options (file path, remote URL, rotation size).

Debug-level redaction

Debug and trace levels are the highest-risk levels for secret exfiltration — they widen the aperture on request/response bodies, tool inputs, and provider metadata that might carry resolved secrets. Therefore:

  • A conforming logger must not disable the redaction filter when its effective level is debug or trace. A configuration that pairs level: "debug" with redactSecrets: false is a validation error, not a warning.
  • The redaction pipeline that runs for debug logs is the same pipeline that runs for info-level logs. There is no "debug-only" bypass. See Secrets Hygiene § Redaction pipeline.
  • A debug log entry that contains a resolved secret is a bug in the record producer, not a logger configuration question. Loggers are defense in depth; the primary duty remains on producers.

Lifecycle

Phase Logger responsibilities
init Validate config; open the file / connect the socket / prepare the queue.
activate Subscribe to the log stream.
deactivate Flush pending records; stop accepting new ones.
dispose Close the file / socket; flush one final time. Idempotent.

Loggers write asynchronously where possible. A logger that blocks on every record creates backpressure into core and is non-conformant. Use a bounded queue and drop-with-warning on overflow.


Cardinality

Loaded: unlimited.

Active: unlimited. Every loaded logger receives every record that passes its accepts filter.


State slot

Optional. Typical uses:

  • Rotation counters (file loggers that roll every N MB).
  • Last-flushed watermark (remote loggers that batch).

See Extension State.


Validation severity

Optional by default. A logger that fails to load skips with a warning; the session runs without it. A critical record that no logger accepts still lands in the Audit Trail because audit is a core durable surface, not a logger responsibility.

Config may escalate a specific logger to critical (useful for regulated environments where a compliance sink must be present).


Discovery path

Loggers live in a loggers/ folder under each configuration scope layer:

Layer Location
Bundled Ships with the package. See File logger reference — the bundled file logger is always loaded.
Global ~/.stud/loggers/…
Project <cwd>/.stud/loggers/…

Ordering

Loggers are an unordered category. Fan-out order is undefined; every logger receives a copy.


Reload behavior

reloadBehavior: in-turn. Loggers are among the few categories safe to reload mid-turn — reattaching a sink does not change any semantic output. The previous logger drains pending records, then detaches; the new one attaches fresh.


Interaction with core

A logger reads and writes only through the Host API:

  • host.events.subscribe(kinds) — subscribe to events, audit records, diagnostics.
  • host.cancel.session — react to session shutdown by flushing.
  • host.session.stateSlot(extId) — own slot for rotation/batch state.

A logger never:

  • Drives the Interaction Protocol.
  • Writes to the tool registry.
  • Reads env values directly — record payloads already carry whatever values should appear.

Security notes

  • Log records are external by default. Treat every field as externally visible. redactSecrets is defense in depth; the primary duty is on the record producer to not carry a secret in the first place.
  • No resolved-secret exfiltration via logging. See LLM Context Isolation and Secrets Hygiene.
  • Audit records are special. A logger may redact non-audit fields but must not mutate audit records — they are legally/operationally meaningful. If redactSecrets is true, apply it to event payloads, not to audit.
  • Backpressure is a security concern. A logger that blocks core starves the UI and slows down approvals. Bounded queue + drop-with-warn is the contract.

Related pages


Changelog

1.0.0 — initial

  • Logger contract as documented above. Fan-out model; in-turn reload; audit records pass through un-redacted.

Introduction

Reading

Core runtime

Contracts

Category contracts

Context

Security

Runtime behavior

Operations

Providers (bundled)

Integrations

Reference extensions

Tools

UI

Session Stores

Loggers

Providers

Hooks

Context Providers

Commands

Case studies

Flows

Maintainers

Clone this wiki locally