Payload processing

This page documents payload processing APIs.

Payload processing is split into two layers:

base abstractions
    protocols that define what payload processing means

default implementation
    the built-in processor and its configuration types

The base abstractions are independent from the default implementation. The default implementation uses them, but they are not the same API layer.

Base abstractions

The base payload-processing API contains two protocols:

LogPayloadProcessorProto
LogPayloadProvider

LogPayloadProcessorProto defines what a payload processor must provide.

LogPayloadProvider lets an object provide its own structured logging representation.

class mvx.common.logger.LogPayloadProcessorProto(*args, **kwargs)

Protocol for payload processors.

A payload processor converts arbitrary payload values into log-ready structured data.

normalize_payload(payload, *, unbounded=False)

Normalize a structured payload for logging.

Parameters:
  • payload (Mapping[str, Any]) – payload mapping to normalize.

  • unbounded (bool) – whether item-count limiting should be disabled while normalizing this payload.

Return type:

dict[str, Any]

Returns:

normalized payload dictionary.

normalize_value_for_log(value, *, unbounded=False)

Normalize a single value for inclusion in a log payload.

Parameters:
  • value (Any) – value to normalize.

  • unbounded (bool) – whether item-count limiting should be disabled for this value.

Return type:

str | int | float | bool | bytes | dict[str, Any] | list[Any] | None

Returns:

normalized log-ready value.

get_plain_verbosity_level()

Return the current verbosity level as a plain string.

This method is used by components such as log_invocation to evaluate verbosity-gated field specifications.

Return type:

str | None

Returns:

plain verbosity level, or None if no verbosity level is available.

class mvx.common.logger.LogPayloadProvider(*args, **kwargs)

Protocol for objects that provide their own logging payload.

When an object implements this protocol, its to_log_payload() result is used as the object’s logging representation.

The returned payload is expected to be log-ready. Implementers are responsible for keeping it reasonably sized and free of sensitive data.

This protocol takes precedence over type-based log adapters.

to_log_payload()

Return this object’s structured logging payload.

Return type:

dict[str, Any]

Returns:

log-ready payload dictionary.

Processor protocol

LogPayloadProcessorProto is the contract used by LogContext and logging components.

A processor must be able to normalize:

complete payload mappings
single values

It also exposes the current verbosity level as a plain string. Components such as log_invocation use that string for verbosity-gated field specifications.

The protocol does not require a specific implementation strategy. A custom processor may use any normalization rules as long as it returns log-ready values compatible with the protocol.

Payload provider protocol

LogPayloadProvider is an object-level escape hatch.

When an object implements this protocol, its to_log_payload() result is used as the object’s logging representation.

The returned payload is expected to be log-ready. The object that implements the protocol is responsible for keeping the payload reasonably sized and free of sensitive data.

In the default implementation, LogPayloadProvider takes precedence over type-based log adapters.

Default implementation

LogPayloadProcessor is the built-in payload processor.

It provides conservative default normalization for common Python values and extension points for domain objects.

class mvx.common.logger.LogPayloadProcessor(*, verbosity_level=None, max_str_len=None, max_items=None, log_adapter_resolver=None)

Default implementation of payload normalization.

LogPayloadProcessor converts payload mappings and individual values into log-ready structured data.

The processor supports configurable verbosity, string length limiting, collection item limiting, explicit LogPayloadProvider objects, and optional type-based log adapters.

Create the default payload processor.

Parameters:
  • verbosity_level (LogVerbosityLevel | None) – optional verbosity level. If omitted, NORMAL is used.

  • max_str_len (int | None) – optional maximum string length. If omitted, DEFAULT_MAX_STR_LEN is used.

  • max_items (int | None) – optional maximum number of mapping or sequence items. If omitted, DEFAULT_MAX_ITEMS is used.

  • log_adapter_resolver (Optional[Callable[[Any], Optional[Callable[[Any, LogVerbosityLevel], dict[str, Any]]]]]) – optional callable used to resolve type-based log adapters.

Raises:
  • TypeError – if an argument has an invalid type.

  • ValueError – if max_str_len or max_items is less than 1.

property verbosity_level: LogVerbosityLevel

Return the effective verbosity level.

If no local verbosity level was configured, returns LogVerbosityLevel.NORMAL.

Returns:

effective verbosity level.

set_verbosity_level(verbosity_level)

Set the local verbosity level.

Parameters:

verbosity_level (LogVerbosityLevel) – verbosity level to use.

Return type:

None

Returns:

None.

Raises:

TypeError – if verbosity_level is not a LogVerbosityLevel.

reset_verbosity_level()

Reset the local verbosity level.

After reset, the processor uses LogVerbosityLevel.NORMAL.

Return type:

None

Returns:

None.

property max_str_len: int

Return the effective maximum string length.

If no local value was configured, returns DEFAULT_MAX_STR_LEN.

Returns:

effective maximum string length.

set_max_str_len(max_str_len)

Set the local maximum string length.

Parameters:

max_str_len (int) – maximum string length to use.

Return type:

None

Returns:

None.

Raises:
  • TypeError – if max_str_len is not an integer.

  • ValueError – if max_str_len is less than 1.

reset_max_str_len()

Reset the local maximum string length.

After reset, the processor uses DEFAULT_MAX_STR_LEN.

Return type:

None

Returns:

None.

property max_items: int

Return the effective maximum number of mapping or sequence items.

If no local value was configured, returns DEFAULT_MAX_ITEMS.

Returns:

effective maximum item count.

set_max_items(max_items)

Set the local maximum number of mapping or sequence items.

Parameters:

max_items (int) – maximum item count to use.

Return type:

None

Returns:

None.

Raises:
  • TypeError – if max_items is not an integer.

  • ValueError – if max_items is less than 1.

reset_max_items()

Reset the local maximum number of mapping or sequence items.

After reset, the processor uses DEFAULT_MAX_ITEMS.

Return type:

None

Returns:

None.

property log_adapter_resolver: Callable[[Any], Callable[[Any, LogVerbosityLevel], dict[str, Any]] | None] | None

Return the configured log adapter resolver.

Returns:

log adapter resolver, or None if no resolver is configured.

set_log_adapter_resolver(log_adapter_resolver)

Set the log adapter resolver.

Parameters:

log_adapter_resolver (Callable[[Any], Optional[Callable[[Any, LogVerbosityLevel], dict[str, Any]]]]) – callable used to resolve log adapters for custom values.

Return type:

None

Returns:

None.

Raises:

TypeError – if log_adapter_resolver is not callable.

reset_log_adapter_resolver()

Reset the log adapter resolver.

After reset, no type-based log adapter resolver is used.

Return type:

None

Returns:

None.

normalize_payload(payload, *, unbounded=False)

Normalize a structured payload mapping.

Mapping keys are converted to strings. Mapping values are normalized as individual log values. Item-count limiting is applied unless unbounded is True.

Parameters:
  • payload (Mapping[str, Any]) – payload mapping to normalize.

  • unbounded (bool) – whether item-count limiting should be disabled for this payload.

Return type:

dict[str, Any]

Returns:

normalized payload dictionary.

normalize_value_for_log(value, *, unbounded=False)

Normalize a single value for inclusion in a log payload.

The processor handles primitives, bytes-like values, enums, mappings, sequences, objects implementing LogPayloadProvider, and values supported by the configured log adapter resolver. Unsupported objects are represented by their type name.

Parameters:
  • value (Any) – value to normalize.

  • unbounded (bool) – whether item-count limiting should be disabled for this value.

Return type:

str | int | float | bool | bytes | dict[str, Any] | list[Any] | None

Returns:

normalized log-ready value.

get_plain_verbosity_level()

Return the effective verbosity level as a plain string.

This method is used by components that need string-based verbosity checks, such as verbosity-gated field specs in log_invocation.

Return type:

str | None

Returns:

effective verbosity level name.

Default implementation behavior

The default processor normalizes values using a bounded, log-oriented representation.

It handles:

strings
bytes-like values
integers
floats
booleans
None
enums
mappings
lists and tuples
objects implementing LogPayloadProvider
objects handled by a configured log adapter
unsupported objects

Unsupported objects are represented by their type name.

For mappings, keys are converted to strings and values are normalized individually.

For lists and tuples, items are normalized individually.

String length and collection size are limited by the processor configuration unless item limiting is explicitly disabled for a normalization call.

Verbosity levels

LogVerbosityLevel is part of the default implementation.

It is not required by the base LogPayloadProcessorProto contract, but the built-in processor uses it as its verbosity setting.

enum mvx.common.logger.LogVerbosityLevel(value)

Verbosity levels used by the default payload processor.

The level controls how much detail the default processor and related helpers may include when converting values to log payloads.

Member Type:

str

Valid values are as follows:

MINIMAL = <LogVerbosityLevel.MINIMAL: 'MINIMAL'>

Minimal payload detail.

NORMAL = <LogVerbosityLevel.NORMAL: 'NORMAL'>

Default payload detail.

MAXIMUM = <LogVerbosityLevel.MAXIMUM: 'MAXIMUM'>

Maximum payload detail.

Default limits

The default processor uses two built-in limits when no local values are configured.

DEFAULT_MAX_STR_LEN = 200
    default maximum string length

DEFAULT_MAX_ITEMS = 10
    default maximum number of mapping or sequence items

These constants belong to the default implementation.

Adapter types

The default processor can use type-based log adapters.

LogAdapter is the callable type used to convert a custom object into a log-ready payload dictionary.

LogAdapter = Callable[[Any, LogVerbosityLevel], dict[str, Any]]

The callable receives the value being normalized and the current verbosity level.

LogAdapterResolver is the callable type used to resolve an adapter for a value.

LogAdapterResolver = Callable[[Any], LogAdapter | None]

The resolver receives the value being normalized and returns an adapter for that value, or None if no adapter is available.

These aliases belong to the default implementation. They are not part of the base processor protocol.

Custom object normalization order

The default processor tries custom normalization before falling back to generic normalization.

The order is:

1. LogPayloadProvider.to_log_payload()
2. configured LogAdapterResolver and returned LogAdapter
3. built-in normalization rules

If a LogPayloadProvider returns a dictionary, that dictionary is used.

If provider handling fails or does not return a dictionary, the processor falls back to the next option.

If a resolver is configured and returns an adapter, the adapter is called with the value and the current verbosity level.

If adapter handling fails or does not return a dictionary, the processor falls back to built-in normalization rules.

Bounded normalization

The default processor limits output size by default.

max_str_len limits long strings and mapping keys.

max_items limits mapping entries and sequence items.

If a collection has more items than the effective limit, the processor adds a marker showing that more data exists.

The unbounded argument disables item-count limiting for that normalization call. It does not disable string length limiting.