Sum /facts aggregates across backends
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was canceled

A `/facts` aggregate row carries no certname, so the per-certname fact
merge collapsed every backend's rows into one bucket and served a single
backend's numbers.

- Route a `/facts` query whose `extract` carries a `function` column to
  serveSummed, as /nodes, /resources and /reports already do
- Document which extract functions combine correctly across backends
This commit is contained in:
2026-09-06 15:08:33 +10:00
parent c87ecf65e8
commit 49ce1293de
6 changed files with 180 additions and 44 deletions
+10 -1
View File
@@ -131,7 +131,7 @@ func (s *Server) handleQuery(w http.ResponseWriter, r *http.Request) {
case resourcesPath:
s.serveResources(w, r)
case factsPath:
s.serveMerged(w, r, factsPath, s.mergeFactsResponse(r))
s.serveFacts(w, r)
case reportsPath:
s.serveReports(w, r)
case eventsPath:
@@ -212,6 +212,15 @@ func (s *Server) serveUnion(w http.ResponseWriter, r *http.Request, path string,
})
}
// Aggregate rows carry no certname, so the per-certname fact merge would keep only one backend's; they take the summing path instead.
func (s *Server) serveFacts(w http.ResponseWriter, r *http.Request) {
if spec := parseAggregate(r.URL.Query().Get("query")); spec != nil {
s.serveSummed(w, r, factsPath, spec.columns)
return
}
s.serveMerged(w, r, factsPath, s.mergeFactsResponse(r))
}
// A count row carries no certname, so the certname-keyed merge would collapse every backend's count into one backend's; aggregates take the summing path instead.
func (s *Server) serveNodes(w http.ResponseWriter, r *http.Request) {
if spec := parseAggregate(r.URL.Query().Get("query")); spec != nil {