master
go 387 lines 10.9 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package varnish
4
5 import (
6 "fmt"
7 "strings"
8
9 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
10 )
11
12 const (
13 prioClientSessionConnections = collectorapi.Priority + iota
14 prioClientRequests
15
16 prioBackendsConnections
17 prioBackendsRequests
18 prioBackendDataTransfer
19
20 prioCacheHitRatioTotal
21 prioCacheHitRatioDelta
22
23 prioCacheExpiredObjects
24 prioCacheLRUActivity
25
26 prioThreadsTotal
27 prioThreadManagementActivity
28 prioThreadQueueLen
29
30 prioEsiStatistics
31
32 prioStorageSpaceUsage
33 prioStorageAllocatedObjects
34
35 prioMgmtProcessUptime
36 prioChildProcessUptime
37 )
38
39 var varnishCharts = collectorapi.Charts{
40 clientSessionConnectionsChart.Copy(),
41 clientRequestsChart.Copy(),
42
43 backendConnectionsChart.Copy(),
44 backendRequestsChart.Copy(),
45
46 cacheHitRatioTotalChart.Copy(),
47 cacheHitRatioDeltaChart.Copy(),
48 cachedObjectsExpiredChart.Copy(),
49 cacheLRUActivityChart.Copy(),
50
51 threadsTotalChart.Copy(),
52 threadManagementActivityChart.Copy(),
53 threadQueueLenChart.Copy(),
54
55 esiParsingIssuesChart.Copy(),
56
57 mgmtProcessUptimeChart.Copy(),
58 childProcessUptimeChart.Copy(),
59 }
60
61 var backendChartsTmpl = collectorapi.Charts{
62 backendDataTransferChartTmpl.Copy(),
63 }
64
65 var storageChartsTmpl = collectorapi.Charts{
66 storageSpaceUsageChartTmpl.Copy(),
67 storageAllocatedObjectsChartTmpl.Copy(),
68 }
69
70 // Client metrics
71 var (
72 clientSessionConnectionsChart = collectorapi.Chart{
73 ID: "client_session_connections",
74 Title: "Client Session Connections",
75 Fam: "client connections",
76 Units: "connections/s",
77 Ctx: "varnish.client_session_connections",
78 Type: collectorapi.Line,
79 Priority: prioClientSessionConnections,
80 Dims: collectorapi.Dims{
81 {ID: "MAIN.sess_conn", Name: "accepted", Algo: collectorapi.Incremental},
82 {ID: "MAIN.sess_dropped", Name: "dropped", Algo: collectorapi.Incremental},
83 },
84 }
85
86 clientRequestsChart = collectorapi.Chart{
87 ID: "client_requests",
88 Title: "Client Requests",
89 Fam: "client requests",
90 Units: "requests/s",
91 Ctx: "varnish.client_requests",
92 Type: collectorapi.Line,
93 Priority: prioClientRequests,
94 Dims: collectorapi.Dims{
95 {ID: "MAIN.client_req", Name: "received", Algo: collectorapi.Incremental},
96 },
97 }
98 )
99
100 // Cache activity
101 var (
102 cacheHitRatioTotalChart = collectorapi.Chart{
103 ID: "cache_hit_ratio_total",
104 Title: "Cache Hit Ratio Total",
105 Fam: "cache activity",
106 Units: "percent",
107 Ctx: "varnish.cache_hit_ratio_total",
108 Type: collectorapi.Stacked,
109 Priority: prioCacheHitRatioTotal,
110 Dims: collectorapi.Dims{
111 {ID: "MAIN.cache_hit", Name: "hit", Algo: collectorapi.PercentOfAbsolute},
112 {ID: "MAIN.cache_miss", Name: "miss", Algo: collectorapi.PercentOfAbsolute},
113 {ID: "MAIN.cache_hitpass", Name: "hitpass", Algo: collectorapi.PercentOfAbsolute},
114 {ID: "MAIN.cache_hitmiss", Name: "hitmiss", Algo: collectorapi.PercentOfAbsolute},
115 },
116 }
117 cacheHitRatioDeltaChart = collectorapi.Chart{
118 ID: "cache_hit_ratio_delta",
119 Title: "Cache Hit Ratio Current Poll",
120 Fam: "cache activity",
121 Units: "percent",
122 Ctx: "varnish.cache_hit_ratio_delta",
123 Type: collectorapi.Stacked,
124 Priority: prioCacheHitRatioDelta,
125 Dims: collectorapi.Dims{
126 {ID: "MAIN.cache_hit", Name: "hit", Algo: collectorapi.PercentOfIncremental},
127 {ID: "MAIN.cache_miss", Name: "miss", Algo: collectorapi.PercentOfIncremental},
128 {ID: "MAIN.cache_hitpass", Name: "hitpass", Algo: collectorapi.PercentOfIncremental},
129 {ID: "MAIN.cache_hitmiss", Name: "hitmiss", Algo: collectorapi.PercentOfIncremental},
130 },
131 }
132 cachedObjectsExpiredChart = collectorapi.Chart{
133 ID: "cache_expired_objects",
134 Title: "Cache Expired Objects",
135 Fam: "cache activity",
136 Units: "objects/s",
137 Ctx: "varnish.cache_expired_objects",
138 Type: collectorapi.Line,
139 Priority: prioCacheExpiredObjects,
140 Dims: collectorapi.Dims{
141 {ID: "MAIN.n_expired", Name: "expired", Algo: collectorapi.Incremental},
142 },
143 }
144 cacheLRUActivityChart = collectorapi.Chart{
145 ID: "cache_lru_activity",
146 Title: "Cache LRU Activity",
147 Fam: "cache activity",
148 Units: "objects/s",
149 Ctx: "varnish.cache_lru_activity",
150 Type: collectorapi.Line,
151 Priority: prioCacheLRUActivity,
152 Dims: collectorapi.Dims{
153 {ID: "MAIN.n_lru_nuked", Name: "nuked", Algo: collectorapi.Incremental},
154 {ID: "MAIN.n_lru_moved", Name: "moved", Algo: collectorapi.Incremental},
155 },
156 }
157 )
158
159 // Threads
160 var (
161 threadsTotalChart = collectorapi.Chart{
162 ID: "threads",
163 Title: "Threads In All Pools",
164 Fam: "threads",
165 Units: "threads",
166 Ctx: "varnish.threads",
167 Type: collectorapi.Line,
168 Priority: prioThreadsTotal,
169 Dims: collectorapi.Dims{
170 {ID: "MAIN.threads", Name: "threads"},
171 },
172 }
173 threadManagementActivityChart = collectorapi.Chart{
174 ID: "thread_management_activity",
175 Title: "Thread Management Activity",
176 Fam: "threads",
177 Units: "threads/s",
178 Ctx: "varnish.thread_management_activity",
179 Type: collectorapi.Line,
180 Priority: prioThreadManagementActivity,
181 Dims: collectorapi.Dims{
182 {ID: "MAIN.threads_created", Name: "created", Algo: collectorapi.Incremental},
183 {ID: "MAIN.threads_failed", Name: "failed", Algo: collectorapi.Incremental},
184 {ID: "MAIN.threads_destroyed", Name: "destroyed", Algo: collectorapi.Incremental},
185 {ID: "MAIN.threads_limited", Name: "limited", Algo: collectorapi.Incremental},
186 },
187 }
188 threadQueueLenChart = collectorapi.Chart{
189 ID: "thread_queue_len",
190 Title: "Session Queue Length",
191 Fam: "threads",
192 Units: "requests",
193 Ctx: "varnish.thread_queue_len",
194 Type: collectorapi.Line,
195 Priority: prioThreadQueueLen,
196 Dims: collectorapi.Dims{
197 {ID: "MAIN.thread_queue_len", Name: "queue_len"},
198 },
199 }
200 )
201
202 var (
203 backendConnectionsChart = collectorapi.Chart{
204 ID: "backends_connections",
205 Title: "Backend Connections",
206 Fam: "backend connections",
207 Units: "connections/s",
208 Ctx: "varnish.backends_connections",
209 Type: collectorapi.Line,
210 Priority: prioBackendsConnections,
211 Dims: collectorapi.Dims{
212 {ID: "MAIN.backend_conn", Name: "successful", Algo: collectorapi.Incremental},
213 {ID: "MAIN.backend_unhealthy", Name: "unhealthy", Algo: collectorapi.Incremental},
214 {ID: "MAIN.backend_busy", Name: "busy", Algo: collectorapi.Incremental},
215 {ID: "MAIN.backend_fail", Name: "failed", Algo: collectorapi.Incremental},
216 {ID: "MAIN.backend_reuse", Name: "reused", Algo: collectorapi.Incremental},
217 {ID: "MAIN.backend_recycle", Name: "recycled", Algo: collectorapi.Incremental},
218 {ID: "MAIN.backend_retry", Name: "retry", Algo: collectorapi.Incremental},
219 },
220 }
221 backendRequestsChart = collectorapi.Chart{
222 ID: "backends_requests",
223 Title: "Backend Requests",
224 Fam: "backend requests",
225 Units: "requests/s",
226 Ctx: "varnish.backends_requests",
227 Type: collectorapi.Line,
228 Priority: prioBackendsRequests,
229 Dims: collectorapi.Dims{
230 {ID: "MAIN.backend_req", Name: "sent", Algo: collectorapi.Incremental},
231 },
232 }
233 )
234
235 // ESI
236 var (
237 esiParsingIssuesChart = collectorapi.Chart{
238 ID: "esi_parsing_issues",
239 Title: "ESI Parsing Issues",
240 Fam: "esi",
241 Units: "issues/s",
242 Ctx: "varnish.esi_parsing_issues",
243 Type: collectorapi.Line,
244 Priority: prioEsiStatistics,
245 Dims: collectorapi.Dims{
246 {ID: "MAIN.esi_errors", Name: "errors", Algo: collectorapi.Incremental},
247 {ID: "MAIN.esi_warnings", Name: "warnings", Algo: collectorapi.Incremental},
248 },
249 }
250 )
251
252 // Uptime
253 var (
254 mgmtProcessUptimeChart = collectorapi.Chart{
255 ID: "mgmt_process_uptime",
256 Title: "Management Process Uptime",
257 Fam: "uptime",
258 Units: "seconds",
259 Ctx: "varnish.mgmt_process_uptime",
260 Type: collectorapi.Line,
261 Priority: prioMgmtProcessUptime,
262 Dims: collectorapi.Dims{
263 {ID: "MGT.uptime", Name: "uptime"},
264 },
265 }
266 childProcessUptimeChart = collectorapi.Chart{
267 ID: "child_process_uptime",
268 Title: "Child Process Uptime",
269 Fam: "uptime",
270 Units: "seconds",
271 Ctx: "varnish.child_process_uptime",
272 Type: collectorapi.Line,
273 Priority: prioChildProcessUptime,
274 Dims: collectorapi.Dims{
275 {ID: "MAIN.uptime", Name: "uptime"},
276 },
277 }
278 )
279
280 var (
281 backendDataTransferChartTmpl = collectorapi.Chart{
282 ID: "backend_%s_data_transfer",
283 Title: "Backend Data Transfer",
284 Fam: "backend traffic",
285 Units: "bytes/s",
286 Ctx: "varnish.backend_data_transfer",
287 Type: collectorapi.Area,
288 Priority: prioBackendDataTransfer,
289 Dims: collectorapi.Dims{
290 {ID: "VBE.%s.bereq_hdrbytes", Name: "req_header", Algo: collectorapi.Incremental},
291 {ID: "VBE.%s.bereq_bodybytes", Name: "req_body", Algo: collectorapi.Incremental},
292 {ID: "VBE.%s.beresp_hdrbytes", Name: "resp_header", Algo: collectorapi.Incremental, Mul: -1},
293 {ID: "VBE.%s.beresp_bodybytes", Name: "resp_body", Algo: collectorapi.Incremental, Mul: -1},
294 },
295 }
296 )
297
298 var (
299 storageSpaceUsageChartTmpl = collectorapi.Chart{
300 ID: "storage_%s_usage",
301 Title: "Storage Space Usage",
302 Fam: "storage usage",
303 Units: "bytes",
304 Ctx: "varnish.storage_space_usage",
305 Type: collectorapi.Stacked,
306 Priority: prioStorageSpaceUsage,
307 Dims: collectorapi.Dims{
308 {ID: "%s.g_space", Name: "free"},
309 {ID: "%s.g_bytes", Name: "used"},
310 },
311 }
312
313 storageAllocatedObjectsChartTmpl = collectorapi.Chart{
314 ID: "storage_%s_allocated_objects",
315 Title: "Storage Allocated Objects",
316 Fam: "storage usage",
317 Units: "objects",
318 Ctx: "varnish.storage_allocated_objects",
319 Type: collectorapi.Line,
320 Priority: prioStorageAllocatedObjects,
321 Dims: collectorapi.Dims{
322 {ID: "%s.g_alloc", Name: "allocated"},
323 },
324 }
325 )
326
327 func (c *Collector) addBackendCharts(fullName string) {
328 charts := backendChartsTmpl.Copy()
329
330 for _, chart := range *charts {
331 chart.ID = cleanChartID(fmt.Sprintf(chart.ID, fullName))
332 chart.Labels = []collectorapi.Label{
333 {Key: "backend", Value: fullName},
334 }
335 for _, dim := range chart.Dims {
336 dim.ID = fmt.Sprintf(dim.ID, fullName)
337 }
338 }
339
340 if err := c.Charts().Add(*charts...); err != nil {
341 c.Warning(err)
342 }
343
344 }
345
346 func (c *Collector) addStorageCharts(name string) {
347 charts := storageChartsTmpl.Copy()
348
349 for _, chart := range *charts {
350 chart.ID = cleanChartID(fmt.Sprintf(chart.ID, name))
351 chart.Labels = []collectorapi.Label{
352 {Key: "storage", Value: name},
353 }
354 for _, dim := range chart.Dims {
355 dim.ID = fmt.Sprintf(dim.ID, name)
356 }
357 }
358
359 if err := c.Charts().Add(*charts...); err != nil {
360 c.Warning(err)
361 }
362
363 }
364
365 func (c *Collector) removeBackendCharts(name string) {
366 px := fmt.Sprintf("backend_%s_", name)
367 c.removeCharts(cleanChartID(px))
368 }
369
370 func (c *Collector) removeStorageCharts(name string) {
371 px := fmt.Sprintf("storage_%s_", name)
372 c.removeCharts(cleanChartID(px))
373 }
374
375 func (c *Collector) removeCharts(prefix string) {
376 for _, chart := range *c.Charts() {
377 if strings.HasPrefix(chart.ID, prefix) {
378 chart.MarkRemove()
379 chart.MarkNotCreated()
380 }
381 }
382 }
383
384 func cleanChartID(id string) string {
385 id = strings.ReplaceAll(id, ".", "_")
386 return strings.ToLower(id)
387 }