Skip to content

Commit

Permalink
Collect index definition on a best effort basis.
Browse files Browse the repository at this point in the history
  • Loading branch information
mdevan committed Dec 4, 2020
1 parent 37eb50a commit 17be4a7
Showing 1 changed file with 35 additions and 3 deletions.
38 changes: 35 additions & 3 deletions collector/collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ func (c *collector) collectDatabase(o CollectConfig) {
}
if !arrayHas(o.Omit, "tables") && !arrayHas(o.Omit, "indexes") {
c.getIndexes(!o.NoSizes)
c.getIndexDef()
}
if !arrayHas(o.Omit, "sequences") {
c.getSequences()
Expand Down Expand Up @@ -1419,7 +1420,7 @@ func (c *collector) getIndexes(fillSize bool) {
current_database(), S.idx_scan, S.idx_tup_read, S.idx_tup_fetch,
pg_stat_get_blocks_fetched(S.indexrelid) - pg_stat_get_blocks_hit(S.indexrelid) AS idx_blks_read,
pg_stat_get_blocks_hit(S.indexrelid) AS idx_blks_hit,
C.relnatts, AM.amname, C.reltablespace, pg_get_indexdef(S.indexrelid)
C.relnatts, AM.amname, C.reltablespace
FROM pg_stat_user_indexes AS S
JOIN pg_class AS C
ON S.indexrelid = C.oid
Expand All @@ -1439,8 +1440,7 @@ func (c *collector) getIndexes(fillSize bool) {
if err := rows.Scan(&idx.TableOID, &idx.OID, &idx.SchemaName,
&idx.TableName, &idx.Name, &idx.DBName, &idx.IdxScan,
&idx.IdxTupRead, &idx.IdxTupFetch, &idx.IdxBlksRead,
&idx.IdxBlksHit, &idx.RelNAtts, &idx.AMName, &tblspcOID,
&idx.Definition); err != nil {
&idx.IdxBlksHit, &idx.RelNAtts, &idx.AMName, &tblspcOID); err != nil {
log.Fatalf("pg_stat_user_indexes query failed: %v", err)
}
idx.Size = -1 // will be filled in later if asked for
Expand Down Expand Up @@ -1469,6 +1469,38 @@ func (c *collector) getIndexes(fillSize bool) {
}
}

// getIndexDef gets the definition of all indexes. Used to be collected along
// with getIndexes(), but pg_get_indexdef() will wait for access exclusive
// locks on the table in question. By collecting this separately, we'll
// silently fail the collection of just the index defs, and let the collection
// of index stats succeed.
func (c *collector) getIndexDef() {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()

q := `SELECT indexrelid, pg_get_indexdef(indexrelid) FROM pg_stat_user_indexes`
rows, err := c.db.QueryContext(ctx, q)
if err != nil {
return // ignore errors silently, ok to fail to get the defn
}
defer rows.Close()

for rows.Next() {
var oid int
var defn string
if err := rows.Scan(&oid, &defn); err != nil {
break // abort silently
}
for i := range c.result.Indexes {
if c.result.Indexes[i].OID == oid {
c.result.Indexes[i].Definition = defn
break
}
}
}
// ignore checking for rows.Err()
}

func (c *collector) getSequences() {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
Expand Down

0 comments on commit 17be4a7

Please sign in to comment.