diff --git a/README.md b/README.md index de6d5b6..b47bcf1 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,16 @@ The status page is configured using a yaml config file: prometheus: http://prometheus:9090 services: - name: Postgres + # Optional. Group services together + group: Infra query: # If multiple values are returned, only the first one is used query: sum(pg_up) # The expressions uses https://expr-lang.org and must evaluate to true/false expression: float(pg_up) == 1 - # The time range to calculate the uptime percentage with (default: 24h) + # Optional. The time range to calculate the uptime percentage with (default: 24h) range: 24h - # The resoltuion of the range query (default: 5m) + # Optional. The resoltuion of the range query (default: 5m) step: 5m ``` diff --git a/internal/config/config.go b/internal/config/config.go index d1b7b35..550f305 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -20,6 +20,7 @@ type Query struct { type Service struct { Name string `yaml:"name"` Query Query `yaml:"query"` + Group string `yaml:"group"` // Extras []Query `yaml:"extras"` } @@ -73,6 +74,9 @@ func setDefaults(conf *Config) { if svc.Query.Step == 0 { svc.Query.Step = time.Minute * 5 } + if svc.Group == "" { + svc.Group = "default" + } conf.Services[i] = svc } diff --git a/internal/http/status.go b/internal/http/status.go index 20a8ca8..ff8df64 100644 --- a/internal/http/status.go +++ b/internal/http/status.go @@ -22,9 +22,14 @@ var ( OutageFull = "Full" ) +type group struct { + Name string + Results []collector.Result +} + type statusData struct { Config config.Config - Results []collector.Result + Results []group Age time.Duration Outage string BannerClasses string @@ -49,7 +54,7 @@ func NewStatusPageHandler(app *app.App, cache *ResultCache) echo.HandlerFunc { data := statusData{ Config: *app.Config, - Results: res, + Results: groupResults(res), Age: age.Round(time.Second), Outage: op, BannerClasses: bannerClasses(op), @@ -95,3 +100,27 @@ func bannerClasses(outage string) string { return "bg-orange-400" } } + +func groupResults(res []collector.Result) []group { + grouped := []group{} + // Add the default group at index 0 + grouped = append(grouped, group{Name: "default"}) + + for _, r := range res { + added := false + for i, g := range grouped { + if g.Name == r.Service.Group { + g.Results = append(g.Results, r) + grouped[i] = g + added = true + } + } + if !added { + grouped = append(grouped, group{ + Name: r.Service.Group, + Results: []collector.Result{r}, + }) + } + } + return grouped +} diff --git a/internal/resources/views/index.html b/internal/resources/views/index.html index 9343729..928d2ac 100644 --- a/internal/resources/views/index.html +++ b/internal/resources/views/index.html @@ -17,25 +17,34 @@ {{- end }} -
- {{- range .Results }} -
-
-

{{ .Service.Name }}

- {{ $.Sprintf "%.2f" .Uptime }}% over the last {{ $.PrettyDuration .Service.Query.Range }} -
-
- {{- if not .Success }} - unknown icon - {{- else if .Status }} - up icon - {{- else }} - down icon - {{- end }} + {{- range .Results }} + {{- if .Results }} +
+ {{- if not (eq .Name "default") }} +

{{ .Name }}

+ {{- end }} +
+ {{- range .Results }} +
+
+

{{ .Service.Name }}

+ {{ $.Sprintf "%.2f" .Uptime }}% over the last {{ $.PrettyDuration .Service.Query.Range }} +
+
+ {{- if not .Success }} + unknown icon + {{- else if .Status }} + up icon + {{- else }} + down icon + {{- end }} +
+ {{- end }}
- {{- end }}
+ {{- end }} + {{- end }}
{{/* Footer */}}