Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ Prometheus exporter for PostgreSQL server metrics.
- stat_archiver
- stat_bgwriter
- stat_database
- stat_progress_vacuum
- stat_replication
- stat_user_indexes
- stat_user_tables
- info
- locks

Expand Down Expand Up @@ -69,6 +72,9 @@ Prometheus exporter for PostgreSQL server metrics.
| postgres_stat_vacuum_progress_phase_vacuuming_heap | VACUUM is currently vacuuming the heap | pid, query_start, schemaname, datname, relname |
| postgres_stat_vacuum_progress_phase_vacuuming_indexes | VACUUM is currently vacuuming the indexes | pid, query_start, schemaname, datname, relname |
| postgres_stat_vacuum_progress_running | VACUUM is running | pid, query_start, schemaname, datname, relname |
| postgres_stat_user_indexes_scan_total | Number of times this index has been scanned | datname, schemaname, tablename, indexname |
| postgres_stat_user_indexes_tuple_read_total | Number of times tuples have been returned from scanning this index | datname, schemaname, tablename, indexname |
| postgres_stat_user_indexes_tuple_fetch_total | Number of live tuples fetched by scans on this index | datname, schemaname, tablename, indexname |
| postgres_up | Whether the Postgres server is up | |

### Run
Expand Down
1 change: 1 addition & 0 deletions collector/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ func NewExporter(ctx context.Context, logger kitlog.Logger, connConfig *pgx.Conn
datnameScrapers: []Scraper{
NewStatVacuumProgressScraper(),
NewStatUserTablesScraper(),
NewStatUserIndexesScraper(),
NewDiskUsageScraper(),
},
}
Expand Down
103 changes: 103 additions & 0 deletions collector/stat_user_indexes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package collector

import (
"context"

pgx "github.com/jackc/pgx/v4"
"github.com/prometheus/client_golang/prometheus"
)

// The Statistics Scraper
// PostgreSQL's statistics collector is a subsystem that supports collection and reporting of information about
// server activity. Presently, the collector can count accesses to tables and indexes in both disk-block and
// individual-row terms. It also tracks the total number of rows in each table, and information about vacuum
// and analyze actions for each table. It can also count calls to user-defined functions and the total time
// spent in each one.
//https://www.postgresql.org/docs/9.4/static/monitoring-stats.html#PG-STAT-ALL-INDEXES-VIEW
const (
// Scrape query
statUserIndexesQuery = `
SELECT schemaname
, relname
, indexrelname
, idx_scan::float
, idx_tup_read::float
, idx_tup_fetch::float
FROM pg_stat_user_indexes
WHERE schemaname != 'information_schema'
AND idx_tup_fetch IS NOT NULL /*postgres_exporter*/`
)

type statUserIndexesScraper struct {
idxScan *prometheus.Desc
idxTupRead *prometheus.Desc
idxTupFetch *prometheus.Desc
}

// NewStatUserIndexesScraper returns a new Scraper exposing postgres pg_stat_user_indexes view
func NewStatUserIndexesScraper() Scraper {
return &statUserIndexesScraper{
idxScan: prometheus.NewDesc(
"postgres_stat_user_indexes_scan_total",
"Number of times this index has been scanned",
[]string{"datname", "schemaname", "relname", "indexname"},
nil,
),
idxTupRead: prometheus.NewDesc(
"postgres_stat_user_indexes_tuple_read_total",
"Number of times tuples have been returned from scanning this index",
[]string{"datname", "schemaname", "relname", "indexname"},
nil,
),
idxTupFetch: prometheus.NewDesc(
"postgres_stat_user_indexes_tuple_fetch_total",
"Number of live tuples fetched by scans on this index",
[]string{"datname", "schemaname", "relname", "indexname"},
nil,
),
}
}

func (c *statUserIndexesScraper) Name() string {
return "StatUserIndexesScraper"
}

func (c *statUserIndexesScraper) Scrape(ctx context.Context, conn *pgx.Conn, version Version, ch chan<- prometheus.Metric) error {
var datname string
if err := conn.QueryRow(ctx, "SELECT current_database() /*postgres_exporter*/").Scan(&datname); err != nil {
return err
}

rows, err := conn.Query(ctx, statUserIndexesQuery)
if err != nil {
return err
}
defer rows.Close()

var schemaname, relname, indexname string
var idxScan, idxTupRead, idxTupFetch float64
for rows.Next() {
if err := rows.Scan(&schemaname,
&relname,
&indexname,
&idxScan,
&idxTupRead,
&idxTupFetch); err != nil {
return err
}

// postgres_stat_user_indexes_idx_scan_total
ch <- prometheus.MustNewConstMetric(c.idxScan, prometheus.CounterValue, idxScan, datname, schemaname, relname, indexname)
// postgres_stat_user_indexes_idx_tup_read_total
ch <- prometheus.MustNewConstMetric(c.idxTupRead, prometheus.CounterValue, idxTupRead, datname, schemaname, relname, indexname)
// postgres_stat_user_indexes_idx_tup_fetch_total
ch <- prometheus.MustNewConstMetric(c.idxTupFetch, prometheus.CounterValue, idxTupFetch, datname, schemaname, relname, indexname)
}

err = rows.Err()
if err != nil {
return err
}

return nil
}