|
|
|
package sqlx
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
"github.com/zeromicro/go-zero/core/metric"
|
|
|
|
)
|
|
|
|
|
|
|
|
const namespace = "sql_client"
|
|
|
|
|
|
|
|
var (
|
|
|
|
metricReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
|
|
|
|
Namespace: namespace,
|
|
|
|
Subsystem: "requests",
|
|
|
|
Name: "duration_ms",
|
|
|
|
Help: "mysql client requests duration(ms).",
|
|
|
|
Labels: []string{"command"},
|
|
|
|
Buckets: []float64{0.25, 0.5, 1, 1.5, 2, 3, 5, 10, 25, 50, 100, 250, 500, 1000, 2000, 5000, 10000, 15000},
|
|
|
|
})
|
|
|
|
metricReqErr = metric.NewCounterVec(&metric.CounterVecOpts{
|
|
|
|
Namespace: namespace,
|
|
|
|
Subsystem: "requests",
|
|
|
|
Name: "error_total",
|
|
|
|
Help: "mysql client requests error count.",
|
|
|
|
Labels: []string{"command", "error"},
|
|
|
|
})
|
|
|
|
metricSlowCount = metric.NewCounterVec(&metric.CounterVecOpts{
|
|
|
|
Namespace: namespace,
|
|
|
|
Subsystem: "requests",
|
|
|
|
Name: "slow_total",
|
|
|
|
Help: "mysql client requests slow count.",
|
|
|
|
Labels: []string{"command"},
|
|
|
|
})
|
|
|
|
|
|
|
|
connLabels = []string{"db_name", "hash"}
|
|
|
|
connCollector = newCollector()
|
|
|
|
_ prometheus.Collector = (*collector)(nil)
|
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
statGetter struct {
|
|
|
|
dbName string
|
|
|
|
hash string
|
|
|
|
poolStats func() sql.DBStats
|
|
|
|
}
|
|
|
|
|
|
|
|
// collector collects statistics from a redis client.
|
|
|
|
// It implements the prometheus.Collector interface.
|
|
|
|
collector struct {
|
|
|
|
maxOpenConnections *prometheus.Desc
|
|
|
|
|
|
|
|
openConnections *prometheus.Desc
|
|
|
|
inUseConnections *prometheus.Desc
|
|
|
|
idleConnections *prometheus.Desc
|
|
|
|
|
|
|
|
waitCount *prometheus.Desc
|
|
|
|
waitDuration *prometheus.Desc
|
|
|
|
maxIdleClosed *prometheus.Desc
|
|
|
|
maxIdleTimeClosed *prometheus.Desc
|
|
|
|
maxLifetimeClosed *prometheus.Desc
|
|
|
|
|
|
|
|
clients []*statGetter
|
|
|
|
lock sync.Mutex
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func newCollector() *collector {
|
|
|
|
c := &collector{
|
|
|
|
maxOpenConnections: prometheus.NewDesc(
|
|
|
|
prometheus.BuildFQName(namespace, "", "max_open_connections"),
|
|
|
|
"Maximum number of open connections to the database.",
|
|
|
|
connLabels, nil,
|
|
|
|
),
|
|
|
|
openConnections: prometheus.NewDesc(
|
|
|
|
prometheus.BuildFQName(namespace, "", "open_connections"),
|
|
|
|
"The number of established connections both in use and idle.",
|
|
|
|
connLabels, nil,
|
|
|
|
),
|
|
|
|
inUseConnections: prometheus.NewDesc(
|
|
|
|
prometheus.BuildFQName(namespace, "", "in_use_connections"),
|
|
|
|
"The number of connections currently in use.",
|
|
|
|
connLabels, nil,
|
|
|
|
),
|
|
|
|
idleConnections: prometheus.NewDesc(
|
|
|
|
prometheus.BuildFQName(namespace, "", "idle_connections"),
|
|
|
|
"The number of idle connections.",
|
|
|
|
connLabels, nil,
|
|
|
|
),
|
|
|
|
waitCount: prometheus.NewDesc(
|
|
|
|
prometheus.BuildFQName(namespace, "", "wait_count_total"),
|
|
|
|
"The total number of connections waited for.",
|
|
|
|
connLabels, nil,
|
|
|
|
),
|
|
|
|
waitDuration: prometheus.NewDesc(
|
|
|
|
prometheus.BuildFQName(namespace, "", "wait_duration_seconds_total"),
|
|
|
|
"The total time blocked waiting for a new connection.",
|
|
|
|
connLabels, nil,
|
|
|
|
),
|
|
|
|
maxIdleClosed: prometheus.NewDesc(
|
|
|
|
prometheus.BuildFQName(namespace, "", "max_idle_closed_total"),
|
|
|
|
"The total number of connections closed due to SetMaxIdleConns.",
|
|
|
|
connLabels, nil,
|
|
|
|
),
|
|
|
|
maxIdleTimeClosed: prometheus.NewDesc(
|
|
|
|
prometheus.BuildFQName(namespace, "", "max_idle_time_closed_total"),
|
|
|
|
"The total number of connections closed due to SetConnMaxIdleTime.",
|
|
|
|
connLabels, nil,
|
|
|
|
),
|
|
|
|
maxLifetimeClosed: prometheus.NewDesc(
|
|
|
|
prometheus.BuildFQName(namespace, "", "max_lifetime_closed_total"),
|
|
|
|
"The total number of connections closed due to SetConnMaxLifetime.",
|
|
|
|
connLabels, nil,
|
|
|
|
),
|
|
|
|
}
|
|
|
|
|
|
|
|
prometheus.MustRegister(c)
|
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
// Describe implements the prometheus.Collector interface.
|
|
|
|
func (c *collector) Describe(ch chan<- *prometheus.Desc) {
|
|
|
|
ch <- c.maxOpenConnections
|
|
|
|
ch <- c.openConnections
|
|
|
|
ch <- c.inUseConnections
|
|
|
|
ch <- c.idleConnections
|
|
|
|
ch <- c.waitCount
|
|
|
|
ch <- c.waitDuration
|
|
|
|
ch <- c.maxIdleClosed
|
|
|
|
ch <- c.maxLifetimeClosed
|
|
|
|
ch <- c.maxIdleTimeClosed
|
|
|
|
}
|
|
|
|
|
|
|
|
// Collect implements the prometheus.Collector interface.
|
|
|
|
func (c *collector) Collect(ch chan<- prometheus.Metric) {
|
|
|
|
c.lock.Lock()
|
|
|
|
defer c.lock.Unlock()
|
|
|
|
|
|
|
|
for _, client := range c.clients {
|
|
|
|
dbName, hash := client.dbName, client.hash
|
|
|
|
stats := client.poolStats()
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.maxOpenConnections, prometheus.GaugeValue,
|
|
|
|
float64(stats.MaxOpenConnections), dbName, hash)
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.openConnections, prometheus.GaugeValue,
|
|
|
|
float64(stats.OpenConnections), dbName, hash)
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.inUseConnections, prometheus.GaugeValue,
|
|
|
|
float64(stats.InUse), dbName, hash)
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.idleConnections, prometheus.GaugeValue,
|
|
|
|
float64(stats.Idle), dbName, hash)
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.waitCount, prometheus.CounterValue,
|
|
|
|
float64(stats.WaitCount), dbName, hash)
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.waitDuration, prometheus.CounterValue,
|
|
|
|
stats.WaitDuration.Seconds(), dbName, hash)
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.maxIdleClosed, prometheus.CounterValue,
|
|
|
|
float64(stats.MaxIdleClosed), dbName, hash)
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.maxLifetimeClosed, prometheus.CounterValue,
|
|
|
|
float64(stats.MaxLifetimeClosed), dbName, hash)
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.maxIdleTimeClosed, prometheus.CounterValue,
|
|
|
|
float64(stats.MaxIdleTimeClosed), dbName, hash)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *collector) registerClient(client *statGetter) {
|
|
|
|
c.lock.Lock()
|
|
|
|
defer c.lock.Unlock()
|
|
|
|
|
|
|
|
c.clients = append(c.clients, client)
|
|
|
|
}
|