blob: 537e2e966832bb731f24e8977ef0281f950af34f [file] [log] [blame]
Matthias Andreas Benkard832a54e2019-01-29 09:27:38 +01001// Copyright 2018 The Kubernetes Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package metrics
16
17import (
18 "time"
19
20 "github.com/prometheus/client_golang/prometheus"
21)
22
23// BucketsForScrapeDuration calculates a variant of the prometheus default histogram
24// buckets that includes relevant buckets around out scrape timeout.
25func BucketsForScrapeDuration(scrapeTimeout time.Duration) []float64 {
26 // set up some buckets that include our scrape timeout,
27 // so that we can easily pinpoint scrape timeout issues.
28 // The default buckets provide a sane starting point for
29 // the smaller numbers.
30 buckets := append([]float64(nil), prometheus.DefBuckets...)
31 maxBucket := buckets[len(buckets)-1]
32 timeoutSeconds := float64(scrapeTimeout) / float64(time.Second)
33 if timeoutSeconds > maxBucket {
34 // [defaults, (scrapeTimeout + (scrapeTimeout - maxBucket)/ 2), scrapeTimeout, scrapeTimeout*1.5, scrapeTimeout*2]
35 halfwayToScrapeTimeout := maxBucket + (timeoutSeconds-maxBucket)/2
36 buckets = append(buckets, halfwayToScrapeTimeout, timeoutSeconds, timeoutSeconds*1.5, timeoutSeconds*2.0)
37 } else if timeoutSeconds < maxBucket {
38 var i int
39 var bucket float64
40 for i, bucket = range buckets {
41 if bucket > timeoutSeconds {
42 break
43 }
44 }
45
46 if bucket-timeoutSeconds < buckets[0] || (i > 0 && timeoutSeconds-buckets[i-1] < buckets[0]) {
47 // if we're sufficiently close to another bucket, just skip this
48 return buckets
49 }
50
51 // likely that our scrape timeout is close to another bucket, so don't bother injecting more than just our scrape timeout
52 oldRest := append([]float64(nil), buckets[i:]...) // make a copy so we don't overwrite it
53 buckets = append(buckets[:i], timeoutSeconds)
54 buckets = append(buckets, oldRest...)
55 }
56
57 return buckets
58}