master
go 175 lines 4.17 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package oracledb
4
5 import (
6 "context"
7 "database/sql"
8 _ "embed"
9 "errors"
10 "fmt"
11 "time"
12
13 "github.com/netdata/netdata/go/plugins/pkg/confopt"
14 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
15 )
16
17 //go:embed "config_schema.json"
18 var configSchema string
19
20 func init() {
21 collectorapi.Register("oracledb", collectorapi.Creator{
22 JobConfigSchema: configSchema,
23 Create: func() collectorapi.CollectorV1 { return New() },
24 Config: func() any { return &Config{} },
25 Methods: oracledbMethods,
26 MethodHandler: oracledbFunctionHandler,
27 })
28 }
29
30 func New() *Collector {
31 return &Collector{
32 Config: Config{
33 Timeout: confopt.Duration(time.Second * 2),
34 Functions: FunctionsConfig{
35 TopQueries: TopQueriesConfig{
36 Limit: 500,
37 },
38 RunningQueries: RunningQueriesConfig{
39 Limit: 500,
40 },
41 },
42 charts: globalCharts.Copy(),
43 seenTablespaces: make(map[string]bool),
44 seenWaitClasses: make(map[string]bool),
45 },
46 }
47 }
48
49 type Config struct {
50 Vnode string `yaml:"vnode,omitempty" json:"vnode"`
51 UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
52 AutoDetectionRetry int `yaml:"autodetection_retry,omitempty" json:"autodetection_retry"`
53 DSN string `json:"dsn" yaml:"dsn"`
54 Timeout confopt.Duration `yaml:"timeout,omitempty" json:"timeout"`
55 Functions FunctionsConfig `yaml:"functions,omitempty" json:"functions"`
56
57 charts *collectorapi.Charts
58
59 publicDSN string // with hidden username/password
60
61 seenTablespaces map[string]bool
62 seenWaitClasses map[string]bool
63 }
64
65 type FunctionsConfig struct {
66 TopQueries TopQueriesConfig `yaml:"top_queries,omitempty" json:"top_queries"`
67 RunningQueries RunningQueriesConfig `yaml:"running_queries,omitempty" json:"running_queries"`
68 }
69
70 type TopQueriesConfig struct {
71 Disabled bool `yaml:"disabled" json:"disabled"`
72 Timeout confopt.Duration `yaml:"timeout,omitempty" json:"timeout"`
73 Limit int `yaml:"limit,omitempty" json:"limit"`
74 }
75
76 type RunningQueriesConfig 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 func (c Config) topQueriesTimeout() time.Duration {
83 if c.Functions.TopQueries.Timeout == 0 {
84 return c.Timeout.Duration()
85 }
86 return c.Functions.TopQueries.Timeout.Duration()
87 }
88
89 func (c Config) topQueriesLimit() int {
90 if c.Functions.TopQueries.Limit <= 0 {
91 return 500
92 }
93 return c.Functions.TopQueries.Limit
94 }
95
96 func (c Config) runningQueriesTimeout() time.Duration {
97 if c.Functions.RunningQueries.Timeout == 0 {
98 return c.Timeout.Duration()
99 }
100 return c.Functions.RunningQueries.Timeout.Duration()
101 }
102
103 func (c Config) runningQueriesLimit() int {
104 if c.Functions.RunningQueries.Limit <= 0 {
105 return 500
106 }
107 return c.Functions.RunningQueries.Limit
108 }
109
110 type Collector struct {
111 collectorapi.Base
112 Config `yaml:",inline" json:""`
113
114 db *sql.DB
115
116 funcRouter *funcRouter
117 }
118
119 func (c *Collector) Configuration() any {
120 return c.Config
121 }
122
123 func (c *Collector) Init(context.Context) error {
124 dsn, err := c.validateDSN()
125 if err != nil {
126 return fmt.Errorf("invalid oracle DSN: %w", err)
127 }
128
129 c.publicDSN = dsn
130
131 c.funcRouter = newFuncRouter(c)
132
133 return nil
134 }
135
136 func (c *Collector) Check(context.Context) error {
137 mx, err := c.collect()
138 if err != nil {
139 return fmt.Errorf("failed to collect metrics [%s]: %w", c.publicDSN, err)
140 }
141 if len(mx) == 0 {
142 return errors.New("no metrics collected")
143 }
144
145 return nil
146 }
147
148 func (c *Collector) Charts() *collectorapi.Charts {
149 return c.charts
150 }
151
152 func (c *Collector) Collect(context.Context) map[string]int64 {
153 mx, err := c.collect()
154 if err != nil {
155 c.Error(fmt.Sprintf("failed to collect metrics [%s]: %s", c.publicDSN, err))
156 }
157
158 if len(mx) == 0 {
159 return nil
160 }
161
162 return mx
163 }
164
165 func (c *Collector) Cleanup(ctx context.Context) {
166 if c.funcRouter != nil {
167 c.funcRouter.Cleanup(ctx)
168 }
169 if c.db != nil {
170 if err := c.db.Close(); err != nil {
171 c.Errorf("cleanup: error on closing connection [%s]: %v", c.publicDSN, err)
172 }
173 c.db = nil
174 }
175 }