feat(db): implement PostgreSQL monitoring and maintenance features
CI / changes (push) Successful in 9s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 26s
CI / web (push) Successful in 33s
CI / go (push) Successful in 2m11s
CI / bird2 (push) Successful in 16s
CI / release (push) Successful in 3m27s
CI / changes (push) Successful in 9s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 26s
CI / web (push) Successful in 33s
CI / go (push) Successful in 2m11s
CI / bird2 (push) Successful in 16s
CI / release (push) Successful in 3m27s
Added PostgreSQL monitoring and maintenance capabilities to the API, including new endpoints for instance-level metrics, maintenance operations, and job scheduling. Updated the HTTP API to support PostgreSQL monitoring routes and integrated a background scheduler for metrics collection. Enhanced the CLI with database commands for maintenance tasks. Updated documentation to reflect these changes.
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package pgmonitor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// Service provides PostgreSQL observability and maintenance helpers (control plane instance scope).
|
||||
type Service struct {
|
||||
pool *pgxpool.Pool
|
||||
cache *ttlCache
|
||||
}
|
||||
|
||||
// NewService constructs a metrics service for the API PostgreSQL pool.
|
||||
func NewService(pool *pgxpool.Pool) *Service {
|
||||
if pool == nil {
|
||||
return nil
|
||||
}
|
||||
return &Service{
|
||||
pool: pool,
|
||||
cache: newTTLCache(10 * time.Second),
|
||||
}
|
||||
}
|
||||
|
||||
// Pool exposes the underlying pool for job workers.
|
||||
func (s *Service) Pool() *pgxpool.Pool {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
return s.pool
|
||||
}
|
||||
|
||||
// Overview returns cached instance-level stats.
|
||||
func (s *Service) Overview(ctx context.Context) (Overview, error) {
|
||||
if s == nil || s.pool == nil {
|
||||
return Overview{}, errors.New("pgmonitor: postgres not configured")
|
||||
}
|
||||
if v, ok := s.cache.get("overview"); ok {
|
||||
if o, ok := v.(Overview); ok {
|
||||
return o, nil
|
||||
}
|
||||
}
|
||||
o, err := s.fetchOverview(ctx)
|
||||
if err != nil {
|
||||
return Overview{}, err
|
||||
}
|
||||
s.cache.set("overview", o)
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// Locks returns active / blocking locks.
|
||||
func (s *Service) Locks(ctx context.Context) ([]LockRow, error) {
|
||||
if s == nil || s.pool == nil {
|
||||
return nil, errors.New("pgmonitor: postgres not configured")
|
||||
}
|
||||
if v, ok := s.cache.get("locks"); ok {
|
||||
if rows, ok := v.([]LockRow); ok {
|
||||
return rows, nil
|
||||
}
|
||||
}
|
||||
rows, err := queryLocks(ctx, s.pool)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.cache.set("locks", rows)
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// Tables returns top tables by size with I/O stats.
|
||||
func (s *Service) Tables(ctx context.Context, limit int) ([]TableStat, error) {
|
||||
if s == nil || s.pool == nil {
|
||||
return nil, errors.New("pgmonitor: postgres not configured")
|
||||
}
|
||||
key := fmt.Sprintf("tables:%d", limit)
|
||||
if v, ok := s.cache.get(key); ok {
|
||||
if rows, ok := v.([]TableStat); ok {
|
||||
return rows, nil
|
||||
}
|
||||
}
|
||||
rows, err := queryTables(ctx, s.pool, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.cache.set(key, rows)
|
||||
return rows, nil
|
||||
}
|
||||
Reference in New Issue
Block a user