From 4bb84e9fa3b571b5531ba3f7bf12494b30803cf2 Mon Sep 17 00:00:00 2001 From: Felix Yuan Date: Wed, 9 Apr 2025 09:49:04 -0700 Subject: [PATCH 1/4] Record table only size bytes as well in addition to the total size bytes Signed-off-by: Felix Yuan --- collector/pg_stat_user_tables.go | 24 +++++++++++++++++++++--- collector/pg_stat_user_tables_test.go | 14 +++++++++++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/collector/pg_stat_user_tables.go b/collector/pg_stat_user_tables.go index 254d76a66..5e489fa85 100644 --- a/collector/pg_stat_user_tables.go +++ b/collector/pg_stat_user_tables.go @@ -156,6 +156,12 @@ var ( []string{"datname", "schemaname", "relname"}, prometheus.Labels{}, ) + statUserTablesOnlySize = prometheus.NewDesc( + prometheus.BuildFQName(namespace, userTableSubsystem, "only_size_bytes"), + "Total disk space used by only this table, in bytes", + []string{"datname", "schemaname", "relname"}, + prometheus.Labels{}, + ) statUserTablesQuery = `SELECT current_database() datname, @@ -180,7 +186,8 @@ var ( autovacuum_count, analyze_count, autoanalyze_count, - pg_total_relation_size(relid) as total_size + pg_total_relation_size(relid) as total_size, + pg_table_size(relid) as table_only_size FROM pg_stat_user_tables` ) @@ -198,10 +205,10 @@ 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 + nModSinceAnalyze, vacuumCount, autovacuumCount, analyzeCount, autoanalyzeCount, totalSize, tableOnlySize 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, &seqScan, &seqTupRead, &idxScan, &idxTupFetch, &nTupIns, &nTupUpd, &nTupDel, &nTupHotUpd, &nLiveTup, &nDeadTup, &nModSinceAnalyze, &lastVacuum, &lastAutovacuum, &lastAnalyze, &lastAutoanalyze, &vacuumCount, &autovacuumCount, &analyzeCount, &autoanalyzeCount, &totalSize, &tableOnlySize); err != nil { return err } @@ -437,6 +444,17 @@ func (c *PGStatUserTablesCollector) Update(ctx context.Context, instance *instan totalSizeMetric, datnameLabel, schemanameLabel, relnameLabel, ) + + tableOnlySizeMetric := 0.0 + if tableOnlySize.Valid { + tableOnlySizeMetric = float64(tableOnlySize.Int64) + } + ch <- prometheus.MustNewConstMetric( + statUserTablesOnlySize, + prometheus.GaugeValue, + tableOnlySizeMetric, + datnameLabel, schemanameLabel, relnameLabel, + ) } if err := rows.Err(); err != nil { diff --git a/collector/pg_stat_user_tables_test.go b/collector/pg_stat_user_tables_test.go index 5e82335c3..c4e6ee29b 100644 --- a/collector/pg_stat_user_tables_test.go +++ b/collector/pg_stat_user_tables_test.go @@ -72,7 +72,8 @@ func TestPGStatUserTablesCollector(t *testing.T) { "autovacuum_count", "analyze_count", "autoanalyze_count", - "total_size"} + "total_size", + "table_only_size"} rows := sqlmock.NewRows(columns). AddRow("postgres", "public", @@ -96,7 +97,8 @@ func TestPGStatUserTablesCollector(t *testing.T) { 12, 13, 14, - 15) + 15, + 16) mock.ExpectQuery(sanitizeQuery(statUserTablesQuery)).WillReturnRows(rows) ch := make(chan prometheus.Metric) go func() { @@ -128,6 +130,8 @@ func TestPGStatUserTablesCollector(t *testing.T) { {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_GAUGE, value: 15}, + {labels: labelMap{"datname": "postgres", "schemaname": "public", "relname": "a_table"}, metricType: dto.MetricType_GAUGE, value: 16}, } convey.Convey("Metrics comparison", t, func() { @@ -173,7 +177,8 @@ func TestPGStatUserTablesCollectorNullValues(t *testing.T) { "autovacuum_count", "analyze_count", "autoanalyze_count", - "total_size"} + "total_size", + "table_only_size"} rows := sqlmock.NewRows(columns). AddRow("postgres", nil, @@ -197,6 +202,7 @@ func TestPGStatUserTablesCollectorNullValues(t *testing.T) { nil, nil, nil, + nil, nil) mock.ExpectQuery(sanitizeQuery(statUserTablesQuery)).WillReturnRows(rows) ch := make(chan prometheus.Metric) @@ -229,6 +235,8 @@ func TestPGStatUserTablesCollectorNullValues(t *testing.T) { {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}, + {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}, } convey.Convey("Metrics comparison", t, func() { From 5fbd93056babb355bf82090faf52db7ec3a6990a Mon Sep 17 00:00:00 2001 From: Felix Yuan Date: Thu, 17 Apr 2025 14:38:57 -0700 Subject: [PATCH 2/4] Update collector/pg_stat_user_tables.go Co-authored-by: Ben Kochie Signed-off-by: Felix Yuan --- collector/pg_stat_user_tables.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collector/pg_stat_user_tables.go b/collector/pg_stat_user_tables.go index 5e489fa85..40f0edf79 100644 --- a/collector/pg_stat_user_tables.go +++ b/collector/pg_stat_user_tables.go @@ -157,7 +157,7 @@ var ( prometheus.Labels{}, ) statUserTablesOnlySize = prometheus.NewDesc( - prometheus.BuildFQName(namespace, userTableSubsystem, "only_size_bytes"), + prometheus.BuildFQName(namespace, userTableSubsystem, "table_size_bytes"), "Total disk space used by only this table, in bytes", []string{"datname", "schemaname", "relname"}, prometheus.Labels{}, From b9505389e72fa159896287f6ebc359f4d25f566e Mon Sep 17 00:00:00 2001 From: Felix Yuan Date: Thu, 17 Apr 2025 14:39:17 -0700 Subject: [PATCH 3/4] Update collector/pg_stat_user_tables.go Co-authored-by: Ben Kochie Signed-off-by: Felix Yuan --- collector/pg_stat_user_tables.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/collector/pg_stat_user_tables.go b/collector/pg_stat_user_tables.go index 40f0edf79..1fd8c503c 100644 --- a/collector/pg_stat_user_tables.go +++ b/collector/pg_stat_user_tables.go @@ -186,8 +186,8 @@ var ( autovacuum_count, analyze_count, autoanalyze_count, - pg_total_relation_size(relid) as total_size, - pg_table_size(relid) as table_only_size + pg_indexes_size(relid) as indexes_size, + pg_table_size(relid) as table_size FROM pg_stat_user_tables` ) From 34b93cf34b13686d88f12b517d849b32f23c4038 Mon Sep 17 00:00:00 2001 From: Felix Yuan Date: Thu, 17 Apr 2025 14:44:02 -0700 Subject: [PATCH 4/4] Finish renaming elements to index and table size Signed-off-by: Felix Yuan --- collector/pg_stat_user_tables.go | 34 +++++++++++++-------------- collector/pg_stat_user_tables_test.go | 8 +++---- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/collector/pg_stat_user_tables.go b/collector/pg_stat_user_tables.go index 1fd8c503c..ad8bcace7 100644 --- a/collector/pg_stat_user_tables.go +++ b/collector/pg_stat_user_tables.go @@ -150,15 +150,15 @@ 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", + statUserIndexSize = prometheus.NewDesc( + prometheus.BuildFQName(namespace, userTableSubsystem, "index_size_bytes"), + "Total disk space used by this index, in bytes", []string{"datname", "schemaname", "relname"}, prometheus.Labels{}, ) - statUserTablesOnlySize = prometheus.NewDesc( + statUserTableSize = prometheus.NewDesc( prometheus.BuildFQName(namespace, userTableSubsystem, "table_size_bytes"), - "Total disk space used by only this table, in bytes", + "Total disk space used by this table, in bytes", []string{"datname", "schemaname", "relname"}, prometheus.Labels{}, ) @@ -205,10 +205,10 @@ 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, tableOnlySize sql.NullInt64 + nModSinceAnalyze, vacuumCount, autovacuumCount, analyzeCount, autoanalyzeCount, indexSize, tableSize 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, &tableOnlySize); err != nil { + 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, &indexSize, &tableSize); err != nil { return err } @@ -434,25 +434,25 @@ func (c *PGStatUserTablesCollector) Update(ctx context.Context, instance *instan datnameLabel, schemanameLabel, relnameLabel, ) - totalSizeMetric := 0.0 - if totalSize.Valid { - totalSizeMetric = float64(totalSize.Int64) + indexSizeMetric := 0.0 + if indexSize.Valid { + indexSizeMetric = float64(indexSize.Int64) } ch <- prometheus.MustNewConstMetric( - statUserTablesTotalSize, + statUserIndexSize, prometheus.GaugeValue, - totalSizeMetric, + indexSizeMetric, datnameLabel, schemanameLabel, relnameLabel, ) - tableOnlySizeMetric := 0.0 - if tableOnlySize.Valid { - tableOnlySizeMetric = float64(tableOnlySize.Int64) + tableSizeMetric := 0.0 + if tableSize.Valid { + tableSizeMetric = float64(tableSize.Int64) } ch <- prometheus.MustNewConstMetric( - statUserTablesOnlySize, + statUserTableSize, prometheus.GaugeValue, - tableOnlySizeMetric, + tableSizeMetric, datnameLabel, schemanameLabel, relnameLabel, ) } diff --git a/collector/pg_stat_user_tables_test.go b/collector/pg_stat_user_tables_test.go index c4e6ee29b..4649bdbc5 100644 --- a/collector/pg_stat_user_tables_test.go +++ b/collector/pg_stat_user_tables_test.go @@ -72,8 +72,8 @@ func TestPGStatUserTablesCollector(t *testing.T) { "autovacuum_count", "analyze_count", "autoanalyze_count", - "total_size", - "table_only_size"} + "index_size", + "table_size"} rows := sqlmock.NewRows(columns). AddRow("postgres", "public", @@ -177,8 +177,8 @@ func TestPGStatUserTablesCollectorNullValues(t *testing.T) { "autovacuum_count", "analyze_count", "autoanalyze_count", - "total_size", - "table_only_size"} + "index_size", + "table_size"} rows := sqlmock.NewRows(columns). AddRow("postgres", nil,