diff --git a/README.md b/README.md index 110a7d02..9f5233e3 100644 --- a/README.md +++ b/README.md @@ -296,7 +296,6 @@ mappings: name: "${2}_total" labels: provider: "$1" -mappings: - match: "(.*)\\.(.*)--(.*)\\.status\.(.*)\\.count" match_type: regex name: "request_total" @@ -403,6 +402,8 @@ mappings: observer_type: histogram histogram_options: buckets: [ 0.01, 0.025, 0.05, 0.1 ] + native_histogram_bucket_factor: 1.1 + native_histogram_max_buckets: 256 name: "my_timer" labels: provider: "$2" @@ -416,6 +417,11 @@ values](https://godoc.org/github.com/prometheus/client_golang/prometheus#pkg-var are used for the histogram buckets: `[.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10]`. `+Inf` is added automatically. +If your Prometheus server is enabled to scrape native histograms (v2.40.0+), +then you can set the `native_histogram_bucket_factor` to configure precision of the +buckets in the sparse histogram. More about this in the original [client_golang docs](https://github.com/prometheus/client_golang/blob/449b46435075e6e069e05af920fe028b941033cf/prometheus/histogram.go#L399-L430). +Also, a configuration of the maximum number of buckets can be set with `native_histogram_max_buckets`, this +avoids the histograms to grow too large in memory. More about this in the original [client_golang docs](https://github.com/prometheus/client_golang/blob/449b46435075e6e069e05af920fe028b941033cf/prometheus/histogram.go#L443-L467). `observer_type` is only used when the statsd metric type is a timer, histogram, or distribution. `buckets` is only used when the statsd metric type is one of these, and the `observer_type` is set to `histogram`. @@ -470,6 +476,8 @@ defaults: observer_type: histogram histogram_options: buckets: [.005, .01, .025, .05, .1, .25, .5, 1, 2.5 ] + native_histogram_bucket_factor: 1.1 + native_histogram_max_buckets: 256 summary_options: quantiles: - quantile: 0.99 @@ -549,7 +557,7 @@ Possible values for `match_metric_type` are `gauge`, `counter` and `observer`. There is a cache used to improve the performance of the metric mapping, that can greatly improvement performance. The cache has a default maximum of 1000 unique statsd metric names -> prometheus metrics mappings that it can store. -This maximum can be adjust using the `statsd.cache-size` flag. +This maximum can be adjusted using the `statsd.cache-size` flag. If the maximum is reached, entries are by default rotated using the [least recently used replacement policy](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)). This strategy is optimal when memory is constrained as only the most recent entries are retained. diff --git a/pkg/mapper/mapper.go b/pkg/mapper/mapper.go index 879f18c5..0f171655 100644 --- a/pkg/mapper/mapper.go +++ b/pkg/mapper/mapper.go @@ -64,7 +64,9 @@ type SummaryOptions struct { } type HistogramOptions struct { - Buckets []float64 `yaml:"buckets"` + Buckets []float64 `yaml:"buckets"` + NativeHistogramBucketFactor float64 `yaml:"native_histogram_bucket_factor"` + NativeHistogramMaxBuckets uint32 `yaml:"native_histogram_max_buckets"` } type metricObjective struct { @@ -88,6 +90,12 @@ func (m *MetricMapper) InitFromYAMLString(fileContents string) error { if len(n.Defaults.HistogramOptions.Buckets) == 0 { n.Defaults.HistogramOptions.Buckets = prometheus.DefBuckets } + if n.Defaults.HistogramOptions.NativeHistogramBucketFactor == 0 { + n.Defaults.HistogramOptions.NativeHistogramBucketFactor = 1.1 + } + if n.Defaults.HistogramOptions.NativeHistogramMaxBuckets <= 0 { + n.Defaults.HistogramOptions.NativeHistogramMaxBuckets = 256 + } if len(n.Defaults.SummaryOptions.Quantiles) == 0 { n.Defaults.SummaryOptions.Quantiles = defaultQuantiles diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go index 87d39a16..825cb14c 100644 --- a/pkg/registry/registry.go +++ b/pkg/registry/registry.go @@ -274,10 +274,22 @@ func (r *Registry) GetHistogram(metricName string, labels prometheus.Labels, hel if mapping.HistogramOptions != nil && len(mapping.HistogramOptions.Buckets) > 0 { buckets = mapping.HistogramOptions.Buckets } + + bucketFactor := r.Mapper.Defaults.HistogramOptions.NativeHistogramBucketFactor + if mapping.HistogramOptions != nil && mapping.HistogramOptions.NativeHistogramBucketFactor > 0 { + bucketFactor = mapping.HistogramOptions.NativeHistogramBucketFactor + } + + maxBuckets := r.Mapper.Defaults.HistogramOptions.NativeHistogramMaxBuckets + if mapping.HistogramOptions != nil && mapping.HistogramOptions.NativeHistogramMaxBuckets > 0 { + maxBuckets = mapping.HistogramOptions.NativeHistogramMaxBuckets + } histogramVec = prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Name: metricName, - Help: help, - Buckets: buckets, + Name: metricName, + Help: help, + Buckets: buckets, + NativeHistogramBucketFactor: bucketFactor, + NativeHistogramMaxBucketNumber: maxBuckets, }, labelNames) if err := r.Registerer.Register(uncheckedCollector{histogramVec}); err != nil {