v0.7.0: the clients and the labels
v0.7.0 is about the words your data is filed under and the surfaces that read it. v0.6 opened both ends of the pipe; what arrived was only as useful as the vocabulary available to slice it — and, it turned out, as truthful as the map drawing it.
-
Slice telemetry by the words your organisation already uses. A cluster encodes ownership in labels —
team=payments,tier=critical— and none of it reached the product. Map one intags.labelsand it rides every signal asavuru.tag.<key>, applied where telemetry is collected, so the workloads nobody instrumented are tagged too. The discovered keys and their values are offered as filter controls on traces and logs, so nobody has to remember what the cluster is labelled with, and both screens share one filter string — a link carries between them. A trace matches when any service that took part carries the tag, not only the one that started it: filtering by a team shows the requests that reached it, not just the ones it began. Deliberately bounded — every mapped tag is a dimension on the metrics it touches, so the chart refuses more than twelve. -
Let a service say what it is. Services exporting OTLP straight to the gateway carry no Kubernetes namespace, so they all collapsed into one
(unlabeled)group: correct, and useless. Now a service can setservice.namespace,deployment.environment.nameandavuru.tieras resource attributes and the health board groups it accordingly — across Kubernetes namespaces, one domain becoming one group per environment with its own tier. Operator config still has the last word, and a declaration the hub cannot use (anavuru.tierthat is not a tier) falls back to the default and says so on the board, because a fail-soft rule that stays silent is how a team never learns their declaration did nothing. -
Two more clients of the same API. The
avuruobsCLI readsservices,health,traces,logsandstatuswith a personal API token, and gates a pipeline:avuruobs health --fail-on 'status!=healthy'exits 2 when the predicate matches, 1 when the command itself failed and 0 when nothing matched — three different things a deploy gate must tell apart, since with a single non-zero exit an expired token returns no rows and the gate reads "nothing over threshold" as success. It has no third-party dependencies. A Grafana data source brings service RED, service health, trace search and cross-zone traffic into dashboards you already run; it is a backend plugin, so the API token never reaches a browser and queries leave the Grafana server — a hub reachable only inside the cluster still works. -
Every screen links to the page that explains it. A small
docs ↗beside the breadcrumb, because the question "what am I looking at?" is asked while looking at the screen. -
Cross-zone traffic, explained. Cloud providers bill data that crosses an availability zone, and the usual way to find out why is a flow-log pipeline. The sensor already watches every connection in the kernel:
sensor.obi.network.interZone.enabledturns that into a byte matrix per zone pair. It works on its own — it does not require the per-edge network feature — so the number of series is the number of zones a cluster spans, not the number of workload pairs.
Fixed
-
A mesh hop is not a dependency. On a cluster running a service mesh every application call is intercepted by a proxy, so what reached the service map was
app → proxy → app: two edges, neither of them a dependency, joining services that never talk to each other. The hub now recognises transport workloads — mesh sidecars, waypoint and ztunnel proxies, ingress and egress gateways — and the map hides them behind a Show mesh & gateways toggle. The classification is a name match and therefore install-specific, so it is configurable and hot-reloaded:topology.transportadds patterns for a mesh the built-ins do not know,topology.applicationsrescues a real service they catch. Deliberately narrow by default — erasing a real service from the map is a worse failure than the noise removed. -
The map counted connections as calls. Edges derived from kernel flows carry no call volume by construction, so a map showing "5 call edges" could have observed no calls at all. Traced calls and observed network flows are now counted apart, a flow-only edge is drawn dotted, and hovering it says "network flow · no traced calls" instead of claiming 0 rpm.
-
Turning on network flows stopped the sensor instead of enriching it.
sensor.obi.network.enabled=truerendered a sensor config with the sameattributes:key twice. Nothing on the Kubernetes side validates that — it is a ConfigMap value, not a manifest — but the sensor parses it strictly and refuses to start on a repeated key, so the whole eBPF container crash-looped and took traces, flows and per-edge health with it. Two further keys in the same block were not fields the sensor has at all, leaving TCP-stats collection inert and the documented cardinality bound unapplied — which means those metrics carried source and destination IP addresses, a series per address pair. All three are fixed, and rendered configs are now parsed in the chart's own tests, so a document the sensor cannot load fails the build. If you had per-edge network health enabled, it is worth re-checking the sensor pod.
Upgrading from v0.6.x is a normal helm upgrade. Everything added here is
off or unchanged by default: no tags are mapped until you map one, inter-zone
accounting is opt-in, and an install with no service mesh sees a byte-identical
service map. See the Releases page and the
GitHub release.