Repository navigation
feat(proxy): vm_service_map action for VM fleets on a Prometheus datasource - #167
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces the vm_service_map action on http-proxy Prometheus datasources, allowing the construction of a VM fleet call graph from node-agent series. It adds a standalone servicemap CLI subcommand, documentation, and tests. Feedback on the implementation highlights a potential integer overflow bug in pkg/proxy/http/vmservicemap.go when maxResp is equal to math.MaxInt64, which would cause io.LimitReader to immediately return EOF.
43dadd8 to
817dffc
Compare
…source The server can already read a VM's metrics through the forager but had no way to ask which service calls which: that needs the node-agent's per-container connection series joined per host, and pulling the raw series over the relay to do it is far more than the answer. Add the vm_service_map action to the http proxy. It runs a fixed set of queries against the datasource's store and returns the hosts that reported, the active services on them (systemd units and containers, with image, application types and listen addresses), and per-call requests, errors, average latency and bytes between services. A destination that belongs to a reporting host is resolved to that host and the service listening on the port. Failures use the same verdict as the Kubernetes runner's service map. Nothing from the request reaches PromQL. Also add `nudgebee-forager servicemap --url ...` so the answer can be checked against a store without a relay. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
817dffc to
86cf821
Compare
mayankpande88
left a comment
There was a problem hiding this comment.
Checked the query set against the series node-agent actually writes (node-agent @ d64f632). Metric names, group-by labels, histogram _sum/_count, the ok/failed statuses and IP:port destinations for vm/private kinds all line up, and go test -race ./pkg/proxy/http/ passes.
Two things to fix before merge (inline): loopback calls never reach the resolver with the agent's default config, and gRPC failures are not counted as errors. Plus:
- HTTP error verdict: the PR body says 5xx, code and docs say 4xx/5xx. Please pick one; counting 4xx makes every 404/401 an error.
- Public repo: the PR body links issues/PRs in a private repo, and the docs name internal components (see inline). Please describe these generically ("the server").
Fix the integer overflow in instantQuerier's read limit when max_response_bytes equals math.MaxInt64, cancel outstanding queries on the first error instead of letting up to 24h of them keep running, and count gRPC failures (status="grpc:<CODE>" on container_http_requests_total) as HTTP errors since the existing 5xx/failed pattern can't match them. Drop the loopback-address resolution path: with the agent's default config a same-host call never carries a loopback IP, it arrives as the name "localhost/localhost" (kind localhost) with no port to resolve against a listener. Stop dropping it and instead normalize its kind explicitly, so the call stays visible as an edge to "localhost" rather than disappearing or being mislabeled "external". Revert the failure verdict to 5xx-only (4xx included every 404/401), and reword the docs and code comments to describe internal components generically for the public repo. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Pushed c496b45 addressing all review feedback:
|
Description
The server can already read a VM's metrics through the forager, but had no way to ask which VM calls what. This adds a
vm_service_mapaction to the HTTP proxy on a Prometheus datasource: it returns the hosts that reported in a window and, per call, requests, errors, average latency and bytes, built from the node-agent series.Decision: The forager computes the answer next to the store and returns a small result; the alternative was the server pulling the raw connection series over the relay and joining them itself. The action sends a fixed query set only, so unlike
http_requestit cannot be used to read anything else from the store.Look at:
pkg/proxy/http/vmservicemap.go— the PromQL set and how errors are decided (HTTP5xx,failedfor other protocols). The wire shape is documented indocs/proxy-modules.mdand is what the server reads.Part of an internal initiative to let the server build a call graph for VM fleets.
Type of change
How Has This Been Tested?
nudgebee-forager servicemap --url http://<prometheus>:9090 --window 15mon a host that can reach a store holding node-agent series: printshosts(one per reporting VM, with its instance id and addresses) andedges(one per call).vm_service_mapwith the datasource id of the Prometheus datasource andstart/end.Unit tests cover the aggregation, errors/latency, the TCP fallback and the request path against an HTTP store; the sample label sets in them were copied from a live store.
Checklist
make validatepasses (fmt + lint + test,-race)Engineering detail
endover a[window]range:last_over_timefor the four host series,increase()for counters, summed byinstance, destination, destination_workload_kind, destination_workload_name.instanceis the node-agent's machine id (ormd5(machine_id + system_uuid)when a system UUID is present), as written by remote-write, so hostname and cloud instance id join throughnode_infoandnode_cloud_infoon it.localhost(kindlocalhost) with no address, so it cannot be resolved to a specific local service; it still shows as a visible, unresolved edge tolocalhostrather than being dropped or mislabeled.status="grpc:<CODE>"label, caught by a second, separate PromQL query since gRPC statuses can't share a single regex with HTTP status codes.truncatedis set), response size follows the datasource'smax_response_bytes, 8 concurrent queries; the first failing query cancels the rest.error_codefor "this store has no node-agent series" (an empty map is returned), and non-AWS cloud labels.