Skip to content

Commit 9e0b470

Browse files
committed
add histogram support
1 parent a4d81f6 commit 9e0b470

File tree

2 files changed

+111
-5
lines changed

2 files changed

+111
-5
lines changed

exporter/metrics.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package exporter
1717

1818
import (
19+
"math"
1920
"regexp"
2021
"strings"
2122
"sync"
@@ -370,9 +371,119 @@ func makeMetrics(prefix string, m bson.M, labels map[string]string, compatibleMo
370371
return res
371372
}
372373

374+
// isHistogramArray detects histogram arrays in the MongoDB structures.
375+
// Currently, we assume histograms are in the form:
376+
//
377+
// "histograms": {
378+
// "classicMicros": [
379+
// {
380+
// "lowerBound": {
381+
// "low": 0,
382+
// "high": 0,
383+
// "unsigned": false
384+
// },
385+
// "count": {
386+
// "low": 0,
387+
// "high": 0,
388+
// "unsigned": false
389+
// }
390+
// },
391+
// ...
392+
// ]
393+
// }
394+
//
395+
// The "histograms" key is the one that tells us this is a histogram array.
396+
// Each element in the array must have a "lowerBound" and a "count" field.
397+
func isHistogramArray(prefix string, slice primitive.A) bool {
398+
if !strings.Contains(prefix, "histograms") || len(slice) == 0 {
399+
return false
400+
}
401+
402+
if bucket, ok := slice[0].(bson.M); ok {
403+
_, hasLowerBound := bucket["lowerBound"]
404+
_, hasCount := bucket["count"]
405+
return hasLowerBound && hasCount
406+
}
407+
408+
return false
409+
}
410+
411+
func processHistogramArray(prefix string, histogramArray primitive.A, labels map[string]string) []prometheus.Metric {
412+
var metrics []prometheus.Metric
413+
histogramName := strings.TrimSuffix(prefix, ".histograms")
414+
415+
buckets := make(map[float64]uint64)
416+
var totalCount uint64
417+
418+
for _, item := range histogramArray {
419+
bucket, ok := item.(bson.M)
420+
if !ok {
421+
continue
422+
}
423+
424+
lowerBoundVal, hasBound := bucket["lowerBound"]
425+
countVal, hasCount := bucket["count"]
426+
427+
if !hasBound || !hasCount {
428+
continue
429+
}
430+
431+
bound, err := asFloat64(lowerBoundVal)
432+
if err != nil || bound == nil {
433+
continue
434+
}
435+
436+
count, err := asFloat64(countVal)
437+
if err != nil || count == nil {
438+
continue
439+
}
440+
441+
buckets[*bound] += uint64(*count)
442+
totalCount += uint64(*count)
443+
}
444+
445+
// Add +Inf bucket
446+
if buckets[math.Inf(1)] == 0 {
447+
buckets[math.Inf(1)] = totalCount
448+
}
449+
450+
if len(buckets) > 0 {
451+
labelNames := make([]string, 0, len(labels))
452+
labelValues := make([]string, 0, len(labels))
453+
for k, v := range labels {
454+
labelNames = append(labelNames, k)
455+
labelValues = append(labelValues, v)
456+
}
457+
458+
desc := prometheus.NewDesc(
459+
prometheusize(histogramName),
460+
metricHelp("", histogramName),
461+
labelNames,
462+
nil,
463+
)
464+
465+
histogram, err := prometheus.NewConstHistogram(
466+
desc,
467+
totalCount,
468+
0, // sum - we don't have this from MongoDB data
469+
buckets,
470+
labelValues...,
471+
)
472+
473+
if err == nil {
474+
metrics = append(metrics, histogram)
475+
}
476+
}
477+
478+
return metrics
479+
}
480+
373481
// Extract maps from arrays. Only some structures like replicasets have arrays of members
374482
// and each member is represented by a map[string]interface{}.
375483
func processSlice(prefix string, v []interface{}, commonLabels map[string]string, compatibleMode bool) []prometheus.Metric {
484+
if isHistogramArray(prefix, v) {
485+
return processHistogramArray(prefix, v, commonLabels)
486+
}
376487
metrics := make([]prometheus.Metric, 0)
377488
labels := make(map[string]string)
378489
for name, value := range commonLabels {

exporter/v1_compatibility.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,6 @@ var conversions = []conversion{
341341
"writeConflicts": "writeConflicts",
342342
},
343343
},
344-
{
345-
oldName: "mongodb_mongod_metrics_query_executor_total",
346-
prefix: "mongodb_ss_metrics_query",
347-
suffixLabel: "state",
348-
},
349344
{
350345
oldName: "mongodb_mongod_metrics_record_moves_total",
351346
newName: "mongodb_ss_metrics_record_moves",

0 commit comments

Comments
 (0)