master
go 187 lines 4.56 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package cockroachdb
4
5 import (
6 "context"
7 _ "embed"
8 "errors"
9 "fmt"
10 "time"
11
12 "github.com/netdata/netdata/go/plugins/pkg/confopt"
13 "github.com/netdata/netdata/go/plugins/pkg/prometheus"
14 "github.com/netdata/netdata/go/plugins/pkg/web"
15 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
16 )
17
18 //go:embed "config_schema.json"
19 var configSchema string
20
21 // DefaultMetricsSampleInterval hard coded to 10
22 // https://github.com/cockroachdb/cockroach/blob/d5ffbf76fb4c4ef802836529188e4628476879bd/pkg/server/config.go#L56-L58
23 const dbSamplingInterval = 10
24
25 func init() {
26 collectorapi.Register("cockroachdb", collectorapi.Creator{
27 JobConfigSchema: configSchema,
28 Defaults: collectorapi.Defaults{
29 UpdateEvery: dbSamplingInterval,
30 },
31 Methods: cockroachMethods,
32 MethodHandler: cockroachFunctionHandler,
33 Create: func() collectorapi.CollectorV1 { return New() },
34 Config: func() any { return &Config{} },
35 })
36 }
37
38 func New() *Collector {
39 return &Collector{
40 Config: Config{
41 HTTPConfig: web.HTTPConfig{
42 RequestConfig: web.RequestConfig{
43 URL: "http://127.0.0.1:8080/_status/vars",
44 },
45 ClientConfig: web.ClientConfig{
46 Timeout: confopt.Duration(time.Second),
47 },
48 },
49 Functions: FunctionsConfig{
50 TopQueries: TopQueriesConfig{
51 Limit: 500,
52 },
53 RunningQueries: RunningQueriesConfig{
54 Limit: 500,
55 },
56 },
57 },
58 charts: charts.Copy(),
59 }
60 }
61
62 type Config struct {
63 Vnode string `yaml:"vnode,omitempty" json:"vnode"`
64 UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
65 AutoDetectionRetry int `yaml:"autodetection_retry,omitempty" json:"autodetection_retry"`
66 Functions FunctionsConfig `yaml:"functions,omitempty" json:"functions"`
67 web.HTTPConfig `yaml:",inline" json:""`
68 }
69
70 type FunctionsConfig struct {
71 DSN string `yaml:"dsn,omitempty" json:"dsn,omitempty"`
72 TopQueries TopQueriesConfig `yaml:"top_queries,omitempty" json:"top_queries"`
73 RunningQueries RunningQueriesConfig `yaml:"running_queries,omitempty" json:"running_queries"`
74 }
75
76 type TopQueriesConfig struct {
77 Disabled bool `yaml:"disabled" json:"disabled"`
78 Timeout confopt.Duration `yaml:"timeout,omitempty" json:"timeout"`
79 Limit int `yaml:"limit,omitempty" json:"limit"`
80 }
81
82 type RunningQueriesConfig struct {
83 Disabled bool `yaml:"disabled" json:"disabled"`
84 Timeout confopt.Duration `yaml:"timeout,omitempty" json:"timeout"`
85 Limit int `yaml:"limit,omitempty" json:"limit"`
86 }
87
88 func (c Config) topQueriesTimeout() time.Duration {
89 if c.Functions.TopQueries.Timeout == 0 {
90 return c.Timeout.Duration()
91 }
92 return c.Functions.TopQueries.Timeout.Duration()
93 }
94
95 func (c Config) topQueriesLimit() int {
96 if c.Functions.TopQueries.Limit <= 0 {
97 return 500
98 }
99 return c.Functions.TopQueries.Limit
100 }
101
102 func (c Config) runningQueriesTimeout() time.Duration {
103 if c.Functions.RunningQueries.Timeout == 0 {
104 return c.Timeout.Duration()
105 }
106 return c.Functions.RunningQueries.Timeout.Duration()
107 }
108
109 func (c Config) runningQueriesLimit() int {
110 if c.Functions.RunningQueries.Limit <= 0 {
111 return 500
112 }
113 return c.Functions.RunningQueries.Limit
114 }
115
116 type Collector struct {
117 collectorapi.Base
118 Config `yaml:",inline" json:""`
119
120 charts *Charts
121
122 prom prometheus.Prometheus
123
124 funcRouter *funcRouter
125 }
126
127 func (c *Collector) Configuration() any {
128 return c.Config
129 }
130
131 func (c *Collector) Init(context.Context) error {
132 if err := c.validateConfig(); err != nil {
133 return fmt.Errorf("error on validating config: %v", err)
134 }
135
136 prom, err := c.initPrometheusClient()
137 if err != nil {
138 return fmt.Errorf("error on initializing prometheus client: %v", err)
139 }
140 c.prom = prom
141
142 c.funcRouter = newFuncRouter(c)
143
144 if c.UpdateEvery < dbSamplingInterval {
145 c.Warningf("'update_every'(%d) is lower then CockroachDB default sampling interval (%d)",
146 c.UpdateEvery, dbSamplingInterval)
147 }
148
149 return nil
150 }
151
152 func (c *Collector) Check(context.Context) error {
153 mx, err := c.collect()
154 if err != nil {
155 return err
156 }
157 if len(mx) == 0 {
158 return errors.New("no metrics collected")
159
160 }
161 return nil
162 }
163
164 func (c *Collector) Charts() *Charts {
165 return c.charts
166 }
167
168 func (c *Collector) Collect(context.Context) map[string]int64 {
169 mx, err := c.collect()
170 if err != nil {
171 c.Error(err)
172 }
173
174 if len(mx) == 0 {
175 return nil
176 }
177 return mx
178 }
179
180 func (c *Collector) Cleanup(ctx context.Context) {
181 if c.prom != nil && c.prom.HTTPClient() != nil {
182 c.prom.HTTPClient().CloseIdleConnections()
183 }
184 if c.funcRouter != nil {
185 c.funcRouter.Cleanup(ctx)
186 }
187 }