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