forked from percona/mysqld_exporter
/
heartbeat.go
89 lines (76 loc) · 2.18 KB
/
heartbeat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Scrape heartbeat data.
package collector
import (
"database/sql"
"fmt"
"strconv"
"github.com/prometheus/client_golang/prometheus"
)
const (
// heartbeat is the Metric subsystem we use.
heartbeat = "heartbeat"
// heartbeatQuery is the query used to fetch the stored and current
// timestamps. %s will be replaced by the database and table name.
// The second column allows gets the server timestamp at the exact same
// time the query is run.
heartbeatQuery = "SELECT UNIX_TIMESTAMP(ts), UNIX_TIMESTAMP(NOW(6)), server_id from `%s`.`%s`"
)
// Metric descriptors.
var (
HeartbeatStoredDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, heartbeat, "stored_timestamp_seconds"),
"Timestamp stored in the heartbeat table.",
[]string{"server_id"}, nil,
)
HeartbeatNowDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, heartbeat, "now_timestamp_seconds"),
"Timestamp of the current server.",
[]string{"server_id"}, nil,
)
)
// ScrapeHeartbeat scrapes from the heartbeat table.
// This is mainly targeting pt-heartbeat, but will work with any heartbeat
// implementation that writes to a table with two columns:
// CREATE TABLE heartbeat (
// ts varchar(26) NOT NULL,
// server_id int unsigned NOT NULL PRIMARY KEY,
// );
func ScrapeHeartbeat(db *sql.DB, ch chan<- prometheus.Metric, collectDatabase, collectTable *string) error {
query := fmt.Sprintf(heartbeatQuery, *collectDatabase, *collectTable)
heartbeatRows, err := db.Query(query)
if err != nil {
return err
}
defer heartbeatRows.Close()
var (
now, ts sql.RawBytes
serverId int
)
for heartbeatRows.Next() {
if err := heartbeatRows.Scan(&ts, &now, &serverId); err != nil {
return err
}
tsFloatVal, err := strconv.ParseFloat(string(ts), 64)
if err != nil {
return err
}
nowFloatVal, err := strconv.ParseFloat(string(now), 64)
if err != nil {
return err
}
serverId := strconv.Itoa(serverId)
ch <- prometheus.MustNewConstMetric(
HeartbeatNowDesc,
prometheus.GaugeValue,
nowFloatVal,
serverId,
)
ch <- prometheus.MustNewConstMetric(
HeartbeatStoredDesc,
prometheus.GaugeValue,
tsFloatVal,
serverId,
)
}
return nil
}