Result logging

This example shows how log_result_on_success adds selected return-value data to the success payload.

Result logging is opt-in. By default, log_invocation does not log operation results.

Example

from dataclasses import dataclass

from mvx.common.logger import LogContextProto, LogEvent, LogLevel, log_invocation


@dataclass(frozen=True, slots=True)
class Session:
    session_id: str
    ttl_ms: int


class SessionService:
    def __init__(self, log_context: LogContextProto) -> None:
        self._log_context = log_context

    def get_log_context(self) -> LogContextProto | None:
        return self._log_context

    @log_invocation(
        "create_session",
        log_result_on_success=("session_id", "ttl_ms"),
    )
    def create_session(self, user_id: str) -> Session:
        return Session(session_id=f"session-{user_id}", ttl_ms=30_000)

The decorated public API operation is create_session.

The selected result fields are:

session_id
ttl_ms

The method still returns the original Session object. Result logging does not replace or modify the return value.

Emitted records

A successful call:

result = service.create_session("u1")

returns:

Session(session_id="session-u1", ttl_ms=30_000)

and emits records conceptually equivalent to:

[
    {
        "event_name": "create_session",
        "event_outcome": "invoke",
        "payload": {},
    },
    {
        "event_name": "create_session",
        "event_outcome": "success",
        "payload": {
            "result": {
                "session_id": "session-u1",
                "ttl_ms": 30000,
            },
        },
    },
]

The invoke payload is empty because this example does not use context_fields, log_kwargs_on_invoke, or closure values.

The success payload contains the selected result data under the result key.

Why result logging is explicit

Operation results may contain sensitive or large data.

For example:

access tokens
raw backend responses
large buffers
objects with internal state

log_result_on_success makes result logging explicit. The decorated method chooses which parts of the result are safe and useful to expose.

What this example demonstrates

This example demonstrates selected result logging for a composite result object:

operation result -> selected attributes -> payload["result"]

It also shows that result logging happens only for the success outcome:

invoke  -> no result
success -> selected result fields

Use this pattern when the result object contains a few stable diagnostic fields that are useful in logs.