Skip to main content

Uniform JSON logging for University Medicine Essen (UME)

Project description

ume-logging

PyPI Python Versions License

Uniform JSON logging for University Medicine Essen applications. Designed for microservices running in Docker/Kubernetes with ELK stack integration.

Features

  • Structured JSON output — Machine-readable logs for ELK/Loki/CloudWatch
  • Context injection — Automatically include app, env, service, request ID in every log
  • Request tracing — Track requests across services with X-Request-ID propagation
  • PII scrubbing — Automatically redact emails and phone numbers from logs
  • OpenTelemetry integration — Trace/span IDs in logs + log→span event bridge
  • FastAPI middleware — Request/response logging with latency tracking
  • User privacy — Hash user identifiers with configurable salt

Installation

pip install ume-logging

# With FastAPI support
pip install "ume-logging[fastapi]"

# With OpenTelemetry support
pip install "ume-logging[otel]"

# Everything
pip install "ume-logging[fastapi,otel]"

Quick Start

import logging
from umelogging import log_configure

log_configure("INFO", app="patient-api", env="prod", service="fhir-import")

log = logging.getLogger(__name__)
log.info("Processing patient records", extra={"count": 42})

Output:

{"time":"2025-01-15T10:30:00","level":"INFO","logger":"__main__","message":"Processing patient records","org":"UME","app":"patient-api","env":"prod","service":"fhir-import","count":42}

Context Management

Track requests and users across your application:

from umelogging import set_context, with_request_id

# Set request ID (or auto-generate with with_request_id())
with_request_id("req-abc-123")

# Track user (automatically hashed for privacy)
set_context(user_id="patient@example.com", component="auth")

# Add custom context
set_context(extra={"tenant": "hospital-a", "study_id": "ST001"})

All subsequent logs will include this context:

{"message":"User authenticated","request_id":"req-abc-123","user":{"hash":"a1b2c3..."},"component":"auth","tenant":"hospital-a"}

PII Scrubbing

Emails and phone numbers are automatically redacted:

log.info("Contact: john.doe@hospital.com, Phone: +49 201 723-0")
# Output: "Contact: [email], Phone: [phone]"

FastAPI Integration

from fastapi import FastAPI
from umelogging import log_configure, UMERequestLoggerMiddleware

log_configure("INFO", app="my-api", env="prod")

app = FastAPI()
app.add_middleware(UMERequestLoggerMiddleware)

@app.get("/patients/{id}")
async def get_patient(id: str):
    return {"id": id}

Every request logs:

{"message":"request.start","method":"GET","path":"/patients/123","request_id":"550e8400-..."}
{"message":"request.end","status":200,"duration_ms":45,"request_id":"550e8400-..."}

The middleware:

  • Extracts X-Request-ID from headers (or generates UUID)
  • Returns X-Request-ID in response headers
  • Measures request latency
  • Sets component context to "http"

OpenTelemetry Integration

Add Trace IDs to Logs

When OpenTelemetry is configured, trace and span IDs are automatically added to every log:

{"message":"Processing","trace_id":"0af7651916cd43dd8448eb211c80319c","span_id":"b7ad6b7169203331"}

Setup Tracing

from umelogging.otel.handler import setup_otel_tracing

setup_otel_tracing(
    service_name="patient-api",
    otlp_endpoint="http://otel-collector:4318",
    sampling_ratio=0.1,  # Sample 10% of traces
)

Mirror Logs to Span Events

Attach logs as events on the current trace span:

import logging
from umelogging.otel.handler import OTelSpanEventHandler

logging.getLogger().addHandler(OTelSpanEventHandler())

Environment Variables

Core Configuration

Variable Description Default
UME_LOG_LEVEL Logging level INFO
UME_APP Application name
UME_ENV Environment (prod/dev/test) prod
UME_SERVICE Service name
UME_COMPONENT Component/module name
UME_USER_HASH_SALT Salt for user ID hashing ume

OpenTelemetry Configuration

Variable Description Default
OTEL_SERVICE_NAME Service name for traces ume-service
OTEL_EXPORTER_OTLP_ENDPOINT Collector endpoint http://localhost:4318
OTEL_EXPORTER_OTLP_HEADERS Headers (key=val,k2=v2)
OTEL_TRACES_SAMPLER_ARG Sampling ratio (0.0-1.0) 1.0

API Reference

log_configure(level, *, app, env, service, component, stream, static_fields, propagate_existing)

Configure the root logger with JSON formatting and PII filtering.

set_context(*, app, env, service, component, request_id, user_id, extra)

Set context variables that are included in all subsequent logs.

with_request_id(request_id=None) -> str

Set or generate a request ID. Returns the ID.

get_context() -> dict

Get current context as a dictionary.

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

License

MIT License — Copyright © University Medicine Essen

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

ume_logging-0.0.17.tar.gz (20.7 kB view details)

Uploaded Source

Built Distribution

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

ume_logging-0.0.17-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file ume_logging-0.0.17.tar.gz.

File metadata

  • Download URL: ume_logging-0.0.17.tar.gz
  • Upload date:
  • Size: 20.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ume_logging-0.0.17.tar.gz
Algorithm Hash digest
SHA256 a627c0b2756a4d1c6c2c8f1244a95b0f16ebaab4cfb149f498d6e90ac2e98097
MD5 714c7355b02a45cf077b044e9f44893f
BLAKE2b-256 49b189d08f7df63e6d3bd73febd5e72a499f510e397af8431cb10ff4f7ce02c6

See more details on using hashes here.

Provenance

The following attestation bundles were made for ume_logging-0.0.17.tar.gz:

Publisher: python-publish.yml on UMEssen/ume-logging

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ume_logging-0.0.17-py3-none-any.whl.

File metadata

  • Download URL: ume_logging-0.0.17-py3-none-any.whl
  • Upload date:
  • Size: 10.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ume_logging-0.0.17-py3-none-any.whl
Algorithm Hash digest
SHA256 f575b24bd4dc6f3711b9ea53fb28a916a85f8d741858520270c3c102553dbdbc
MD5 7b59ac47fd789a61a9d63a27b297adeb
BLAKE2b-256 db55cb341f43ce61f605360ca31ae36f456472152745f71589e6b4bdd3f85d3e

See more details on using hashes here.

Provenance

The following attestation bundles were made for ume_logging-0.0.17-py3-none-any.whl:

Publisher: python-publish.yml on UMEssen/ume-logging

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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