Skip to content

Logging

  • Start here: Logging guide
  • Common recipes: configure(...) for JSON, LOGFMT, TEXT, PRETTY output. Filters: DuplicateFilter, RateLimitFilter.

grelmicro.log

Logging.

DuplicateFilter

DuplicateFilter(
    *,
    allowed_repetitions: PositiveInt | None = None,
    cache_size: PositiveInt | None = None,
    key_mode: KeyMode | None = None,
    ttl: PositiveFloat | None = None,
    key: Callable[[LogRecord], Hashable] | None = None,
    env_name: str = "default",
    env_prefix: str | None = None,
    env_load: bool | None = None,
)

Bases: Filter

Drop log records that repeat beyond allowed_repetitions.

Keys are tracked in an LRU cache with at most cache_size entries. Use key_mode to pick the default key, or pass key to override it.

Set ttl to emit a new burst of allowed_repetitions records every ttl during a long flood. This gives operators regular reminders that the issue is still active.

key_mode="template" is about 3 times faster than "rendered" because it skips message formatting.

Thread-safe.

State is kept in the current process only. There is no reset method. Create a new filter to clear all counters.

Initialize the filter.

PARAMETER DESCRIPTION
allowed_repetitions

Maximum number of records per key that pass the filter before subsequent records are dropped.

Default: 5. When unset and env reads are enabled (see env_load and GREL_ENV_LOAD), resolves from the environment variable GREL_DUPLICATEFILTER_ALLOWED_REPETITIONS if present, otherwise falls back to the DuplicateFilterConfig default.

TYPE: PositiveInt | None DEFAULT: None

cache_size

Maximum number of distinct keys tracked. When exceeded, the least-recently-seen key is evicted.

Default: 100.

TYPE: PositiveInt | None DEFAULT: None

key_mode

Default key strategy: "logger", "level", "global", "template" (default), or "rendered". Ignored when key is set.

TYPE: KeyMode | None DEFAULT: None

ttl

Silence window for automatic counter reset. None (default) disables time-based expiry.

TYPE: PositiveFloat | None DEFAULT: None

key

Override the default key function. Receives the record and returns any hashable value.

TYPE: Callable[[LogRecord], Hashable] | None DEFAULT: None

env_name

Environment variable namespace segment.

Default: "default", which reads the bare prefix. A named instance segments its env vars under the name, so env_name="audit" reads GREL_DUPLICATEFILTER_AUDIT_*.

TYPE: str DEFAULT: 'default'

env_prefix

Override the auto-derived environment variable prefix.

Default: GREL_DUPLICATEFILTER_. A named instance segments via env_name to GREL_DUPLICATEFILTER_{NAME}_.

TYPE: str | None DEFAULT: None

env_load

Whether to read environment variables.

When None (the default), follow the process-wide GREL_ENV_LOAD flag. Pass True or False to override the flag for this construction.

TYPE: bool | None DEFAULT: None

config property

Return the config.

from_config classmethod

from_config(
    config: DuplicateFilterConfig,
    *,
    key: Callable[[LogRecord], Hashable] | None = None,
) -> Self

Construct a DuplicateFilter from a pre-built DuplicateFilterConfig.

PARAMETER DESCRIPTION
config

The pre-built duplicate filter configuration.

Use this path when the configuration is assembled at startup from a settings tree. The environment path is bypassed and the config is used as-is.

TYPE: DuplicateFilterConfig

key

Override the default key function. Receives the record and returns any hashable value.

TYPE: Callable[[LogRecord], Hashable] | None DEFAULT: None

filter

filter(record: LogRecord) -> bool

Return True if the record should pass, False to drop.

DuplicateFilterConfig

Bases: BaseModel

Duplicate Filter Config.

allowed_repetitions class-attribute instance-attribute

allowed_repetitions: PositiveInt = 5

Maximum number of records per key that pass the filter before subsequent records are dropped.

cache_size class-attribute instance-attribute

cache_size: PositiveInt = 100

Maximum number of distinct keys tracked. When exceeded, the least-recently-seen key is evicted.

key_mode class-attribute instance-attribute

key_mode: KeyMode = 'template'

Default key strategy. "logger" keys per logger name. "level" keys per log level. "global" shares one counter for every record. "template" (default) keys per (logger, level, str(record.msg)): collapses across arg values of the same template and is about 3x faster. "rendered" keys per (logger, level, record.getMessage()): distinguishes fully-rendered messages.

ttl class-attribute instance-attribute

ttl: PositiveFloat | None = None

Silence window for automatic counter reset. If a key has not been seen for ttl, its counter resets the next time it appears. None (default) disables time-based expiry, so only LRU eviction can reset a counter.

ErrorDict

Bases: TypedDict

Structured error representation.

type instance-attribute

type: str

message instance-attribute

message: str

stack instance-attribute

stack: NotRequired[str]

JSONRecordDict

Bases: TypedDict

Structured JSON log record after serialization.

Describes the shape of each log line after it is serialized to JSON. Internally, formatters use datetime objects for time. The JSON serializer converts them to ISO 8601.

The core fields follow common structured-logging conventions. Extra context fields are added flat at the top level.

Example::

{"time": "2026-03-30T14:00:00+00:00", "level": "INFO",
 "msg": "request handled", "logger": "myapp.api",
 "caller": "handle:45",
 "method": "GET", "status": 200}

time instance-attribute

time: str

level instance-attribute

level: str

msg instance-attribute

msg: str

logger instance-attribute

logger: str

caller instance-attribute

caller: NotRequired[str]

trace_id instance-attribute

trace_id: NotRequired[str]

span_id instance-attribute

span_id: NotRequired[str]

error instance-attribute

error: NotRequired[ErrorDict]

Log

Log(
    *,
    name: str = "default",
    config: LogConfig | None = None,
    backend: LogBackendType | None = None,
    level: LogLevelType | None = None,
    format: LogFormatType | str | None = None,
    timezone: LogTimeZoneType | None = None,
    json_serializer: LogSerializerType | None = None,
    caller_enabled: bool | None = None,
    otel_enabled: bool | None = None,
    env_load: bool | None = None,
)

Log component: installs logging on enter, restores stdlib root state on exit.

Registered as micro.log after Grelmicro.use(Log(...)). Mirrors the knobs on grelmicro.log.configure(...). Construction stays cheap, the backend is configured when the surrounding Grelmicro opens.

Example
from grelmicro import Grelmicro
from grelmicro.log import Log

micro = Grelmicro(uses=[Log()])

async with micro:
    ...

On exit, the previous stdlib root handlers and level are restored so sequential Grelmicro(...) blocks do not pile handlers up. The loguru and structlog backends keep the configuration installed on enter (no restore).

The stdlib root logger is a single global. Log.__aenter__ and Log.__aexit__ serialize on a class-level threading.Lock so the snapshot/restore sequence cannot interleave across concurrent Grelmicro lifecycles in the same process. Run one Log at a time per process.

Read more in the Logging docs.

Initialize the component (defer configuration until __aenter__).

PARAMETER DESCRIPTION
name

Registration name. Log configures the process-wide root logger, so only one may be registered per app.

TYPE: str DEFAULT: 'default'

config

Pre-built configuration. When provided, individual kwargs must be None. The env path is bypassed.

TYPE: LogConfig | None DEFAULT: None

backend

Logging backend (stdlib, loguru, structlog).

TYPE: LogBackendType | None DEFAULT: None

level

Log level threshold.

TYPE: LogLevelType | None DEFAULT: None

format

Log format.

TYPE: LogFormatType | str | None DEFAULT: None

timezone

IANA timezone for timestamps.

TYPE: LogTimeZoneType | None DEFAULT: None

json_serializer

JSON serializer.

TYPE: LogSerializerType | None DEFAULT: None

caller_enabled

Include caller (function and line) in log records.

TYPE: bool | None DEFAULT: None

otel_enabled

Extract OpenTelemetry trace context.

TYPE: bool | None DEFAULT: None

env_load

Whether to read GREL_LOG_* environment variables. When None (default), follow GREL_ENV_LOAD.

TYPE: bool | None DEFAULT: None

kind class-attribute

kind: str = 'log'

singleton class-attribute

singleton: bool = True

name property

name: str

Return the registration name.

config property

config: LogConfig

Return the resolved LogConfig.

RAISES DESCRIPTION
RuntimeError

If accessed before the component has been entered.

from_config classmethod

from_config(
    config: LogConfig, *, name: str = "default"
) -> Self

Construct a Log from a pre-built LogConfig.

PARAMETER DESCRIPTION
config

The pre-built logging configuration.

Use this path when the configuration is assembled at startup from a settings tree (for example YAML, Vault, or a pydantic-settings aggregator). The environment path is bypassed and the config is used as-is.

TYPE: LogConfig

name

Registration name. Defaults to 'default'.

TYPE: str DEFAULT: 'default'

LogConfig

Bases: BaseModel

Log Config.

backend class-attribute instance-attribute

backend: LogBackendType = STDLIB

Logging backend implementation.

level class-attribute instance-attribute

level: LogLevelType = INFO

Log level threshold.

format class-attribute instance-attribute

format: LogFormatType | str = AUTO

Log format. Built-in option or a custom template string.

timezone class-attribute instance-attribute

timezone: LogTimeZoneType = LogTimeZoneType('UTC')

IANA timezone for timestamps.

json_serializer class-attribute instance-attribute

json_serializer: LogSerializerType = STDLIB

JSON serializer used for structured output.

caller_enabled class-attribute instance-attribute

caller_enabled: bool = False

Include caller (function and line) in log records.

otel_enabled class-attribute instance-attribute

otel_enabled: bool = opentelemetry is not None

Extract OpenTelemetry trace context into log records.

LogError

Bases: GrelmicroError

Base log error.

LogSettingsValidationError

LogSettingsValidationError(error: ValidationError | str)

Bases: LogError, SettingsValidationError

Log Settings Validation Error.

RateLimitFilter

RateLimitFilter(
    *,
    capacity: PositiveInt | None = None,
    refill_rate: PositiveFloat | None = None,
    key_mode: KeyMode | None = None,
    cost: PositiveFloat | None = None,
    key: Callable[[LogRecord], str] | None = None,
    env_name: str = "default",
    env_prefix: str | None = None,
    env_load: bool | None = None,
)

Bases: Filter

Rate-limit log records with a token bucket.

Drops records once the per-key bucket is empty. Each key refills at refill_rate tokens per second, capped at capacity.

Pick the default key strategy via key_mode (per-logger, per-level, global, template, rendered) or supply a custom key callable. Tune capacity and refill_rate to match your acceptable burst and sustained log rate.

Thread-safe. State lives in a MemoryTokenBucket.

State is kept in the current process only. It is not shared between processes. Create a new filter to clear all counters, or call reset for a single key.

Example:

import logging

from grelmicro.log import RateLimitFilter

logger = logging.getLogger("grelmicro.ingest")
logger.addFilter(RateLimitFilter(capacity=10, refill_rate=1))

Read more in the Logging docs.

Initialize the filter.

PARAMETER DESCRIPTION
capacity

Maximum burst size.

Default: 5. When unset and env reads are enabled (see env_load and GREL_ENV_LOAD), resolves from the environment variable GREL_RATELIMITFILTER_CAPACITY if present, otherwise falls back to the RateLimitFilterConfig default.

TYPE: PositiveInt | None DEFAULT: None

refill_rate

Tokens replenished per second.

Default: 1.

TYPE: PositiveFloat | None DEFAULT: None

key_mode

Default key strategy: "logger" (default), "level", "global", "template", or "rendered". Ignored when key is set.

TYPE: KeyMode | None DEFAULT: None

cost

Tokens consumed per record.

Default: 1.0.

TYPE: PositiveFloat | None DEFAULT: None

key

Override the default key function. It receives the record and returns a string key. Returned keys share the same namespace as the default key function. Add a unique prefix if you need to avoid collisions.

TYPE: Callable[[LogRecord], str] | None DEFAULT: None

env_name

Environment variable namespace segment.

Default: "default", which reads the bare prefix. A named instance segments its env vars under the name, so env_name="audit" reads GREL_RATELIMITFILTER_AUDIT_*.

TYPE: str DEFAULT: 'default'

env_prefix

Override the auto-derived environment variable prefix.

Default: GREL_RATELIMITFILTER_. A named instance segments via env_name to GREL_RATELIMITFILTER_{NAME}_.

TYPE: str | None DEFAULT: None

env_load

Whether to read environment variables.

When None (the default), follow the process-wide GREL_ENV_LOAD flag. Pass True or False to override the flag for this construction.

TYPE: bool | None DEFAULT: None

config property

Return the config.

from_config classmethod

from_config(
    config: RateLimitFilterConfig,
    *,
    key: Callable[[LogRecord], str] | None = None,
) -> Self

Construct a RateLimitFilter from a pre-built RateLimitFilterConfig.

PARAMETER DESCRIPTION
config

The pre-built rate limit filter configuration.

Use this path when the configuration is assembled at startup from a settings tree. The environment path is bypassed and the config is used as-is.

TYPE: RateLimitFilterConfig

key

Override the default key function. It receives the record and returns a string key.

TYPE: Callable[[LogRecord], str] | None DEFAULT: None

filter

filter(record: LogRecord) -> bool

Return True to keep the record, False to drop it.

reset

reset(key: str = '') -> None

Restore key's bucket to full capacity.

PARAMETER DESCRIPTION
key

Identifier to reset. Use the same value the key function produces for the records you want to clear. Pass "" for the "global" key mode.

TYPE: str DEFAULT: ''

RateLimitFilterConfig

Bases: BaseModel

Rate Limit Filter Config.

capacity class-attribute instance-attribute

capacity: PositiveInt = 5

Maximum burst size: the bucket holds at most this many tokens. A burst of up to capacity records is allowed before any are dropped.

refill_rate class-attribute instance-attribute

refill_rate: PositiveFloat = 1

Tokens (records) replenished per second. Sets the sustained rate after the initial burst is exhausted.

key_mode class-attribute instance-attribute

key_mode: KeyMode = 'logger'

Default key strategy. "logger" (default) buckets per logger name (each logger gets its own burst budget). "level" buckets per log level. "global" uses a single shared bucket for all records. "template" buckets per (logger, level, str(record.msg)): collapses across arg values of the same template. "rendered" buckets per (logger, level, record.getMessage()): distinguishes fully-rendered messages. Ignored when key is set.

cost class-attribute instance-attribute

cost: PositiveFloat = 1.0

Tokens used per record. Increase this to make some filters drain their bucket faster than others. For example, a filter on a verbose-level handler.

configure

configure(
    *,
    backend: LogBackendType | None = None,
    level: LogLevelType | None = None,
    format: LogFormatType | str | None = None,
    timezone: LogTimeZoneType | None = None,
    json_serializer: LogSerializerType | None = None,
    caller_enabled: bool | None = None,
    otel_enabled: bool | None = None,
    env_load: bool | None = None,
) -> LogConfig

Configure logging with the selected backend.

Two paths:

  • Programmatic: pass any of the per-field kwargs. Unset fields resolve from GREL_LOG_* env vars (when env_load=True), then from LogConfig defaults.
  • Environmental: omit all kwargs. GREL_LOG_* env vars populate every field.

For the declarative path, use configure_with.

PARAMETER DESCRIPTION
backend

Logging backend (stdlib, loguru, structlog). Default: stdlib.

TYPE: LogBackendType | None DEFAULT: None

level

Log level threshold. Default: INFO.

TYPE: LogLevelType | None DEFAULT: None

format

Log format. Default: AUTO.

TYPE: LogFormatType | str | None DEFAULT: None

timezone

IANA timezone for timestamps. Default: UTC.

TYPE: LogTimeZoneType | None DEFAULT: None

json_serializer

JSON serializer. Default: stdlib.

TYPE: LogSerializerType | None DEFAULT: None

caller_enabled

Include caller (function and line) in log records. Default: False.

TYPE: bool | None DEFAULT: None

otel_enabled

Extract OpenTelemetry trace context.

Default: True if OpenTelemetry is installed, else False.

TYPE: bool | None DEFAULT: None

env_load

Whether to read GREL_LOG_* environment variables. When None (default), follow GREL_ENV_LOAD. Pass True or False to override.

TYPE: bool | None DEFAULT: None

RETURNS DESCRIPTION
LogConfig

The applied LogConfig. Snapshot of what was resolved.

RAISES DESCRIPTION
DependencyNotFoundError

If the selected backend module is not installed.

LogSettingsValidationError

If configuration is invalid.

configure_with

configure_with(config: LogConfig) -> LogConfig

Configure logging from a pre-built LogConfig.

PARAMETER DESCRIPTION
config

Pre-built logging configuration.

Use this path when the configuration is assembled at startup from a settings tree. The environment path is bypassed and the config is used as-is.

TYPE: LogConfig

RETURNS DESCRIPTION
LogConfig

The same LogConfig, for symmetry with configure.

grelmicro.log.uvicorn

Uvicorn-friendly formatters for dictConfig usage.

UvicornFormatter

UvicornFormatter()

Bases: _UvicornBaseFormatter

Format-aware uvicorn formatter compatible with logging.config.dictConfig.

Reads LOG_FORMAT and produces the matching output (AUTO, JSON, LOGFMT, TEXT, PRETTY). No constructor arguments required.

Initialize with settings from environment variables.

format

format(record: LogRecord) -> str

Format the log record.

caller is always disabled (caller_enabled=False) because uvicorn's caller info points to uvicorn internals, which is not useful. The logger field (e.g., uvicorn.error, uvicorn.access) already identifies the source.

UvicornAccessFormatter

UvicornAccessFormatter()

Bases: UvicornFormatter

Format-aware uvicorn access log formatter.

Parses uvicorn's access log tuple arguments into structured fields (client_addr, method, full_path, http_version, status_code).

format

format(record: LogRecord) -> str

Format access records with split request fields.