github.com/netdata/go.d.plugin@v0.58.1/modules/haproxy/collect.go (about) 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/go.d.plugin/agent/module" 10 "github.com/netdata/go.d.plugin/pkg/prometheus" 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 (h *Haproxy) collect() (map[string]int64, error) { 34 pms, err := h.prom.ScrapeSeries() 35 if err != nil { 36 return nil, err 37 } 38 39 if h.validateMetrics && !isHaproxyMetrics(pms) { 40 return nil, errors.New("unexpected metrics (not HAProxy)") 41 } 42 h.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 !h.proxies[proxy] { 52 h.proxies[proxy] = true 53 h.addProxyToCharts(proxy) 54 } 55 56 mx[dimID(pm)] = int64(pm.Value * multiplier(pm)) 57 } 58 59 return mx, nil 60 } 61 62 func (h *Haproxy) addProxyToCharts(proxy string) { 63 h.addDimToChart(chartBackendCurrentSessions.ID, &module.Dim{ 64 ID: proxyDimID(metricBackendCurrentSessions, proxy), 65 Name: proxy, 66 }) 67 h.addDimToChart(chartBackendSessions.ID, &module.Dim{ 68 ID: proxyDimID(metricBackendSessionsTotal, proxy), 69 Name: proxy, 70 Algo: module.Incremental, 71 }) 72 73 h.addDimToChart(chartBackendResponseTimeAverage.ID, &module.Dim{ 74 ID: proxyDimID(metricBackendResponseTimeAverageSeconds, proxy), 75 Name: proxy, 76 }) 77 if err := h.Charts().Add(newChartBackendHTTPResponses(proxy)); err != nil { 78 h.Warning(err) 79 } 80 81 h.addDimToChart(chartBackendCurrentQueue.ID, &module.Dim{ 82 ID: proxyDimID(metricBackendCurrentQueue, proxy), 83 Name: proxy, 84 }) 85 h.addDimToChart(chartBackendQueueTimeAverage.ID, &module.Dim{ 86 ID: proxyDimID(metricBackendQueueTimeAverageSeconds, proxy), 87 Name: proxy, 88 }) 89 90 if err := h.Charts().Add(newChartBackendNetworkIO(proxy)); err != nil { 91 h.Warning(err) 92 } 93 } 94 95 func (h *Haproxy) addDimToChart(chartID string, dim *module.Dim) { 96 chart := h.Charts().Get(chartID) 97 if chart == nil { 98 h.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 h.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 }