pain001.observability package#
Observability surface for pain001: metric events + OpenTelemetry tracing.
Two complementary mechanisms:
emit_metric_event()and theregister_metrics_callback/clear_metrics_callbacks/has_metrics_callbackshelpers implement the in-process metric-event fan-out the generator core has used since v0.0.40. Callbacks seeMetricEventinstances enriched with any active OpenTelemetry trace context.traced(),init_otel(),set_span_attributes(),is_enabled(), andreset_for_tests()(re-exported frompain001.observability.otel) implement opt-in OpenTelemetry distributed tracing. Off by default; flipped on withOTEL_ENABLED=trueandpip install "pain001[otel]".
The two surfaces compose: when OTel is enabled, every
emit_metric_event call attaches the active span’s
(trace_id, span_id, is_remote) to the event so the downstream
metrics backend can correlate metrics back to traces.
- class pain001.observability.MetricEvent(name: str, timestamp: float, attributes: dict[str, ~typing.Any] = <factory>, trace_context: dict[str, ~typing.Any] = <factory>)[source]#
Structured event emitted from processing steps.
- pain001.observability.clear_metrics_callbacks() None[source]#
Remove all registered metric callbacks.
- pain001.observability.emit_metric_event(name: str, **attributes: Any) None[source]#
Emit a structured metric event to registered callbacks.
- pain001.observability.has_metrics_callbacks() bool[source]#
Return True when metrics emission is enabled.
- pain001.observability.register_metrics_callback(fn: Callable[[MetricEvent], None]) None[source]#
Register a callback for structured metric events.
Submodules#
pain001.observability.otel module#
OpenTelemetry tracing surface for pain001 (opt-in, zero-cost when off).
Enterprise teams running pain001 in a microservices mesh need distributed traces across their generator + REST surface alongside Datadog / Honeycomb / Tempo / Jaeger. This module provides a single, env-gated tracing seam that:
defaults to a complete no-op (zero startup or per-call overhead) when
OTEL_ENABLEDis unset or when thepain001[otel]extra is not installed;exposes one decorator (
traced()) the generator and the REST handlers wear unconditionally - the decorator decides at call time whether to create a span;exposes one bootstrap (
init_otel()) called from the CLIservesubcommand and from the FastAPI app’s startup hook so the SDK is initialised once per process.
When enabled, the decorator stamps the span with rich attributes the operator can pivot on:
pain001.message_type- ISO 20022 message type being generated.pain001.row_count- number of payment rows in the batch.pain001.scheme- active scheme profile (sepa-sctetc.).pain001.format- input format (csv,json, …).http.route- the canonical route of a REST handler span.
Span names: pain001.generate (one batch, process_files),
pain001.generate.streaming, pain001.render (template to
string), pain001.validate (XSD), pain001.validate.scheme
(rulebooks), pain001.write (render + validate + file write), and
pain001.api.* for each REST handler.
Configuration via the OpenTelemetry SDK’s own env vars
(OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_SERVICE_NAME, …) so the
operator surface stays the one every OTel-aware tool already uses.
OTEL_ENABLED=true is the master switch pain001 owns on top of
that.
- pain001.observability.otel.OTEL_ENABLED_ENV = 'OTEL_ENABLED'#
Master switch operators flip to opt in to tracing.
- pain001.observability.otel.PAIN001_SERVICE_NAME = 'pain001'#
Default
service.nameresource attribute (overridable byOTEL_SERVICE_NAME).
- pain001.observability.otel.init_otel(service_name: str = 'pain001') Any[source]#
Initialise the OTel SDK once per process and return the tracer.
Idempotent: subsequent calls return the cached tracer without re-initialising. Safe to call when
OTEL_ENABLEDis unset or when thepain001[otel]extra is missing - both cases returnNoneand tracing stays off.- Parameters:
service_name –
service.nameresource attribute. Defaults to"pain001"; override when wrapping pain001 inside a larger service ("acme-payments").- Returns:
The tracer object the rest of the SDK exposes (an
opentelemetry.trace.Tracer), orNonewhen tracing is disabled or the SDK is not installed.
- pain001.observability.otel.is_enabled() bool[source]#
Return
Trueiff the operator has setOTEL_ENABLED=true.A separate env-var name from OTel’s own toggle so pain001 can be instrumented without enabling tracing for every other library in the same process.
- Returns:
Truewhen the env var is one oftrue/1/yes(case-insensitive);Falseotherwise.
- pain001.observability.otel.reset_for_tests() None[source]#
Drop the cached tracer + reset the init flag.
Test-only seam. Production code never resets; the tracer lives for the lifetime of the process.
- pain001.observability.otel.set_span_attributes(**attributes: Any) None[source]#
Stamp the current span with the supplied attributes.
Helper for tracing-aware call sites that want to enrich the span set up by
traced()without restructuring the function. Safe to call when tracing is disabled (no-op) and when called outside any span (no-op).Conventionally pain001 attribute names are kebab-cased and prefixed with
pain001.(pain001.message_type,pain001.row_count).- Parameters:
**attributes – Keyword arguments mapped onto span attributes.
- pain001.observability.otel.traced(span_name: str, attributes: dict[str, Any] | None = None) Callable[[F], F][source]#
Decorate a function so each call becomes an OTel span when enabled.
The decorator is always applied; the per-call decision is made by checking
is_enabled()(cached after the first call). When tracing is off, the wrapper is a singleifplus the original call - effectively free.Coroutine functions (the FastAPI handlers) get an
asyncwrapper so the span stays open acrossawaitand the function is still recognised as a coroutine by the framework. Call sites enrich the span withset_span_attributes().- Parameters:
span_name – Stable, kebab-cased span name (
"pain001.generate","pain001.validate").attributes – Static attributes stamped on every span the decorator opens, such as
{"http.route": "/api/v1/validate"}for a REST handler.
- Returns:
A decorator producing a function that creates a span on each call (when enabled) and propagates the original function’s result + exceptions verbatim.