master
go 141 lines 3.24 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package maxscale
4
5 import (
6 "fmt"
7 "net"
8 "strconv"
9 "strings"
10 "unicode"
11
12 "github.com/netdata/netdata/go/plugins/pkg/web"
13 )
14
15 const (
16 urlPathMaxscale = "/maxscale"
17 urlPathMaxscaleThreads = "/maxscale/threads"
18 urlPathServers = "/servers"
19 )
20
21 func (c *Collector) collect() (map[string]int64, error) {
22 mx := make(map[string]int64)
23
24 if err := c.collectMaxScaleGlobal(mx); err != nil {
25 return nil, err
26 }
27 if err := c.collectMaxScaleThreads(mx); err != nil {
28 return nil, err
29 }
30 if err := c.collectServers(mx); err != nil {
31 return nil, err
32 }
33
34 return mx, nil
35 }
36
37 func (c *Collector) collectMaxScaleGlobal(mx map[string]int64) error {
38 req, err := web.NewHTTPRequestWithPath(c.RequestConfig, urlPathMaxscale)
39 if err != nil {
40 return fmt.Errorf("failed to create HTTP request: %v", err)
41 }
42
43 var resp maxscaleGlobalResponse
44
45 if err := web.DoHTTP(c.httpClient).RequestJSON(req, &resp); err != nil {
46 return err
47 }
48
49 if resp.Data == nil {
50 return fmt.Errorf("invalid response from '%s': missing expected MaxScale data", req.URL)
51 }
52
53 mx["uptime"] = resp.Data.Attrs.Uptime
54
55 return nil
56 }
57
58 func (c *Collector) collectMaxScaleThreads(mx map[string]int64) error {
59 req, err := web.NewHTTPRequestWithPath(c.RequestConfig, urlPathMaxscaleThreads)
60 if err != nil {
61 return fmt.Errorf("failed to create HTTP request: %v", err)
62 }
63
64 var resp maxscaleThreadsResponse
65
66 if err := web.DoHTTP(c.httpClient).RequestJSON(req, &resp); err != nil {
67 return err
68 }
69
70 for _, r := range resp.Data {
71 st := r.Attrs.Stats
72 mx["threads_reads"] += st.Reads
73 mx["threads_writes"] += st.Writes
74 mx["threads_errors"] += st.Errors
75 mx["threads_hangups"] += st.Hangups
76 mx["threads_accepts"] += st.Accepts
77 mx["threads_sessions"] += st.Sessions
78 mx["threads_zombies"] += st.Zombies
79 mx["threads_current_fds"] += st.CurrentDescriptors
80 mx["threads_total_fds"] += st.TotalDescriptors
81 mx["threads_qc_cache_inserts"] += st.QCCache.Inserts
82 mx["threads_qc_cache_evictions"] += st.QCCache.Evictions
83 mx["threads_qc_cache_hits"] += st.QCCache.Hits
84 mx["threads_qc_cache_misses"] += st.QCCache.Misses
85 for _, v := range threadStates {
86 mx["threads_state_"+v] = 0
87 }
88 mx["threads_state_"+st.State]++
89 }
90
91 return nil
92 }
93
94 func (c *Collector) collectServers(mx map[string]int64) error {
95 req, err := web.NewHTTPRequestWithPath(c.RequestConfig, urlPathServers)
96 if err != nil {
97 return fmt.Errorf("failed to create HTTP request: %v", err)
98 }
99
100 var resp serversResponse
101
102 if err := web.DoHTTP(c.httpClient).RequestJSON(req, &resp); err != nil {
103 return err
104 }
105
106 seen := make(map[string]bool)
107
108 for _, r := range resp.Data {
109 if r.ID == "" {
110 continue
111 }
112
113 seen[r.ID] = true
114
115 if !c.seenServers[r.ID] {
116 c.seenServers[r.ID] = true
117 addr := net.JoinHostPort(r.Attrs.Params.Address, strconv.Itoa(int(r.Attrs.Params.Port)))
118 c.addServerCharts(r.ID, addr)
119 }
120
121 px := fmt.Sprintf("server_%s_", r.ID)
122
123 mx[px+"connections"] = r.Attrs.Statistics.Connections
124
125 for _, v := range serverStates {
126 mx[px+"state_"+v] = 0
127 }
128 for _, v := range strings.FieldsFunc(r.Attrs.State, unicode.IsSpace) {
129 mx[px+"state_"+v] = 1
130 }
131 }
132
133 for id := range c.seenServers {
134 if !seen[id] {
135 delete(c.seenServers, id)
136 c.removeServerCharts(id)
137 }
138 }
139
140 return nil
141 }