Skip to main content

Standardized logging context, observation, masking and Kafka schema events for Mobius Python (FastAPI) services.

Project description

Mobius Logging for Python

Python port of the Java Mobius logging library. It standardizes logging context for Mobius FastAPI / Starlette services: a contextvars-based context store (the analog of SLF4J MDC), a request middleware, an @observed method decorator, sensitive-data masking, OpenTelemetry trace sync, JSON logging, and a Kafka schema-event producer.

The Kafka topic, schema id and tenant id come with preconfigured defaults (overridable in setup_logging), so events from Python services land in the same pipeline as the rest of the platform.

Requires Python 3.10+.

Install

pip install mobius-logging-py

# or directly from git
pip install "mobius-logging-py @ git+https://<your-git-host>/mobius-logging-py.git@v1.0.0"

The import package is mobius_logging (e.g. from mobius_logging import setup_logging).

Optional extras: mobius-logging-py[otel] (OpenTelemetry trace sync), mobius-logging-py[fastapi] (Starlette middleware).

Quick start

from fastapi import FastAPI
from mobius_logging import setup_logging, observed, LogType
from py_kafka_producer_client import Producer  # your internal client

app = FastAPI()

setup_logging(
    app,
    service_name="orders-service",
    profile="prod",                       # json logs for staging/prod/production
    sensitive_keys=["session_id", "refresh_token"],
    kafka_producer=Producer(...),         # wrapped in PyKafkaProducerClientSender
)

@app.post("/orders")
@observed(event_type="order.create", log_type=LogType.AUDIT, resource_type="order")
async def create_order(order_id: str):
    ...

setup_logging is the one-call equivalent of Java's Spring auto-configuration (Python has no auto-config, so wiring is explicit). It configures logging, registers custom sensitive keys, builds the schema producer, and adds the request middleware.

Java → Python mapping

Java Mobius logging library Python (mobius_logging)
SLF4J MDC contextvars.ContextVar (context.py)
PlatformLogContext mobius_logging.context functions
PlatformLogFields mobius_logging.fields
LogType enum LogType enum
PlatformLoggingFilter (servlet) PlatformLoggingMiddleware (ASGI)
@PlatformObserved + AOP aspect @observed decorator
KafkaLogProducer (KafkaTemplate) KafkaLogProducer + LogEventSender
PlatformKafka*Context producer_headers / apply_consumer_record
SensitiveDataMasker mobius_logging.masking
LogbackConfigurator configure_platform_logging
Spring auto-config classes setup_logging (explicit)

Out of scope for v1 (present in Java): JDBC/JPA, MongoDB, and Camunda logging.

Context API

from mobius_logging import context, LogType

context.init()                       # sets schema_version
context.tenant_id("tenant-123")
context.log_type(LogType.AUDIT)
context.resource_type("order")
context.resource_id("order-789")
context.field("custom_key", "value")
context.ensure_correlation_id()      # generates one if missing
context.sync_trace_from_opentelemetry()

snap = context.snapshot()
try:
    context.put("event_type", "order.approved")
finally:
    context.restore(snap)

Note: Java's ensureCorrelationId() has an inverted condition and only regenerates when one already exists. This port fixes that — it generates a correlation id when none is present.

@observed

Works on sync and async functions. Adds log_type, event_type, resource_type, class_name, method_name, outcome, method_duration_ms, and exception_type/exception_message on failure. After completion it ships the context to the schema producer (if one is registered), then restores the pre-call context snapshot (Java clears MDC instead).

@observed(event_type="order.create", resource_type="order")
def create_order(order_id: str): ...

Kafka

Schema event producer

The producer depends only on a small protocol, so the library has no hard Kafka dependency. It matches the py-kafka-producer-client (>=0.1.7) signature — the event is a dict and topic is keyword-only:

class LogEventSender(Protocol):
    def send(self, value: dict, *, topic: str) -> Any: ...

For the internal py-kafka-producer-client, pass the client to setup_logging(kafka_producer=...) or wrap it directly:

from mobius_logging import KafkaLogProducer, PyKafkaProducerClientSender, set_log_producer

producer = KafkaLogProducer(PyKafkaProducerClientSender(client), "orders-service")
set_log_producer(producer)

PyKafkaProducerClientSender calls client.send(value, topic=...), passing the DataIngestionOperation envelope as a dict (the client serializes it). To use a different client, pass any object exposing send(value, *, topic) as kafka_sender=.

Sending runs on a background thread pool (best-effort, never raises, never blocks the request) — the analog of the Java @Async method.

Context propagation

from mobius_logging import producer_headers, apply_consumer_record

# producer side
client.send(topic, value, headers=producer_headers())

# consumer side
apply_consumer_record(record.headers(), topic=record.topic(),
                      partition=record.partition(), offset=record.offset())

Propagated header fields: trace_id, span_id, correlation_id, causation_id, tenant_id. Consumer also sets kafka_topic, kafka_partition, kafka_offset.

Logging output

configure_platform_logging(service_name, profile) installs a root handler that injects the current context onto every record. Profiles staging/prod/ production emit JSON; others use a readable text pattern. A daily-rotating file handler writes to logs/<service>.log (30 days retained).

In JSON mode every context field is included automatically. For the text pattern, txn_id, tenant_id, and trace_id are surfaced inline.

Sensitive data masking

from mobius_logging import mask, mask_map, init_custom_keys

init_custom_keys(["session_id", "refresh_token"])
mask("authorization", token)      # masked
mask_map(context.copy())          # masks all sensitive keys in a dict

Default sensitive keys: password, token, secret, authorization, cookie, apikey, privatekey, kubeconfig. Matching is case-insensitive. Masking keeps the last 4 characters of generic values and partially masks emails — identical behaviour to the Java masker.

Development

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mobius_logging_py-1.0.4.tar.gz (19.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mobius_logging_py-1.0.4-py3-none-any.whl (19.3 kB view details)

Uploaded Python 3

File details

Details for the file mobius_logging_py-1.0.4.tar.gz.

File metadata

  • Download URL: mobius_logging_py-1.0.4.tar.gz
  • Upload date:
  • Size: 19.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for mobius_logging_py-1.0.4.tar.gz
Algorithm Hash digest
SHA256 4f011df2b04b1fbc054f9afb137be707db088e79c628b52d7e9ad2a5f96a50db
MD5 ebf2e7abfa9ff6d11221e4fb2ea52c0c
BLAKE2b-256 1e1eb8d65bce47456bd8381c4878aa142e0de71581fd7a6a7fc0fdd68a5f7131

See more details on using hashes here.

File details

Details for the file mobius_logging_py-1.0.4-py3-none-any.whl.

File metadata

File hashes

Hashes for mobius_logging_py-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 7213d63a7af652d8fe2e4bc63295694cd0dec726ab6054912ae926e4fbe860b6
MD5 0667e7580e60fd04bcba0372e45a161e
BLAKE2b-256 798b3ab98c42545bad4dd9587f4a0c26042e5aead1b24b3fef5b5c02c3bf0adb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page