core.log_config module

Structured logging configuration for the distributed Stargazer services.

Provides StructuredFormatter, a JSON-lines log formatter that stamps every record with the process-wide NODE_ID / NODE_ROLE (read once from the SG_NODE_ID / SG_NODE_ROLE environment variables) plus any per-event trace fields, and configure_logging(), which installs that formatter on the root logger from a Config. The shared envelope of fields is what makes a single message greppable as it hops across the gateway / inference / agents / consolidation / web services over Redis Streams.

Note: this module is the original core.log_config implementation; the live runtime path is the newer core.structured_logger (which exposes its own configure_logging). The symbols here are currently referenced only by the tests under tests/core/ that pin this module’s behaviour.

class core.log_config.StructuredFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)[source]

Bases: Formatter

Logging formatter that renders each record as one line of JSON.

A logging.Formatter subclass whose format() emits a flat JSON object per log record – timestamp, level, logger, message, the process-wide NODE_ID / NODE_ROLE, and any optional trace fields the caller attached via extra – so logs from every Stargazer service can be aggregated and correlated by trace_id or stream_msg_id with simple text tooling.

Installed on the root logger’s stdout handler by configure_logging() when structured logging is enabled, and constructed directly by tests/core/test_log_config.py.

format(record)[source]

Render a single log record as a one-line JSON string for distributed tracing.

Builds a flat dictionary containing the timestamp, level, logger name, rendered message, and the process-wide NODE_ID / NODE_ROLE (read once at import time from the SG_NODE_ID and SG_NODE_ROLE environment variables). It then opportunistically copies a fixed set of optional trace fields off the record – stream_msg_id, channel_id, platform, user_id, and trace_id – whenever the caller has attached them via logger.x(..., extra={...}), which is what enables grep-based correlation of a single message as it flows across the gateway / inference / agents / consolidation / web services over Redis Streams. If the record carries exception info, the formatted traceback is added under exception. The result is serialised with json.dumps.

This is invoked implicitly by the logging framework for every record once an instance is installed as a handler’s formatter; the formatter itself is instantiated by configure_logging() in this module and constructed directly in tests/core/test_log_config.py.

Parameters:

record (LogRecord) – The log record produced by the standard logging machinery.

Return type:

str

Returns:

A JSON-encoded string terminated by no newline (the handler adds it), containing the core fields plus any present optional trace fields and exception traceback.

core.log_config.configure_logging(cfg)[source]

Reconfigure the root logger from a Config object.

Sets the root log level from cfg.log_level, strips any existing handlers to avoid duplicate output on re-init, and attaches a single fresh StreamHandler writing to stdout. The handler is given either a StructuredFormatter (JSON lines, when cfg.structured_logging is truthy) or a plain text formatter, and an ApiKeyRedactionFilter from log_redaction so secrets are scrubbed before anything is emitted.

Mutates global logging state (the root logger’s level, handlers, and filters) as a side effect and reads log_level / structured_logging off the supplied config. No production callers were found by grep; it is invoked by the logging tests under tests/core/ and stands in parallel to the live core.structured_logger.configure_logging.

Parameters:

cfg (Any) – A configuration object exposing log_level and structured_logging attributes (both read defensively via getattr with safe defaults).

Return type:

None