A unified observability platform built on Zenoh pub/sub. Visualize telemetry from SNMP, Syslog, NetFlow, Modbus, gNMI, and system metrics in a native Iced GUI.
  • Rust 99%
  • Shell 0.5%
  • Just 0.4%
Find a file
Marc Pardo dc136aa558
feat(gui): Logs-feed time-range picker (#554) (#609)
Add a relative time-range picker to the Logs filter panel (All time / 15 min /
hour / 6h / 24h / 7d). Selecting a window resolves to an absolute `from` bound
against now and drives both:

- the events query — `query_log_events` now pushes `from=`/`to=` selectors, so
  the sensor scopes history server-side from its durable store (#544/#553)
  rather than only the client buffer;
- the filtered export — `LogBundle.from` now carries the range lower bound (the
  live-tail pause point remains the upper bound).

The picker stores only the relative selection in `SyslogFilterState`
(`time_range`); the update handler resolves it to `range_from` with `now_ms()`,
keeping the view pure. `has_active_filters`/`clear` account for it.

Tests: `set_time_range` resolution + bundle mapping (unit), picker row renders
(simulator). Full suite green (461 lib + 152 ui).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 10:01:07 +02:00
.cargo test(snmp): in-process SNMP e2e harness — sim agent, flaky proxy, v3 matrix (#540) 2026-07-23 15:01:38 +02:00
.github/workflows feat(snmp)!: migrate the poller to async-snmp — persistent sessions, GETBULK, retries, no C deps (#526) 2026-07-23 15:25:48 +02:00
configs chore(logs): document new epic-#542 config surface + enable it in the demo profile (#606) 2026-07-24 08:52:06 +02:00
docker feat!: split the repo — zblob and zenkey graduate to their own repos (#518) 2026-07-18 16:13:01 +02:00
docs feat(logs): log sentinel — declarative pattern→alert rules (#543) 2026-07-23 22:27:29 +02:00
flatpak feat: add release workflow for deb, rpm, flatpak, and docker builds 2025-12-28 11:49:34 +01:00
packaging/systemd feat(demo): full-surface just run — hwmon fans/temps, detector suite, sysinfo eBPF 2026-07-16 23:17:07 +02:00
scripts chore(logs): document new epic-#542 config surface + enable it in the demo profile (#606) 2026-07-24 08:52:06 +02:00
zensight feat(gui): Logs-feed time-range picker (#554) (#609) 2026-07-24 10:01:07 +02:00
zensight-common feat(gui): Export logs button on the logs sensor card (#555) (#607) 2026-07-24 09:25:37 +02:00
zensight-correlator feat(snmp): identity evidence for polled devices — observer role (#537) 2026-07-23 17:45:46 +02:00
zensight-exporter-otel refactor(common+gui): one severity model — LogSeverity (#557) 2026-07-24 01:58:14 +02:00
zensight-exporter-prometheus feat(snmp)!: counter semantics — derived rates, wrap/reset detection, typed values, units (#527) 2026-07-23 15:43:34 +02:00
zensight-key-semantic feat(keyspace)!: the version chunk is plain v1, not verbatim @v1 2026-07-14 00:28:04 +02:00
zensight-rerun feat!: the empty base is the legal default — no more implicit "zensight" namespace 2026-07-20 23:21:54 +02:00
zensight-sensor-core feat(snmp): credential hygiene — secret indirection, named sets, scrubbing audit (#538) 2026-07-23 17:53:53 +02:00
zensight-sensor-gnmi feat(snmp)!: counter semantics — derived rates, wrap/reset detection, typed values, units (#527) 2026-07-23 15:43:34 +02:00
zensight-sensor-logs fix(logs): re-parse folded multiline syslog records instead of dropping (#584) 2026-07-24 08:07:00 +02:00
zensight-sensor-modbus feat(snmp)!: counter semantics — derived rates, wrap/reset detection, typed values, units (#527) 2026-07-23 15:43:34 +02:00
zensight-sensor-netflow feat(snmp)!: counter semantics — derived rates, wrap/reset detection, typed values, units (#527) 2026-07-23 15:43:34 +02:00
zensight-sensor-netlink feat!: migrate to zenkey 0.3.1 / zenkey-build 0.3.1 2026-07-19 16:35:35 +02:00
zensight-sensor-netlink-ebpf feat(demo): full-surface just run — hwmon fans/temps, detector suite, sysinfo eBPF 2026-07-16 23:17:07 +02:00
zensight-sensor-netlink-ebpf-common feat(netlink-ebpf): emit ConnRecord at ESTABLISHED for live attribution (tier 2b) (#304) 2026-07-04 23:24:19 +02:00
zensight-sensor-netring feat!: the empty base is the legal default — no more implicit "zensight" namespace 2026-07-20 23:21:54 +02:00
zensight-sensor-parallax feat: RFC 08 §7 payload self-description + sample Encoding 2026-07-19 20:25:04 +02:00
zensight-sensor-snmp feat(snmp): subnet auto-discovery — sweep, identify, propose (#541) 2026-07-23 18:23:10 +02:00
zensight-sensor-sysinfo feat(snmp)!: counter semantics — derived rates, wrap/reset detection, typed values, units (#527) 2026-07-23 15:43:34 +02:00
zensight-sensor-sysinfo-ebpf feat(demo): full-surface just run — hwmon fans/temps, detector suite, sysinfo eBPF 2026-07-16 23:17:07 +02:00
zensight-sensor-sysinfo-ebpf-common feat(demo): full-surface just run — hwmon fans/temps, detector suite, sysinfo eBPF 2026-07-16 23:17:07 +02:00
zensight-sensor-systemd feat!: consume zenkey 0.2 + zblob from crates.io; registry lives in-repo 2026-07-18 21:45:06 +02:00
.dockerignore feat!: split the repo — zblob and zenkey graduate to their own repos (#518) 2026-07-18 16:13:01 +02:00
.gitignore chore: add justfile to build/configure/run GUI + sensors 2026-06-17 09:27:42 +02:00
Cargo.lock Merge pull request #599 from p13marc/logs/554-gui-search 2026-07-24 07:10:22 +02:00
Cargo.toml chore: bump zenkey/zenkey-build to 0.3.2 2026-07-21 06:54:12 +02:00
CHANGELOG.md feat!: the empty base is the legal default — no more implicit "zensight" namespace 2026-07-20 23:21:54 +02:00
CLAUDE.md feat(snmp)!: migrate the poller to async-snmp — persistent sessions, GETBULK, retries, no C deps (#526) 2026-07-23 15:25:48 +02:00
example.yml feat: add release workflow for deb, rpm, flatpak, and docker builds 2025-12-28 11:49:34 +01:00
justfile feat(demo): full-surface just run — hwmon fans/temps, detector suite, sysinfo eBPF 2026-07-16 23:17:07 +02:00
LICENSE chore: add MIT license 2025-12-25 17:57:31 +01:00
README.md feat(snmp)!: migrate the poller to async-snmp — persistent sessions, GETBULK, retries, no C deps (#526) 2026-07-23 15:25:48 +02:00
RELEASING.md chore(release): 0.8.0 — the v1 keyspace 2026-07-16 09:55:07 +02:00

ZenSight

A unified observability platform that sensors legacy monitoring protocols into Zenoh's pub/sub infrastructure.

Overview

ZenSight is a suite of protocol sensors that collect telemetry from many sources and publish it to Zenoh under one data model, a desktop frontend that visualizes it in real time, a correlator that fuses per-sensor identity evidence into one entity per host, and exporters that forward everything to Prometheus / OpenTelemetry. Everything is auto-discovered over Zenoh — add a sensor and it shows up.

Components

Every crate documents itself in its own README.md + docs/ directory; this table links to each. The canonical cross-cutting references live in docs/.

Crate Role
zensight Iced 0.14 desktop frontend (host/incident-centric viewer)
zensight-common Shared model — telemetry, alert/command, identity/evidence/entity, artifact, QoS, keyspace helpers
zensight-sensor-core Shared sensor framework — runner, publishers, health, alerting, identity, artifacts
zensight-sensor-snmp SNMP v1/v2c/v3 polling + trap receiver
zensight-sensor-logs Network syslog (RFC 3164/5424, UDP/TCP/Unix) + systemd journald
zensight-sensor-netflow NetFlow / IPFIX receiver (v5/v7/v9/IPFIX)
zensight-sensor-modbus Modbus TCP/RTU register polling
zensight-sensor-sysinfo Host USE metrics + saturation + threshold alerts
zensight-sensor-gnmi gNMI streaming telemetry (gRPC)
zensight-sensor-netlink Linux kernel networking (RTNETLINK/sock_diag) + sentinel
zensight-sensor-netring Wire-level flow/L7/NDR (AF_PACKET/AF_XDP or pcap) + detectors
zensight-sensor-systemd systemd unit/service/boot telemetry (D-Bus) + sentinel + gated actions
zensight-correlator Fuses identity evidence → one HostEntity per host
zensight-exporter-prometheus Prometheus /metrics + remote-write
zensight-exporter-otel OpenTelemetry OTLP metrics/logs/traces
zenoh-blob Resumable content-addressed large-data transfer over Zenoh

Key expressions

Everything rides the ratified keyspace-v2 convention (v1). zensight is the session namespace, not a key chunk; <origin> is h-<12hex>, derived from the host's machine-id.

zensight/v1/<origin>/<class>/<producer>/<subject...>     data planes
zensight/v1/<origin>/@rpc/<producer>/<procedure...>      request/reply
zensight/v1/<origin>/@media/<producer>/<stream>/…        opaque video
zensight/v1/<origin>/@blob/{artifact,tree,store}/…       bulk content
zensight/v1/@catalog/…                                   the identity catalog

  zensight/v1/h-9706b31ddad3/telemetry/sysinfo/cpu/usage
  zensight/v1/h-9706b31ddad3/state/netlink/health
  zensight/v1/h-9706b31ddad3/@rpc/netlink/sockets

<class> is telemetry (periodic samples), state (LWW documents), or events (append-only). Commands are @rpc GETs, not publications. Never format! a key — use the typed builders in zensight-keyspace.

The deployed-profile summary is docs/KEYSPACE.md; the normative spec is docs/rfcs/keyspace-v2/. The machine-readable truth is zensight-common/registry/*.toml — or ask a running build: zenctl topic list.

Quick start

# Build everything (release)
cargo build --release --workspace

# Build + configure + launch the GUI with the local sensors (netring, netlink,
# sysinfo, logs/journald, systemd, parallax live video). Close the GUI to stop
# everything.
just run

# Or split the two halves:
just gui listen=tcp/0.0.0.0:7447     # just the GUI (non-loopback for remote sensors)
just sensors                         # just the local sensors (Ctrl-C stops them)
just sensors connect=tcp/<gui-host>:7447   # …feeding a GUI on another machine

# One sensor at a time
just netring   # | netlink | sysinfo | logs | systemd | parallax

just run / just gui build the GUI with H.264 live video for parallax streams (openh264 compiled from source → a C++ compiler is required); a plain cargo build --workspace stays codec-free (JPEG previews only).

just sensors spawns five sensors — sysinfo, netlink, netring, logs, systemd — plus parallax if its binary has been built (it is skipped otherwise). As of 0.8.0 parallax is source-only: it ships in no .deb/.rpm, is not in the sensors container image, and has no systemd unit. Build it with cargo build --release -p zensight-sensor-parallax.

To monitor multiple machines, run the GUI (+ correlator) on one host and the all-in-one sensors container (ghcr.io/p13marc/zensight-sensors) on each of the others — the only configuration is ZENSIGHT_ZENOH_CONNECT=tcp/<gui-host>:7447. See docs/DEPLOYMENT.md.

just run pins an explicit loopback rendezvous (the GUI listens on tcp/127.0.0.1:7447; sensors connect to it) so the pieces always find each other without relying on multicast peer discovery — which is unreliable on hosts with a VPN or extra interfaces (tailscale, docker, …). Since the endpoints are pinned, just run also sets ZENSIGHT_ZENOH_SCOUTING=false to turn multicast off; that silences the loopback CONNECTION_TO_SELF / "transport to itself" warnings Zenoh otherwise logs (gossip stays on, so the correlator still finds the sensors). To target specific endpoints, set ZENSIGHT_ZENOH_CONNECT, ZENSIGHT_ZENOH_LISTEN, or ZENSIGHT_ZENOH_MODE (comma-separated), which override the config.

Seeing no data in the GUI? It's almost always discovery — the GUI and sensors didn't form a Zenoh session. just run fixes this; if you launch pieces by hand, give them matching connect/listen endpoints (or the env vars above) instead of bare peer mode.

Install from packages

Each sensor and exporter ships a .deb / .rpm (built by the release workflow) that installs the binary, a hardened systemd unit, and an example config to /etc/zensight/<name>.json5 (a conf-file, so edits survive upgrades). Units are not enabled automatically:

sudo dpkg -i zensight-sensor-sysinfo_*.deb          # or: rpm -i …
sudoedit /etc/zensight/sysinfo.json5                 # point it at your Zenoh router
sudo systemctl enable --now zensight-sensor-sysinfo

See packaging/systemd/README.md for per-unit privileges (most run unprivileged under a transient DynamicUser).

Configuration

All sensors and exporters use JSON5 configs; see configs/ for a working example per crate. Each shares a zenoh block (mode/connect/listen) and a logging block, all overridable via the ZENSIGHT_ZENOH_* env vars. The per-field reference for each crate lives in that crate's docs/.

Data model

Every sensor emits a common TelemetryPoint (full model in zensight-common/docs/data-model.md):

pub struct TelemetryPoint {
    pub timestamp: i64,          // Unix epoch milliseconds
    pub source: String,          // device/host identifier
    pub protocol: Protocol,      // snmp, logs, netflow, modbus, sysinfo, gnmi, netlink, netring, systemd
    pub metric: String,          // metric name/path
    pub value: TelemetryValue,   // Counter | Gauge | Text | Boolean | Binary
    pub labels: HashMap<String, String>,
}

Documentation

  • docs/ — cross-cutting references: ARCHITECTURE (system overview, data flow, lifecycle) · KEYSPACE (the canonical Zenoh key contract) · design/ (archived design rationale).
  • Per-crate docs — each crate's README.md + docs/ is the authoritative reference for that crate (see the Components table above).

Development

cargo test --workspace          # all tests
cargo test -p <crate>           # one crate (gnmi needs protoc; systemd needs systemd-devel)
cargo fmt --all                 # CI enforces rustfmt + clippy -D warnings + a design-system color guard
cargo clippy --workspace

License

MIT — see LICENSE.