Skip to content
Snippets Groups Projects
Commit 814460db authored by Ivan Metlushko's avatar Ivan Metlushko
Browse files

Add slave offset metrics

parent ed8d8e98
No related branches found
No related tags found
No related merge requests found
Loading
@@ -3,6 +3,7 @@ package exporter
Loading
@@ -3,6 +3,7 @@ package exporter
import ( import (
"fmt" "fmt"
"net/url" "net/url"
"regexp"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
Loading
@@ -131,6 +132,11 @@ func (e *Exporter) initGauges() {
Loading
@@ -131,6 +132,11 @@ func (e *Exporter) initGauges() {
Name: "master_link_up", Name: "master_link_up",
Help: "Master link status on Redis slave", Help: "Master link status on Redis slave",
}, []string{"addr", "alias"}) }, []string{"addr", "alias"})
e.metrics["connected_slave_offset"] = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: e.namespace,
Name: "connected_slave_offset",
Help: "Offset of connected slave",
}, []string{"addr", "alias", "slave_ip", "slave_state"})
e.metrics["db_keys"] = prometheus.NewGaugeVec(prometheus.GaugeOpts{ e.metrics["db_keys"] = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: e.namespace, Namespace: e.namespace,
Name: "db_keys", Name: "db_keys",
Loading
@@ -334,6 +340,36 @@ func parseDBKeyspaceString(db string, stats string) (keysTotal float64, keysExpi
Loading
@@ -334,6 +340,36 @@ func parseDBKeyspaceString(db string, stats string) (keysTotal float64, keysExpi
return return
} }
   
/*
slave0:ip=10.254.11.1,port=6379,state=online,offset=1751844676,lag=0
slave1:ip=10.254.11.2,port=6379,state=online,offset=1751844222,lag=0
*/
func parseConnectedSlaveString(slaveName string, slaveInfo string) (offset float64, ip string, state string, ok bool) {
ok = false
if matched, _ := regexp.MatchString(`^slave\d+`, slaveName); !matched {
return
}
connectedSlaveInfo := make(map[string]string)
for _, kvPart := range strings.Split(slaveInfo, ",") {
x := strings.Split(kvPart, "=")
if len(x) != 2 {
log.Debugf("Invalid format for connected slave string, got: %s", kvPart)
return
}
connectedSlaveInfo[x[0]] = x[1]
}
offset, err := strconv.ParseFloat(connectedSlaveInfo["offset"], 64)
if err != nil {
log.Debugf("Can not parse connected slave offset, got: %s", connectedSlaveInfo["offset"])
return
}
ok = true
ip = connectedSlaveInfo["ip"]
state = connectedSlaveInfo["state"]
return
}
func (e *Exporter) extractInfoMetrics(info, addr string, alias string, scrapes chan<- scrapeResult) error { func (e *Exporter) extractInfoMetrics(info, addr string, alias string, scrapes chan<- scrapeResult) error {
cmdstats := false cmdstats := false
lines := strings.Split(info, "\r\n") lines := strings.Split(info, "\r\n")
Loading
@@ -376,6 +412,17 @@ func (e *Exporter) extractInfoMetrics(info, addr string, alias string, scrapes c
Loading
@@ -376,6 +412,17 @@ func (e *Exporter) extractInfoMetrics(info, addr string, alias string, scrapes c
continue continue
} }
   
if slaveOffset, slaveIp, slaveState, ok := parseConnectedSlaveString(split[0], split[1]); ok {
e.metricsMtx.RLock()
e.metrics["connected_slave_offset"].WithLabelValues(
addr,
alias,
slaveIp,
slaveState,
).Set(slaveOffset)
e.metricsMtx.RUnlock()
}
if len(split) != 2 || !includeMetric(split[0]) { if len(split) != 2 || !includeMetric(split[0]) {
continue continue
} }
Loading
Loading
Loading
@@ -392,6 +392,38 @@ func TestKeyspaceStringParser(t *testing.T) {
Loading
@@ -392,6 +392,38 @@ func TestKeyspaceStringParser(t *testing.T) {
} }
} }
   
type slaveData struct {
k, v string
ip, state string
offset float64
ok bool
}
func TestParseConnectedSlaveString(t *testing.T) {
tsts := []slaveData{
{k: "slave0", v: "ip=10.254.11.1,port=6379,state=online,offset=1751844676,lag=0", offset: 1751844676, ip: "10.254.11.1", state: "online", ok: true},
{k: "slave1", v: "offset=1", offset: 1, ok: true},
{k: "slave2", v: "ip=1.2.3.4,state=online,offset=123", offset: 123, ip: "1.2.3.4", state: "online", ok: true},
{k: "slave", v: "offset=1751844676", ok: false},
{k: "slaveA", v: "offset=1751844676", ok: false},
{k: "slave0", v: "offset=abc", ok: false},
}
for _, tst := range tsts {
if offset, ip, state, ok := parseConnectedSlaveString(tst.k, tst.v); true {
if ok != tst.ok {
t.Errorf("failed for: db:%s stats:%s", tst.k, tst.v)
continue
}
if offset != tst.offset || ip != tst.ip || state != tst.state {
t.Errorf("values not matching, string:%s %f %s %s", tst.v, offset, ip, state)
}
}
}
}
func TestKeyValuesAndSizes(t *testing.T) { func TestKeyValuesAndSizes(t *testing.T) {
   
e, _ := NewRedisExporter(defaultRedisHost, "test", dbNumStrFull+"="+url.QueryEscape(keys[0])) e, _ := NewRedisExporter(defaultRedisHost, "test", dbNumStrFull+"="+url.QueryEscape(keys[0]))
Loading
@@ -552,7 +584,7 @@ func TestHTTPEndpoint(t *testing.T) {
Loading
@@ -552,7 +584,7 @@ func TestHTTPEndpoint(t *testing.T) {
`test_instance_info`, `test_instance_info`,
   
// labels and label values // labels and label values
`addr="redis://localhost:6379"`, `addr="redis://` + *redisAddr,
`redis_mode`, `redis_mode`,
`standalone`, `standalone`,
`cmd="get"`, `cmd="get"`,
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment