diff --git a/collector/slave_status.go b/collector/slave_status.go index 5d3b11ae..0957a6e9 100644 --- a/collector/slave_status.go +++ b/collector/slave_status.go @@ -20,6 +20,7 @@ import ( "database/sql" "fmt" "log/slog" + "strconv" "strings" "github.com/prometheus/client_golang/prometheus" @@ -139,9 +140,46 @@ func (ScrapeSlaveStatus) Scrape(ctx context.Context, instance *instance, ch chan ) } } + + ScrapeMariaDBGtid(scanArgs, slaveCols, "Gtid_IO_Pos", ch, masterHost, masterUUID, channelName, connectionName) + ScrapeMariaDBGtid(scanArgs, slaveCols, "Gtid_Slave_Pos", ch, masterHost, masterUUID, channelName, connectionName) } return nil } +func ScrapeMariaDBGtid(scanArgs []interface{}, slaveCols []string, name string, ch chan<- prometheus.Metric, masterHost string, masterUUID string, channelName string, connectionName string) { + value := columnValue(scanArgs, slaveCols, name) + if value == "" { + return + } + + for _, gtid := range strings.Split(value, ",") { + parts := strings.Split(gtid, "-") + if len(parts) != 3 { + continue + } + + domainID := parts[0] + serverID := parts[1] + + sequence_num, err := strconv.ParseUint(parts[2], 10, 64) + if err != nil { + continue + } + + ch <- prometheus.MustNewConstMetric( + prometheus.NewDesc( + prometheus.BuildFQName(namespace, slaveStatus, strings.ToLower(name)), + fmt.Sprintf("%s metric from SHOW SLAVE STATUS.", name), + []string{"master_host", "master_uuid", "channel_name", "connection_name", "domain_id", "server_id"}, + nil, + ), + prometheus.GaugeValue, + float64(sequence_num), + masterHost, masterUUID, channelName, connectionName, domainID, serverID, + ) + } +} + // check interface var _ Scraper = ScrapeSlaveStatus{} diff --git a/collector/slave_status_test.go b/collector/slave_status_test.go index c4942316..987da81d 100644 --- a/collector/slave_status_test.go +++ b/collector/slave_status_test.go @@ -32,9 +32,9 @@ func TestScrapeSlaveStatus(t *testing.T) { defer db.Close() inst := &instance{db: db} - columns := []string{"Master_Host", "Read_Master_Log_Pos", "Slave_IO_Running", "Slave_SQL_Running", "Seconds_Behind_Master"} + columns := []string{"Master_Host", "Read_Master_Log_Pos", "Slave_IO_Running", "Slave_SQL_Running", "Seconds_Behind_Master", "Gtid_IO_Pos"} rows := sqlmock.NewRows(columns). - AddRow("127.0.0.1", "1", "Connecting", "Yes", "2") + AddRow("127.0.0.1", "1", "Connecting", "Yes", "2", "0-1-2,3-4-5") mock.ExpectQuery(sanitizeQuery("SHOW SLAVE STATUS")).WillReturnRows(rows) ch := make(chan prometheus.Metric) @@ -50,6 +50,8 @@ func TestScrapeSlaveStatus(t *testing.T) { {labels: labelMap{"channel_name": "", "connection_name": "", "master_host": "127.0.0.1", "master_uuid": ""}, value: 0, metricType: dto.MetricType_UNTYPED}, {labels: labelMap{"channel_name": "", "connection_name": "", "master_host": "127.0.0.1", "master_uuid": ""}, value: 1, metricType: dto.MetricType_UNTYPED}, {labels: labelMap{"channel_name": "", "connection_name": "", "master_host": "127.0.0.1", "master_uuid": ""}, value: 2, metricType: dto.MetricType_UNTYPED}, + {labels: labelMap{"channel_name": "", "connection_name": "", "master_host": "127.0.0.1", "master_uuid": "", "domain_id": "0", "server_id": "1"}, value: 2, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"channel_name": "", "connection_name": "", "master_host": "127.0.0.1", "master_uuid": "", "domain_id": "3", "server_id": "4"}, value: 5, metricType: dto.MetricType_GAUGE}, } convey.Convey("Metrics comparison", t, func() { for _, expect := range counterExpected {