Skip to content

v0.3.0 — Operational visibility & distribution

Latest

Choose a tag to compare

@AndreaBozzo AndreaBozzo released this 26 Jul 12:32
· 9 commits to main since this release
485ecbb

Nephtys now ships as a multi-architecture container image, exposes a coherent nephtys_-namespaced metrics surface, and comes with a provisioned Grafana operations dashboard that works from docker compose up with nothing to import.

docker run --rm ghcr.io/andreabozzo/nephtys:0.3.0 --version

Images are published for linux/amd64 and linux/arm64 as 0.3.0, 0.3, and latest.

⚠️ Breaking: metric names

Every Prometheus metric gained the nephtys_ prefix. Label sets, help text and histogram buckets are unchanged — this is a rename only, and the old names are not dual-emitted. Update scrape rules, alerts and dashboards:

Old New
events_ingested_total nephtys_events_ingested_total
events_dropped_by_pipeline_total nephtys_events_dropped_by_pipeline_total
events_published_total nephtys_events_published_total
bytes_ingested_total nephtys_bytes_ingested_total
bytes_published_total nephtys_bytes_published_total
event_processing_duration_seconds nephtys_event_processing_duration_seconds
dedup_cache_size nephtys_dedup_cache_size
dedup_cache_evictions_total nephtys_dedup_cache_evictions_total
nephtys_stream_state unchanged

Go runtime and process collector series (go_*, process_*, promhttp_*) keep their standard names. Pre-1.0 the compatibility promise does not extend to metric names, and this was the last cheap moment to fix the namespace before adopters pinned it.

Highlights

Distribution — multi-arch images on GHCR, built from a hardened Dockerfile: runs as nonroot (uid 65532), version stamped through a build arg so --version reports a release rather than a commit hash, and cross-compiled so the arm64 leg never runs the Go toolchain under emulation. Pull requests build the image in a job holding no registry credential.

Operations dashboarddocker compose up -d yields a Grafana with the Prometheus datasource and a Nephtys — Operations dashboard already provisioned. Per-stream state, ingest/publish event and byte rates, drops broken down by middleware, latency quantiles, and dedup cache saturation against configured capacity, scoped by Instance and Stream variables. The dashboard JSON is committed under deploy/grafana/ and reviewed as source. An optional nephtys compose service behind a profile runs the published image inside the stack.

Stream health — one-hot nephtys_stream_state{stream_id,state} plus additive health and last_message_at fields on GET /v1/streams. New nephtys_dedup_cache_capacity gauge makes dedup saturation computable from metrics alone.

WebSocket on_connect_send — frames sent verbatim after every handshake including reconnects, unlocking sources that require a subscribe or auth frame.

Notable fixes

  • Binary payloads were being corrupted by the pipeline. Dedup hashed the empty JSON payload, giving every binary event the same hash and dropping all but the first as a duplicate; batch discarded binary data and its content type entirely.
  • Batch silently discarded buffered events when a stream was stopped or its pipeline hot-swapped. It now drains before exiting.
  • NEPHTYS_LOG_LEVEL was a documented no-op — loaded into config but never applied, so debug did nothing.
  • Grafana never started in the compose stack: recent releases refuse to boot the rendering service while renderer_token is at its default, so the container exited during boot.
  • Compose NATS was perpetually unhealthy — the distroless image has no wget for its own healthcheck.
  • The Wikimedia SSE example published nothing — it filtered on payload type values, but filter matches the envelope type the connector sets, which for SSE is the event: frame name.
  • Unregistered streams leaked metrics — all per-stream series now go away with the stream.

Evaluation

The peer-reviewed comparison against Node-RED 5.0.1 (IEEE UIC 2026 short paper, accepted) is summarized in docs/benchmarks/: 19.5 ± 0.1 MB vs 128.5 ± 0.4 MB tool RSS on a Raspberry Pi 5 at identical filtering results and matching event-sequence hashes. Wall power was indistinguishable between the two systems — the board's idle floor dominates at 40 events/s — so the footprint buys memory headroom for co-located workloads, not lower energy.

Full changelog: v0.2.0...v0.3.0