You've already forked mysqld_exporter
mirror of
https://github.com/prometheus/mysqld_exporter.git
synced 2025-07-30 06:43:05 +03:00
Add the instance struct to handle connections (#859)
The intent is to use the instance struct to hold the connection to the database as well as metadata about the instance: - version - flavor (mariadb or mysql) Change is similar to prometheus-community/postgres_exporter#785 Signed-off-by: Vlad Gusev <vlad.esten@gmail.com>
This commit is contained in:
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -72,8 +71,9 @@ func (ScrapeBinlogSize) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeBinlogSize) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeBinlogSize) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var logBin uint8
|
||||
db := instance.getDB()
|
||||
err := db.QueryRowContext(ctx, logbinQuery).Scan(&logBin)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -31,6 +31,8 @@ func TestScrapeBinlogSize(t *testing.T) {
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
inst := &instance{db: db}
|
||||
|
||||
mock.ExpectQuery(logbinQuery).WillReturnRows(sqlmock.NewRows([]string{""}).AddRow(1))
|
||||
|
||||
columns := []string{"Log_name", "File_size"}
|
||||
@ -42,7 +44,7 @@ func TestScrapeBinlogSize(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeBinlogSize{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeBinlogSize{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -52,7 +51,8 @@ func (ScrapeEngineInnodbStatus) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeEngineInnodbStatus) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeEngineInnodbStatus) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
rows, err := db.QueryContext(ctx, engineInnodbStatusQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -152,10 +152,10 @@ END OF INNODB MONITOR OUTPUT
|
||||
rows := sqlmock.NewRows(columns).AddRow("InnoDB", "", sample)
|
||||
|
||||
mock.ExpectQuery(sanitizeQuery(engineInnodbStatusQuery)).WillReturnRows(rows)
|
||||
|
||||
inst := &instance{db: db}
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeEngineInnodbStatus{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeEngineInnodbStatus{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -50,7 +50,8 @@ func (ScrapeEngineTokudbStatus) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeEngineTokudbStatus) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeEngineTokudbStatus) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
tokudbRows, err := db.QueryContext(ctx, engineTokudbStatusQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -46,6 +46,7 @@ func TestScrapeEngineTokudbStatus(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"Type", "Name", "Status"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -59,7 +60,7 @@ func TestScrapeEngineTokudbStatus(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeEngineTokudbStatus{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeEngineTokudbStatus{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -15,10 +15,7 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -38,18 +35,12 @@ const (
|
||||
|
||||
// SQL queries and parameters.
|
||||
const (
|
||||
versionQuery = `SELECT @@version`
|
||||
|
||||
// System variable params formatting.
|
||||
// See: https://github.com/go-sql-driver/mysql#system-variables
|
||||
sessionSettingsParam = `log_slow_filter=%27tmp_table_on_disk,filesort_on_disk%27`
|
||||
timeoutParam = `lock_wait_timeout=%d`
|
||||
)
|
||||
|
||||
var (
|
||||
versionRE = regexp.MustCompile(`^\d+\.\d+`)
|
||||
)
|
||||
|
||||
// Tunable flags.
|
||||
var (
|
||||
exporterLockTimeout = kingpin.Flag(
|
||||
@ -92,6 +83,7 @@ type Exporter struct {
|
||||
logger log.Logger
|
||||
dsn string
|
||||
scrapers []Scraper
|
||||
instance *instance
|
||||
}
|
||||
|
||||
// New returns a new MySQL exporter for the provided DSN.
|
||||
@ -135,27 +127,23 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
|
||||
func (e *Exporter) scrape(ctx context.Context, ch chan<- prometheus.Metric) float64 {
|
||||
var err error
|
||||
scrapeTime := time.Now()
|
||||
db, err := sql.Open("mysql", e.dsn)
|
||||
instance, err := newInstance(e.dsn)
|
||||
if err != nil {
|
||||
level.Error(e.logger).Log("msg", "Error opening connection to database", "err", err)
|
||||
return 0.0
|
||||
}
|
||||
defer db.Close()
|
||||
defer instance.Close()
|
||||
e.instance = instance
|
||||
|
||||
// By design exporter should use maximum one connection per request.
|
||||
db.SetMaxOpenConns(1)
|
||||
db.SetMaxIdleConns(1)
|
||||
// Set max lifetime for a connection.
|
||||
db.SetConnMaxLifetime(1 * time.Minute)
|
||||
|
||||
if err := db.PingContext(ctx); err != nil {
|
||||
if err := instance.Ping(); err != nil {
|
||||
level.Error(e.logger).Log("msg", "Error pinging mysqld", "err", err)
|
||||
return 0.0
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(mysqlScrapeDurationSeconds, prometheus.GaugeValue, time.Since(scrapeTime).Seconds(), "connection")
|
||||
|
||||
version := getMySQLVersion(db, e.logger)
|
||||
version := instance.versionMajorMinor
|
||||
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
for _, scraper := range e.scrapers {
|
||||
@ -169,7 +157,7 @@ func (e *Exporter) scrape(ctx context.Context, ch chan<- prometheus.Metric) floa
|
||||
label := "collect." + scraper.Name()
|
||||
scrapeTime := time.Now()
|
||||
collectorSuccess := 1.0
|
||||
if err := scraper.Scrape(ctx, db, ch, log.With(e.logger, "scraper", scraper.Name())); err != nil {
|
||||
if err := scraper.Scrape(ctx, instance, ch, log.With(e.logger, "scraper", scraper.Name())); err != nil {
|
||||
level.Error(e.logger).Log("msg", "Error from scraper", "scraper", scraper.Name(), "target", e.getTargetFromDsn(), "err", err)
|
||||
collectorSuccess = 0.0
|
||||
}
|
||||
@ -189,19 +177,3 @@ func (e *Exporter) getTargetFromDsn() string {
|
||||
}
|
||||
return dsnConfig.Addr
|
||||
}
|
||||
|
||||
func getMySQLVersion(db *sql.DB, logger log.Logger) float64 {
|
||||
var versionStr string
|
||||
var versionNum float64
|
||||
if err := db.QueryRow(versionQuery).Scan(&versionStr); err == nil {
|
||||
versionNum, _ = strconv.ParseFloat(versionRE.FindString(versionStr), 64)
|
||||
} else {
|
||||
level.Debug(logger).Log("msg", "Error querying version", "err", err)
|
||||
}
|
||||
// If we can't match/parse the version, set it some big value that matches all versions.
|
||||
if versionNum == 0 {
|
||||
level.Debug(logger).Log("msg", "Error parsing version string", "version", versionStr)
|
||||
versionNum = 999
|
||||
}
|
||||
return versionNum
|
||||
}
|
||||
|
@ -15,12 +15,9 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/smartystreets/goconvey/convey"
|
||||
@ -68,20 +65,3 @@ func TestExporter(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetMySQLVersion(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("-short is passed, skipping test")
|
||||
}
|
||||
|
||||
logger := log.NewLogfmtLogger(os.Stderr)
|
||||
logger = level.NewFilter(logger, level.AllowDebug())
|
||||
|
||||
convey.Convey("Version parsing", t, func() {
|
||||
db, err := sql.Open("mysql", dsn)
|
||||
convey.So(err, convey.ShouldBeNil)
|
||||
defer db.Close()
|
||||
|
||||
convey.So(getMySQLVersion(db, logger), convey.ShouldBeBetweenOrEqual, 5.6, 12.0)
|
||||
})
|
||||
}
|
||||
|
@ -99,7 +99,8 @@ func (ScrapeGlobalStatus) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeGlobalStatus) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeGlobalStatus) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
globalStatusRows, err := db.QueryContext(ctx, globalStatusQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -30,6 +30,7 @@ func TestScrapeGlobalStatus(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"Variable_name", "Value"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -63,7 +64,7 @@ func TestScrapeGlobalStatus(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeGlobalStatus{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeGlobalStatus{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -138,7 +138,8 @@ func (ScrapeGlobalVariables) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeGlobalVariables) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeGlobalVariables) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
globalVariablesRows, err := db.QueryContext(ctx, globalVariablesQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -30,6 +30,7 @@ func TestScrapeGlobalVariables(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"Variable_name", "Value"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -52,7 +53,7 @@ func TestScrapeGlobalVariables(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeGlobalVariables{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeGlobalVariables{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -100,7 +100,8 @@ func nowExpr() string {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeHeartbeat) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeHeartbeat) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
query := fmt.Sprintf(heartbeatQuery, nowExpr(), *collectHeartbeatDatabase, *collectHeartbeatTable)
|
||||
heartbeatRows, err := db.QueryContext(ctx, query)
|
||||
if err != nil {
|
||||
|
@ -65,6 +65,7 @@ func TestScrapeHeartbeat(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
rows := sqlmock.NewRows(tt.Columns).
|
||||
AddRow("1487597613.001320", "1487598113.448042", 1)
|
||||
@ -72,7 +73,7 @@ func TestScrapeHeartbeat(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeHeartbeat{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeHeartbeat{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -70,7 +69,8 @@ func (ScrapeAutoIncrementColumns) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeAutoIncrementColumns) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeAutoIncrementColumns) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
autoIncrementRows, err := db.QueryContext(ctx, infoSchemaAutoIncrementQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@ -161,8 +160,9 @@ func (ScrapeClientStat) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeClientStat) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeClientStat) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var varName, varVal string
|
||||
db := instance.getDB()
|
||||
err := db.QueryRowContext(ctx, userstatCheckQuery).Scan(&varName, &varVal)
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "Detailed client stats are not available.")
|
||||
|
@ -30,6 +30,7 @@ func TestScrapeClientStat(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
mock.ExpectQuery(sanitizeQuery(userstatCheckQuery)).WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).
|
||||
AddRow("userstat", "ON"))
|
||||
@ -41,7 +42,7 @@ func TestScrapeClientStat(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeClientStat{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeClientStat{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -77,7 +76,8 @@ func (ScrapeInnodbCmp) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeInnodbCmp) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeInnodbCmp) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
informationSchemaInnodbCmpRows, err := db.QueryContext(ctx, innodbCmpQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -30,6 +30,7 @@ func TestScrapeInnodbCmp(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"page_size", "compress_ops", "compress_ops_ok", "compress_time", "uncompress_ops", "uncompress_time"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -38,7 +39,7 @@ func TestScrapeInnodbCmp(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeInnodbCmp{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeInnodbCmp{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -72,7 +71,8 @@ func (ScrapeInnodbCmpMem) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeInnodbCmpMem) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeInnodbCmpMem) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
informationSchemaInnodbCmpMemRows, err := db.QueryContext(ctx, innodbCmpMemQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -30,6 +30,7 @@ func TestScrapeInnodbCmpMem(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"page_size", "buffer_pool", "pages_used", "pages_free", "relocation_ops", "relocation_time"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -38,7 +39,7 @@ func TestScrapeInnodbCmpMem(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeInnodbCmpMem{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeInnodbCmpMem{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
@ -93,10 +92,11 @@ func (ScrapeInnodbMetrics) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeInnodbMetrics) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeInnodbMetrics) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var enabledColumnName string
|
||||
var query string
|
||||
|
||||
db := instance.getDB()
|
||||
err := db.QueryRowContext(ctx, infoSchemaInnodbMetricsEnabledColumnQuery).Scan(&enabledColumnName)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -31,6 +31,7 @@ func TestScrapeInnodbMetrics(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
enabledColumnName := []string{"COLUMN_NAME"}
|
||||
rows := sqlmock.NewRows(enabledColumnName).
|
||||
@ -53,7 +54,7 @@ func TestScrapeInnodbMetrics(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeInnodbMetrics{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeInnodbMetrics{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
@ -85,9 +84,10 @@ func (ScrapeInfoSchemaInnodbTablespaces) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeInfoSchemaInnodbTablespaces) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeInfoSchemaInnodbTablespaces) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var tablespacesTablename string
|
||||
var query string
|
||||
db := instance.getDB()
|
||||
err := db.QueryRowContext(ctx, innodbTablespacesTablenameQuery).Scan(&tablespacesTablename)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -31,6 +31,7 @@ func TestScrapeInfoSchemaInnodbTablespaces(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"TABLE_NAME"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -47,7 +48,7 @@ func TestScrapeInfoSchemaInnodbTablespaces(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeInfoSchemaInnodbTablespaces{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeInfoSchemaInnodbTablespaces{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
@ -97,11 +96,12 @@ func (ScrapeProcesslist) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeProcesslist) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeProcesslist) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
processQuery := fmt.Sprintf(
|
||||
infoSchemaProcesslistQuery,
|
||||
*processlistMinTime,
|
||||
)
|
||||
db := instance.getDB()
|
||||
processlistRows, err := db.QueryContext(ctx, processQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -40,6 +40,7 @@ func TestScrapeProcesslist(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
query := fmt.Sprintf(infoSchemaProcesslistQuery, 0)
|
||||
columns := []string{"user", "host", "command", "state", "processes", "seconds"}
|
||||
@ -56,7 +57,7 @@ func TestScrapeProcesslist(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeProcesslist{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeProcesslist{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -56,7 +55,8 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func processQueryResponseTimeTable(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, query string, i int) error {
|
||||
func processQueryResponseTimeTable(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, query string, i int) error {
|
||||
db := instance.getDB()
|
||||
queryDistributionRows, err := db.QueryContext(ctx, query)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -119,8 +119,9 @@ func (ScrapeQueryResponseTime) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeQueryResponseTime) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeQueryResponseTime) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var queryStats uint8
|
||||
db := instance.getDB()
|
||||
err := db.QueryRowContext(ctx, queryResponseCheckQuery).Scan(&queryStats)
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "Query response time distribution is not available.")
|
||||
@ -132,7 +133,7 @@ func (ScrapeQueryResponseTime) Scrape(ctx context.Context, db *sql.DB, ch chan<-
|
||||
}
|
||||
|
||||
for i, query := range queryResponseTimeQueries {
|
||||
err := processQueryResponseTimeTable(ctx, db, ch, query, i)
|
||||
err := processQueryResponseTimeTable(ctx, instance, ch, query, i)
|
||||
// The first query should not fail if query_response_time_stats is ON,
|
||||
// unlike the other two when the read/write tables exist only with Percona Server 5.6/5.7.
|
||||
if i == 0 && err != nil {
|
||||
|
@ -30,6 +30,7 @@ func TestScrapeQueryResponseTime(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
mock.ExpectQuery(queryResponseCheckQuery).WillReturnRows(sqlmock.NewRows([]string{""}).AddRow(1))
|
||||
|
||||
@ -52,7 +53,7 @@ func TestScrapeQueryResponseTime(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeQueryResponseTime{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeQueryResponseTime{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
@ -84,7 +83,8 @@ func (ScrapeReplicaHost) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeReplicaHost) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeReplicaHost) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
replicaHostRows, err := db.QueryContext(ctx, replicaHostQuery)
|
||||
if err != nil {
|
||||
if mysqlErr, ok := err.(*MySQL.MySQLError); ok { // Now the error number is accessible directly
|
||||
|
@ -30,6 +30,7 @@ func TestScrapeReplicaHost(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"SERVER_ID", "ROLE", "CPU", "MASTER_SLAVE_LATENCY_IN_MICROSECONDS", "REPLICA_LAG_IN_MILLISECONDS", "LOG_STREAM_SPEED_IN_KiB_PER_SECOND", "CURRENT_REPLAY_LATENCY_IN_MICROSECONDS"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -39,7 +40,7 @@ func TestScrapeReplicaHost(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeReplicaHost{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeReplicaHost{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
@ -72,9 +71,10 @@ func (ScrapeSchemaStat) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeSchemaStat) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeSchemaStat) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var varName, varVal string
|
||||
|
||||
db := instance.getDB()
|
||||
err := db.QueryRowContext(ctx, userstatCheckQuery).Scan(&varName, &varVal)
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "Detailed schema stats are not available.")
|
||||
|
@ -29,6 +29,7 @@ func TestScrapeSchemaStat(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
mock.ExpectQuery(sanitizeQuery(userstatCheckQuery)).WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).
|
||||
AddRow("userstat", "ON"))
|
||||
@ -41,7 +42,7 @@ func TestScrapeSchemaStat(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeSchemaStat{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeSchemaStat{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@ -97,8 +96,9 @@ func (ScrapeTableSchema) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeTableSchema) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeTableSchema) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var dbList []string
|
||||
db := instance.getDB()
|
||||
if *tableSchemaDatabases == "*" {
|
||||
dbListRows, err := db.QueryContext(ctx, dbListQuery)
|
||||
if err != nil {
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
@ -72,8 +71,9 @@ func (ScrapeTableStat) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeTableStat) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeTableStat) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var varName, varVal string
|
||||
db := instance.getDB()
|
||||
err := db.QueryRowContext(ctx, userstatCheckQuery).Scan(&varName, &varVal)
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "Detailed table stats are not available.")
|
||||
|
@ -29,6 +29,7 @@ func TestScrapeTableStat(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
mock.ExpectQuery(sanitizeQuery(userstatCheckQuery)).WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).
|
||||
AddRow("userstat", "ON"))
|
||||
@ -42,7 +43,7 @@ func TestScrapeTableStat(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeTableStat{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeTableStat{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@ -157,8 +156,9 @@ func (ScrapeUserStat) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeUserStat) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeUserStat) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var varName, varVal string
|
||||
db := instance.getDB()
|
||||
err := db.QueryRowContext(ctx, userstatCheckQuery).Scan(&varName, &varVal)
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "Detailed user stats are not available.")
|
||||
|
@ -30,6 +30,7 @@ func TestScrapeUserStat(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
mock.ExpectQuery(sanitizeQuery(userstatCheckQuery)).WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).
|
||||
AddRow("userstat", "ON"))
|
||||
@ -41,7 +42,7 @@ func TestScrapeUserStat(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeUserStat{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeUserStat{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
114
collector/instance.go
Normal file
114
collector/instance.go
Normal file
@ -0,0 +1,114 @@
|
||||
// Copyright 2024 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
FlavorMySQL = "mysql"
|
||||
FlavorMariaDB = "mariadb"
|
||||
)
|
||||
|
||||
type instance struct {
|
||||
db *sql.DB
|
||||
flavor string
|
||||
version semver.Version
|
||||
versionMajorMinor float64
|
||||
}
|
||||
|
||||
func newInstance(dsn string) (*instance, error) {
|
||||
i := &instance{}
|
||||
db, err := sql.Open("mysql", dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.SetMaxOpenConns(1)
|
||||
db.SetMaxIdleConns(1)
|
||||
i.db = db
|
||||
|
||||
version, versionString, err := queryVersion(db)
|
||||
if err != nil {
|
||||
db.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i.version = version
|
||||
|
||||
versionMajorMinor, err := strconv.ParseFloat(fmt.Sprintf("%d.%d", i.version.Major, i.version.Minor), 64)
|
||||
if err != nil {
|
||||
db.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i.versionMajorMinor = versionMajorMinor
|
||||
|
||||
if strings.Contains(strings.ToLower(versionString), "mariadb") {
|
||||
i.flavor = FlavorMariaDB
|
||||
} else {
|
||||
i.flavor = FlavorMySQL
|
||||
}
|
||||
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (i *instance) getDB() *sql.DB {
|
||||
return i.db
|
||||
}
|
||||
|
||||
func (i *instance) Close() error {
|
||||
return i.db.Close()
|
||||
}
|
||||
|
||||
// Ping checks connection availability and possibly invalidates the connection if it fails.
|
||||
func (i *instance) Ping() error {
|
||||
if err := i.db.Ping(); err != nil {
|
||||
if cerr := i.Close(); cerr != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// The result of SELECT version() is something like:
|
||||
// for MariaDB: "10.5.17-MariaDB-1:10.5.17+maria~ubu2004-log"
|
||||
// for MySQL: "8.0.36-28.1"
|
||||
var versionRegex = regexp.MustCompile(`^((\d+)(\.\d+)(\.\d+))`)
|
||||
|
||||
func queryVersion(db *sql.DB) (semver.Version, string, error) {
|
||||
var version string
|
||||
err := db.QueryRow("SELECT @@version;").Scan(&version)
|
||||
if err != nil {
|
||||
return semver.Version{}, version, err
|
||||
}
|
||||
|
||||
matches := versionRegex.FindStringSubmatch(version)
|
||||
if len(matches) > 1 {
|
||||
parsedVersion, err := semver.ParseTolerant(matches[1])
|
||||
if err != nil {
|
||||
return semver.Version{}, version, fmt.Errorf("could not parse version from %q", matches[1])
|
||||
}
|
||||
return parsedVersion, version, nil
|
||||
}
|
||||
|
||||
return semver.Version{}, version, fmt.Errorf("could not parse version from %q", version)
|
||||
}
|
@ -120,7 +120,8 @@ func (ScrapeUser) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeUser) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeUser) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
var (
|
||||
userRows *sql.Rows
|
||||
err error
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
@ -168,13 +167,14 @@ func (ScrapePerfEventsStatements) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfEventsStatements) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfEventsStatements) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
perfQuery := fmt.Sprintf(
|
||||
perfEventsStatementsQuery,
|
||||
*perfEventsStatementsDigestTextLimit,
|
||||
*perfEventsStatementsTimeLimit,
|
||||
*perfEventsStatementsLimit,
|
||||
)
|
||||
db := instance.getDB()
|
||||
// Timers here are returned in picoseconds.
|
||||
perfSchemaEventsStatementsRows, err := db.QueryContext(ctx, perfQuery)
|
||||
if err != nil {
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -177,7 +176,8 @@ func (ScrapePerfEventsStatementsSum) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfEventsStatementsSum) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfEventsStatementsSum) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
// Timers here are returned in picoseconds.
|
||||
perfEventsStatementsSumRows, err := db.QueryContext(ctx, perfEventsStatementsSumQuery)
|
||||
if err != nil {
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -61,7 +60,8 @@ func (ScrapePerfEventsWaits) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfEventsWaits) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfEventsWaits) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
// Timers here are returned in picoseconds.
|
||||
perfSchemaEventsWaitsRows, err := db.QueryContext(ctx, perfEventsWaitsQuery)
|
||||
if err != nil {
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -70,7 +69,8 @@ func (ScrapePerfFileEvents) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfFileEvents) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfFileEvents) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
// Timers here are returned in picoseconds.
|
||||
perfSchemaFileEventsRows, err := db.QueryContext(ctx, perfFileEventsQuery)
|
||||
if err != nil {
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
@ -80,7 +79,8 @@ func (ScrapePerfFileInstances) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfFileInstances) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfFileInstances) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
// Timers here are returned in picoseconds.
|
||||
perfSchemaFileInstancesRows, err := db.QueryContext(ctx, perfFileInstancesQuery, *performanceSchemaFileInstancesFilter)
|
||||
if err != nil {
|
||||
|
@ -37,6 +37,7 @@ func TestScrapePerfFileInstances(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"FILE_NAME", "EVENT_NAME", "COUNT_READ", "COUNT_WRITE", "SUM_NUMBER_OF_BYTES_READ", "SUM_NUMBER_OF_BYTES_WRITE"}
|
||||
|
||||
@ -48,7 +49,7 @@ func TestScrapePerfFileInstances(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapePerfFileInstances{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapePerfFileInstances{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
panic(fmt.Sprintf("error calling function on test: %s", err))
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -64,7 +63,8 @@ func (ScrapePerfIndexIOWaits) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfIndexIOWaits) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfIndexIOWaits) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
perfSchemaIndexWaitsRows, err := db.QueryContext(ctx, perfIndexIOWaitsQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -30,6 +30,7 @@ func TestScrapePerfIndexIOWaits(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"OBJECT_SCHEMA", "OBJECT_NAME", "INDEX_NAME", "COUNT_FETCH", "COUNT_INSERT", "COUNT_UPDATE", "COUNT_DELETE", "SUM_TIMER_FETCH", "SUM_TIMER_INSERT", "SUM_TIMER_UPDATE", "SUM_TIMER_DELETE"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -40,7 +41,7 @@ func TestScrapePerfIndexIOWaits(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapePerfIndexIOWaits{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapePerfIndexIOWaits{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
@ -79,7 +78,8 @@ func (ScrapePerfMemoryEvents) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfMemoryEvents) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfMemoryEvents) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
perfSchemaMemoryEventsRows, err := db.QueryContext(ctx, perfMemoryEventsQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -37,6 +37,7 @@ func TestScrapePerfMemoryEvents(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{
|
||||
"EVENT_NAME",
|
||||
@ -54,7 +55,7 @@ func TestScrapePerfMemoryEvents(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapePerfMemoryEvents{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapePerfMemoryEvents{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
panic(fmt.Sprintf("error calling function on test: %s", err))
|
||||
}
|
||||
close(ch)
|
||||
|
@ -15,7 +15,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
@ -101,7 +100,8 @@ func (ScrapePerfReplicationApplierStatsByWorker) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfReplicationApplierStatsByWorker) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfReplicationApplierStatsByWorker) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
perfReplicationApplierStatsByWorkerRows, err := db.QueryContext(ctx, perfReplicationApplierStatsByWorkerQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -31,6 +31,7 @@ func TestScrapePerfReplicationApplierStatsByWorker(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{
|
||||
"CHANNEL_NAME",
|
||||
@ -54,7 +55,7 @@ func TestScrapePerfReplicationApplierStatsByWorker(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapePerfReplicationApplierStatsByWorker{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapePerfReplicationApplierStatsByWorker{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -79,7 +79,8 @@ func (ScrapePerfReplicationGroupMemberStats) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfReplicationGroupMemberStats) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfReplicationGroupMemberStats) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
rows, err := db.QueryContext(ctx, perfReplicationGroupMemberStatsQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -30,6 +30,7 @@ func TestScrapePerfReplicationGroupMemberStats(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{
|
||||
"CHANNEL_NAME",
|
||||
@ -66,7 +67,7 @@ func TestScrapePerfReplicationGroupMemberStats(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapePerfReplicationGroupMemberStats{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapePerfReplicationGroupMemberStats{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -16,9 +16,10 @@ package collector
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const perfReplicationGroupMembersQuery = `
|
||||
@ -44,7 +45,8 @@ func (ScrapePerfReplicationGroupMembers) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfReplicationGroupMembers) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfReplicationGroupMembers) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
perfReplicationGroupMembersRows, err := db.QueryContext(ctx, perfReplicationGroupMembersQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -15,12 +15,13 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"github.com/smartystreets/goconvey/convey"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestScrapePerfReplicationGroupMembers(t *testing.T) {
|
||||
@ -29,6 +30,7 @@ func TestScrapePerfReplicationGroupMembers(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{
|
||||
"CHANNEL_NAME",
|
||||
@ -49,7 +51,7 @@ func TestScrapePerfReplicationGroupMembers(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapePerfReplicationGroupMembers{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapePerfReplicationGroupMembers{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
@ -82,6 +84,7 @@ func TestScrapePerfReplicationGroupMembersMySQL57(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{
|
||||
"CHANNEL_NAME",
|
||||
@ -100,7 +103,7 @@ func TestScrapePerfReplicationGroupMembersMySQL57(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapePerfReplicationGroupMembers{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapePerfReplicationGroupMembers{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -65,7 +64,8 @@ func (ScrapePerfTableIOWaits) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfTableIOWaits) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfTableIOWaits) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
perfSchemaTableWaitsRows, err := db.QueryContext(ctx, perfTableIOWaitsQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -17,7 +17,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -94,7 +93,8 @@ func (ScrapePerfTableLockWaits) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapePerfTableLockWaits) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapePerfTableLockWaits) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
db := instance.getDB()
|
||||
perfSchemaTableLockWaitsRows, err := db.QueryContext(ctx, perfTableLockWaitsQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -15,7 +15,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@ -35,5 +34,5 @@ type Scraper interface {
|
||||
Version() float64
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error
|
||||
Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error
|
||||
}
|
||||
|
@ -63,11 +63,12 @@ func (ScrapeSlaveHosts) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeSlaveHosts) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeSlaveHosts) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var (
|
||||
slaveHostsRows *sql.Rows
|
||||
err error
|
||||
)
|
||||
db := instance.getDB()
|
||||
// Try the both syntax for MySQL 8.0 and MySQL 8.4
|
||||
if slaveHostsRows, err = db.QueryContext(ctx, slaveHostsQuery); err != nil {
|
||||
if slaveHostsRows, err = db.QueryContext(ctx, showReplicasQuery); err != nil {
|
||||
|
@ -30,6 +30,7 @@ func TestScrapeSlaveHostsOldFormat(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"Server_id", "Host", "Port", "Rpl_recovery_rank", "Master_id"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -39,7 +40,7 @@ func TestScrapeSlaveHostsOldFormat(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeSlaveHosts{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeSlaveHosts{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
@ -68,6 +69,7 @@ func TestScrapeSlaveHostsNewFormat(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"Server_id", "Host", "Port", "Master_id", "Slave_UUID"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -77,7 +79,7 @@ func TestScrapeSlaveHostsNewFormat(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeSlaveHosts{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeSlaveHosts{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
@ -106,6 +108,7 @@ func TestScrapeSlaveHostsWithoutSlaveUuid(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"Server_id", "Host", "Port", "Master_id"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -115,7 +118,7 @@ func TestScrapeSlaveHostsWithoutSlaveUuid(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeSlaveHosts{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeSlaveHosts{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -69,11 +69,12 @@ func (ScrapeSlaveStatus) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape collects data from database connection and sends it over channel as prometheus metric.
|
||||
func (ScrapeSlaveStatus) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeSlaveStatus) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
var (
|
||||
slaveStatusRows *sql.Rows
|
||||
err error
|
||||
)
|
||||
db := instance.getDB()
|
||||
// Try the both syntax for MySQL/Percona and MariaDB
|
||||
for _, query := range slaveStatusQueries {
|
||||
slaveStatusRows, err = db.QueryContext(ctx, query)
|
||||
|
@ -30,6 +30,7 @@ func TestScrapeSlaveStatus(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{"Master_Host", "Read_Master_Log_Pos", "Slave_IO_Running", "Slave_SQL_Running", "Seconds_Behind_Master"}
|
||||
rows := sqlmock.NewRows(columns).
|
||||
@ -38,7 +39,7 @@ func TestScrapeSlaveStatus(t *testing.T) {
|
||||
|
||||
ch := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
if err = (ScrapeSlaveStatus{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeSlaveStatus{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
@ -15,7 +15,6 @@ package collector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -99,7 +98,9 @@ func (ScrapeSysUserSummary) Version() float64 {
|
||||
}
|
||||
|
||||
// Scrape the information from sys.user_summary, creating a metric for each value of each row, labeled with the user
|
||||
func (ScrapeSysUserSummary) Scrape(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
func (ScrapeSysUserSummary) Scrape(ctx context.Context, instance *instance, ch chan<- prometheus.Metric, logger log.Logger) error {
|
||||
|
||||
db := instance.getDB()
|
||||
|
||||
userSummaryRows, err := db.QueryContext(ctx, sysUserSummaryQuery)
|
||||
if err != nil {
|
||||
|
@ -16,14 +16,15 @@ package collector
|
||||
import (
|
||||
"context"
|
||||
"database/sql/driver"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"github.com/smartystreets/goconvey/convey"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestScrapeSysUserSummary(t *testing.T) {
|
||||
@ -33,6 +34,7 @@ func TestScrapeSysUserSummary(t *testing.T) {
|
||||
t.Fatalf("error opening a stub database connection: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
inst := &instance{db: db}
|
||||
|
||||
columns := []string{
|
||||
"user",
|
||||
@ -111,7 +113,7 @@ func TestScrapeSysUserSummary(t *testing.T) {
|
||||
ch := make(chan prometheus.Metric)
|
||||
|
||||
go func() {
|
||||
if err = (ScrapeSysUserSummary{}).Scrape(context.Background(), db, ch, log.NewNopLogger()); err != nil {
|
||||
if err = (ScrapeSysUserSummary{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
|
||||
t.Errorf("error calling function on test: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
|
1
go.mod
1
go.mod
@ -5,6 +5,7 @@ go 1.21
|
||||
require (
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0
|
||||
github.com/blang/semver/v4 v4.0.0
|
||||
github.com/go-kit/log v0.2.1
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/google/go-cmp v0.6.0
|
||||
|
2
go.sum
2
go.sum
@ -8,6 +8,8 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAu
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
|
Reference in New Issue
Block a user