master
go 143 lines 3.65 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package haproxy
4
5 import (
6 "errors"
7 "strings"
8
9 "github.com/netdata/netdata/go/plugins/pkg/prometheus"
10 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
11 )
12
13 const (
14 metricBackendSessionsTotal = "haproxy_backend_sessions_total"
15 metricBackendCurrentSessions = "haproxy_backend_current_sessions"
16 metricBackendHTTPResponsesTotal = "haproxy_backend_http_responses_total"
17 metricBackendResponseTimeAverageSeconds = "haproxy_backend_response_time_average_seconds"
18 metricBackendCurrentQueue = "haproxy_backend_current_queue"
19 metricBackendQueueTimeAverageSeconds = "haproxy_backend_queue_time_average_seconds"
20 metricBackendBytesInTotal = "haproxy_backend_bytes_in_total"
21 metricBackendBytesOutTotal = "haproxy_backend_bytes_out_total"
22 )
23
24 func isHaproxyMetrics(pms prometheus.Series) bool {
25 for _, pm := range pms {
26 if strings.HasPrefix(pm.Name(), "haproxy_") {
27 return true
28 }
29 }
30 return false
31 }
32
33 func (c *Collector) collect() (map[string]int64, error) {
34 pms, err := c.prom.ScrapeSeries()
35 if err != nil {
36 return nil, err
37 }
38
39 if c.validateMetrics && !isHaproxyMetrics(pms) {
40 return nil, errors.New("unexpected metrics (not HAProxy)")
41 }
42 c.validateMetrics = false
43
44 mx := make(map[string]int64)
45 for _, pm := range pms {
46 proxy := pm.Labels.Get("proxy")
47 if proxy == "" {
48 continue
49 }
50
51 if !c.proxies[proxy] {
52 c.proxies[proxy] = true
53 c.addProxyToCharts(proxy)
54 }
55
56 mx[dimID(pm)] = int64(pm.Value * multiplier(pm))
57 }
58
59 return mx, nil
60 }
61
62 func (c *Collector) addProxyToCharts(proxy string) {
63 c.addDimToChart(chartBackendCurrentSessions.ID, &collectorapi.Dim{
64 ID: proxyDimID(metricBackendCurrentSessions, proxy),
65 Name: proxy,
66 })
67 c.addDimToChart(chartBackendSessions.ID, &collectorapi.Dim{
68 ID: proxyDimID(metricBackendSessionsTotal, proxy),
69 Name: proxy,
70 Algo: collectorapi.Incremental,
71 })
72
73 c.addDimToChart(chartBackendResponseTimeAverage.ID, &collectorapi.Dim{
74 ID: proxyDimID(metricBackendResponseTimeAverageSeconds, proxy),
75 Name: proxy,
76 })
77 if err := c.Charts().Add(newChartBackendHTTPResponses(proxy)); err != nil {
78 c.Warning(err)
79 }
80
81 c.addDimToChart(chartBackendCurrentQueue.ID, &collectorapi.Dim{
82 ID: proxyDimID(metricBackendCurrentQueue, proxy),
83 Name: proxy,
84 })
85 c.addDimToChart(chartBackendQueueTimeAverage.ID, &collectorapi.Dim{
86 ID: proxyDimID(metricBackendQueueTimeAverageSeconds, proxy),
87 Name: proxy,
88 })
89
90 if err := c.Charts().Add(newChartBackendNetworkIO(proxy)); err != nil {
91 c.Warning(err)
92 }
93 }
94
95 func (c *Collector) addDimToChart(chartID string, dim *collectorapi.Dim) {
96 chart := c.Charts().Get(chartID)
97 if chart == nil {
98 c.Warningf("error on adding '%s' dimension: can not find '%s' chart", dim.ID, chartID)
99 return
100 }
101 if err := chart.AddDim(dim); err != nil {
102 c.Warning(err)
103 return
104 }
105 chart.MarkNotCreated()
106 }
107
108 func multiplier(pm prometheus.SeriesSample) float64 {
109 switch pm.Name() {
110 case metricBackendResponseTimeAverageSeconds,
111 metricBackendQueueTimeAverageSeconds:
112 // to milliseconds
113 return 1000
114 }
115 return 1
116 }
117
118 func dimID(pm prometheus.SeriesSample) string {
119 proxy := pm.Labels.Get("proxy")
120 if proxy == "" {
121 return ""
122 }
123
124 name := cleanMetricName(pm.Name())
125 if pm.Name() == metricBackendHTTPResponsesTotal {
126 name += "_" + pm.Labels.Get("code")
127 }
128 return proxyDimID(name, proxy)
129 }
130
131 func proxyDimID(metric, proxy string) string {
132 return cleanMetricName(metric) + "_proxy_" + proxy
133 }
134
135 func cleanMetricName(name string) string {
136 if strings.HasSuffix(name, "_total") {
137 return name[:len(name)-6]
138 }
139 if strings.HasSuffix(name, "_seconds") {
140 return name[:len(name)-8]
141 }
142 return name
143 }