Files

79 lines
1.9 KiB
Go
Raw Permalink Normal View History

package redis
import (
"context"
"strconv"
"strings"
"time"
"github.com/redis/go-redis/v9"
"bugs.watch/agent/internal/aggregate"
)
// Collector queries Redis INFO each sample interval.
// All queries run under a 3-second timeout; any failure is silently skipped.
// Metrics mapping:
// db_conn_pct → used_memory / maxmemory * 100 (skipped when maxmemory=0)
// db_threads_running → connected_clients
// db_size_bytes → used_memory
type Collector struct {
client *redis.Client
}
func New(addr string) (*Collector, error) {
opts, err := redis.ParseURL(addr)
if err != nil {
return nil, err
}
opts.DialTimeout = 3 * time.Second
opts.ReadTimeout = 3 * time.Second
opts.WriteTimeout = 3 * time.Second
return &Collector{client: redis.NewClient(opts)}, nil
}
func (c *Collector) Name() string { return "redis" }
func (c *Collector) Close() { c.client.Close() }
func (c *Collector) Collect(window *aggregate.Window) {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
info, err := c.client.Info(ctx, "memory", "clients").Result()
if err != nil {
return
}
fields := parseInfo(info)
usedMem, _ := strconv.ParseUint(fields["used_memory"], 10, 64)
maxMem, _ := strconv.ParseUint(fields["maxmemory"], 10, 64)
clients, _ := strconv.ParseUint(fields["connected_clients"], 10, 64)
if usedMem > 0 {
window.SetDBSizeBytes(usedMem)
}
if clients > 0 {
window.AddDBThreadsRunning(float64(clients))
}
if maxMem > 0 && usedMem > 0 {
window.AddDBConnPct(float64(usedMem) / float64(maxMem) * 100)
}
}
func parseInfo(s string) map[string]string {
out := make(map[string]string)
for _, line := range strings.Split(s, "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
k, v, ok := strings.Cut(line, ":")
if ok {
out[strings.TrimSpace(k)] = strings.TrimSpace(v)
}
}
return out
}