API Reference

logstruct.getLogger(name)[source]

Retrieve or get a StructuredLogger instance.

getLogger(None) will produce a StructuredLogger delegating to the root logger.

Parameters:

name (str | None)

Return type:

StructuredLogger

class logstruct.StructuredLogger(name)[source]

A structured logger forwarding log calls to an underlying stdlib logger with the same name.

The core difference over the stdlib is passing kwargs as the extra dict. It isn’t necessary to use this class to make use of the structured formatter.

Not all methods are proxied. Use the StructuredLogger.logger attribute to reach the stdlib logger.

Parameters:

name (str | None)

__init__(name)[source]

Initialise the underlying stdlib logger.

Parameters:

name (str | None) – Underlying stdlib logger name, None means the root logger.

Return type:

None

critical(msg, *args, exc_info=None, stack_info=False, stacklevel=1, extra=None, **kwargs)[source]

Delegate a critical call to the underlying logger, merging leftover kwargs into extra.

Parameters:
Return type:

None

debug(msg, *args, exc_info=None, stack_info=False, stacklevel=1, extra=None, **kwargs)[source]

Delegate a debug call to the underlying logger, merging leftover kwargs into extra.

Parameters:
Return type:

None

error(msg, *args, exc_info=None, stack_info=False, stacklevel=1, extra=None, **kwargs)[source]

Delegate an error call to the underlying logger, merging leftover kwargs into extra.

Parameters:
Return type:

None

exception(msg, *args, exc_info=True, stack_info=False, stacklevel=1, extra=None, **kwargs)[source]

Call error with exc_info=True.

logging.Logger.exception, fails to increment stacklevel, but somehow gets away with it and manages to find the correct caller frame. We don’t get away with it so we have to increment it.

Parameters:
Return type:

None

getEffectiveLevel()[source]

Get the effective log level of the underlying logger.

Return type:

int

property handlers: list[Handler]

Get handlers of the underlying stdlib logger.

info(msg, *args, exc_info=None, stack_info=False, stacklevel=1, extra=None, **kwargs)[source]

Delegate a info call to the underlying logger, merging leftover kwargs into extra.

Parameters:
Return type:

None

isEnabledFor(level)[source]

Check if the underlying logger is enabled for this method.

Parameters:

level (int)

Return type:

bool

property level: int

Get the log level of the underlying logger.

log(level, msg, *args, exc_info=None, stack_info=False, stacklevel=1, extra=None, **kwargs)[source]

Delegate a log call to the underlying logger, merging leftover kwargs into extra.

Parameters:
Return type:

None

logger: Logger
property name: str

Get the name of the underlying logger.

property parent: Logger | None

Get the parent of the underlying stdlib logger.

setLevel(level)[source]

Set log level of the underlying logger.

Parameters:

level (int)

Return type:

None

warning(msg, *args, exc_info=None, stack_info=False, stacklevel=1, extra=None, **kwargs)[source]

Delegate a warning call to the underlying logger, merging leftover kwargs into extra.

Parameters:
Return type:

None

logstruct.context_scope(**kwargs)[source]

Push variables to the context on enter, restore context on exit.

>>> from logstruct import context_scope, get_context
>>> with context_scope(a=11, b=22):
...     print(get_context())
...
...     with context_scope(a=222, c=33):
...         print(get_context())
...     print(get_context())
{'a': 11, 'b': 22}
{'a': 222, 'c': 33, 'b': 22}
{'a': 11, 'b': 22}
Parameters:

kwargs (object)

Return type:

Iterator[None]

logstruct.add_context(**kwargs)[source]

Associate context key-value pairs with the current scope.

If running without a scope, key-value pairs will be associated with the global scope. They will remain there until cleared.

Parameters:

kwargs (object)

Return type:

None

logstruct.remove_context(*keys)[source]

Disassociate keys from the current scope, leaving other scopes unaffected.

Parameters:

keys (str)

Return type:

None

logstruct.clear_scope()[source]

Clear the current context scope, leaving enclosing scopes unaffected.

Return type:

None

class logstruct.StructuredFormatter(*args, structured_formatter_config=None, **kwargs)[source]

A logging formatter that turns LogRecords into structured data.

Parameters:

structured_formatter_config (StructuredFormatterConfig | None)

format(record)[source]

Format the specified record according to the config.

Key-value pairs are discovered in the log record, the context (unless disabled), and the extra dict passed to the log call. They are merged into a single dict with precedence: extras, context, record.

Mostly a clone of logging.Formatter.format but writes structured data. The self.formatMessage, method, which normally produces a log line prefix, is not called since record attributes are included as data instead. The message itself is still formatted by calling record.getMessage() if enabled by the config.

The reason for mutating the record is compatibility with logging.Formatter which does the same thing.

Parameters:

record (LogRecord)

Return type:

str

usesTime()[source]

Check if “asctime” should be assigned to the log record.

The standard formatter checks if “asctime” is used in the log style. We don’t use the log styles.

Return type:

bool

class logstruct.StructuredFormatterConfig(format_message=True, uses_time=True, log_fields=(LogField(log_record_attr='asctime', struct_key='time', condition=<class 'bool'>), LogField(log_record_attr='name', struct_key='logger', condition=None), LogField(log_record_attr='levelname', struct_key='level', condition=None), LogField(log_record_attr='funcName', struct_key='func', condition=None), LogField(log_record_attr='lineno', struct_key='line', condition=None), LogField(log_record_attr='message', struct_key='message', condition=None), LogField(log_record_attr='exc_text', struct_key='exc_text', condition=<class 'bool'>), LogField(log_record_attr='stack_info', struct_key='stack_info', condition=<class 'bool'>)), get_context_fn=<function get_context>, dumps_fn=functools.partial(<function dumps>, default=<built-in function repr>))[source]

Logrecord formatter config.

Can be used to reflect any LogRecord attribute as a key-value of a dict, later passed to dumps_fn.

A major difference from structlog is that by default the log message goes to the “message” key rather than “event”.

Parameters:
dumps_fn(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=<built-in function repr>, sort_keys=False, **kw)

By default dumps_fn is json.dumps() which will apply repr() to otherwise unserialisable objects, however any serialiser func can be used.

format_message: bool = True

If True, take the message from record.getMessage() otherwise record.msg (unformatted).

get_context_fn()

Get current context as dict, topmost keys win over later keys.

Return type:

dict[str, Any]

log_fields: Sequence[LogField] = (LogField(log_record_attr='asctime', struct_key='time', condition=<class 'bool'>), LogField(log_record_attr='name', struct_key='logger', condition=None), LogField(log_record_attr='levelname', struct_key='level', condition=None), LogField(log_record_attr='funcName', struct_key='func', condition=None), LogField(log_record_attr='lineno', struct_key='line', condition=None), LogField(log_record_attr='message', struct_key='message', condition=None), LogField(log_record_attr='exc_text', struct_key='exc_text', condition=<class 'bool'>), LogField(log_record_attr='stack_info', struct_key='stack_info', condition=<class 'bool'>))
uses_time: bool = True
class logstruct.LogField(log_record_attr, struct_key, condition=None)[source]

A mapping of a single LogRecord attribute to its corresponding output data key.

May contain an optional inclusion condition.

Parameters:
condition: Callable[[Any], bool] | None = None
log_record_attr: str
struct_key: str
logstruct.make_friendly_dump_fn(log_fields=(LogField(log_record_attr='asctime', struct_key='time', condition=<class 'bool'>), LogField(log_record_attr='name', struct_key='logger', condition=None), LogField(log_record_attr='levelname', struct_key='level', condition=None), LogField(log_record_attr='funcName', struct_key='func', condition=None), LogField(log_record_attr='lineno', struct_key='line', condition=None), LogField(log_record_attr='message', struct_key='message', condition=None), LogField(log_record_attr='exc_text', struct_key='exc_text', condition=<class 'bool'>), LogField(log_record_attr='stack_info', struct_key='stack_info', condition=<class 'bool'>)), dumps_fn=functools.partial(<function dumps>, default=<built-in function repr>), colours=False)[source]

Build a function serialising structured data in a developer-friendly way.

A typical message looks like:

2024-08-07 23:10:06,605 INFO     __main__:<module>:35 A message {"key": "val"}

This is not meant to be the only way to serialise logged data in development. Users can supply their own friendly dump function.

Parameters:
Return type:

Callable[[dict[str, object]], str]