postgres_exporter/collector/pg_extensions.go
Dmytro Liakhov f92f0b3ba1
PMM-11984: Add new metrics pg_available_extensions and pg_extensions to expose info about available extensions and installed extensions accordingly (#117)
* PMM-11984: Add new metrics `pg_available_extensions` and `pg_extensions` to expose info about available extensions and installed extensions accordingly

* PMM-11984: Exclude comment from the metric

* PMM-11984: Fix small issues

* PMM-11984: Update label values

---------

Co-authored-by: Alexey Mukas <91831719+ritbl@users.noreply.github.com>
2023-05-19 16:42:12 +03:00

123 lines
2.6 KiB
Go

package collector
import (
"context"
"database/sql"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
"strconv"
)
func init() {
registerCollector("extensions", defaultEnabled, NewExtensionsCollector)
}
var pgExtensions = map[string]*prometheus.Desc{
"pg_available_extensions": prometheus.NewDesc(
"pg_available_extensions",
"Extensions that are available for installation",
[]string{
"name",
"default_version",
"installed_version",
},
prometheus.Labels{},
),
"pg_extensions": prometheus.NewDesc(
"pg_extensions",
"Installed extensions",
[]string{
"name",
"relocatable",
"version",
},
prometheus.Labels{},
),
}
type ExtensionsCollector struct {
logger log.Logger
}
func NewExtensionsCollector(logger log.Logger) (Collector, error) {
return &ExtensionsCollector{logger: logger}, nil
}
func (e *ExtensionsCollector) Update(ctx context.Context, server *server, ch chan<- prometheus.Metric) error {
db, err := server.GetDB()
if err != nil {
return err
}
err = e.scrapeAvailableExtensions(ctx, db, ch)
if err != nil {
return err
}
err = e.scrapeInstalledExtensions(ctx, db, ch)
if err != nil {
return err
}
return nil
}
func (e *ExtensionsCollector) scrapeInstalledExtensions(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric) error {
rowsExtensions, err := db.QueryContext(ctx, `SELECT extname, extrelocatable, extversion FROM pg_extension`)
if err != nil {
return err
}
defer rowsExtensions.Close()
for rowsExtensions.Next() {
var extname string
var extrelocatable bool
var extversion string
if err := rowsExtensions.Scan(&extname, &extrelocatable, &extversion); err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(
pgExtensions["pg_extensions"],
prometheus.GaugeValue,
1,
extname,
strconv.FormatBool(extrelocatable),
extversion,
)
}
return nil
}
func (e *ExtensionsCollector) scrapeAvailableExtensions(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric) error {
rows, err := db.QueryContext(ctx, `SELECT name, default_version, installed_version FROM pg_available_extensions`)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var name sql.NullString
var defaultVersion sql.NullString
var installedVersion sql.NullString
if err := rows.Scan(&name, &defaultVersion, &installedVersion); err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(
pgExtensions["pg_available_extensions"],
prometheus.GaugeValue,
1,
name.String,
defaultVersion.String,
installedVersion.String,
)
}
return nil
}
var _ = (Collector)(&ExtensionsCollector{})