340 lines
10 KiB
Go
340 lines
10 KiB
Go
// 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"
|
|
"time"
|
|
|
|
"github.com/go-kit/log"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
)
|
|
|
|
const userTableSubsystem = "stat_user_tables"
|
|
|
|
func init() {
|
|
registerCollector(userTableSubsystem, defaultEnabled, NewPGStatUserTablesCollector)
|
|
}
|
|
|
|
type PGStatUserTablesCollector struct {
|
|
log log.Logger
|
|
}
|
|
|
|
func NewPGStatUserTablesCollector(config collectorConfig) (Collector, error) {
|
|
return &PGStatUserTablesCollector{log: config.logger}, nil
|
|
}
|
|
|
|
var (
|
|
statUserTablesSeqScan = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "seq_scan"),
|
|
"Number of sequential scans initiated on this table",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesSeqTupRead = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "seq_tup_read"),
|
|
"Number of live rows fetched by sequential scans",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesIdxScan = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "idx_scan"),
|
|
"Number of index scans initiated on this table",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesIdxTupFetch = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "idx_tup_fetch"),
|
|
"Number of live rows fetched by index scans",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesNTupIns = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "n_tup_ins"),
|
|
"Number of rows inserted",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesNTupUpd = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "n_tup_upd"),
|
|
"Number of rows updated",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesNTupDel = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "n_tup_del"),
|
|
"Number of rows deleted",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesNTupHotUpd = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "n_tup_hot_upd"),
|
|
"Number of rows HOT updated (i.e., with no separate index update required)",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesNLiveTup = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "n_live_tup"),
|
|
"Estimated number of live rows",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesNDeadTup = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "n_dead_tup"),
|
|
"Estimated number of dead rows",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesNModSinceAnalyze = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "n_mod_since_analyze"),
|
|
"Estimated number of rows changed since last analyze",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesLastVacuum = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "last_vacuum"),
|
|
"Last time at which this table was manually vacuumed (not counting VACUUM FULL)",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesLastAutovacuum = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "last_autovacuum"),
|
|
"Last time at which this table was vacuumed by the autovacuum daemon",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesLastAnalyze = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "last_analyze"),
|
|
"Last time at which this table was manually analyzed",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesLastAutoanalyze = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "last_autoanalyze"),
|
|
"Last time at which this table was analyzed by the autovacuum daemon",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesVacuumCount = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "vacuum_count"),
|
|
"Number of times this table has been manually vacuumed (not counting VACUUM FULL)",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesAutovacuumCount = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "autovacuum_count"),
|
|
"Number of times this table has been vacuumed by the autovacuum daemon",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesAnalyzeCount = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "analyze_count"),
|
|
"Number of times this table has been manually analyzed",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
statUserTablesAutoanalyzeCount = prometheus.NewDesc(
|
|
prometheus.BuildFQName(namespace, userTableSubsystem, "autoanalyze_count"),
|
|
"Number of times this table has been analyzed by the autovacuum daemon",
|
|
[]string{"datname", "schemaname", "relname"},
|
|
prometheus.Labels{},
|
|
)
|
|
|
|
statUserTablesQuery = `SELECT
|
|
current_database() datname,
|
|
schemaname,
|
|
relname,
|
|
seq_scan,
|
|
seq_tup_read,
|
|
idx_scan,
|
|
idx_tup_fetch,
|
|
n_tup_ins,
|
|
n_tup_upd,
|
|
n_tup_del,
|
|
n_tup_hot_upd,
|
|
n_live_tup,
|
|
n_dead_tup,
|
|
n_mod_since_analyze,
|
|
COALESCE(last_vacuum, '1970-01-01Z') as last_vacuum,
|
|
COALESCE(last_autovacuum, '1970-01-01Z') as last_autovacuum,
|
|
COALESCE(last_analyze, '1970-01-01Z') as last_analyze,
|
|
COALESCE(last_autoanalyze, '1970-01-01Z') as last_autoanalyze,
|
|
vacuum_count,
|
|
autovacuum_count,
|
|
analyze_count,
|
|
autoanalyze_count
|
|
FROM
|
|
pg_stat_user_tables`
|
|
)
|
|
|
|
func (c *PGStatUserTablesCollector) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error {
|
|
db := instance.getDB()
|
|
rows, err := db.QueryContext(ctx,
|
|
statUserTablesQuery)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
var datname string
|
|
var schemaname string
|
|
var relname string
|
|
var seqScan int64
|
|
var seqTupRead int64
|
|
var idxScan int64
|
|
var idxTupFetch int64
|
|
var nTupIns int64
|
|
var nTupUpd int64
|
|
var nTupDel int64
|
|
var nTupHotUpd int64
|
|
var nLiveTup int64
|
|
var nDeadTup int64
|
|
var nModSinceAnalyze int64
|
|
var lastVacuum time.Time
|
|
var lastAutovacuum time.Time
|
|
var lastAnalyze time.Time
|
|
var lastAutoanalyze time.Time
|
|
var vacuumCount int64
|
|
var autovacuumCount int64
|
|
var analyzeCount int64
|
|
var autoanalyzeCount int64
|
|
|
|
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); err != nil {
|
|
return err
|
|
}
|
|
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesSeqScan,
|
|
prometheus.CounterValue,
|
|
float64(seqScan),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesSeqTupRead,
|
|
prometheus.CounterValue,
|
|
float64(seqTupRead),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesIdxScan,
|
|
prometheus.CounterValue,
|
|
float64(idxScan),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesIdxTupFetch,
|
|
prometheus.CounterValue,
|
|
float64(idxTupFetch),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesNTupIns,
|
|
prometheus.CounterValue,
|
|
float64(nTupIns),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesNTupUpd,
|
|
prometheus.CounterValue,
|
|
float64(nTupUpd),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesNTupDel,
|
|
prometheus.CounterValue,
|
|
float64(nTupDel),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesNTupHotUpd,
|
|
prometheus.CounterValue,
|
|
float64(nTupHotUpd),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesNLiveTup,
|
|
prometheus.GaugeValue,
|
|
float64(nLiveTup),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesNDeadTup,
|
|
prometheus.GaugeValue,
|
|
float64(nDeadTup),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesNModSinceAnalyze,
|
|
prometheus.GaugeValue,
|
|
float64(nModSinceAnalyze),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesLastVacuum,
|
|
prometheus.GaugeValue,
|
|
float64(lastVacuum.Unix()),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesLastAutovacuum,
|
|
prometheus.GaugeValue,
|
|
float64(lastAutovacuum.Unix()),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesLastAnalyze,
|
|
prometheus.GaugeValue,
|
|
float64(lastAnalyze.Unix()),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesLastAutoanalyze,
|
|
prometheus.GaugeValue,
|
|
float64(lastAutoanalyze.Unix()),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesVacuumCount,
|
|
prometheus.CounterValue,
|
|
float64(vacuumCount),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesAutovacuumCount,
|
|
prometheus.CounterValue,
|
|
float64(autovacuumCount),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesAnalyzeCount,
|
|
prometheus.CounterValue,
|
|
float64(analyzeCount),
|
|
datname, schemaname, relname,
|
|
)
|
|
ch <- prometheus.MustNewConstMetric(
|
|
statUserTablesAutoanalyzeCount,
|
|
prometheus.CounterValue,
|
|
float64(autoanalyzeCount),
|
|
datname, schemaname, relname,
|
|
)
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|