master
go 125 lines 2.84 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package dnsquery
4
5 import (
6 "context"
7 _ "embed"
8 "fmt"
9 "time"
10
11 "github.com/miekg/dns"
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("dns_query", collectorapi.Creator{
22 JobConfigSchema: configSchema,
23 Defaults: collectorapi.Defaults{
24 UpdateEvery: 5,
25 },
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 * 2),
35 Network: "udp",
36 RecordTypes: []string{"A"},
37 Port: 53,
38 },
39 newDNSClient: func(network string, timeout time.Duration) dnsClient {
40 return &dns.Client{
41 Net: network,
42 ReadTimeout: timeout,
43 }
44 },
45 }
46 }
47
48 type Config struct {
49 Vnode string `yaml:"vnode,omitempty" json:"vnode"`
50 UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
51 Timeout confopt.Duration `yaml:"timeout,omitempty" json:"timeout"`
52 Domains []string `yaml:"domains" json:"domains"`
53 Servers []string `yaml:"servers" json:"servers"`
54 Network string `yaml:"network,omitempty" json:"network"`
55 RecordType string `yaml:"record_type,omitempty" json:"record_type"`
56 RecordTypes []string `yaml:"record_types,omitempty" json:"record_types"`
57 Port int `yaml:"port,omitempty" json:"port"`
58 }
59
60 type (
61 Collector struct {
62 collectorapi.Base
63 Config `yaml:",inline" json:""`
64
65 charts *collectorapi.Charts
66
67 dnsClient dnsClient
68 newDNSClient func(network string, duration time.Duration) dnsClient
69
70 recordTypes map[string]uint16
71 }
72 dnsClient interface {
73 Exchange(msg *dns.Msg, address string) (response *dns.Msg, rtt time.Duration, err error)
74 }
75 )
76
77 func (c *Collector) Configuration() any {
78 return c.Config
79 }
80
81 func (c *Collector) Init(context.Context) error {
82 if err := c.verifyConfig(); err != nil {
83 return fmt.Errorf("config validation: %v", err)
84 }
85
86 if err := c.initServers(); err != nil {
87 return fmt.Errorf("failed to initialize servers: %v", err)
88 }
89
90 rt, err := c.initRecordTypes()
91 if err != nil {
92 return fmt.Errorf("init record type: %v", err)
93 }
94 c.recordTypes = rt
95
96 charts, err := c.initCharts()
97 if err != nil {
98 return fmt.Errorf("init charts: %v", err)
99 }
100 c.charts = charts
101
102 return nil
103 }
104
105 func (c *Collector) Check(context.Context) error {
106 return nil
107 }
108
109 func (c *Collector) Charts() *collectorapi.Charts {
110 return c.charts
111 }
112
113 func (c *Collector) Collect(context.Context) map[string]int64 {
114 mx, err := c.collect()
115 if err != nil {
116 c.Error(err)
117 }
118
119 if len(mx) == 0 {
120 return nil
121 }
122 return mx
123 }
124
125 func (c *Collector) Cleanup(context.Context) {}