Skip to content

Utility functions

Helper functions for logs, traces, and custom metrics provided by django-o11y.

Some of these are thin wrappers around structlog or OpenTelemetry primitives. The point is to give your codebase a single import path for observability calls, so you're not scattering direct structlog or OTel imports across every module. If you ever need to swap an implementation detail, there's one place to change it.

Logging (django_o11y.logging.utils)

get_logger

Returns a structlog logger bound to the caller module.

from django_o11y.logging.utils import get_logger

logger = get_logger()
logger.info("checkout_started", order_id=order_id)

add_log_context

Adds key-value pairs to structlog context for the current request or task.

from django_o11y.logging.utils import add_log_context

add_log_context(tenant_id="acme", request_source="web")

clear_custom_context

Clears all bound structlog contextvars.

from django_o11y.logging.utils import clear_custom_context

clear_custom_context()

add_severity

Structlog processor that injects a GCP-compatible numeric severity field into log events. Only needed if you build a custom processor chain outside of build_logging_dict(), or if you ship logs to Google Cloud Logging.

from django_o11y.logging.utils import add_severity
import structlog

structlog.configure(
    processors=[
        structlog.stdlib.add_log_level,
        add_severity,
        # ...
    ]
)

Maps standard levels to Cloud Logging severity values: debug → 100, info → 200, warning → 400, error → 500, critical → 600. Unknown or missing levels fall back to 0 (DEFAULT).

add_open_telemetry_spans

Structlog processor that injects trace_id, span_id, and parent_span_id from the active OpenTelemetry span. django-o11y includes this automatically. Only needed if you build a custom processor chain outside of build_logging_dict().

from django_o11y.logging.utils import add_open_telemetry_spans
import structlog

structlog.configure(
    processors=[
        add_open_telemetry_spans,
        # ...
    ]
)

Fields are omitted when no recording span is active.

Tracing (django_o11y.tracing.utils)

get_tracer

Returns an OpenTelemetry tracer. If name is omitted, uses the caller module (same rule as get_logger).

from django_o11y.tracing.utils import get_tracer

tracer = get_tracer()
with tracer.start_as_current_span("checkout"):
    ...

set_custom_tags

Adds tags to the active span and binds the same values to structlog context.

from django_o11y.tracing.utils import set_custom_tags

set_custom_tags({"tenant_id": "acme", "plan": "pro"})

Tags are written as custom.<key> on spans.

add_span_attribute

Adds one custom.<key> attribute to the active span only.

from django_o11y.tracing.utils import add_span_attribute

add_span_attribute("cart_size", len(cart.items))

get_current_trace_id

Returns the current trace ID as a 32-char hex string, or None if no recording span is active.

from django_o11y.tracing.utils import get_current_trace_id

trace_id = get_current_trace_id()
if trace_id:
    send_to_external_system(trace_id=trace_id)

get_current_span_id

Returns the current span ID as a 16-char hex string, or None if no recording span is active.

from django_o11y.tracing.utils import get_current_span_id

span_id = get_current_span_id()

Metrics (django_o11y.metrics)

counter

Creates a Prometheus counter wrapper.

from django_o11y.metrics import counter

payments_total = counter(
    "payments_processed_total",
    description="Total number of processed payments",
    labelnames=["status", "provider"],
)

payments_total.add(1, {"status": "success", "provider": "stripe"})

Use add(amount=1, attributes=None) to increment the metric.

histogram

Creates a Prometheus histogram wrapper with direct observations and timing support.

from django_o11y.metrics import histogram

checkout_latency = histogram(
    "checkout_seconds",
    description="Checkout processing latency",
    labelnames=["payment_method"],
)

checkout_latency.record(0.84, {"payment_method": "card"})

with checkout_latency.time({"payment_method": "card"}):
    process_checkout()

time() measures elapsed seconds and records it automatically.

Notes

  • Declare label names up front when creating metrics.
  • unit is accepted for API consistency and future compatibility.
  • Custom metrics are registered in the default Prometheus registry and exposed on your configured /metrics endpoint.