master
go 117 lines 2.48 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package pgbouncer
4
5 import (
6 "context"
7 "database/sql"
8 _ "embed"
9 "errors"
10 "fmt"
11 "time"
12
13 "github.com/blang/semver/v4"
14 _ "github.com/jackc/pgx/v5/stdlib"
15
16 "github.com/netdata/netdata/go/plugins/pkg/confopt"
17 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
18 )
19
20 //go:embed "config_schema.json"
21 var configSchema string
22
23 func init() {
24 collectorapi.Register("pgbouncer", collectorapi.Creator{
25 JobConfigSchema: configSchema,
26 Create: func() collectorapi.CollectorV1 { return New() },
27 Config: func() any { return &Config{} },
28 })
29 }
30
31 func New() *Collector {
32 return &Collector{
33 Config: Config{
34 Timeout: confopt.Duration(time.Second),
35 DSN: "postgres://postgres:postgres@127.0.0.1:6432/pgbouncer",
36 },
37 charts: globalCharts.Copy(),
38 recheckSettingsEvery: time.Minute * 5,
39 metrics: &metrics{
40 dbs: make(map[string]*dbMetrics),
41 },
42 }
43 }
44
45 type Config struct {
46 Vnode string `yaml:"vnode,omitempty" json:"vnode"`
47 UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
48 AutoDetectionRetry int `yaml:"autodetection_retry,omitempty" json:"autodetection_retry"`
49 DSN string `yaml:"dsn" json:"dsn"`
50 Timeout confopt.Duration `yaml:"timeout,omitempty" json:"timeout"`
51 }
52
53 type Collector struct {
54 collectorapi.Base
55 Config `yaml:",inline" json:""`
56
57 charts *collectorapi.Charts
58
59 db *sql.DB
60
61 version *semver.Version
62 recheckSettingsTime time.Time
63 recheckSettingsEvery time.Duration
64 maxClientConn int64
65
66 metrics *metrics
67 }
68
69 func (c *Collector) Configuration() any {
70 return c.Config
71 }
72
73 func (c *Collector) Init(context.Context) error {
74 err := c.validateConfig()
75 if err != nil {
76 return fmt.Errorf("config validation: %v", err)
77 }
78
79 return nil
80 }
81
82 func (c *Collector) Check(context.Context) error {
83 mx, err := c.collect()
84 if err != nil {
85 return err
86 }
87 if len(mx) == 0 {
88 return errors.New("no metrics collected")
89 }
90 return nil
91 }
92
93 func (c *Collector) Charts() *collectorapi.Charts {
94 return c.charts
95 }
96
97 func (c *Collector) Collect(context.Context) map[string]int64 {
98 mx, err := c.collect()
99 if err != nil {
100 c.Error(err)
101 }
102
103 if len(mx) == 0 {
104 return nil
105 }
106 return mx
107 }
108
109 func (c *Collector) Cleanup(context.Context) {
110 if c.db == nil {
111 return
112 }
113 if err := c.db.Close(); err != nil {
114 c.Warningf("cleanup: error on closing the PgBouncer database [%s]: %v", c.DSN, err)
115 }
116 c.db = nil
117 }