From bd1b526ae9b69f71a6cb7bfce17341ebdcd87fa8 Mon Sep 17 00:00:00 2001 From: Felix Yuan Date: Wed, 28 Jun 2023 10:58:49 -0700 Subject: [PATCH 1/5] Autovacuum active collector and test Signed-off-by: Felix Yuan --- collector/collector_test.go | 1 + .../pg_stat_activity_autovacuum_active.go | 91 +++++++++++++++++++ ...pg_stat_activity_autovacuum_active_test.go | 62 +++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 collector/pg_stat_activity_autovacuum_active.go create mode 100644 collector/pg_stat_activity_autovacuum_active_test.go diff --git a/collector/collector_test.go b/collector/collector_test.go index 00c21ed2..18101f00 100644 --- a/collector/collector_test.go +++ b/collector/collector_test.go @@ -49,6 +49,7 @@ func readMetric(m prometheus.Metric) MetricResult { func sanitizeQuery(q string) string { q = strings.Join(strings.Fields(q), " ") q = strings.Replace(q, "(", "\\(", -1) + q = strings.Replace(q, "?", "\\?", -1) q = strings.Replace(q, ")", "\\)", -1) q = strings.Replace(q, "[", "\\[", -1) q = strings.Replace(q, "]", "\\]", -1) diff --git a/collector/pg_stat_activity_autovacuum_active.go b/collector/pg_stat_activity_autovacuum_active.go new file mode 100644 index 00000000..1ad960e3 --- /dev/null +++ b/collector/pg_stat_activity_autovacuum_active.go @@ -0,0 +1,91 @@ +// Copyright 2023 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 ( + "context" + + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" +) + +const statActivityAutovacuumActiveSubsystem = "stat_activity_autovacuum_active" + +func init() { + registerCollector(statActivityAutovacuumActiveSubsystem, defaultDisabled, NewPGStatActivityAutovacuumActiveCollector) +} + +type PGStatActivityAutovacuumActiveCollector struct { + log log.Logger +} + +func NewPGStatActivityAutovacuumActiveCollector(config collectorConfig) (Collector, error) { + return &PGStatActivityAutovacuumActiveCollector{log: config.logger}, nil +} + +var ( + statActivityAutovacuumActiveWorkersCount = prometheus.NewDesc( + prometheus.BuildFQName(namespace, statActivityAutovacuumActiveSubsystem, "workers"), + "Current number of statActivityAutovacuumActive queries", + []string{"phase", "mode"}, + prometheus.Labels{}, + ) + + statActivityAutovacuumActiveQuery = ` + SELECT + v.phase, + CASE + when a.query ~ '^autovacuum.*to prevent wraparound' then 'wraparound' + when a.query ~* '^vacuum' then 'user' + when a.pid is null then 'idle' + ELSE 'regular' + END as mode, + count(1) as workers_count + FROM pg_stat_progress_vacuum v + LEFT JOIN pg_catalog.pg_stat_activity a using (pid) + GROUP BY 1,2 + ` +) + +func (PGStatActivityAutovacuumActiveCollector) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error { + db := instance.getDB() + rows, err := db.QueryContext(ctx, + statActivityAutovacuumActiveQuery) + + if err != nil { + return err + } + defer rows.Close() + + for rows.Next() { + var phase, mode string + var workersCount float64 + + if err := rows.Scan(&phase, &mode, &workersCount); err != nil { + return err + } + labels := []string{phase, mode} + + ch <- prometheus.MustNewConstMetric( + statActivityAutovacuumActiveWorkersCount, + prometheus.GaugeValue, + workersCount, + labels..., + ) + } + if err := rows.Err(); err != nil { + return err + } + return nil +} diff --git a/collector/pg_stat_activity_autovacuum_active_test.go b/collector/pg_stat_activity_autovacuum_active_test.go new file mode 100644 index 00000000..edde1ef9 --- /dev/null +++ b/collector/pg_stat_activity_autovacuum_active_test.go @@ -0,0 +1,62 @@ +// Copyright 2023 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 ( + "context" + "testing" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/prometheus/client_golang/prometheus" + dto "github.com/prometheus/client_model/go" + "github.com/smartystreets/goconvey/convey" +) + +func TestPGStatActivityAutovacuumActiveCollector(t *testing.T) { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("Error opening a stub db connection: %s", err) + } + defer db.Close() + inst := &instance{db: db} + columns := []string{ + "phase", + "mode", + "workers_count", + } + rows := sqlmock.NewRows(columns). + AddRow("Scanning heap", "regular", 2) + mock.ExpectQuery(sanitizeQuery(statActivityAutovacuumActiveQuery)).WillReturnRows(rows) + + ch := make(chan prometheus.Metric) + go func() { + defer close(ch) + c := PGStatActivityAutovacuumActiveCollector{} + + if err := c.Update(context.Background(), inst, ch); err != nil { + t.Errorf("Error calling PGStatActivityAutovacuumActiveCollector.Update: %s", err) + } + }() + expected := []MetricResult{ + {labels: labelMap{"phase": "Scanning heap", "mode": "regular"}, value: 2, metricType: dto.MetricType_GAUGE}, + } + convey.Convey("Metrics comparison", t, func() { + for _, expect := range expected { + m := readMetric(<-ch) + convey.So(expect, convey.ShouldResemble, m) + } + }) + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unfulfilled exceptions: %s", err) + } +} From 71754c748e5f560841cc5489838c2e5618728068 Mon Sep 17 00:00:00 2001 From: Felix Yuan Date: Thu, 29 Jun 2023 12:41:47 -0700 Subject: [PATCH 2/5] Update collector/pg_stat_activity_autovacuum_active.go Co-authored-by: Joe Adams Signed-off-by: Felix Yuan --- collector/pg_stat_activity_autovacuum_active.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collector/pg_stat_activity_autovacuum_active.go b/collector/pg_stat_activity_autovacuum_active.go index 1ad960e3..329c3037 100644 --- a/collector/pg_stat_activity_autovacuum_active.go +++ b/collector/pg_stat_activity_autovacuum_active.go @@ -50,7 +50,7 @@ var ( when a.query ~* '^vacuum' then 'user' when a.pid is null then 'idle' ELSE 'regular' - END as mode, + END AS mode, count(1) as workers_count FROM pg_stat_progress_vacuum v LEFT JOIN pg_catalog.pg_stat_activity a using (pid) From 804044a264ac7928601a9e7a5540074fc4c97343 Mon Sep 17 00:00:00 2001 From: Felix Yuan Date: Thu, 29 Jun 2023 12:41:53 -0700 Subject: [PATCH 3/5] Update collector/pg_stat_activity_autovacuum_active.go Co-authored-by: Joe Adams Signed-off-by: Felix Yuan --- collector/pg_stat_activity_autovacuum_active.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collector/pg_stat_activity_autovacuum_active.go b/collector/pg_stat_activity_autovacuum_active.go index 329c3037..c516f955 100644 --- a/collector/pg_stat_activity_autovacuum_active.go +++ b/collector/pg_stat_activity_autovacuum_active.go @@ -51,7 +51,7 @@ var ( when a.pid is null then 'idle' ELSE 'regular' END AS mode, - count(1) as workers_count + count(1) AS workers_count FROM pg_stat_progress_vacuum v LEFT JOIN pg_catalog.pg_stat_activity a using (pid) GROUP BY 1,2 From ca9e35927429722da6b825a41bb2f1184777fbb5 Mon Sep 17 00:00:00 2001 From: Felix Yuan Date: Thu, 29 Jun 2023 15:50:40 -0700 Subject: [PATCH 4/5] SQL formatting Signed-off-by: Felix Yuan --- collector/pg_stat_activity_autovacuum_active.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/collector/pg_stat_activity_autovacuum_active.go b/collector/pg_stat_activity_autovacuum_active.go index c516f955..48fe5a7b 100644 --- a/collector/pg_stat_activity_autovacuum_active.go +++ b/collector/pg_stat_activity_autovacuum_active.go @@ -46,14 +46,23 @@ var ( SELECT v.phase, CASE +<<<<<<< HEAD when a.query ~ '^autovacuum.*to prevent wraparound' then 'wraparound' when a.query ~* '^vacuum' then 'user' when a.pid is null then 'idle' ELSE 'regular' END AS mode, count(1) AS workers_count +======= + WHEN a.query ~ '^autovacuum.*to prevent wraparound' THEN 'wraparound' + WHEN a.query ~* '^vacuum' THEN 'user' + WHEN a.pid is NULL THEN 'idle' + ELSE 'regular' + END as mode, + count(1) as workers_count +>>>>>>> c928d57 (SQL formatting) FROM pg_stat_progress_vacuum v - LEFT JOIN pg_catalog.pg_stat_activity a using (pid) + LEFT JOIN pg_catalog.pg_stat_activity a USING (pid) GROUP BY 1,2 ` ) From 589bb25590aded68fd2b00a233cd99db249ab9cc Mon Sep 17 00:00:00 2001 From: Felix Yuan Date: Thu, 29 Jun 2023 15:52:18 -0700 Subject: [PATCH 5/5] Commit markers Signed-off-by: Felix Yuan --- collector/pg_stat_activity_autovacuum_active.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/collector/pg_stat_activity_autovacuum_active.go b/collector/pg_stat_activity_autovacuum_active.go index 48fe5a7b..6e6b41fd 100644 --- a/collector/pg_stat_activity_autovacuum_active.go +++ b/collector/pg_stat_activity_autovacuum_active.go @@ -46,21 +46,12 @@ var ( SELECT v.phase, CASE -<<<<<<< HEAD - when a.query ~ '^autovacuum.*to prevent wraparound' then 'wraparound' - when a.query ~* '^vacuum' then 'user' - when a.pid is null then 'idle' - ELSE 'regular' - END AS mode, - count(1) AS workers_count -======= WHEN a.query ~ '^autovacuum.*to prevent wraparound' THEN 'wraparound' WHEN a.query ~* '^vacuum' THEN 'user' WHEN a.pid is NULL THEN 'idle' ELSE 'regular' END as mode, count(1) as workers_count ->>>>>>> c928d57 (SQL formatting) FROM pg_stat_progress_vacuum v LEFT JOIN pg_catalog.pg_stat_activity a USING (pid) GROUP BY 1,2