Observability
Opt-in, dependency-free logging + tracing. openvc emits structured events on
logging.getLogger("openvc") at the resolve / fetch / status / verify boundaries and
wraps each in an optional span you can wire to
OpenTelemetry. Both are off by default and never carry secrets.
openvc.observability
openvc.observability — optional, dependency-free logging + tracing hooks.
On a production failure an operator otherwise gets only an exception and no trace of which
hop or check produced it. openvc emits structured events on the stdlib logger
logging.getLogger("openvc") at the resolve / fetch / status / verify boundaries,
and wraps each in an optional tracing :func:span an integrator can wire to OpenTelemetry
via :func:set_span_hook.
Both are off by default and dependency-free: the logger is silent until the application
attaches a handler and sets a level (standard stdlib logging — openvc never configures
handlers or calls basicConfig), and the span hook is a no-op until installed. No
tracing dependency enters core.
Never logs secrets. Events and span attributes carry public identifiers only — the
credential format, an issuer / subject DID, the DID or URL host being resolved, and a
check's outcome. Private-key material, token bytes, proofValue, SD-JWT disclosures and
claim contents are never logged.
Enable logs::
import logging; logging.getLogger("openvc").setLevel(logging.DEBUG)
Wire tracing to OpenTelemetry::
from opentelemetry import trace
from openvc.observability import set_span_hook
tracer = trace.get_tracer("openvc")
set_span_hook(lambda name, attrs: tracer.start_as_current_span(name, attributes=attrs))
set_span_hook(hook)
Install a span factory called around each resolve / fetch / status / verify
boundary — e.g. one that opens an OpenTelemetry span. Pass None to reset to the
no-op default. The hook receives (name, attributes) where attributes are public
identifiers only (never keys/tokens); the returned context manager is entered for the
duration of the operation (so it also observes any exception on exit).
Source code in src/openvc/observability.py
60 61 62 63 64 65 66 67 | |
span(name, **attributes)
A tracing span around an operation — a no-op unless a hook is installed via
:func:set_span_hook. Pass only public identifiers as attributes (never secrets).
Observability never changes a verification outcome. A hook that errors on enter or
exit is logged and ignored, and a hook can not suppress the wrapped operation's
exception — it always propagates regardless of the hook's __exit__ return value —
so a buggy tracing hook can never turn a fail-closed check (e.g. an unreachable status
list) into a fail-open one.
Source code in src/openvc/observability.py
70 71 72 73 74 75 76 77 78 79 80 81 82 | |