This commit is contained in:
Sylvain Rabot 2025-03-30 13:57:45 +00:00 committed by GitHub
commit 23382c8762
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 92 additions and 40 deletions

View File

@ -36,6 +36,24 @@ func NewPGStatUserTablesCollector(config collectorConfig) (Collector, error) {
}
var (
statUserTablesRelPages = prometheus.NewDesc(
prometheus.BuildFQName(namespace, userTableSubsystem, "relpages"),
"Estimated number of live pages",
[]string{"datname", "schemaname", "relname"},
prometheus.Labels{},
)
statUserTablesRelSize = prometheus.NewDesc(
prometheus.BuildFQName(namespace, userTableSubsystem, "relsize_bytes"),
"Estimated table size",
[]string{"datname", "schemaname", "relname"},
prometheus.Labels{},
)
statUserTablesRelSizeTotal = prometheus.NewDesc(
prometheus.BuildFQName(namespace, userTableSubsystem, "relsize_total_bytes"),
"Total disk space used by this table, in bytes, including all indexes and TOAST data",
[]string{"datname", "schemaname", "relname"},
prometheus.Labels{},
)
statUserTablesSeqScan = prometheus.NewDesc(
prometheus.BuildFQName(namespace, userTableSubsystem, "seq_scan"),
"Number of sequential scans initiated on this table",
@ -150,17 +168,14 @@ var (
[]string{"datname", "schemaname", "relname"},
prometheus.Labels{},
)
statUserTablesTotalSize = prometheus.NewDesc(
prometheus.BuildFQName(namespace, userTableSubsystem, "size_bytes"),
"Total disk space used by this table, in bytes, including all indexes and TOAST data",
[]string{"datname", "schemaname", "relname"},
prometheus.Labels{},
)
statUserTablesQuery = `SELECT
current_database() datname,
schemaname,
relname,
pg_stat_user_tables.relname,
relpages,
pg_relation_size(relid) AS relsize,
pg_total_relation_size(relid) as relsize_total,
seq_scan,
seq_tup_read,
idx_scan,
@ -179,10 +194,11 @@ var (
vacuum_count,
autovacuum_count,
analyze_count,
autoanalyze_count,
pg_total_relation_size(relid) as total_size
autoanalyze_count
FROM
pg_stat_user_tables`
pg_stat_user_tables
JOIN
pg_class ON pg_stat_user_tables.relid = pg_class.oid`
)
func (c *PGStatUserTablesCollector) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error {
@ -197,11 +213,11 @@ func (c *PGStatUserTablesCollector) Update(ctx context.Context, instance *instan
for rows.Next() {
var datname, schemaname, relname sql.NullString
var seqScan, seqTupRead, idxScan, idxTupFetch, nTupIns, nTupUpd, nTupDel, nTupHotUpd, nLiveTup, nDeadTup,
nModSinceAnalyze, vacuumCount, autovacuumCount, analyzeCount, autoanalyzeCount, totalSize sql.NullInt64
var relPages, relSize, relSizeTotal, seqScan, seqTupRead, idxScan, idxTupFetch, nTupIns, nTupUpd, nTupDel, nTupHotUpd, nLiveTup, nDeadTup,
nModSinceAnalyze, vacuumCount, autovacuumCount, analyzeCount, autoanalyzeCount sql.NullInt64
var lastVacuum, lastAutovacuum, lastAnalyze, lastAutoanalyze sql.NullTime
if err := rows.Scan(&datname, &schemaname, &relname, &seqScan, &seqTupRead, &idxScan, &idxTupFetch, &nTupIns, &nTupUpd, &nTupDel, &nTupHotUpd, &nLiveTup, &nDeadTup, &nModSinceAnalyze, &lastVacuum, &lastAutovacuum, &lastAnalyze, &lastAutoanalyze, &vacuumCount, &autovacuumCount, &analyzeCount, &autoanalyzeCount, &totalSize); err != nil {
if err := rows.Scan(&datname, &schemaname, &relname, &relPages, &relSize, &relSizeTotal, &seqScan, &seqTupRead, &idxScan, &idxTupFetch, &nTupIns, &nTupUpd, &nTupDel, &nTupHotUpd, &nLiveTup, &nDeadTup, &nModSinceAnalyze, &lastVacuum, &lastAutovacuum, &lastAnalyze, &lastAutoanalyze, &vacuumCount, &autovacuumCount, &analyzeCount, &autoanalyzeCount); err != nil {
return err
}
@ -218,6 +234,39 @@ func (c *PGStatUserTablesCollector) Update(ctx context.Context, instance *instan
relnameLabel = relname.String
}
relPagesMetric := 0.0
if relPages.Valid {
relPagesMetric = float64(relPages.Int64)
}
ch <- prometheus.MustNewConstMetric(
statUserTablesRelPages,
prometheus.GaugeValue,
relPagesMetric,
datnameLabel, schemanameLabel, relnameLabel,
)
relSizeMetric := 0.0
if relSize.Valid {
relSizeMetric = float64(relSize.Int64)
}
ch <- prometheus.MustNewConstMetric(
statUserTablesRelSize,
prometheus.GaugeValue,
relSizeMetric,
datnameLabel, schemanameLabel, relnameLabel,
)
relSizeTotalMetric := 0.0
if relSizeTotal.Valid {
relSizeTotalMetric = float64(relSizeTotal.Int64)
}
ch <- prometheus.MustNewConstMetric(
statUserTablesRelSizeTotal,
prometheus.GaugeValue,
relSizeTotalMetric,
datnameLabel, schemanameLabel, relnameLabel,
)
seqScanMetric := 0.0
if seqScan.Valid {
seqScanMetric = float64(seqScan.Int64)
@ -426,17 +475,6 @@ func (c *PGStatUserTablesCollector) Update(ctx context.Context, instance *instan
autoanalyzeCountMetric,
datnameLabel, schemanameLabel, relnameLabel,
)
totalSizeMetric := 0.0
if totalSize.Valid {
totalSizeMetric = float64(totalSize.Int64)
}
ch <- prometheus.MustNewConstMetric(
statUserTablesTotalSize,
prometheus.GaugeValue,
totalSizeMetric,
datnameLabel, schemanameLabel, relnameLabel,
)
}
if err := rows.Err(); err != nil {

View File

@ -53,6 +53,9 @@ func TestPGStatUserTablesCollector(t *testing.T) {
"datname",
"schemaname",
"relname",
"relpages",
"relsize",
"relsize_total",
"seq_scan",
"seq_tup_read",
"idx_scan",
@ -71,8 +74,7 @@ func TestPGStatUserTablesCollector(t *testing.T) {
"vacuum_count",
"autovacuum_count",
"analyze_count",
"autoanalyze_count",
"total_size"}
"autoanalyze_count"}
rows := sqlmock.NewRows(columns).
AddRow("postgres",
"public",
@ -87,16 +89,18 @@ func TestPGStatUserTablesCollector(t *testing.T) {
8,
9,
10,
11,
12,
13,
0,
lastVacuumTime,
lastAutoVacuumTime,
lastAnalyzeTime,
lastAutoAnalyzeTime,
11,
12,
13,
14,
15)
15,
16,
17)
mock.ExpectQuery(sanitizeQuery(statUserTablesQuery)).WillReturnRows(rows)
ch := make(chan prometheus.Metric)
go func() {
@ -109,25 +113,28 @@ func TestPGStatUserTablesCollector(t *testing.T) {
}()
expected := []MetricResult{
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 1},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 2},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 3},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 1},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 2},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 3},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 4},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 5},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 6},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 7},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 8},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 9},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 10},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 9},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 10},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 11},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 12},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 13},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 0},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 1685664000},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 1685750400},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 1685836800},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 1685923200},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 11},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 12},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 13},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 14},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 15},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 16},
{labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_COUNTER, value: 17},
}
convey.Convey("Metrics comparison", t, func() {
@ -154,6 +161,9 @@ func TestPGStatUserTablesCollectorNullValues(t *testing.T) {
"datname",
"schemaname",
"relname",
"relpages",
"relsize",
"relsize_total",
"seq_scan",
"seq_tup_read",
"idx_scan",
@ -172,8 +182,7 @@ func TestPGStatUserTablesCollectorNullValues(t *testing.T) {
"vacuum_count",
"autovacuum_count",
"analyze_count",
"autoanalyze_count",
"total_size"}
"autoanalyze_count"}
rows := sqlmock.NewRows(columns).
AddRow("postgres",
nil,
@ -197,6 +206,8 @@ func TestPGStatUserTablesCollectorNullValues(t *testing.T) {
nil,
nil,
nil,
nil,
nil,
nil)
mock.ExpectQuery(sanitizeQuery(statUserTablesQuery)).WillReturnRows(rows)
ch := make(chan prometheus.Metric)
@ -210,6 +221,9 @@ func TestPGStatUserTablesCollectorNullValues(t *testing.T) {
}()
expected := []MetricResult{
{labels: labelMap{"datname": "postgres", "schemaname": "unknown", "relname": "unknown"}, metricType: dto.MetricType_GAUGE, value: 0},
{labels: labelMap{"datname": "postgres", "schemaname": "unknown", "relname": "unknown"}, metricType: dto.MetricType_GAUGE, value: 0},
{labels: labelMap{"datname": "postgres", "schemaname": "unknown", "relname": "unknown"}, metricType: dto.MetricType_GAUGE, value: 0},
{labels: labelMap{"datname": "postgres", "schemaname": "unknown", "relname": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"datname": "postgres", "schemaname": "unknown", "relname": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},
{labels: labelMap{"datname": "postgres", "schemaname": "unknown", "relname": "unknown"}, metricType: dto.MetricType_COUNTER, value: 0},