Skip to content

Logging

Starkite scripts use the log module to write structured, severity-labeled logs during execution. By routing log messages to standard error (stderr) by default, the module keeps diagnostic output separate from the standard data stream (stdout) generated by your script.

Logging messages

To write a log entry, use one of the level functions. Each function accepts a log message string as the first positional argument, and an optional dictionary of key-value attributes via the attrs keyword argument:

log.info("server started", attrs={"port": 8080})
log.warn("retrying", attrs={"attempt": 3})
log.error("request failed", attrs={"status": 500, "path": "/api"})
log.debug("cache miss", attrs={"key": "user:42"})

Using attributes instead of embedding values in the message string makes the log stream searchable and parser-friendly for downstream log aggregators.

Configuring output

The default module-wide logger can be configured using three setup functions:

Function Values Default Purpose
log.set_level(level) "debug", "info", "warn", "error" "info" Sets the minimum severity threshold for log emission.
log.set_format(format) "text", "json" "text" Selects human-readable console output or machine-readable JSON.
log.set_output(destination) "stderr", "stdout" "stderr" Configures the output stream target.

Example configuration workflow:

# Enable verbose debug logging
log.set_level("debug")

# Switch formatting to machine-readable JSON
log.set_format("json")

# Route logs to stdout instead of stderr
log.set_output("stdout")

Named loggers

For larger scripts or multi-module environments, you can instantiate isolated logger objects using log.logger(). A custom logger maintains its own level, format, and destination settings independently of the global module defaults:

# Create an isolated logger that outputs JSON to stdout
l = log.logger(level="debug", format="json", output="stdout")
l.info("custom logger initialized", attrs={"component": "auth"})

Attribute binding

To automatically include a set of default attributes on every log message emitted by a component, derive a new logger using the attrs() method:

# Create a base logger
base_log = log.logger(format="json")

# Derive a specialized logger with persistent attributes
app_log = base_log.attrs({"app": "myservice", "version": "1.2.0"})

# Emits: {"time":"...","level":"INFO","msg":"started","app":"myservice","version":"1.2.0"}
app_log.info("started")

The attrs() method returns a new logger instance and does not mutate the logger it was called on, allowing safe instantiation of nested context loggers.

Attribute grouping

To namespace related attributes under a nested JSON key or prefix block, derive a logger using the group(name) method:

# Create a base logger
l = log.logger(format="json")

# Group all database-related logs under a 'db' namespace
db_log = l.group("db")

# Emits: {"time":"...","level":"INFO","msg":"connected","db":{"host":"pg.local","port":5432}}
db_log.info("connected", attrs={"host": "pg.local", "port": 5432})

See also