Skip to content

observability

This crate is the single happy-path entrypoint for PromptFleet observability. It installs global structured logging once (via observability_core) and provides a shareable Obs handle that subcomponents (A2A client/server, LLM client, etc.) can accept as Arc<dyn ObsHandle>.

Design goals:

  • One initializer (Obs::init) per process
  • One handle (Obs) passed into subcomponents
  • Backend-agnostic usage (OTEL / Prometheus are optional, best-effort)
type ObsResult = observability_core::ObservabilityResult<T>;

Convenience result type for the facade.

type SharedObs = Arc<dyn ObsHandle>;

A small, stable interface that subcomponents can depend on.

Prefer taking SharedObs (Arc<dyn ObsHandle>) in A2A/LLM components.

Required / Provided Methods

fn span(&self, name: &str, attrs: &[(&str, &str)]) -> observability_core::SpanGuard

Start a span. The returned guard ends the span on drop.

fn metric(&self, name: &str, value: f64, labels: &[(&str, &str)])

Record a metric (counter/histogram/gauge depending on backend configuration).

fn log(&self, level: LogLevel, message: &str, fields: &JsonValue) -> ObsResult<()>

Emit a structured log event (best effort).

fn log_kv(&self, level: LogLevel, message: &str, fields: &[(&str, &str)])

Emit a log event with low-cardinality key/value fields.

This method is intentionally always available (no serde types in the signature). When the logging feature is disabled, it becomes a best-effort no-op.

fn flush(&self) -> ObsResult<()>

Flush any buffered telemetry (best effort).

fn health(&self) -> ObsHealth

Health status of configured backends (best effort; does not do network probes).

Main facade handle. Cloneable and cheap to pass around.

Methods

fn noop() -> Self

Create a no-op handle (spans/metrics/logging are best-effort no-ops).

Useful for tests and for components that want an Obs even when observability is not configured.

fn init_from_env() -> ObsResult<Self>

Initialize from process environment.

This intentionally stays minimal: it uses OTEL/Prometheus env helpers from backend crates when those features are enabled.

fn extract_context(headers: &HashMap<String, String>) -> ObsResult<Option<observability_core::W3CTraceContext>>

Extract W3C trace context from inbound headers.

fn inject_context(headers: &mut HashMap<String, String>, context: &observability_core::W3CTraceContext)

Inject W3C trace context into outbound headers.

fn init(cfg: ObservabilityConfig) -> ObsResult<Self>

Initialize global logging once and configure optional backends.

Call this once during agent startup and pass the returned handle into all subcomponents (A2A client/server, LLM client, etc.).

fn maybe_flush(&self) -> ObsResult<()>

Flush buffered telemetry at most once per configured interval.

This is intended for WASM request-driven workloads (SpinKube): call at the end of request handling to ensure spans/metrics/logs are exported within bounded time without flushing on every single request.

fn shared(self) -> SharedObs

Fields

FieldTypeDescription
loggingbool
otelOption&lt;bool&gt;
prometheusOption&lt;bool&gt;
notesVec&lt;String&gt;

Unified configuration for the happy path.

Fields

FieldTypeDescription
service_nameStringService identity (used for correlation fields and backend configs).
service_versionString
service_namespaceString
loggingobservability_core::ObservabilityConfigGlobal structured logging configuration (installed once per process).
otelOtelConfigOptional OTEL exporter configuration.
prometheusPrometheusConfigOptional Prometheus exporter configuration.

Methods

fn with_service<impl Into<String>, impl Into<String>, impl Into<String>>(self, name: impl Into, version: impl Into, namespace: impl Into) -> Self
fn from_env() -> Self

Build an ObservabilityConfig from environment variables.

Supported (minimal) env vars:

  • Service identity: OTEL_SERVICE_NAME, OTEL_SERVICE_VERSION, OTEL_SERVICE_NAMESPACE
  • Logging:
    • Filtering: OBS_LOG_LEVEL (PromptFleet) or RUST_LOG (Rust ecosystem)
    • Format: PF_LOG_FORMAT (PromptFleet) or OBS_LOG_FORMAT (back-compat) or LOG_FORMAT (alias)
    • Flags: OBS_LOG_STRUCTURED, OBS_LOG_CONTEXT
  • OTEL: OBS_OTEL_ENABLED, OBS_OTEL_METRICS_ENABLED, OTEL_EXPORTER_OTLP_ENDPOINT, OBS_OTEL_SAMPLING, OBS_OTEL_SAMPLING_RATIO
  • Prometheus: OBS_PROMETHEUS_ENABLED, PROMETHEUS_PUSHGATEWAY, PROMETHEUS_JOB_NAME, PROMETHEUS_INSTANCE
fn from_value(root: &ConfigValue) -> Self

Build an ObservabilityConfig from a JSON value (typically produced by pf_config).

Expected shapes (both accepted):

  • { "observability": { ... } }
  • { ... } (the observability object directly)

Missing fields fall back to defaults.

Fields

FieldTypeDescription
enabledbool
metrics_enabledbool
otlp_endpointString
batch_sizeusize
export_timeoutweb_time::Duration
samplingOtelSampling

Methods

fn disabled() -> Self

Fields

FieldTypeDescription
enabledbool
pushgateway_endpointOption&lt;String&gt;
job_nameString
instanceString
push_intervalweb_time::Duration
cardinality_reductionbool
max_cardinalityusize

Methods

fn disabled() -> Self

Variants

VariantDescription
AlwaysOn
AlwaysOff
TraceIdRatio(f64)
ParentBased