Skip to content

Commit 5bc0599

Browse files
authored
feat: Made sure summaries actually give output quantile objectives as well; improved flag docs and tests for complex type series calculation. (#93)
Signed-off-by: bwplotka <bwplotka@gmail.com>
1 parent 9b0a010 commit 5bc0599

File tree

2 files changed

+45
-17
lines changed

2 files changed

+45
-17
lines changed

metrics/serve.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ func (c *Collector) UpdateNotifyCh() chan struct{} {
8181

8282
type Config struct {
8383
MetricCount, GaugeMetricCount, CounterMetricCount, HistogramMetricCount, NativeHistogramMetricCount, SummaryMetricCount int
84-
HistogramBuckets int
84+
85+
HistogramBuckets, SummaryObjectives int
8586

8687
LabelCount, SeriesCount int
8788
MaxSeriesCount, MinSeriesCount int
@@ -103,14 +104,16 @@ func NewConfigFromFlags(flagReg func(name, help string) *kingpin.FlagClause) *Co
103104
IntVar(&cfg.GaugeMetricCount)
104105
flagReg("counter-metric-count", "Number of counter metrics to serve.").Default("200").
105106
IntVar(&cfg.CounterMetricCount)
106-
flagReg("histogram-metric-count", "Number of explicit (classic) histogram metrics to serve.").Default("10").
107+
flagReg("histogram-metric-count", "Number of explicit (classic) histogram metrics to serve. Use -histogram-metric-bucket-count to control number of buckets. Note that the overall number of series for a single classic histogram metric is equal to 2 (count and sum) + <histogram-metric-bucket-count> + 1 (+Inf bucket).").Default("10").
107108
IntVar(&cfg.HistogramMetricCount)
108-
flagReg("histogram-metric-bucket-count", "Number of explicit buckets (classic) histogram metrics.").Default("8").
109+
flagReg("histogram-metric-bucket-count", "Number of explicit buckets (classic) histogram metrics, excluding +Inf bucket.").Default("7").
109110
IntVar(&cfg.HistogramBuckets)
110111
flagReg("native-histogram-metric-count", "Number of native (exponential) histogram metrics to serve.").Default("0").
111112
IntVar(&cfg.NativeHistogramMetricCount)
112-
flagReg("summary-metric-count", "Number of summary metrics to serve.").Default("0").
113+
flagReg("summary-metric-count", "Number of summary metrics to serve. Use -summary-metric-objective-count to control number of quantile objectives. Note that the overall number of series for a single summary metric is equal to 2 (count and sum) + <summary-metric-objective-count>.").Default("0").
113114
IntVar(&cfg.SummaryMetricCount)
115+
flagReg("summary-metric-objective-count", "Number of objectives in the summary metrics to serve.").Default("2").
116+
IntVar(&cfg.SummaryObjectives)
114117

115118
flagReg("label-count", "Number of labels per-metric.").Default("10").
116119
IntVar(&cfg.LabelCount)
@@ -242,10 +245,22 @@ func (c *Collector) recreateMetrics(unsafeGetState readOnlyStateFn) {
242245
c.nativeHistograms[id] = histogram
243246
}
244247

248+
// Mimic some quantile objectives.
249+
objectives := map[float64]float64{}
250+
if c.cfg.SummaryObjectives > 0 {
251+
parts := 100 / c.cfg.SummaryObjectives
252+
for i := 0; i < c.cfg.SummaryObjectives; i++ {
253+
q := parts * (i + 1)
254+
if q == 100 {
255+
q = 99
256+
}
257+
objectives[float64(q)/100.0] = float64(100-q) / 1000.0
258+
}
259+
}
245260
for id := range c.summaries {
246261
mName := fmt.Sprintf("avalanche_summary_metric_%s_%v_%v", strings.Repeat("m", c.cfg.MetricLength), s.metricCycle, id)
247262
summary := prometheus.NewSummaryVec(
248-
prometheus.SummaryOpts{Name: mName, Help: help(mName)},
263+
prometheus.SummaryOpts{Name: mName, Help: help(mName), Objectives: objectives},
249264
append([]string{"series_id", "cycle_id"}, c.labelKeys...),
250265
)
251266
c.summaries[id] = summary

metrics/serve_test.go

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ package metrics
1515

1616
import (
1717
"fmt"
18+
"math"
1819
"strconv"
1920
"testing"
2021
"time"
@@ -40,6 +41,8 @@ func countSeries(t *testing.T, registry *prometheus.Registry) (seriesCount int)
4041
return seriesCount
4142
}
4243

44+
// countSeriesTypes gives exact count of all types. For complex types that are represented by counters in Prometheus
45+
// data model (and text exposition formats), we count all individual resulting series.
4346
func countSeriesTypes(t *testing.T, registry *prometheus.Registry) (gauges, counters, histograms, nhistograms, summaries int) {
4447
t.Helper()
4548

@@ -54,13 +57,20 @@ func countSeriesTypes(t *testing.T, registry *prometheus.Registry) (gauges, coun
5457
case io_prometheus_client.MetricType_COUNTER:
5558
counters++
5659
case io_prometheus_client.MetricType_HISTOGRAM:
57-
if len(m.GetHistogram().Bucket) == 0 {
60+
if bkts := len(m.GetHistogram().Bucket); bkts == 0 {
5861
nhistograms++
5962
} else {
60-
histograms++
63+
histograms += 2 // count and sum.
64+
histograms += len(m.GetHistogram().GetBucket())
65+
if m.GetHistogram().GetBucket()[bkts-1].GetUpperBound() != math.Inf(+1) {
66+
// In the proto model we don't put explicit +Inf bucket, unless there is an exemplar,
67+
// but it will appear as series in text format and Prometheus model. Account for that.
68+
histograms++
69+
}
6170
}
6271
case io_prometheus_client.MetricType_SUMMARY:
63-
summaries++
72+
summaries += 2 // count and sum.
73+
summaries += len(m.GetSummary().GetQuantile())
6474
default:
6575
t.Fatalf("unknown metric type found %v", mf.GetType())
6676
}
@@ -74,9 +84,10 @@ func TestRunMetrics(t *testing.T) {
7484
GaugeMetricCount: 200,
7585
CounterMetricCount: 200,
7686
HistogramMetricCount: 10,
77-
HistogramBuckets: 8,
87+
HistogramBuckets: 7,
7888
NativeHistogramMetricCount: 10,
7989
SummaryMetricCount: 10,
90+
SummaryObjectives: 2,
8091

8192
MinSeriesCount: 0,
8293
MaxSeriesCount: 1000,
@@ -102,19 +113,20 @@ func TestRunMetrics(t *testing.T) {
102113
g, c, h, nh, s := countSeriesTypes(t, reg)
103114
assert.Equal(t, testCfg.GaugeMetricCount*testCfg.SeriesCount, g)
104115
assert.Equal(t, testCfg.CounterMetricCount*testCfg.SeriesCount, c)
105-
assert.Equal(t, testCfg.HistogramMetricCount*testCfg.SeriesCount, h)
116+
assert.Equal(t, (2+testCfg.HistogramBuckets+1)*testCfg.HistogramMetricCount*testCfg.SeriesCount, h)
106117
assert.Equal(t, testCfg.NativeHistogramMetricCount*testCfg.SeriesCount, nh)
107-
assert.Equal(t, testCfg.SummaryMetricCount*testCfg.SeriesCount, s)
118+
assert.Equal(t, (2+testCfg.SummaryObjectives)*testCfg.SummaryMetricCount*testCfg.SeriesCount, s)
108119
}
109120

110121
func TestRunMetrics_ValueChange_SeriesCountSame(t *testing.T) {
111122
testCfg := Config{
112123
GaugeMetricCount: 200,
113124
CounterMetricCount: 200,
114125
HistogramMetricCount: 10,
115-
HistogramBuckets: 8,
126+
HistogramBuckets: 7,
116127
NativeHistogramMetricCount: 10,
117128
SummaryMetricCount: 10,
129+
SummaryObjectives: 2,
118130

119131
MinSeriesCount: 0,
120132
MaxSeriesCount: 1000,
@@ -145,9 +157,9 @@ func TestRunMetrics_ValueChange_SeriesCountSame(t *testing.T) {
145157
g, c, h, nh, s := countSeriesTypes(t, reg)
146158
assert.Equal(t, testCfg.GaugeMetricCount*testCfg.SeriesCount, g)
147159
assert.Equal(t, testCfg.CounterMetricCount*testCfg.SeriesCount, c)
148-
assert.Equal(t, testCfg.HistogramMetricCount*testCfg.SeriesCount, h)
160+
assert.Equal(t, (2+testCfg.HistogramBuckets+1)*testCfg.HistogramMetricCount*testCfg.SeriesCount, h)
149161
assert.Equal(t, testCfg.NativeHistogramMetricCount*testCfg.SeriesCount, nh)
150-
assert.Equal(t, testCfg.SummaryMetricCount*testCfg.SeriesCount, s)
162+
assert.Equal(t, (2+testCfg.SummaryObjectives)*testCfg.SummaryMetricCount*testCfg.SeriesCount, s)
151163
}
152164
}
153165

@@ -184,9 +196,10 @@ func TestRunMetrics_SeriesChurn(t *testing.T) {
184196
GaugeMetricCount: 200,
185197
CounterMetricCount: 200,
186198
HistogramMetricCount: 10,
187-
HistogramBuckets: 8,
199+
HistogramBuckets: 7,
188200
NativeHistogramMetricCount: 10,
189201
SummaryMetricCount: 10,
202+
SummaryObjectives: 2,
190203

191204
MinSeriesCount: 0,
192205
MaxSeriesCount: 1000,
@@ -220,9 +233,9 @@ func TestRunMetrics_SeriesChurn(t *testing.T) {
220233
g, c, h, nh, s := countSeriesTypes(t, reg)
221234
assert.Equal(t, testCfg.GaugeMetricCount*testCfg.SeriesCount, g)
222235
assert.Equal(t, testCfg.CounterMetricCount*testCfg.SeriesCount, c)
223-
assert.Equal(t, testCfg.HistogramMetricCount*testCfg.SeriesCount, h)
236+
assert.Equal(t, (2+testCfg.HistogramBuckets+1)*testCfg.HistogramMetricCount*testCfg.SeriesCount, h)
224237
assert.Equal(t, testCfg.NativeHistogramMetricCount*testCfg.SeriesCount, nh)
225-
assert.Equal(t, testCfg.SummaryMetricCount*testCfg.SeriesCount, s)
238+
assert.Equal(t, (2+testCfg.SummaryObjectives)*testCfg.SummaryMetricCount*testCfg.SeriesCount, s)
226239

227240
gotCycleID := currentCycleID(t, reg)
228241
require.Greater(t, gotCycleID, cycleID)

0 commit comments

Comments
 (0)