Skip to content
This repository was archived by the owner on Nov 28, 2022. It is now read-only.

ignore deadtuples if not superuser and ext not installed #11

Merged
merged 2 commits into from
Aug 14, 2017
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
12 changes: 12 additions & 0 deletions gauges/deadtuples.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package gauges
import (
"time"

"github.com/apex/log"
"github.com/prometheus/client_golang/prometheus"
)

Expand All @@ -18,6 +19,17 @@ func (g *Gauges) DeadTuples() *prometheus.GaugeVec {
}
var gauge = prometheus.NewGaugeVec(opts, []string{"table"})

if !g.isSuperuser {
g.Errs.Inc()
log.Error("postgresql_dead_tuples_pct disabled because pgstattuple requires a superuser")
return gauge
}
if !g.hasExtension("pgstattuple") {
g.Errs.Inc()
log.Error("postgresql_dead_tuples_pct disabled because pgstattuple extension is not installed")
return gauge
}

go func() {
for {
var tables []Relation
Expand Down
17 changes: 17 additions & 0 deletions gauges/deadtuples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,20 @@ func TestDeadTuples(t *testing.T) {
}
assertNoErrs(t, gauges)
}

func TestDeadTuplesWithoutPgstatTuple(t *testing.T) {
var assert = assert.New(t)
db, gauges, close := prepare(t)
defer close()
_, err := db.Exec("CREATE TABLE IF NOT EXISTS testtable(id bigint)")
assert.NoError(err)
_, err = db.Exec("DROP EXTENSION IF EXISTS pgstattuple")
assert.NoError(err)

var metrics = evaluate(t, gauges.DeadTuples())
assert.Len(metrics, 1)
for _, m := range metrics {
assert.Equal(0.0, m.Value)
}
assertErrs(t, gauges, 1)
}
40 changes: 31 additions & 9 deletions gauges/gauge.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,25 @@ import (
)

type Gauges struct {
name string
db *sqlx.DB
interval time.Duration
labels prometheus.Labels
Errs prometheus.Gauge
name string
db *sqlx.DB
interval time.Duration
labels prometheus.Labels
Errs prometheus.Gauge
isSuperuser bool
}

func New(name string, db *sql.DB, interval time.Duration) *Gauges {
var labels = prometheus.Labels{
"database_name": name,
}
var dbx = sqlx.NewDb(db, "postgres")
return &Gauges{
name: name,
db: sqlx.NewDb(db, "postgres"),
interval: interval,
labels: labels,
name: name,
db: dbx,
interval: interval,
labels: labels,
isSuperuser: isSuperuser(dbx),
Errs: prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "postgresql_query_errors",
Expand All @@ -39,6 +42,25 @@ func New(name string, db *sql.DB, interval time.Duration) *Gauges {
}
}

func isSuperuser(db *sqlx.DB) (super bool) {
if err := db.Get(&super, "select usesuper from pg_user where usename = CURRENT_USER"); err != nil {
log.WithError(err).Error("failed to detect user privileges")
}
return
}

func (g *Gauges) hasExtension(ext string) bool {
var count int64
if err := g.db.Get(
&count,
"select count(*) from pg_available_extensions where name = $1",
ext,
); err != nil {
log.WithError(err).Errorf("failed to determine if %s is installed", ext)
}
return count > 0
}

func paramsFix(params []string) []interface{} {
iparams := make([]interface{}, len(params))
for i, v := range params {
Expand Down
7 changes: 7 additions & 0 deletions gauges/gauge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ func assertNoErrs(t *testing.T, gauges *Gauges) {
assert.Equal(0.0, errs[0].Value)
}

func assertErrs(t *testing.T, gauges *Gauges, errors int) {
var assert = assert.New(t)
var errs = evaluate(t, gauges.Errs)
assert.Len(errs, 1)
assert.Equal(float64(errors), errs[0].Value)
}

func assertGreaterThan(t *testing.T, expected float64, m Metric) {
var assert = assert.New(t)
assert.True(
Expand Down