Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions grafana/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# GoBot Grafana dashboard

[`gobot-dashboard.json`](gobot-dashboard.json) is the importable Grafana
dashboard for GoBot's `/metrics` endpoint. It covers:
[`gobot-dashboard.json`](gobot-dashboard.json) is a portable Classic JSON
dashboard for GoBot's `/metrics` endpoint. Grafana maps its Prometheus data
source during import instead of retaining an instance-specific data-source
identifier. It covers:

- Prometheus scrape and IRC connection health
- process uptime and reliability events
Expand Down Expand Up @@ -75,6 +77,11 @@ Prometheus host to `10.69.0.22:8082` before importing the dashboard.
- **Instance:** `10.69.0.22:8082`
- **IRC network:** `All`, or one configured GoBot network

The JSON intentionally uses Grafana's portable Classic import model. It does
not contain API-managed resource fields such as `generation`,
`resourceVersion`, or `creationTimestamp`, so it can be imported through the
normal UI and used to overwrite an earlier copy safely.

The dashboard refreshes every 30 seconds, matching the Prometheus scrape
interval. A newly started bot may need two scrapes (about one minute) before
rate panels have enough samples to draw a line.
Expand Down
47 changes: 24 additions & 23 deletions grafana/dashboard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,43 @@ import (
"testing"
)

type dashboardResource struct {
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
Spec struct {
Title string `json:"title"`
Elements map[string]dashboardElement `json:"elements"`
Variables []struct {
Spec struct {
Name string `json:"name"`
} `json:"spec"`
} `json:"variables"`
} `json:"spec"`
}

type dashboardElement struct {
Spec struct {
type dashboardModel struct {
SchemaVersion int `json:"schemaVersion"`
Title string `json:"title"`
UID string `json:"uid"`
Inputs []struct {
Name string `json:"name"`
PluginID string `json:"pluginId"`
} `json:"__inputs"`
Panels []struct {
Title string `json:"title"`
} `json:"spec"`
} `json:"panels"`
Templating struct {
List []struct {
Name string `json:"name"`
} `json:"list"`
} `json:"templating"`
}

func TestDashboardJSONUsesExpandedMetrics(t *testing.T) {
raw, err := os.ReadFile("gobot-dashboard.json")
if err != nil {
t.Fatal(err)
}
var dashboard dashboardResource
var dashboard dashboardModel
if err := json.Unmarshal(raw, &dashboard); err != nil {
t.Fatalf("dashboard JSON is invalid: %v", err)
}
if dashboard.APIVersion == "" || dashboard.Kind != "Dashboard" || dashboard.Spec.Title != "GoBot Operations" {
if dashboard.SchemaVersion < 39 || dashboard.Title != "GoBot Operations" || dashboard.UID != "gobot-operations" {
t.Fatalf("unexpected dashboard identity: %#v", dashboard)
}
if len(dashboard.Inputs) != 1 || dashboard.Inputs[0].Name != "DS_PROMETHEUS" || dashboard.Inputs[0].PluginID != "prometheus" {
t.Fatalf("dashboard Prometheus input is not portable: %#v", dashboard.Inputs)
}

panelTitles := make(map[string]bool)
for _, element := range dashboard.Spec.Elements {
panelTitles[element.Spec.Title] = true
for _, panel := range dashboard.Panels {
panelTitles[panel.Title] = true
}
for _, title := range []string{
"IRC connection",
Expand All @@ -61,8 +62,8 @@ func TestDashboardJSONUsesExpandedMetrics(t *testing.T) {
}

variables := make(map[string]bool)
for _, variable := range dashboard.Spec.Variables {
variables[variable.Spec.Name] = true
for _, variable := range dashboard.Templating.List {
variables[variable.Name] = true
}
for _, name := range []string{"job", "environment", "hostname", "instance", "network"} {
if !variables[name] {
Expand Down
Loading