Import and harden the OpenTelemetry logging work from #1382. Preserve default stderr behavior, register and validate RuView semantic conventions, attach a published schema, enable TLS roots, pin demo images, and fix first-CSI node lifecycle reporting. Supersedes #1382 Closes #1460 Co-authored-by: Jens Holdgaard Pedersen <jens@holdgaard.org>
4.5 KiB
Observability: OTLP log export
The sensing server can export every tracing log event as an
OpenTelemetry log record over OTLP, with a curated set of sensing events
(presence transitions, vitals estimates, node online/offline, fall
detections, CSI capture stats, MQTT errors, model loads) carrying
registry-backed event names and attributes under the ruview.*
namespace.
The event registry
The names are not ad hoc: they are defined in a weaver-validated
semantic-conventions registry at semconv/registry/ (attributes and log
event names, OpenTelemetry registry format). The Rust constants module
v2/crates/wifi-densepose-sensing-server/src/semconv.rs is generated
from that registry (weaver registry generate, template under
templates/registry/rust/) and CI (.github/workflows/semconv.yml)
fails if either the registry stops validating or the generated module
drifts. Executed Rust tests additionally reject any hard-coded
ruview.* instrumentation key that is absent from the generated registry.
Exported resources carry the registry's schema URL so downstream consumers
can identify the exact conventions version.
Curated events:
| Event | Emitted when |
|---|---|
ruview.node.online |
first frame from a sensing node (CSI or edge vitals) |
ruview.node.offline |
node evicted after 60 s without frames |
ruview.presence.changed |
smoothed presence classification flips (transition-only) |
ruview.vitals.estimate |
periodic breathing / heart-rate estimate (every 100 ticks) |
ruview.fall.detected |
edge-vitals fall flag rising edge, per node |
ruview.csi.stats |
periodic capture snapshot: frames processed, active nodes |
ruview.mqtt.error |
MQTT publish/connection error in the HA publisher |
ruview.model.loaded |
inference model loaded via the model API |
Enabling export
Export is doubly gated so the default build and the default runtime are both unaffected:
-
Build with the
otelcargo feature (compiles in the OTLP exporter stack, same gating principle asmqtt):cargo build --release -p wifi-densepose-sensing-server --features mqtt,otel -
Run with
OTEL_EXPORTER_OTLP_ENDPOINTset (unset ⇒ the OTLP pipeline is never constructed and logging behaves exactly as before):OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \ ./target/release/sensing-server --source simulated
Use an https:// collector endpoint outside a trusted local network. The
otel feature includes Rustls and native certificate roots; standard OTLP
environment variables can supply authentication headers. The Compose example
uses plaintext only for container-to-container traffic on its private network.
Logs export with resource attribute service.name = "ruview" and schema URL
https://raw.githubusercontent.com/ruvnet/RuView/main/semconv/schema/ruview-0.1.0.yaml.
Curated sensing
events are emitted only after the configured exporter initializes
successfully; without it, the pre-existing stderr output is unchanged.
Full stack: docker compose
docker/otel-compose.yml brings up the whole pipeline —
sensing server (synthetic CSI by default) → OpenTelemetry Collector →
Ourios, an OTLP-native log
backend built on Parquet + online log-template mining + DataFusion:
docker compose -f docker/otel-compose.yml up
The collector and backend image tags are pinned to immutable multi-platform digests so the demo resolves to the reviewed images.
Ourios derives the tenant from service.name, so all RuView logs land
in tenant ruview.
Example queries
Ourios mines every log line into a stable template_id online at
ingest, which makes template-level questions cheap. Its query endpoint
speaks a small logs DSL:
Which log templates dominate RuView's output?
curl -s http://localhost:4319/v1/query \
-H 'X-Ourios-Tenant: ruview' \
-H 'Content-Type: text/plain' \
-d 'severity >= trace | range(-1h, now) | count by template_id | sort count desc | limit 10'
Recent warnings and errors (fall detections, MQTT failures):
curl -s http://localhost:4319/v1/query \
-H 'X-Ourios-Tenant: ruview' \
-H 'Content-Type: text/plain' \
-d 'severity >= warn | limit 50'
Did a RuView deploy change what the service logs? Template drift between two time windows (new / vanished / changed templates):
curl -s http://localhost:4319/v1/query \
-H 'X-Ourios-Tenant: ruview' \
-H 'Content-Type: text/plain' \
-d 'drift from -7d to now'