master
go 354 lines 10 KB
Raw
1 //go:build cgo
2
3 package db2
4
5 import (
6 "fmt"
7 "sort"
8 "strings"
9
10 "github.com/netdata/netdata/go/plugins/plugin/ibm.d/modules/db2/contexts"
11 )
12
13 type bufferpoolEntry struct {
14 name string
15 meta *bufferpoolMetrics
16 metrics bufferpoolInstanceMetrics
17 }
18
19 type bufferpoolGroupAggregate struct {
20 Hits, Misses int64
21 DataHits, DataMisses int64
22 IndexHits, IndexMisses int64
23 XDAHits, XDAMisses int64
24 ColumnHits, ColumnMisses int64
25
26 LogicalReads, PhysicalReads int64
27 DataLogicalReads, DataPhysicalReads int64
28 IndexLogicalReads, IndexPhysicalReads int64
29
30 UsedPages, TotalPages int64
31 Writes int64
32 }
33
34 func bufferpoolGroupKey(name string) string {
35 if name == "" {
36 return "__unknown__"
37 }
38 up := strings.ToUpper(name)
39 if idx := strings.Index(up, "_"); idx > 0 {
40 return up[:idx]
41 }
42 return up
43 }
44
45 func (a *bufferpoolGroupAggregate) add(m bufferpoolInstanceMetrics) {
46 a.Hits += m.Hits
47 a.Misses += m.Misses
48 a.DataHits += m.DataHits
49 a.DataMisses += m.DataMisses
50 a.IndexHits += m.IndexHits
51 a.IndexMisses += m.IndexMisses
52 a.XDAHits += m.XDAHits
53 a.XDAMisses += m.XDAMisses
54 a.ColumnHits += m.ColumnHits
55 a.ColumnMisses += m.ColumnMisses
56
57 a.LogicalReads += m.LogicalReads
58 a.PhysicalReads += m.PhysicalReads
59 a.DataLogicalReads += m.DataLogicalReads
60 a.DataPhysicalReads += m.DataPhysicalReads
61 a.IndexLogicalReads += m.IndexLogicalReads
62 a.IndexPhysicalReads += m.IndexPhysicalReads
63
64 a.UsedPages += m.UsedPages
65 a.TotalPages += m.TotalPages
66 a.Writes += m.Writes
67 }
68
69 func (c *Collector) exportBufferpoolMetrics(mx metricsData) {
70 entries := make([]bufferpoolEntry, 0, len(mx.bufferpools))
71 for name, metrics := range mx.bufferpools {
72 entries = append(entries, bufferpoolEntry{
73 name: name,
74 meta: c.bufferpools[name],
75 metrics: metrics,
76 })
77 }
78
79 if len(entries) == 0 {
80 c.clearWarnOnce("db2_bufferpool_overflow")
81 return
82 }
83
84 sort.Slice(entries, func(i, j int) bool {
85 return entries[i].name < entries[j].name
86 })
87
88 limit := c.MaxBufferpools
89 if limit <= 0 || limit > len(entries) {
90 limit = len(entries)
91 }
92
93 groupAgg := make(map[string]*bufferpoolGroupAggregate)
94 overflowAgg := &bufferpoolGroupAggregate{}
95 overflowCount := 0
96 overflowGroups := make(map[string]int)
97 overflowExample := make(map[string]string)
98
99 for idx, entry := range entries {
100 groupKey := bufferpoolGroupKey(entry.name)
101 agg := groupAgg[groupKey]
102 if agg == nil {
103 agg = &bufferpoolGroupAggregate{}
104 groupAgg[groupKey] = agg
105 }
106 agg.add(entry.metrics)
107
108 if idx < limit {
109 c.emitPerBufferpoolMetrics(entry)
110 continue
111 }
112
113 overflowAgg.add(entry.metrics)
114 overflowCount++
115 overflowGroups[groupKey]++
116 if _, ok := overflowExample[groupKey]; !ok {
117 overflowExample[groupKey] = entry.name
118 }
119 }
120
121 c.emitBufferpoolGroupMetrics(groupAgg, overflowAgg, overflowCount)
122
123 if overflowCount > 0 {
124 parts := make([]string, 0, len(overflowGroups))
125 for group, count := range overflowGroups {
126 parts = append(parts, fmt.Sprintf("%s:%d (e.g. %s)", group, count, overflowExample[group]))
127 }
128 sort.Strings(parts)
129 c.warnOnce("db2_bufferpool_overflow", "too many buffer pools for per-instance charts (MaxBufferpools=%d). Aggregated %d additional pools: %s", c.MaxBufferpools, overflowCount, strings.Join(parts, ", "))
130 } else {
131 c.clearWarnOnce("db2_bufferpool_overflow")
132 }
133 }
134
135 func (c *Collector) emitPerBufferpoolMetrics(entry bufferpoolEntry) {
136 pageSizeLabel := "unknown"
137 if entry.meta != nil && entry.meta.pageSize > 0 {
138 pageSizeLabel = fmt.Sprintf("%d", entry.meta.pageSize)
139 }
140
141 labels := contexts.BufferpoolLabels{
142 Bufferpool: entry.name,
143 Page_size: pageSizeLabel,
144 }
145
146 totalReads := entry.metrics.Hits + entry.metrics.Misses
147 overallRatio := int64(0)
148 if totalReads > 0 {
149 overallRatio = entry.metrics.Hits * 100 * Precision / totalReads
150 }
151
152 dataReads := entry.metrics.DataHits + entry.metrics.DataMisses
153 dataRatio := int64(0)
154 if dataReads > 0 {
155 dataRatio = entry.metrics.DataHits * 100 * Precision / dataReads
156 }
157
158 indexReads := entry.metrics.IndexHits + entry.metrics.IndexMisses
159 indexRatio := int64(0)
160 if indexReads > 0 {
161 indexRatio = entry.metrics.IndexHits * 100 * Precision / indexReads
162 }
163
164 xdaReads := entry.metrics.XDAHits + entry.metrics.XDAMisses
165 xdaRatio := int64(0)
166 if xdaReads > 0 {
167 xdaRatio = entry.metrics.XDAHits * 100 * Precision / xdaReads
168 }
169
170 columnReads := entry.metrics.ColumnHits + entry.metrics.ColumnMisses
171 columnRatio := int64(0)
172 if columnReads > 0 {
173 columnRatio = entry.metrics.ColumnHits * 100 * Precision / columnReads
174 }
175
176 contexts.Bufferpool.HitRatio.Set(c.State, labels, contexts.BufferpoolHitRatioValues{
177 Overall: overallRatio,
178 })
179
180 contexts.Bufferpool.DetailedHitRatio.Set(c.State, labels, contexts.BufferpoolDetailedHitRatioValues{
181 Data: dataRatio,
182 Index: indexRatio,
183 Xda: xdaRatio,
184 Column: columnRatio,
185 })
186
187 contexts.Bufferpool.Reads.Set(c.State, labels, contexts.BufferpoolReadsValues{
188 Logical: entry.metrics.LogicalReads,
189 Physical: entry.metrics.PhysicalReads,
190 })
191
192 contexts.Bufferpool.DataReads.Set(c.State, labels, contexts.BufferpoolDataReadsValues{
193 Logical: entry.metrics.DataLogicalReads,
194 Physical: entry.metrics.DataPhysicalReads,
195 })
196
197 contexts.Bufferpool.IndexReads.Set(c.State, labels, contexts.BufferpoolIndexReadsValues{
198 Logical: entry.metrics.IndexLogicalReads,
199 Physical: entry.metrics.IndexPhysicalReads,
200 })
201
202 contexts.Bufferpool.Pages.Set(c.State, labels, contexts.BufferpoolPagesValues{
203 Used: entry.metrics.UsedPages,
204 Total: entry.metrics.TotalPages,
205 })
206
207 contexts.Bufferpool.Writes.Set(c.State, labels, contexts.BufferpoolWritesValues{
208 Writes: entry.metrics.Writes,
209 })
210
211 contexts.Bufferpool.DataReads.SetUpdateEvery(c.State, labels, c.Config.UpdateEvery)
212 contexts.Bufferpool.IndexReads.SetUpdateEvery(c.State, labels, c.Config.UpdateEvery)
213 }
214
215 func (c *Collector) emitBufferpoolGroupMetrics(groups map[string]*bufferpoolGroupAggregate, overflow *bufferpoolGroupAggregate, overflowCount int) {
216 keys := make([]string, 0, len(groups))
217 for k := range groups {
218 keys = append(keys, k)
219 }
220 sort.Strings(keys)
221
222 for _, key := range keys {
223 agg := groups[key]
224 labels := contexts.BufferpoolGroupLabels{Group: key}
225
226 totalReads := agg.Hits + agg.Misses
227 overallRatio := int64(0)
228 if totalReads > 0 {
229 overallRatio = agg.Hits * 100 * Precision / totalReads
230 }
231
232 dataReads := agg.DataHits + agg.DataMisses
233 dataRatio := int64(0)
234 if dataReads > 0 {
235 dataRatio = agg.DataHits * 100 * Precision / dataReads
236 }
237
238 indexReads := agg.IndexHits + agg.IndexMisses
239 indexRatio := int64(0)
240 if indexReads > 0 {
241 indexRatio = agg.IndexHits * 100 * Precision / indexReads
242 }
243
244 xdaReads := agg.XDAHits + agg.XDAMisses
245 xdaRatio := int64(0)
246 if xdaReads > 0 {
247 xdaRatio = agg.XDAHits * 100 * Precision / xdaReads
248 }
249
250 columnReads := agg.ColumnHits + agg.ColumnMisses
251 columnRatio := int64(0)
252 if columnReads > 0 {
253 columnRatio = agg.ColumnHits * 100 * Precision / columnReads
254 }
255
256 contexts.BufferpoolGroup.HitRatio.Set(c.State, labels, contexts.BufferpoolGroupHitRatioValues{
257 Overall: overallRatio,
258 })
259
260 contexts.BufferpoolGroup.DetailedHitRatio.Set(c.State, labels, contexts.BufferpoolGroupDetailedHitRatioValues{
261 Data: dataRatio,
262 Index: indexRatio,
263 Xda: xdaRatio,
264 Column: columnRatio,
265 })
266
267 contexts.BufferpoolGroup.Reads.Set(c.State, labels, contexts.BufferpoolGroupReadsValues{
268 Logical: agg.LogicalReads,
269 Physical: agg.PhysicalReads,
270 })
271
272 contexts.BufferpoolGroup.DataReads.Set(c.State, labels, contexts.BufferpoolGroupDataReadsValues{
273 Logical: agg.DataLogicalReads,
274 Physical: agg.DataPhysicalReads,
275 })
276
277 contexts.BufferpoolGroup.IndexReads.Set(c.State, labels, contexts.BufferpoolGroupIndexReadsValues{
278 Logical: agg.IndexLogicalReads,
279 Physical: agg.IndexPhysicalReads,
280 })
281
282 contexts.BufferpoolGroup.Pages.Set(c.State, labels, contexts.BufferpoolGroupPagesValues{
283 Used: agg.UsedPages,
284 Total: agg.TotalPages,
285 })
286
287 contexts.BufferpoolGroup.Writes.Set(c.State, labels, contexts.BufferpoolGroupWritesValues{
288 Writes: agg.Writes,
289 })
290 }
291
292 if overflowCount > 0 && overflow != nil {
293 labels := contexts.BufferpoolGroupLabels{Group: "__other__"}
294
295 totalReads := overflow.Hits + overflow.Misses
296 overallRatio := int64(0)
297 if totalReads > 0 {
298 overallRatio = overflow.Hits * 100 * Precision / totalReads
299 }
300
301 dataReads := overflow.DataHits + overflow.DataMisses
302 dataRatio := int64(0)
303 if dataReads > 0 {
304 dataRatio = overflow.DataHits * 100 * Precision / dataReads
305 }
306
307 indexReads := overflow.IndexHits + overflow.IndexMisses
308 indexRatio := int64(0)
309 if indexReads > 0 {
310 indexRatio = overflow.IndexHits * 100 * Precision / indexReads
311 }
312
313 xdaReads := overflow.XDAHits + overflow.XDAMisses
314 xdaRatio := int64(0)
315 if xdaReads > 0 {
316 xdaRatio = overflow.XDAHits * 100 * Precision / xdaReads
317 }
318
319 columnReads := overflow.ColumnHits + overflow.ColumnMisses
320 columnRatio := int64(0)
321 if columnReads > 0 {
322 columnRatio = overflow.ColumnHits * 100 * Precision / columnReads
323 }
324
325 contexts.BufferpoolGroup.HitRatio.Set(c.State, labels, contexts.BufferpoolGroupHitRatioValues{
326 Overall: overallRatio,
327 })
328 contexts.BufferpoolGroup.DetailedHitRatio.Set(c.State, labels, contexts.BufferpoolGroupDetailedHitRatioValues{
329 Data: dataRatio,
330 Index: indexRatio,
331 Xda: xdaRatio,
332 Column: columnRatio,
333 })
334 contexts.BufferpoolGroup.Reads.Set(c.State, labels, contexts.BufferpoolGroupReadsValues{
335 Logical: overflow.LogicalReads,
336 Physical: overflow.PhysicalReads,
337 })
338 contexts.BufferpoolGroup.DataReads.Set(c.State, labels, contexts.BufferpoolGroupDataReadsValues{
339 Logical: overflow.DataLogicalReads,
340 Physical: overflow.DataPhysicalReads,
341 })
342 contexts.BufferpoolGroup.IndexReads.Set(c.State, labels, contexts.BufferpoolGroupIndexReadsValues{
343 Logical: overflow.IndexLogicalReads,
344 Physical: overflow.IndexPhysicalReads,
345 })
346 contexts.BufferpoolGroup.Pages.Set(c.State, labels, contexts.BufferpoolGroupPagesValues{
347 Used: overflow.UsedPages,
348 Total: overflow.TotalPages,
349 })
350 contexts.BufferpoolGroup.Writes.Set(c.State, labels, contexts.BufferpoolGroupWritesValues{
351 Writes: overflow.Writes,
352 })
353 }
354 }