feat(agent) multi-driver db monitoring, hot-plug config, release pipeline
This commit is contained in:
63
internal/collectors/postgres/postgres.go
Normal file
63
internal/collectors/postgres/postgres.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
"bugs.watch/agent/internal/aggregate"
|
||||
)
|
||||
|
||||
// Collector queries PostgreSQL status each sample interval.
|
||||
// All queries run under a 3-second timeout; any failure is silently skipped.
|
||||
type Collector struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func New(dsn string) (*Collector, error) {
|
||||
db, err := sql.Open("postgres", dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.SetMaxOpenConns(2)
|
||||
db.SetMaxIdleConns(1)
|
||||
db.SetConnMaxLifetime(5 * time.Minute)
|
||||
return &Collector{db: db}, nil
|
||||
}
|
||||
|
||||
func (c *Collector) Name() string { return "postgres" }
|
||||
|
||||
func (c *Collector) Close() { c.db.Close() }
|
||||
|
||||
func (c *Collector) Collect(window *aggregate.Window) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// pg_stat_database is readable by any user for their own database.
|
||||
var numBackends, maxConn int
|
||||
err := c.db.QueryRowContext(ctx,
|
||||
`SELECT d.numbackends, s.setting::int
|
||||
FROM pg_stat_database d, pg_settings s
|
||||
WHERE d.datname = current_database() AND s.name = 'max_connections'`,
|
||||
).Scan(&numBackends, &maxConn)
|
||||
if err == nil && maxConn > 0 {
|
||||
window.AddDBConnPct(float64(numBackends) / float64(maxConn) * 100)
|
||||
}
|
||||
|
||||
// pg_stat_activity requires pg_monitor role (PG 10+); silently skip on error.
|
||||
var activeQueries int
|
||||
if err := c.db.QueryRowContext(ctx,
|
||||
`SELECT count(*) FROM pg_stat_activity WHERE state = 'active'`,
|
||||
).Scan(&activeQueries); err == nil {
|
||||
window.AddDBThreadsRunning(float64(activeQueries))
|
||||
}
|
||||
|
||||
var sizeBytes int64
|
||||
if err := c.db.QueryRowContext(ctx,
|
||||
`SELECT pg_database_size(current_database())`,
|
||||
).Scan(&sizeBytes); err == nil {
|
||||
window.SetDBSizeBytes(uint64(sizeBytes))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user