From 3e71891967b0e36d0fde206b59570e2ccdb581f2 Mon Sep 17 00:00:00 2001 From: AK Date: Sun, 30 Aug 2026 01:13:44 -0700 Subject: [PATCH] Expand GoBot metrics and Grafana dashboard --- bot/bot.go | 32 +++- bot/queue.go | 7 + bot/queue_test.go | 14 ++ bot/stats.go | 251 +++++++++++++++++++++++++-- bot/stats_test.go | 131 +++++++++++++- docs/monitoring.md | 36 +++- grafana/README.md | 91 ++++++++-- grafana/dashboard_test.go | 87 ++++++++++ grafana/gobot-dashboard-example.png | Bin 119830 -> 0 bytes grafana/gobot-dashboard.json | 254 ++++++++++++++++++---------- 10 files changed, 774 insertions(+), 129 deletions(-) create mode 100644 grafana/dashboard_test.go delete mode 100644 grafana/gobot-dashboard-example.png diff --git a/bot/bot.go b/bot/bot.go index b089d46..c656661 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -23,6 +23,7 @@ type Bot struct { Plugins []Plugin Log *zap.Logger Queue *Queue + networkStats *networkStats client *irc.Client reloadHandler func(Message) mu sync.RWMutex @@ -45,6 +46,9 @@ func New(cfg Config, db *storage.DB, plugins []Plugin, log *zap.Logger) *Bot { } func NewWithStats(cfg Config, db *storage.DB, plugins []Plugin, log *zap.Logger, stats *Stats) *Bot { + if stats == nil { + stats = NewStats() + } enabledPlugins := make(map[string]bool, len(plugins)) startedPlugins := make(map[string]bool, len(plugins)) for _, plugin := range plugins { @@ -52,6 +56,7 @@ func NewWithStats(cfg Config, db *storage.DB, plugins []Plugin, log *zap.Logger, } b := &Bot{Config: cfg, DB: db, Stats: stats, Plugins: plugins, Log: log, enabledPlugins: enabledPlugins, startedPlugins: startedPlugins, lastCommands: make(map[string]time.Time), lastWarnings: make(map[string]time.Time), lastInvites: make(map[string]time.Time), warmupUntil: make(map[string]time.Time)} b.Queue = NewQueue(cfg.RateLimit.MessagesPerSecond, cfg.RateLimit.Burst, func(o Outgoing) { b.sendNow(o.Target, o.Text) }) + b.networkStats = stats.registerNetwork(cfg.NetworkName, len(cfg.Channels), b.Queue) return b } @@ -175,6 +180,9 @@ func clonePluginOverrides(overrides map[string]map[string]bool) map[string]map[s func (b *Bot) Send(target, text string) { if !b.Queue.Enqueue(Outgoing{target, text}) { b.Stats.dropped.Add(1) + if b.networkStats != nil { + b.networkStats.dropped.Add(1) + } b.Log.Warn("outgoing queue full", zap.String("target", target)) } } @@ -185,6 +193,9 @@ func (b *Bot) sendNow(target, text string) { if c != nil { c.WriteMessage(&irc.Message{Command: "PRIVMSG", Params: []string{target, text}}) b.Stats.sent.Add(1) + if b.networkStats != nil { + b.networkStats.sent.Add(1) + } } } func (b *Bot) connect(ctx context.Context) error { @@ -295,13 +306,16 @@ func (b *Bot) connect(ctx context.Context) error { } if m.Command == "PRIVMSG" { b.Stats.received.Add(1) + if b.networkStats != nil { + b.networkStats.received.Add(1) + } b.dispatch(ParseMessage(m)) } })}) b.mu.Lock() b.client = client b.mu.Unlock() - b.Stats.connected.Store(1) + b.Stats.setNetworkConnected(b.networkStats, true) if mechanism != "" { // irc.v3 has CAP parsing but no SASL mechanism implementation. Start // the capability exchange manually so authentication can complete before 001. @@ -321,10 +335,10 @@ func (b *Bot) connect(ctx context.Context) error { client.Write("QUIT :shutting down") conn.Close() <-errc - b.Stats.connected.Store(0) + b.Stats.setNetworkConnected(b.networkStats, false) return nil case err := <-errc: - b.Stats.connected.Store(0) + b.Stats.setNetworkConnected(b.networkStats, false) b.mu.Lock() b.client = nil b.mu.Unlock() @@ -734,7 +748,7 @@ func (b *Bot) dispatch(msg Message) { if _, _, ok := IsCommand(msg, b.Config.CommandPrefix); ok && !b.AllowCommand(msg) { return } - command := false + _, _, command := IsCommand(msg, b.Config.CommandPrefix) for _, p := range b.Plugins { if !b.pluginEnabled(p.Name()) { continue @@ -748,6 +762,7 @@ func (b *Bot) dispatch(msg Message) { defer func() { b.pluginMu.RUnlock() if r := recover(); r != nil { + b.Stats.recordPluginPanic(b.networkStats, p.Name(), "message") b.Log.Error("plugin panic", zap.String("plugin", p.Name()), zap.Any("panic", r)) } }() @@ -755,13 +770,10 @@ func (b *Bot) dispatch(msg Message) { }() if consumed { if command { - b.Stats.commands.Add(1) + b.Stats.recordCommand(b.networkStats, p.Name()) } return } - if _, _, ok := IsCommand(msg, b.Config.CommandPrefix); ok { - command = true - } } } @@ -782,6 +794,7 @@ func (b *Bot) dispatchEvent(msg Message) { defer func() { b.pluginMu.RUnlock() if r := recover(); r != nil { + b.Stats.recordPluginPanic(b.networkStats, p.Name(), "event") b.Log.Error("plugin event panic", zap.String("plugin", p.Name()), zap.Any("panic", r)) } }() @@ -814,6 +827,9 @@ func (b *Bot) Run(ctx context.Context) error { return nil } b.Stats.reconnects.Add(1) + if b.networkStats != nil { + b.networkStats.reconnects.Add(1) + } b.Log.Warn("IRC connection ended", zap.Error(err), zap.Duration("retry_in", backoff)) jitter := time.Duration(rand.Int63n(int64(backoff/5 + 1))) select { diff --git a/bot/queue.go b/bot/queue.go index 743de2b..45e0fed 100644 --- a/bot/queue.go +++ b/bot/queue.go @@ -43,6 +43,13 @@ func (q *Queue) Enqueue(o Outgoing) bool { return false } } + +// Depth reports the number of messages currently waiting to be sent. +func (q *Queue) Depth() int { return len(q.ch) } + +// Capacity reports the maximum number of queued outbound messages. +func (q *Queue) Capacity() int { return cap(q.ch) } + func (q *Queue) loop() { ticker := time.NewTicker(q.interval) defer ticker.Stop() diff --git a/bot/queue_test.go b/bot/queue_test.go index a220964..ca2b5d8 100644 --- a/bot/queue_test.go +++ b/bot/queue_test.go @@ -30,3 +30,17 @@ func TestQueueClampsExtremeRates(t *testing.T) { t.Fatalf("queue interval = %s, want positive", q.interval) } } + +func TestQueueReportsDepthAndCapacity(t *testing.T) { + q := NewQueue(0.01, 2, func(Outgoing) {}) + defer q.Drain(context.Background()) + if got := q.Capacity(); got != 40 { + t.Fatalf("Capacity() = %d, want 40", got) + } + if !q.Enqueue(Outgoing{Text: "one"}) || !q.Enqueue(Outgoing{Text: "two"}) { + t.Fatal("failed to enqueue messages") + } + if got := q.Depth(); got != 2 { + t.Fatalf("Depth() = %d, want 2", got) + } +} diff --git a/bot/stats.go b/bot/stats.go index 4dfc7bd..fbec85f 100644 --- a/bot/stats.go +++ b/bot/stats.go @@ -5,7 +5,10 @@ import ( "fmt" "net" "net/http" + "sort" "strconv" + "strings" + "sync" "sync/atomic" "time" @@ -15,9 +18,26 @@ import ( type Stats struct { started time.Time received, sent, commands, reconnects, dropped, connected atomic.Uint64 + connectedNetworks atomic.Int64 db *storage.DB persistDone chan struct{} persistOnce atomic.Bool + networkMu sync.RWMutex + networks map[string]*networkStats +} + +type networkStats struct { + name string + configuredChannels int + queue *Queue + connected atomic.Uint64 + received atomic.Uint64 + sent atomic.Uint64 + commands atomic.Uint64 + reconnects atomic.Uint64 + dropped atomic.Uint64 + pluginCommands sync.Map + pluginPanics sync.Map } type persistedStats struct { @@ -28,8 +48,18 @@ type persistedStats struct { Dropped uint64 `json:"messages_dropped"` } +type metricLabel struct { + name string + value string +} + +type prometheusWriter struct { + output strings.Builder + described map[string]struct{} +} + func NewStats(dbs ...*storage.DB) *Stats { - s := &Stats{started: time.Now()} + s := &Stats{started: time.Now(), networks: make(map[string]*networkStats)} if len(dbs) > 0 && dbs[0] != nil { s.db = dbs[0] if raw, err := s.db.Get("stats", "global"); err == nil { @@ -48,6 +78,74 @@ func NewStats(dbs ...*storage.DB) *Stats { return s } +func (s *Stats) registerNetwork(name string, configuredChannels int, queue *Queue) *networkStats { + name = strings.TrimSpace(name) + if name == "" { + name = "default" + } + if configuredChannels < 0 { + configuredChannels = 0 + } + s.networkMu.Lock() + defer s.networkMu.Unlock() + if existing := s.networks[name]; existing != nil { + return existing + } + network := &networkStats{name: name, configuredChannels: configuredChannels, queue: queue} + s.networks[name] = network + return network +} + +func (s *Stats) setNetworkConnected(network *networkStats, value bool) { + if network == nil { + if value { + s.connected.Store(1) + } else { + s.connected.Store(0) + } + return + } + desired := uint64(0) + delta := int64(-1) + if value { + desired = 1 + delta = 1 + } + if network.connected.Swap(desired) == desired { + return + } + active := s.connectedNetworks.Add(delta) + if active > 0 { + s.connected.Store(1) + return + } + if active < 0 { + s.connectedNetworks.Store(0) + } + s.connected.Store(0) +} + +func (s *Stats) recordCommand(network *networkStats, plugin string) { + s.commands.Add(1) + if network == nil { + return + } + network.commands.Add(1) + atomicCounter(&network.pluginCommands, plugin).Add(1) +} + +func (s *Stats) recordPluginPanic(network *networkStats, plugin, handler string) { + if network == nil { + return + } + atomicCounter(&network.pluginPanics, plugin+"\x00"+handler).Add(1) +} + +func atomicCounter(counters *sync.Map, key string) *atomic.Uint64 { + value, _ := counters.LoadOrStore(key, &atomic.Uint64{}) + return value.(*atomic.Uint64) +} + func (s *Stats) persistLoop() { ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() @@ -79,33 +177,156 @@ func (s *Stats) Close() { } func (s *Stats) Snapshot() map[string]interface{} { - return map[string]interface{}{"uptime": time.Since(s.started).Round(time.Second).String(), "connected": s.connected.Load() == 1, "reconnects": s.reconnects.Load(), "messages_received": s.received.Load(), "messages_sent": s.sent.Load(), "messages_dropped": s.dropped.Load(), "commands_handled": s.commands.Load()} + return map[string]interface{}{ + "uptime": time.Since(s.started).Round(time.Second).String(), + "connected": s.connected.Load() == 1, + "reconnects": s.reconnects.Load(), + "messages_received": s.received.Load(), + "messages_sent": s.sent.Load(), + "messages_dropped": s.dropped.Load(), + "commands_handled": s.commands.Load(), + "networks": s.networkSnapshot(), + } } func (s *Stats) MetricsSnapshot() map[string]interface{} { snapshot := s.Snapshot() delete(snapshot, "uptime") + delete(snapshot, "networks") snapshot["uptime_seconds"] = time.Since(s.started).Seconds() return snapshot } + +func (s *Stats) networkSnapshot() map[string]interface{} { + networks := make(map[string]interface{}) + for _, network := range s.sortedNetworks() { + depth, capacity := 0, 0 + if network.queue != nil { + depth = network.queue.Depth() + capacity = network.queue.Capacity() + } + networks[network.name] = map[string]interface{}{ + "connected": network.connected.Load() == 1, + "reconnects": network.reconnects.Load(), + "messages_received": network.received.Load(), + "messages_sent": network.sent.Load(), + "messages_dropped": network.dropped.Load(), + "commands_handled": network.commands.Load(), + "configured_channels": network.configuredChannels, + "queue_depth": depth, + "queue_capacity": capacity, + } + } + return networks +} + +func (s *Stats) sortedNetworks() []*networkStats { + s.networkMu.RLock() + networks := make([]*networkStats, 0, len(s.networks)) + for _, network := range s.networks { + networks = append(networks, network) + } + s.networkMu.RUnlock() + sort.Slice(networks, func(i, j int) bool { return networks[i].name < networks[j].name }) + return networks +} + +func (s *Stats) PrometheusSnapshot() string { + writer := prometheusWriter{described: make(map[string]struct{})} + writer.metric("bot_connected", "Whether at least one IRC network is connected.", "gauge", nil, s.connected.Load()) + writer.metric("bot_reconnects", "Persistent cumulative IRC reconnect count.", "untyped", nil, s.reconnects.Load()) + writer.metric("bot_messages_received", "Persistent cumulative IRC messages received.", "untyped", nil, s.received.Load()) + writer.metric("bot_messages_sent", "Persistent cumulative IRC messages sent.", "untyped", nil, s.sent.Load()) + writer.metric("bot_commands_handled", "Persistent cumulative commands handled.", "untyped", nil, s.commands.Load()) + writer.metric("bot_uptime_seconds", "Current GoBot process uptime in seconds.", "gauge", nil, time.Since(s.started).Seconds()) + writer.metric("bot_messages_dropped", "Persistent cumulative messages dropped because an outbound queue was full.", "untyped", nil, s.dropped.Load()) + writer.metric("bot_process_start_time_seconds", "Unix timestamp when the current GoBot process started.", "gauge", nil, float64(s.started.Unix())) + networks := s.sortedNetworks() + writer.metric("bot_networks_configured", "Number of configured IRC networks.", "gauge", nil, len(networks)) + writer.metric("bot_networks_connected", "Number of currently connected IRC networks.", "gauge", nil, s.connectedNetworks.Load()) + + for _, network := range networks { + labels := []metricLabel{{name: "network", value: network.name}} + writer.metric("bot_network_connected", "Whether the IRC network is connected.", "gauge", labels, network.connected.Load()) + writer.metric("bot_network_reconnects_total", "IRC reconnects during the current process lifetime.", "counter", labels, network.reconnects.Load()) + writer.metric("bot_network_messages_received_total", "IRC messages received during the current process lifetime.", "counter", labels, network.received.Load()) + writer.metric("bot_network_messages_sent_total", "IRC messages sent during the current process lifetime.", "counter", labels, network.sent.Load()) + writer.metric("bot_network_commands_handled_total", "Commands handled during the current process lifetime.", "counter", labels, network.commands.Load()) + writer.metric("bot_network_messages_dropped_total", "Messages dropped because the network outbound queue was full.", "counter", labels, network.dropped.Load()) + writer.metric("bot_network_configured_channels", "Configured IRC channels for the network.", "gauge", labels, network.configuredChannels) + depth, capacity := 0, 0 + if network.queue != nil { + depth = network.queue.Depth() + capacity = network.queue.Capacity() + } + writer.metric("bot_outgoing_queue_depth", "Messages currently waiting in the network outbound queue.", "gauge", labels, depth) + writer.metric("bot_outgoing_queue_capacity", "Maximum messages supported by the network outbound queue.", "gauge", labels, capacity) + writer.syncMapCounters("bot_plugin_commands_handled_total", "Commands handled by each plugin during the current process lifetime.", network.name, &network.pluginCommands, false) + writer.syncMapCounters("bot_plugin_panics_total", "Recovered plugin panics during the current process lifetime.", network.name, &network.pluginPanics, true) + } + return writer.output.String() +} + +func (w *prometheusWriter) syncMapCounters(name, help, network string, counters *sync.Map, includeHandler bool) { + values := make(map[string]uint64) + keys := make([]string, 0) + counters.Range(func(key, value interface{}) bool { + text, ok := key.(string) + counter, counterOK := value.(*atomic.Uint64) + if ok && counterOK { + keys = append(keys, text) + values[text] = counter.Load() + } + return true + }) + sort.Strings(keys) + for _, key := range keys { + plugin, handler := key, "" + if includeHandler { + plugin, handler, _ = strings.Cut(key, "\x00") + } + labels := []metricLabel{{name: "network", value: network}, {name: "plugin", value: plugin}} + if includeHandler { + labels = append(labels, metricLabel{name: "handler", value: handler}) + } + w.metric(name, help, "counter", labels, values[key]) + } +} + +func (w *prometheusWriter) metric(name, help, metricType string, labels []metricLabel, value interface{}) { + if _, ok := w.described[name]; !ok { + fmt.Fprintf(&w.output, "# HELP %s %s\n# TYPE %s %s\n", name, help, name, metricType) + w.described[name] = struct{}{} + } + w.output.WriteString(name) + if len(labels) > 0 { + w.output.WriteByte('{') + for i, label := range labels { + if i > 0 { + w.output.WriteByte(',') + } + fmt.Fprintf(&w.output, `%s="%s"`, label.name, escapePrometheusLabel(label.value)) + } + w.output.WriteByte('}') + } + fmt.Fprintf(&w.output, " %v\n", value) +} + +func escapePrometheusLabel(value string) string { + value = strings.ReplaceAll(value, `\`, `\\`) + value = strings.ReplaceAll(value, "\n", `\n`) + return strings.ReplaceAll(value, `"`, `\"`) +} + func (s *Stats) Serve(address string, port int) { mux := http.NewServeMux() mux.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(s.Snapshot()) + _ = json.NewEncoder(w).Encode(s.Snapshot()) }) mux.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/plain; version=0.0.4") - for k, v := range s.MetricsSnapshot() { - if k == "connected" { - if v == true { - v = 1 - } else { - v = 0 - } - } - fmt.Fprintf(w, "bot_%s %v\n", k, v) - } + w.Header().Set("Content-Type", "text/plain; version=0.0.4; charset=utf-8") + _, _ = w.Write([]byte(s.PrometheusSnapshot())) }) if address == "" { address = "127.0.0.1" @@ -118,7 +339,7 @@ func (s *Stats) Serve(address string, port int) { WriteTimeout: 10 * time.Second, IdleTimeout: 60 * time.Second, } - go server.ListenAndServe() + go func() { _ = server.ListenAndServe() }() } func statsListenAddress(address string, port int) string { diff --git a/bot/stats_test.go b/bot/stats_test.go index 81e37a5..322d583 100644 --- a/bot/stats_test.go +++ b/bot/stats_test.go @@ -1,6 +1,13 @@ package bot -import "testing" +import ( + "context" + "strings" + "testing" + + "github.com/variablenix/GoBot/storage" + "go.uber.org/zap" +) func TestStatsListenAddress(t *testing.T) { tests := []struct { @@ -33,3 +40,125 @@ func TestMetricsSnapshotIncludesUptimeAndDroppedMessages(t *testing.T) { t.Fatal("metrics snapshot should not include human-readable uptime") } } + +func TestExpandedPrometheusMetricsRemainBackwardCompatible(t *testing.T) { + stats := NewStats() + queue := NewQueue(0.01, 2, func(Outgoing) {}) + defer queue.Drain(context.Background()) + network := stats.registerNetwork("libera", 3, queue) + stats.setNetworkConnected(network, true) + stats.received.Store(12) + stats.sent.Store(8) + network.received.Store(7) + network.sent.Store(5) + network.reconnects.Store(2) + stats.recordCommand(network, "help") + stats.recordPluginPanic(network, "weather", "message") + if !queue.Enqueue(Outgoing{Target: "#test", Text: "queued"}) { + t.Fatal("failed to enqueue test message") + } + + metrics := stats.PrometheusSnapshot() + for _, want := range []string{ + "bot_connected 1\n", + "bot_messages_received 12\n", + "bot_messages_sent 8\n", + "bot_commands_handled 1\n", + "bot_networks_configured 1\n", + "bot_networks_connected 1\n", + `bot_network_connected{network="libera"} 1`, + `bot_network_reconnects_total{network="libera"} 2`, + `bot_network_messages_received_total{network="libera"} 7`, + `bot_network_messages_sent_total{network="libera"} 5`, + `bot_network_configured_channels{network="libera"} 3`, + `bot_outgoing_queue_depth{network="libera"} 1`, + `bot_outgoing_queue_capacity{network="libera"} 40`, + `bot_plugin_commands_handled_total{network="libera",plugin="help"} 1`, + `bot_plugin_panics_total{network="libera",plugin="weather",handler="message"} 1`, + } { + if !strings.Contains(metrics, want) { + t.Errorf("PrometheusSnapshot() missing %q\n%s", want, metrics) + } + } + networks, ok := stats.Snapshot()["networks"].(map[string]interface{}) + if !ok { + t.Fatal("Snapshot() networks has an unexpected type") + } + libera, ok := networks["libera"].(map[string]interface{}) + if !ok || libera["configured_channels"] != 3 || libera["queue_depth"] != 1 { + t.Fatalf("Snapshot() network details = %#v", networks["libera"]) + } +} + +type panicMetricsPlugin struct{} + +func (*panicMetricsPlugin) Name() string { return "panic-test" } +func (*panicMetricsPlugin) Commands() []string { return []string{"panic-test"} } +func (*panicMetricsPlugin) Help() string { return "panic-test" } +func (*panicMetricsPlugin) Init(PluginConfig, *storage.DB) error { return nil } +func (*panicMetricsPlugin) Handle(*Bot, Message) bool { panic("test panic") } + +type commandMetricsPlugin struct{} + +func (*commandMetricsPlugin) Name() string { return "choose" } +func (*commandMetricsPlugin) Commands() []string { return []string{"choose"} } +func (*commandMetricsPlugin) Help() string { return "choose" } +func (*commandMetricsPlugin) Init(PluginConfig, *storage.DB) error { return nil } +func (*commandMetricsPlugin) Handle(*Bot, Message) bool { return true } + +func TestPluginPanicsAreRecoveredAndCounted(t *testing.T) { + plugin := &panicMetricsPlugin{} + config := Config{NetworkName: "test", CommandPrefix: "!"} + stats := NewStats() + instance := NewWithStats(config, nil, []Plugin{plugin}, zap.NewNop(), stats) + defer instance.Queue.Drain(context.Background()) + + instance.dispatch(Message{Command: "PRIVMSG", Target: "#test", Text: "!panic-test", IsChannel: true}) + metrics := stats.PrometheusSnapshot() + if !strings.Contains(metrics, `bot_plugin_panics_total{network="test",plugin="panic-test",handler="message"} 1`) { + t.Fatalf("plugin panic metric missing:\n%s", metrics) + } +} + +func TestConnectionGaugeAggregatesMultipleNetworks(t *testing.T) { + stats := NewStats() + first := stats.registerNetwork("first", 1, nil) + second := stats.registerNetwork("second", 1, nil) + + stats.setNetworkConnected(first, true) + stats.setNetworkConnected(second, true) + stats.setNetworkConnected(first, false) + if stats.connected.Load() != 1 || stats.connectedNetworks.Load() != 1 { + t.Fatalf("one connected network reported global=%d active=%d", stats.connected.Load(), stats.connectedNetworks.Load()) + } + stats.setNetworkConnected(second, false) + if stats.connected.Load() != 0 || stats.connectedNetworks.Load() != 0 { + t.Fatalf("zero connected networks reported global=%d active=%d", stats.connected.Load(), stats.connectedNetworks.Load()) + } +} + +func TestPrometheusLabelsAreEscaped(t *testing.T) { + stats := NewStats() + stats.registerNetwork("bad\\\"\nname", 0, nil).reconnects.Store(1) + metrics := stats.PrometheusSnapshot() + if !strings.Contains(metrics, `network="bad\\\"\nname"`) { + t.Fatalf("network label was not escaped safely:\n%s", metrics) + } +} + +func TestFirstPluginHandledCommandIsCounted(t *testing.T) { + plugin := &commandMetricsPlugin{} + config := Config{NetworkName: "test", CommandPrefix: "!"} + stats := NewStats() + instance := NewWithStats(config, nil, []Plugin{plugin}, zap.NewNop(), stats) + defer instance.Queue.Drain(context.Background()) + + instance.dispatch(Message{Command: "PRIVMSG", Target: "#test", Text: "!choose a | b", IsChannel: true}) + if got := stats.commands.Load(); got != 1 { + t.Fatalf("commands handled = %d, want 1", got) + } + metrics := stats.PrometheusSnapshot() + if !strings.Contains(metrics, `bot_plugin_commands_handled_total{network="test",plugin="choose"} 1`) { + t.Fatalf("plugin command metric missing:\n%s", metrics) + } +} diff --git a/docs/monitoring.md b/docs/monitoring.md index 632c17a..9e2cc39 100644 --- a/docs/monitoring.md +++ b/docs/monitoring.md @@ -18,6 +18,8 @@ firewall. ## Metrics +The original global metrics remain available for backward compatibility: + - bot_connected: 1 while at least one IRC connection is active, otherwise 0 - bot_reconnects: cumulative reconnect count - bot_messages_received: cumulative IRC messages received @@ -30,6 +32,35 @@ Cumulative counters are persisted in BoltDB and survive restarts. Connection status and process uptime naturally reset or change when the process restarts. The !stats command reports persistent per-channel message and user statistics. +GoBot also exposes operational metrics for richer dashboards: + +| Metric | Type | Meaning | +| --- | --- | --- | +| `bot_process_start_time_seconds` | gauge | Current process start time as a Unix timestamp | +| `bot_networks_configured` | gauge | Number of configured IRC networks | +| `bot_networks_connected` | gauge | Number of currently connected IRC networks | +| `bot_network_connected{network}` | gauge | Per-network connection state | +| `bot_network_reconnects_total{network}` | counter | Per-network reconnects since process start | +| `bot_network_messages_received_total{network}` | counter | Per-network messages received since process start | +| `bot_network_messages_sent_total{network}` | counter | Per-network messages sent since process start | +| `bot_network_commands_handled_total{network}` | counter | Per-network handled commands since process start | +| `bot_network_messages_dropped_total{network}` | counter | Per-network outbound messages dropped since process start | +| `bot_network_configured_channels{network}` | gauge | Configured channels per network | +| `bot_outgoing_queue_depth{network}` | gauge | Messages currently waiting to be sent | +| `bot_outgoing_queue_capacity{network}` | gauge | Maximum outbound queue size | +| `bot_plugin_commands_handled_total{network,plugin}` | counter | Handled commands grouped by plugin | +| `bot_plugin_panics_total{network,plugin,handler}` | counter | Recovered message/event handler panics | + +Per-network and per-plugin counters reset when the GoBot process restarts; +Prometheus `rate()` and `increase()` account for counter resets. Labels are +limited to configured network names, built-in plugin names, and the bounded +handler type. Channel names, nicknames, accounts, and message contents are not +exported. + +The `/stats` JSON response includes a `networks` object with connection, +traffic, command, reconnect, queue, and configured-channel details for each +network. + ## Prometheus scrape configuration If Prometheus runs on another host, set GoBot's listener to a WireGuard or @@ -71,5 +102,6 @@ curl http://:8082/metrics Import [grafana/gobot-dashboard.json](../grafana/gobot-dashboard.json) into Grafana and select your Prometheus data source. The dashboard variables use -Prometheus queries for the job and instance labels. A sample export is -included at [grafana/gobot-dashboard-example.png](../grafana/gobot-dashboard-example.png). +Prometheus queries for job, environment, hostname, instance, and IRC network +labels. Follow the complete step-by-step instructions in +[grafana/README.md](../grafana/README.md). diff --git a/grafana/README.md b/grafana/README.md index 620e02d..22baf42 100644 --- a/grafana/README.md +++ b/grafana/README.md @@ -1,22 +1,83 @@ # GoBot Grafana dashboard -`gobot-dashboard.json` is an importable Grafana dashboard for the metrics exposed by GoBot at `/metrics`. +[`gobot-dashboard.json`](gobot-dashboard.json) is the importable Grafana +dashboard for GoBot's `/metrics` endpoint. It covers: -## Import +- Prometheus scrape and IRC connection health +- process uptime and reliability events +- per-network incoming and outgoing message rates +- handled-command rates grouped by plugin +- outbound queue depth and capacity by network +- filtering by Prometheus job, environment, hostname, instance, and IRC network -1. In Grafana, open **Dashboards → New → Import**. -2. Upload `gobot-dashboard.json` or paste its contents. -3. Select the Prometheus datasource that scrapes GoBot. -4. Click **Import**. +The dashboard defaults match the production example below, but every filter +is selectable after import. -The dashboard expects the `gobot` Prometheus job and uses these metrics: +## 1. Deploy the expanded metrics -- `bot_connected` -- `bot_reconnects` -- `bot_messages_received` -- `bot_messages_sent` -- `bot_commands_handled` -- `bot_uptime_seconds` -- `bot_messages_dropped` +Pull the current GoBot `main` branch, rebuild the binary, and restart the +service. Confirm the endpoint from the Prometheus host: -The Prometheus job and dashboard are intentionally kept separate: the Ansible monitoring role deploys the scrape configuration, while this repository carries the dashboard definition alongside the application. +~~~sh +curl http://10.69.0.22:8082/metrics +~~~ + +Along with the original `bot_*` metrics, the response should include +`bot_network_connected`, `bot_network_messages_received_total`, +`bot_plugin_commands_handled_total`, and `bot_outgoing_queue_depth`. + +## 2. Configure Prometheus + +Add this job under `scrape_configs` in `prometheus.yml`: + +~~~yaml + # GoBot IRC bot + - job_name: gobot + scrape_interval: 30s + scrape_timeout: 10s + metrics_path: /metrics + static_configs: + - targets: ["10.69.0.22:8082"] + labels: + role: irc-bot + use: gobot + hostname: nexus-node + environment: production +~~~ + +Check the Prometheus configuration and reload it. For a package installation, +the usual commands are: + +~~~sh +promtool check config /etc/prometheus/prometheus.yml +sudo systemctl reload prometheus +~~~ + +In Prometheus, run `up{job="gobot"}`. A value of `1` confirms that scraping is +working. If it is `0` or absent, check routing/firewall access from the +Prometheus host to `10.69.0.22:8082` before importing the dashboard. + +## 3. Import into Grafana + +1. Open **Dashboards → New → Import** in Grafana. +2. Upload `grafana/gobot-dashboard.json` from this repository, or paste the + file contents. +3. Choose the Prometheus data source that contains the `gobot` job when + Grafana asks for a data source. +4. Keep the dashboard name **GoBot Operations** and click **Import**. +5. At the top of the dashboard, verify these filters: + - **Job:** `gobot` + - **Environment:** `production` + - **Host:** `nexus-node` + - **Instance:** `10.69.0.22:8082` + - **IRC network:** `All`, or one configured GoBot network + +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. + +## Security note + +GoBot's `/stats` and `/metrics` endpoints do not provide authentication. Bind +the listener to a private address and allow access only from the Prometheus +host through the firewall. diff --git a/grafana/dashboard_test.go b/grafana/dashboard_test.go new file mode 100644 index 0000000..43618b9 --- /dev/null +++ b/grafana/dashboard_test.go @@ -0,0 +1,87 @@ +package grafana + +import ( + "encoding/json" + "os" + "strings" + "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 { + Title string `json:"title"` + } `json:"spec"` +} + +func TestDashboardJSONUsesExpandedMetrics(t *testing.T) { + raw, err := os.ReadFile("gobot-dashboard.json") + if err != nil { + t.Fatal(err) + } + var dashboard dashboardResource + 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" { + t.Fatalf("unexpected dashboard identity: %#v", dashboard) + } + + panelTitles := make(map[string]bool) + for _, element := range dashboard.Spec.Elements { + panelTitles[element.Spec.Title] = true + } + for _, title := range []string{ + "IRC connection", + "Prometheus scrape", + "Reliability events", + "Message throughput by network", + "Command throughput by plugin", + "Outbound queue pressure", + "Uptime", + } { + if !panelTitles[title] { + t.Errorf("dashboard is missing panel %q", title) + } + } + + variables := make(map[string]bool) + for _, variable := range dashboard.Spec.Variables { + variables[variable.Spec.Name] = true + } + for _, name := range []string{"job", "environment", "hostname", "instance", "network"} { + if !variables[name] { + t.Errorf("dashboard is missing variable %q", name) + } + } + + text := string(raw) + for _, metric := range []string{ + "bot_network_connected", + "bot_network_reconnects_total", + "bot_network_messages_received_total", + "bot_network_messages_sent_total", + "bot_network_messages_dropped_total", + "bot_plugin_commands_handled_total", + "bot_plugin_panics_total", + "bot_outgoing_queue_depth", + "bot_outgoing_queue_capacity", + } { + if !strings.Contains(text, metric) { + t.Errorf("dashboard does not query %s", metric) + } + } +} diff --git a/grafana/gobot-dashboard-example.png b/grafana/gobot-dashboard-example.png deleted file mode 100644 index 01f459b843298cd8ff4f9f8f7519e3947436edff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119830 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 -~u`Rb&DWyJ3p1}3H^ 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 xe;hkyQBvZ(-c(0>~OBGja(I6p`h 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 diff --git a/grafana/gobot-dashboard.json b/grafana/gobot-dashboard.json index 98fce55..f1a566d 100644 --- a/grafana/gobot-dashboard.json +++ b/grafana/gobot-dashboard.json @@ -2,8 +2,8 @@ "apiVersion": "dashboard.grafana.app/v2", "kind": "Dashboard", "metadata": { - "name": "gobot-overview", - "generation": 5, + "name": "gobot-operations", + "generation": 6, "creationTimestamp": "2026-08-01T07:11:36Z", "labels": {}, "annotations": {} @@ -38,7 +38,7 @@ "spec": { "id": 1, "title": "IRC connection", - "description": "", + "description": "Connected only when every selected IRC network reports an active connection.", "links": [], "data": { "kind": "QueryGroup", @@ -52,7 +52,7 @@ "group": "prometheus", "version": "v0", "spec": { - "expr": "max(bot_connected{job=~\"$job\", instance=~\"$instance\"})" + "expr": "min(bot_network_connected{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\", network=~\"$network\"})" }, "labels": { "grafana.app/export-label": "prometheus-1" @@ -134,8 +134,8 @@ "kind": "Panel", "spec": { "id": 2, - "title": "Reconnects", - "description": "", + "title": "Prometheus scrape", + "description": "Whether Prometheus can currently scrape every selected GoBot target.", "links": [], "data": { "kind": "QueryGroup", @@ -149,7 +149,7 @@ "group": "prometheus", "version": "v0", "spec": { - "expr": "max(bot_reconnects{job=~\"$job\", instance=~\"$instance\"})" + "expr": "min(up{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\"})" }, "labels": { "grafana.app/export-label": "prometheus-1" @@ -170,9 +170,9 @@ "version": "13.0.2", "spec": { "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { @@ -189,22 +189,36 @@ "fieldConfig": { "defaults": { "unit": "short", - "decimals": 0, + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "Down", + "color": "red" + }, + "1": { + "text": "Up", + "color": "green" + } + } + } + ], "thresholds": { "mode": "absolute", "steps": [ { "value": 0, - "color": "green" + "color": "red" }, { - "value": 80, - "color": "red" + "value": 1, + "color": "green" } ] }, "color": { - "mode": "palette-classic" + "mode": "thresholds" } }, "overrides": [] @@ -217,8 +231,8 @@ "kind": "Panel", "spec": { "id": 3, - "title": "Commands handled", - "description": "", + "title": "Reliability events", + "description": "Reconnects, dropped outbound messages, and recovered plugin panics during the selected time range.", "links": [], "data": { "kind": "QueryGroup", @@ -232,7 +246,7 @@ "group": "prometheus", "version": "v0", "spec": { - "expr": "max(bot_commands_handled{job=~\"$job\", instance=~\"$instance\"})" + "expr": "sum(increase(bot_network_reconnects_total{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\", network=~\"$network\"}[$__range])) + sum(increase(bot_network_messages_dropped_total{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\", network=~\"$network\"}[$__range])) + (sum(increase(bot_plugin_panics_total{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\", network=~\"$network\"}[$__range])) or vector(0))" }, "labels": { "grafana.app/export-label": "prometheus-1" @@ -281,13 +295,13 @@ "color": "green" }, { - "value": 80, + "value": 1, "color": "red" } ] }, "color": { - "mode": "palette-classic" + "mode": "thresholds" } }, "overrides": [] @@ -300,8 +314,8 @@ "kind": "Panel", "spec": { "id": 4, - "title": "Message throughput", - "description": "", + "title": "Message throughput by network", + "description": "Per-second IRC message rates by network, calculated over Grafana's safe rate interval.", "links": [], "data": { "kind": "QueryGroup", @@ -315,8 +329,8 @@ "group": "prometheus", "version": "v0", "spec": { - "expr": "sum(rate(bot_messages_received{job=~\"$job\", instance=~\"$instance\"}[5m]))", - "legendFormat": "received" + "expr": "sum by (network) (rate(bot_network_messages_received_total{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\", network=~\"$network\"}[$__rate_interval]))", + "legendFormat": "{{network}} received" }, "labels": { "grafana.app/export-label": "prometheus-1" @@ -334,8 +348,8 @@ "group": "prometheus", "version": "v0", "spec": { - "expr": "sum(rate(bot_messages_sent{job=~\"$job\", instance=~\"$instance\"}[5m]))", - "legendFormat": "sent" + "expr": "sum by (network) (rate(bot_network_messages_sent_total{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\", network=~\"$network\"}[$__rate_interval]))", + "legendFormat": "{{network}} sent" }, "labels": { "grafana.app/export-label": "prometheus-1" @@ -440,8 +454,8 @@ "kind": "Panel", "spec": { "id": 5, - "title": "Command throughput", - "description": "", + "title": "Command throughput by plugin", + "description": "Per-second handled-command rate, grouped by plugin.", "links": [], "data": { "kind": "QueryGroup", @@ -455,8 +469,8 @@ "group": "prometheus", "version": "v0", "spec": { - "expr": "sum(rate(bot_commands_handled{job=~\"$job\", instance=~\"$instance\"}[5m]))", - "legendFormat": "commands" + "expr": "sum by (plugin) (rate(bot_plugin_commands_handled_total{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\", network=~\"$network\"}[$__rate_interval]))", + "legendFormat": "{{plugin}}" }, "labels": { "grafana.app/export-label": "prometheus-1" @@ -561,8 +575,8 @@ "kind": "Panel", "spec": { "id": 6, - "title": "Cumulative counters", - "description": "", + "title": "Outbound queue pressure", + "description": "Current queued messages and queue capacity by IRC network. Sustained depth indicates rate limiting or an unhealthy connection.", "links": [], "data": { "kind": "QueryGroup", @@ -576,8 +590,8 @@ "group": "prometheus", "version": "v0", "spec": { - "expr": "max(bot_messages_received{job=~\"$job\", instance=~\"$instance\"})", - "legendFormat": "received" + "expr": "max by (network) (bot_outgoing_queue_depth{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\", network=~\"$network\"})", + "legendFormat": "{{network}} depth" }, "labels": { "grafana.app/export-label": "prometheus-1" @@ -595,8 +609,8 @@ "group": "prometheus", "version": "v0", "spec": { - "expr": "max(bot_messages_sent{job=~\"$job\", instance=~\"$instance\"})", - "legendFormat": "sent" + "expr": "max by (network) (bot_outgoing_queue_capacity{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\", network=~\"$network\"})", + "legendFormat": "{{network}} capacity" }, "labels": { "grafana.app/export-label": "prometheus-1" @@ -605,44 +619,6 @@ "refId": "B", "hidden": false } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "expr": "max(bot_commands_handled{job=~\"$job\", instance=~\"$instance\"})", - "legendFormat": "commands" - }, - "labels": { - "grafana.app/export-label": "prometheus-1" - } - }, - "refId": "C", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "expr": "max(bot_messages_dropped{job=~\"$job\", instance=~\"$instance\"})", - "legendFormat": "dropped" - }, - "labels": { - "grafana.app/export-label": "prometheus-1" - } - }, - "refId": "D", - "hidden": false - } } ], "transformations": [], @@ -739,7 +715,7 @@ "spec": { "id": 7, "title": "Uptime", - "description": "", + "description": "Uptime of the selected GoBot process. This resets after a rebuild or service restart.", "links": [], "data": { "kind": "QueryGroup", @@ -753,7 +729,7 @@ "group": "prometheus", "version": "v0", "spec": { - "expr": "max(bot_uptime_seconds{job=~\"$job\", instance=~\"$instance\"})" + "expr": "max(bot_uptime_seconds{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\"})" }, "labels": { "grafana.app/export-label": "prometheus-1" @@ -800,10 +776,6 @@ { "value": 0, "color": "green" - }, - { - "value": 80, - "color": "red" } ] }, @@ -944,15 +916,16 @@ "hideTimepicker": false, "fiscalYearStartMonth": 0 }, - "title": "GoBot Overview", + "title": "GoBot Operations", + "description": "Operational health, traffic, plugin activity, reliability, and outbound queue pressure for GoBot.", "variables": [ { "kind": "QueryVariable", "spec": { "name": "job", "current": { - "text": "", - "value": "" + "text": "gobot", + "value": "gobot" }, "label": "Job", "hide": "dontHide", @@ -981,13 +954,83 @@ "allowCustomValue": true } }, + { + "kind": "QueryVariable", + "spec": { + "name": "environment", + "current": { + "text": "production", + "value": "production" + }, + "label": "Environment", + "hide": "dontHide", + "refresh": "onDashboardLoad", + "skipUrlSync": false, + "query": { + "kind": "DataQuery", + "group": "prometheus", + "version": "v0", + "spec": { + "qryType": 5, + "query": "label_values(bot_connected{job=~\"$job\"}, environment)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "labels": { + "grafana.app/export-label": "prometheus-1" + } + }, + "regex": "", + "regexApplyTo": "value", + "sort": "alphabeticalAsc", + "definition": "label_values(bot_connected{job=~\"$job\"}, environment)", + "options": [], + "multi": false, + "includeAll": true, + "allowCustomValue": true + } + }, + { + "kind": "QueryVariable", + "spec": { + "name": "hostname", + "current": { + "text": "nexus-node", + "value": "nexus-node" + }, + "label": "Host", + "hide": "dontHide", + "refresh": "onDashboardLoad", + "skipUrlSync": false, + "query": { + "kind": "DataQuery", + "group": "prometheus", + "version": "v0", + "spec": { + "qryType": 5, + "query": "label_values(bot_connected{job=~\"$job\", environment=~\"$environment\"}, hostname)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "labels": { + "grafana.app/export-label": "prometheus-1" + } + }, + "regex": "", + "regexApplyTo": "value", + "sort": "alphabeticalAsc", + "definition": "label_values(bot_connected{job=~\"$job\", environment=~\"$environment\"}, hostname)", + "options": [], + "multi": false, + "includeAll": true, + "allowCustomValue": true + } + }, { "kind": "QueryVariable", "spec": { "name": "instance", "current": { - "text": "", - "value": "" + "text": "10.69.0.22:8082", + "value": "10.69.0.22:8082" }, "label": "Instance", "hide": "dontHide", @@ -999,7 +1042,7 @@ "version": "v0", "spec": { "qryType": 5, - "query": "label_values(bot_connected{job=~\"$job\"}, instance)", + "query": "label_values(bot_connected{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\"}, instance)", "refId": "PrometheusVariableQueryEditor-VariableQuery" }, "labels": { @@ -1009,13 +1052,48 @@ "regex": "", "regexApplyTo": "value", "sort": "disabled", - "definition": "label_values(bot_connected{job=~\"$job\"}, instance)", + "definition": "label_values(bot_connected{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\"}, instance)", "options": [], "multi": false, "includeAll": true, "allowCustomValue": true } + }, + { + "kind": "QueryVariable", + "spec": { + "name": "network", + "current": { + "text": "All", + "value": "$__all" + }, + "label": "IRC network", + "hide": "dontHide", + "refresh": "onDashboardLoad", + "skipUrlSync": false, + "query": { + "kind": "DataQuery", + "group": "prometheus", + "version": "v0", + "spec": { + "qryType": 5, + "query": "label_values(bot_network_connected{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\"}, network)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "labels": { + "grafana.app/export-label": "prometheus-1" + } + }, + "regex": "", + "regexApplyTo": "value", + "sort": "alphabeticalAsc", + "definition": "label_values(bot_network_connected{job=~\"$job\", environment=~\"$environment\", hostname=~\"$hostname\", instance=~\"$instance\"}, network)", + "options": [], + "multi": true, + "includeAll": true, + "allowCustomValue": true + } } ] } -} \ No newline at end of file +}