Skip to content

Commit

Permalink
WIP: pg_stat_database by PG version support
Browse files Browse the repository at this point in the history
  • Loading branch information
df7cb committed Jun 8, 2022
1 parent 01a9fee commit d27b514
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 23 deletions.
20 changes: 10 additions & 10 deletions collector/models/pgStatDatabase.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

// +metric=slice
type PgStatDatabase struct {
tableName struct{} `pg:"pg_stat_database,discard_unknown_columns"`
tableName struct{} `pg:"pg_stat_database"`
DatID int64 `pg:"datid" help:"OID of a database" metric:"database_id,type:label"`
DatName string `pg:"datname" help:"Name of this database" metric:"database,type:label"`
NumBackends int `pg:"numbackends" help:"Number of backends currently connected to this database" metric:"backends,type:gauge"`
Expand All @@ -23,16 +23,16 @@ type PgStatDatabase struct {
TempFiles int64 `pg:"temp_files" help:"Number of temporary files created by queries in this database" metric:"temp_files_total"`
TempBytes int64 `pg:"temp_bytes" help:"Total amount of data written to temporary files by queries in this database" metric:"temp_bytes_total"`
Deadlocks int64 `pg:"deadlocks" help:"Number of deadlocks detected in this database" metric:"deadlocks_total"`
checksumFailures int64 `pg:"checksum_failures" help:"Number of data page checksum failures detected in this database" metric:"checksum_failures_count"` // new in PG12
checksumLastFailure time.Time `pg:"checksum_last_failure" help:"Time at which the last data page checksum failure was detected in this database" metric:"checksum_last_failure"` // new in PG12
ChecksumFailures int64 `pg:"checksum_failures" help:"Number of data page checksum failures detected in this database" metric:"checksum_failures_count"` // new in PG12
ChecksumLastFailure time.Time `pg:"checksum_last_failure" help:"Time at which the last data page checksum failure was detected in this database" metric:"checksum_last_failure"` // new in PG12
BlkReadTime Milliseconds `pg:"blk_read_time" help:"Time spent reading data file blocks by backends in this database" metric:"blk_read_seconds_total"`
BlkWriteTime Milliseconds `pg:"blk_write_time" help:"Time spent writing data file blocks by backends in this database" metric:"blk_write_seconds_total"`
sessionTime Milliseconds `pg:"session_time" help:"Time spent by database sessions in this database, in milliseconds" metric:"session_time_total"` // new in PG14
activeTime Milliseconds `pg:"active_time" help:"Time spent executing SQL statements in this database, in milliseconds" metric:"active_time_total"` // new in PG14
idleInTransactionTime Milliseconds `pg:"idle_in_transaction_time" help:"Time spent idling while in a transaction in this database, in milliseconds" metric:"idle_in_transaction_time_total"` // new in PG14
sessions int64 `pg:"sessions" help:"Total number of sessions established to this database" metric:"sessions_count"` // new in PG14
sessionsAbandoned int64 `pg:"sessions_abandoned" help:"Number of database sessions to this database that were terminated because connection to the client was lost" metric:"sessions_abandoned_count"` // new in PG14
sessionsFatal int64 `pg:"sessions_fatal" help:"Number of database sessions to this database that were terminated by fatal errors" metric:"sessions_fatal_count"` // new in PG14
sessionsKilled int64 `pg:"sessions_killed" help:"Number of database sessions to this database that were terminated by operator intervention" metric:"sessions_killed_count"` // new in PG14
SessionTime Milliseconds `pg:"session_time" help:"Time spent by database sessions in this database, in milliseconds" metric:"session_time_total"` // new in PG14
ActiveTime Milliseconds `pg:"active_time" help:"Time spent executing SQL statements in this database, in milliseconds" metric:"active_time_total"` // new in PG14
IdleInTransactionTime Milliseconds `pg:"idle_in_transaction_time" help:"Time spent idling while in a transaction in this database, in milliseconds" metric:"idle_in_transaction_time_total"` // new in PG14
Sessions int64 `pg:"sessions" help:"Total number of sessions established to this database" metric:"sessions_count"` // new in PG14
SessionsAbandoned int64 `pg:"sessions_abandoned" help:"Number of database sessions to this database that were terminated because connection to the client was lost" metric:"sessions_abandoned_count"` // new in PG14
SessionsFatal int64 `pg:"sessions_fatal" help:"Number of database sessions to this database that were terminated by fatal errors" metric:"sessions_fatal_count"` // new in PG14
SessionsKilled int64 `pg:"sessions_killed" help:"Number of database sessions to this database that were terminated by operator intervention" metric:"sessions_killed_count"` // new in PG14
StatsReset time.Time `pg:"stats_reset" help:"Time at which these statistics were last reset"`
}
20 changes: 10 additions & 10 deletions collector/models/pgStatDatabase_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func (r *PgStatDatabase) ToMetrics(namespace string, subsystem string, ch chan<-
)

// checksum_failures_count (CounterValue)
checksumFailuresCount := float64(r.checksumFailures)
checksumFailuresCount := float64(r.ChecksumFailures)
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, `checksum_failures_count`), `Number of data page checksum failures detected in this database`, nil, labels,
Expand All @@ -149,10 +149,10 @@ func (r *PgStatDatabase) ToMetrics(namespace string, subsystem string, ch chan<-

// checksum_last_failure (CounterValue)
var checksumLastFailure float64
if r.checksumLastFailure.IsZero() {
if r.ChecksumLastFailure.IsZero() {
checksumLastFailure = float64(0)
} else {
checksumLastFailure = float64(r.checksumLastFailure.Unix())
checksumLastFailure = float64(r.ChecksumLastFailure.Unix())
}
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
Expand All @@ -177,55 +177,55 @@ func (r *PgStatDatabase) ToMetrics(namespace string, subsystem string, ch chan<-
)

// session_time_total (CounterValue)
sessionTimeTotal := r.sessionTime.Seconds()
sessionTimeTotal := r.SessionTime.Seconds()
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, `session_time_total`), `Time spent by database sessions in this database, in milliseconds`, nil, labels,
), prometheus.CounterValue, sessionTimeTotal,
)

// active_time_total (CounterValue)
activeTimeTotal := r.activeTime.Seconds()
activeTimeTotal := r.ActiveTime.Seconds()
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, `active_time_total`), `Time spent executing SQL statements in this database, in milliseconds`, nil, labels,
), prometheus.CounterValue, activeTimeTotal,
)

// idle_in_transaction_time_total (CounterValue)
idleInTransactionTimeTotal := r.idleInTransactionTime.Seconds()
idleInTransactionTimeTotal := r.IdleInTransactionTime.Seconds()
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, `idle_in_transaction_time_total`), `Time spent idling while in a transaction in this database, in milliseconds`, nil, labels,
), prometheus.CounterValue, idleInTransactionTimeTotal,
)

// sessions_count (CounterValue)
sessionsCount := float64(r.sessions)
sessionsCount := float64(r.Sessions)
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, `sessions_count`), `Total number of sessions established to this database`, nil, labels,
), prometheus.CounterValue, sessionsCount,
)

// sessions_abandoned_count (CounterValue)
sessionsAbandonedCount := float64(r.sessionsAbandoned)
sessionsAbandonedCount := float64(r.SessionsAbandoned)
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, `sessions_abandoned_count`), `Number of database sessions to this database that were terminated because connection to the client was lost`, nil, labels,
), prometheus.CounterValue, sessionsAbandonedCount,
)

// sessions_fatal_count (CounterValue)
sessionsFatalCount := float64(r.sessionsFatal)
sessionsFatalCount := float64(r.SessionsFatal)
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, `sessions_fatal_count`), `Number of database sessions to this database that were terminated by fatal errors`, nil, labels,
), prometheus.CounterValue, sessionsFatalCount,
)

// sessions_killed_count (CounterValue)
sessionsKilledCount := float64(r.sessionsKilled)
sessionsKilledCount := float64(r.SessionsKilled)
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, `sessions_killed_count`), `Number of database sessions to this database that were terminated by operator intervention`, nil, labels,
Expand Down
20 changes: 17 additions & 3 deletions collector/stat_database.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package collector

import (
"context"
"fmt"

"github.com/go-pg/pg/v9"
"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -39,12 +40,25 @@ func (ScrapeDatabase) Type() ScrapeType {

// Scrape collects data from database connection and sends it over channel as prometheus metric.
func (ScrapeDatabase) Scrape(ctx context.Context, db *pg.DB, ch chan<- prometheus.Metric) error {
// we create a query based on the given commandline flags
columns := "numbackends, xact_commit, xact_rollback, blks_read, blks_hit, tup_returned, tup_fetched, tup_inserted, tup_updated, tup_deleted, conflicts, temp_files, temp_bytes, deadlocks, blk_read_time, blk_write_time"

if pgversion >= 120000 {
columns += ", checksum_failures, checksum_last_failure"
}

if pgversion >= 140000 {
columns += ", session_time, active_time, idle_in_transaction_time, sessions, sessions_abandoned, sessions_fatal, sessions_killed"
}

qs := fmt.Sprintf(`SELECT datid, datname, %s, stats_reset FROM pg_stat_database`+
` WHERE datname IN (?)`,
columns)

var statDatabase models.PgStatDatabaseSlice
if err := db.ModelContext(ctx, &statDatabase).Where("datname IN (?)", pg.In(collectDatabases)).
Select(); err != nil {
if _, err := db.QueryContext(ctx, &statDatabase, qs, pg.In(collectDatabases)); err != nil {
return err
}

if err := statDatabase.ToMetrics(namespace, statdatabase, ch); err != nil {
return err
}
Expand Down

0 comments on commit d27b514

Please sign in to comment.