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.16.tar.gz (19.8 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.16-py3-none-any.whl (10.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: ume_logging-0.0.16.tar.gz
  • Upload date:
  • Size: 19.8 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.16.tar.gz
Algorithm Hash digest
SHA256 09895483d270f6dadf686a5c6c725d73104204bbac99098d26f67444faa175ac
MD5 eaeeedb2b3bb60878dbe41d86dbefefa
BLAKE2b-256 b102469331324d3e42caf80ddd7f58e1a5d3a7548df0931a0cc2851efa00c6b9

See more details on using hashes here.

Provenance

The following attestation bundles were made for ume_logging-0.0.16.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.16-py3-none-any.whl.

File metadata

  • Download URL: ume_logging-0.0.16-py3-none-any.whl
  • Upload date:
  • Size: 10.4 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.16-py3-none-any.whl
Algorithm Hash digest
SHA256 c30fa98f6d06fe7d6feb59c5292ff0405484f89e68f34d9939b9ccf68122d4fd
MD5 eefdf0952b18e433e9010637c44c256a
BLAKE2b-256 feacf0a7d9faccf6648d0ac1da204bae384041799adfd0022b4886985541742d

See more details on using hashes here.

Provenance

The following attestation bundles were made for ume_logging-0.0.16-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