diff options
author | Björn Rabenstein <beorn@grafana.com> | 2019-06-21 11:05:48 +0200 |
---|---|---|
committer | Johannes 'fish' Ziemke <github@freigeist.org> | 2019-06-21 11:05:48 +0200 |
commit | a9231ad6ad82419b7dd56383ec1c62aa93bb3d2b (patch) | |
tree | 36290c42e88088ce668060dc21a426a41883e5cd /vendor | |
parent | 22a7dbae083fbe0d2abd05d555cda0c80951a034 (diff) | |
download | prometheus_node_collector-a9231ad6ad82419b7dd56383ec1c62aa93bb3d2b.tar.bz2 prometheus_node_collector-a9231ad6ad82419b7dd56383ec1c62aa93bb3d2b.tar.xz prometheus_node_collector-a9231ad6ad82419b7dd56383ec1c62aa93bb3d2b.zip |
Update prometheus/client_golang to v1.0.0 (#1382)
Signed-off-by: beorn7 <beorn@grafana.com>
Diffstat (limited to 'vendor')
21 files changed, 887 insertions, 1056 deletions
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/build_info.go b/vendor/github.com/prometheus/client_golang/prometheus/build_info.go new file mode 100644 index 0000000..288f0e8 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/build_info.go | |||
@@ -0,0 +1,29 @@ | |||
1 | // Copyright 2019 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | // +build go1.12 | ||
15 | |||
16 | package prometheus | ||
17 | |||
18 | import "runtime/debug" | ||
19 | |||
20 | // readBuildInfo is a wrapper around debug.ReadBuildInfo for Go 1.12+. | ||
21 | func readBuildInfo() (path, version, sum string) { | ||
22 | path, version, sum = "unknown", "unknown", "unknown" | ||
23 | if bi, ok := debug.ReadBuildInfo(); ok { | ||
24 | path = bi.Main.Path | ||
25 | version = bi.Main.Version | ||
26 | sum = bi.Main.Sum | ||
27 | } | ||
28 | return | ||
29 | } | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/build_info_pre_1.12.go b/vendor/github.com/prometheus/client_golang/prometheus/build_info_pre_1.12.go new file mode 100644 index 0000000..6609e28 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/build_info_pre_1.12.go | |||
@@ -0,0 +1,22 @@ | |||
1 | // Copyright 2019 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | // +build !go1.12 | ||
15 | |||
16 | package prometheus | ||
17 | |||
18 | // readBuildInfo is a wrapper around debug.ReadBuildInfo for Go versions before | ||
19 | // 1.12. Remove this whole file once the minimum supported Go version is 1.12. | ||
20 | func readBuildInfo() (path, version, sum string) { | ||
21 | return "unknown", "unknown", "unknown" | ||
22 | } | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collector.go b/vendor/github.com/prometheus/client_golang/prometheus/collector.go index c0d70b2..1e83965 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/collector.go | |||
@@ -79,7 +79,7 @@ type Collector interface { | |||
79 | // of the Describe method. If a Collector sometimes collects no metrics at all | 79 | // of the Describe method. If a Collector sometimes collects no metrics at all |
80 | // (for example vectors like CounterVec, GaugeVec, etc., which only collect | 80 | // (for example vectors like CounterVec, GaugeVec, etc., which only collect |
81 | // metrics after a metric with a fully specified label set has been accessed), | 81 | // metrics after a metric with a fully specified label set has been accessed), |
82 | // it might even get registered as an unchecked Collecter (cf. the Register | 82 | // it might even get registered as an unchecked Collector (cf. the Register |
83 | // method of the Registerer interface). Hence, only use this shortcut | 83 | // method of the Registerer interface). Hence, only use this shortcut |
84 | // implementation of Describe if you are certain to fulfill the contract. | 84 | // implementation of Describe if you are certain to fulfill the contract. |
85 | // | 85 | // |
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/doc.go b/vendor/github.com/prometheus/client_golang/prometheus/doc.go index 5d9525d..01977de 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/doc.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/doc.go | |||
@@ -122,13 +122,13 @@ | |||
122 | // the Collect method. The Describe method has to return separate Desc | 122 | // the Collect method. The Describe method has to return separate Desc |
123 | // instances, representative of the “throw-away” metrics to be created later. | 123 | // instances, representative of the “throw-away” metrics to be created later. |
124 | // NewDesc comes in handy to create those Desc instances. Alternatively, you | 124 | // NewDesc comes in handy to create those Desc instances. Alternatively, you |
125 | // could return no Desc at all, which will marke the Collector “unchecked”. No | 125 | // could return no Desc at all, which will mark the Collector “unchecked”. No |
126 | // checks are porformed at registration time, but metric consistency will still | 126 | // checks are performed at registration time, but metric consistency will still |
127 | // be ensured at scrape time, i.e. any inconsistencies will lead to scrape | 127 | // be ensured at scrape time, i.e. any inconsistencies will lead to scrape |
128 | // errors. Thus, with unchecked Collectors, the responsibility to not collect | 128 | // errors. Thus, with unchecked Collectors, the responsibility to not collect |
129 | // metrics that lead to inconsistencies in the total scrape result lies with the | 129 | // metrics that lead to inconsistencies in the total scrape result lies with the |
130 | // implementer of the Collector. While this is not a desirable state, it is | 130 | // implementer of the Collector. While this is not a desirable state, it is |
131 | // sometimes necessary. The typical use case is a situatios where the exact | 131 | // sometimes necessary. The typical use case is a situation where the exact |
132 | // metrics to be returned by a Collector cannot be predicted at registration | 132 | // metrics to be returned by a Collector cannot be predicted at registration |
133 | // time, but the implementer has sufficient knowledge of the whole system to | 133 | // time, but the implementer has sufficient knowledge of the whole system to |
134 | // guarantee metric consistency. | 134 | // guarantee metric consistency. |
@@ -183,7 +183,6 @@ | |||
183 | // method can then expose the gathered metrics in some way. Usually, the metrics | 183 | // method can then expose the gathered metrics in some way. Usually, the metrics |
184 | // are served via HTTP on the /metrics endpoint. That's happening in the example | 184 | // are served via HTTP on the /metrics endpoint. That's happening in the example |
185 | // above. The tools to expose metrics via HTTP are in the promhttp sub-package. | 185 | // above. The tools to expose metrics via HTTP are in the promhttp sub-package. |
186 | // (The top-level functions in the prometheus package are deprecated.) | ||
187 | // | 186 | // |
188 | // Pushing to the Pushgateway | 187 | // Pushing to the Pushgateway |
189 | // | 188 | // |
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go index ba3b933..dc9247f 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go | |||
@@ -14,9 +14,9 @@ | |||
14 | package prometheus | 14 | package prometheus |
15 | 15 | ||
16 | import ( | 16 | import ( |
17 | "fmt" | ||
18 | "runtime" | 17 | "runtime" |
19 | "runtime/debug" | 18 | "runtime/debug" |
19 | "sync" | ||
20 | "time" | 20 | "time" |
21 | ) | 21 | ) |
22 | 22 | ||
@@ -26,16 +26,41 @@ type goCollector struct { | |||
26 | gcDesc *Desc | 26 | gcDesc *Desc |
27 | goInfoDesc *Desc | 27 | goInfoDesc *Desc |
28 | 28 | ||
29 | // metrics to describe and collect | 29 | // ms... are memstats related. |
30 | metrics memStatsMetrics | 30 | msLast *runtime.MemStats // Previously collected memstats. |
31 | msLastTimestamp time.Time | ||
32 | msMtx sync.Mutex // Protects msLast and msLastTimestamp. | ||
33 | msMetrics memStatsMetrics | ||
34 | msRead func(*runtime.MemStats) // For mocking in tests. | ||
35 | msMaxWait time.Duration // Wait time for fresh memstats. | ||
36 | msMaxAge time.Duration // Maximum allowed age of old memstats. | ||
31 | } | 37 | } |
32 | 38 | ||
33 | // NewGoCollector returns a collector which exports metrics about the current Go | 39 | // NewGoCollector returns a collector that exports metrics about the current Go |
34 | // process. This includes memory stats. To collect those, runtime.ReadMemStats | 40 | // process. This includes memory stats. To collect those, runtime.ReadMemStats |
35 | // is called. This causes a stop-the-world, which is very short with Go1.9+ | 41 | // is called. This requires to “stop the world”, which usually only happens for |
36 | // (~25µs). However, with older Go versions, the stop-the-world duration depends | 42 | // garbage collection (GC). Take the following implications into account when |
37 | // on the heap size and can be quite significant (~1.7 ms/GiB as per | 43 | // deciding whether to use the Go collector: |
44 | // | ||
45 | // 1. The performance impact of stopping the world is the more relevant the more | ||
46 | // frequently metrics are collected. However, with Go1.9 or later the | ||
47 | // stop-the-world time per metrics collection is very short (~25µs) so that the | ||
48 | // performance impact will only matter in rare cases. However, with older Go | ||
49 | // versions, the stop-the-world duration depends on the heap size and can be | ||
50 | // quite significant (~1.7 ms/GiB as per | ||
38 | // https://go-review.googlesource.com/c/go/+/34937). | 51 | // https://go-review.googlesource.com/c/go/+/34937). |
52 | // | ||
53 | // 2. During an ongoing GC, nothing else can stop the world. Therefore, if the | ||
54 | // metrics collection happens to coincide with GC, it will only complete after | ||
55 | // GC has finished. Usually, GC is fast enough to not cause problems. However, | ||
56 | // with a very large heap, GC might take multiple seconds, which is enough to | ||
57 | // cause scrape timeouts in common setups. To avoid this problem, the Go | ||
58 | // collector will use the memstats from a previous collection if | ||
59 | // runtime.ReadMemStats takes more than 1s. However, if there are no previously | ||
60 | // collected memstats, or their collection is more than 5m ago, the collection | ||
61 | // will block until runtime.ReadMemStats succeeds. (The problem might be solved | ||
62 | // in Go1.13, see https://github.com/golang/go/issues/19812 for the related Go | ||
63 | // issue.) | ||
39 | func NewGoCollector() Collector { | 64 | func NewGoCollector() Collector { |
40 | return &goCollector{ | 65 | return &goCollector{ |
41 | goroutinesDesc: NewDesc( | 66 | goroutinesDesc: NewDesc( |
@@ -54,7 +79,11 @@ func NewGoCollector() Collector { | |||
54 | "go_info", | 79 | "go_info", |
55 | "Information about the Go environment.", | 80 | "Information about the Go environment.", |
56 | nil, Labels{"version": runtime.Version()}), | 81 | nil, Labels{"version": runtime.Version()}), |
57 | metrics: memStatsMetrics{ | 82 | msLast: &runtime.MemStats{}, |
83 | msRead: runtime.ReadMemStats, | ||
84 | msMaxWait: time.Second, | ||
85 | msMaxAge: 5 * time.Minute, | ||
86 | msMetrics: memStatsMetrics{ | ||
58 | { | 87 | { |
59 | desc: NewDesc( | 88 | desc: NewDesc( |
60 | memstatNamespace("alloc_bytes"), | 89 | memstatNamespace("alloc_bytes"), |
@@ -253,7 +282,7 @@ func NewGoCollector() Collector { | |||
253 | } | 282 | } |
254 | 283 | ||
255 | func memstatNamespace(s string) string { | 284 | func memstatNamespace(s string) string { |
256 | return fmt.Sprintf("go_memstats_%s", s) | 285 | return "go_memstats_" + s |
257 | } | 286 | } |
258 | 287 | ||
259 | // Describe returns all descriptions of the collector. | 288 | // Describe returns all descriptions of the collector. |
@@ -262,13 +291,27 @@ func (c *goCollector) Describe(ch chan<- *Desc) { | |||
262 | ch <- c.threadsDesc | 291 | ch <- c.threadsDesc |
263 | ch <- c.gcDesc | 292 | ch <- c.gcDesc |
264 | ch <- c.goInfoDesc | 293 | ch <- c.goInfoDesc |
265 | for _, i := range c.metrics { | 294 | for _, i := range c.msMetrics { |
266 | ch <- i.desc | 295 | ch <- i.desc |
267 | } | 296 | } |
268 | } | 297 | } |
269 | 298 | ||
270 | // Collect returns the current state of all metrics of the collector. | 299 | // Collect returns the current state of all metrics of the collector. |
271 | func (c *goCollector) Collect(ch chan<- Metric) { | 300 | func (c *goCollector) Collect(ch chan<- Metric) { |
301 | var ( | ||
302 | ms = &runtime.MemStats{} | ||
303 | done = make(chan struct{}) | ||
304 | ) | ||
305 | // Start reading memstats first as it might take a while. | ||
306 | go func() { | ||
307 | c.msRead(ms) | ||
308 | c.msMtx.Lock() | ||
309 | c.msLast = ms | ||
310 | c.msLastTimestamp = time.Now() | ||
311 | c.msMtx.Unlock() | ||
312 | close(done) | ||
313 | }() | ||
314 | |||
272 | ch <- MustNewConstMetric(c.goroutinesDesc, GaugeValue, float64(runtime.NumGoroutine())) | 315 | ch <- MustNewConstMetric(c.goroutinesDesc, GaugeValue, float64(runtime.NumGoroutine())) |
273 | n, _ := runtime.ThreadCreateProfile(nil) | 316 | n, _ := runtime.ThreadCreateProfile(nil) |
274 | ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, float64(n)) | 317 | ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, float64(n)) |
@@ -286,9 +329,31 @@ func (c *goCollector) Collect(ch chan<- Metric) { | |||
286 | 329 | ||
287 | ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1) | 330 | ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1) |
288 | 331 | ||
289 | ms := &runtime.MemStats{} | 332 | timer := time.NewTimer(c.msMaxWait) |
290 | runtime.ReadMemStats(ms) | 333 | select { |
291 | for _, i := range c.metrics { | 334 | case <-done: // Our own ReadMemStats succeeded in time. Use it. |
335 | timer.Stop() // Important for high collection frequencies to not pile up timers. | ||
336 | c.msCollect(ch, ms) | ||
337 | return | ||
338 | case <-timer.C: // Time out, use last memstats if possible. Continue below. | ||
339 | } | ||
340 | c.msMtx.Lock() | ||
341 | if time.Since(c.msLastTimestamp) < c.msMaxAge { | ||
342 | // Last memstats are recent enough. Collect from them under the lock. | ||
343 | c.msCollect(ch, c.msLast) | ||
344 | c.msMtx.Unlock() | ||
345 | return | ||
346 | } | ||
347 | // If we are here, the last memstats are too old or don't exist. We have | ||
348 | // to wait until our own ReadMemStats finally completes. For that to | ||
349 | // happen, we have to release the lock. | ||
350 | c.msMtx.Unlock() | ||
351 | <-done | ||
352 | c.msCollect(ch, ms) | ||
353 | } | ||
354 | |||
355 | func (c *goCollector) msCollect(ch chan<- Metric, ms *runtime.MemStats) { | ||
356 | for _, i := range c.msMetrics { | ||
292 | ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms)) | 357 | ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms)) |
293 | } | 358 | } |
294 | } | 359 | } |
@@ -299,3 +364,33 @@ type memStatsMetrics []struct { | |||
299 | eval func(*runtime.MemStats) float64 | 364 | eval func(*runtime.MemStats) float64 |
300 | valType ValueType | 365 | valType ValueType |
301 | } | 366 | } |
367 | |||
368 | // NewBuildInfoCollector returns a collector collecting a single metric | ||
369 | // "go_build_info" with the constant value 1 and three labels "path", "version", | ||
370 | // and "checksum". Their label values contain the main module path, version, and | ||
371 | // checksum, respectively. The labels will only have meaningful values if the | ||
372 | // binary is built with Go module support and from source code retrieved from | ||
373 | // the source repository (rather than the local file system). This is usually | ||
374 | // accomplished by building from outside of GOPATH, specifying the full address | ||
375 | // of the main package, e.g. "GO111MODULE=on go run | ||
376 | // github.com/prometheus/client_golang/examples/random". If built without Go | ||
377 | // module support, all label values will be "unknown". If built with Go module | ||
378 | // support but using the source code from the local file system, the "path" will | ||
379 | // be set appropriately, but "checksum" will be empty and "version" will be | ||
380 | // "(devel)". | ||
381 | // | ||
382 | // This collector uses only the build information for the main module. See | ||
383 | // https://github.com/povilasv/prommod for an example of a collector for the | ||
384 | // module dependencies. | ||
385 | func NewBuildInfoCollector() Collector { | ||
386 | path, version, sum := readBuildInfo() | ||
387 | c := &selfCollector{MustNewConstMetric( | ||
388 | NewDesc( | ||
389 | "go_build_info", | ||
390 | "Build information about the main Go module.", | ||
391 | nil, Labels{"path": path, "version": version, "checksum": sum}, | ||
392 | ), | ||
393 | GaugeValue, 1)} | ||
394 | c.init(c.self) | ||
395 | return c | ||
396 | } | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go index f88da70..d7ea67b 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go | |||
@@ -204,8 +204,8 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr | |||
204 | } | 204 | } |
205 | } | 205 | } |
206 | } | 206 | } |
207 | // Finally we know the final length of h.upperBounds and can make counts | 207 | // Finally we know the final length of h.upperBounds and can make buckets |
208 | // for both states: | 208 | // for both counts: |
209 | h.counts[0].buckets = make([]uint64, len(h.upperBounds)) | 209 | h.counts[0].buckets = make([]uint64, len(h.upperBounds)) |
210 | h.counts[1].buckets = make([]uint64, len(h.upperBounds)) | 210 | h.counts[1].buckets = make([]uint64, len(h.upperBounds)) |
211 | 211 | ||
@@ -224,18 +224,21 @@ type histogramCounts struct { | |||
224 | } | 224 | } |
225 | 225 | ||
226 | type histogram struct { | 226 | type histogram struct { |
227 | // countAndHotIdx is a complicated one. For lock-free yet atomic | 227 | // countAndHotIdx enables lock-free writes with use of atomic updates. |
228 | // observations, we need to save the total count of observations again, | 228 | // The most significant bit is the hot index [0 or 1] of the count field |
229 | // combined with the index of the currently-hot counts struct, so that | 229 | // below. Observe calls update the hot one. All remaining bits count the |
230 | // we can perform the operation on both values atomically. The least | 230 | // number of Observe calls. Observe starts by incrementing this counter, |
231 | // significant bit defines the hot counts struct. The remaining 63 bits | 231 | // and finish by incrementing the count field in the respective |
232 | // represent the total count of observations. This happens under the | 232 | // histogramCounts, as a marker for completion. |
233 | // assumption that the 63bit count will never overflow. Rationale: An | ||
234 | // observations takes about 30ns. Let's assume it could happen in | ||
235 | // 10ns. Overflowing the counter will then take at least (2^63)*10ns, | ||
236 | // which is about 3000 years. | ||
237 | // | 233 | // |
238 | // This has to be first in the struct for 64bit alignment. See | 234 | // Calls of the Write method (which are non-mutating reads from the |
235 | // perspective of the histogram) swap the hot–cold under the writeMtx | ||
236 | // lock. A cooldown is awaited (while locked) by comparing the number of | ||
237 | // observations with the initiation count. Once they match, then the | ||
238 | // last observation on the now cool one has completed. All cool fields must | ||
239 | // be merged into the new hot before releasing writeMtx. | ||
240 | // | ||
241 | // Fields with atomic access first! See alignment constraint: | ||
239 | // http://golang.org/pkg/sync/atomic/#pkg-note-BUG | 242 | // http://golang.org/pkg/sync/atomic/#pkg-note-BUG |
240 | countAndHotIdx uint64 | 243 | countAndHotIdx uint64 |
241 | 244 | ||
@@ -243,16 +246,14 @@ type histogram struct { | |||
243 | desc *Desc | 246 | desc *Desc |
244 | writeMtx sync.Mutex // Only used in the Write method. | 247 | writeMtx sync.Mutex // Only used in the Write method. |
245 | 248 | ||
246 | upperBounds []float64 | ||
247 | |||
248 | // Two counts, one is "hot" for lock-free observations, the other is | 249 | // Two counts, one is "hot" for lock-free observations, the other is |
249 | // "cold" for writing out a dto.Metric. It has to be an array of | 250 | // "cold" for writing out a dto.Metric. It has to be an array of |
250 | // pointers to guarantee 64bit alignment of the histogramCounts, see | 251 | // pointers to guarantee 64bit alignment of the histogramCounts, see |
251 | // http://golang.org/pkg/sync/atomic/#pkg-note-BUG. | 252 | // http://golang.org/pkg/sync/atomic/#pkg-note-BUG. |
252 | counts [2]*histogramCounts | 253 | counts [2]*histogramCounts |
253 | hotIdx int // Index of currently-hot counts. Only used within Write. | ||
254 | 254 | ||
255 | labelPairs []*dto.LabelPair | 255 | upperBounds []float64 |
256 | labelPairs []*dto.LabelPair | ||
256 | } | 257 | } |
257 | 258 | ||
258 | func (h *histogram) Desc() *Desc { | 259 | func (h *histogram) Desc() *Desc { |
@@ -271,11 +272,11 @@ func (h *histogram) Observe(v float64) { | |||
271 | // 300 buckets: 154 ns/op linear - binary 61.6 ns/op | 272 | // 300 buckets: 154 ns/op linear - binary 61.6 ns/op |
272 | i := sort.SearchFloat64s(h.upperBounds, v) | 273 | i := sort.SearchFloat64s(h.upperBounds, v) |
273 | 274 | ||
274 | // We increment h.countAndHotIdx by 2 so that the counter in the upper | 275 | // We increment h.countAndHotIdx so that the counter in the lower |
275 | // 63 bits gets incremented by 1. At the same time, we get the new value | 276 | // 63 bits gets incremented. At the same time, we get the new value |
276 | // back, which we can use to find the currently-hot counts. | 277 | // back, which we can use to find the currently-hot counts. |
277 | n := atomic.AddUint64(&h.countAndHotIdx, 2) | 278 | n := atomic.AddUint64(&h.countAndHotIdx, 1) |
278 | hotCounts := h.counts[n%2] | 279 | hotCounts := h.counts[n>>63] |
279 | 280 | ||
280 | if i < len(h.upperBounds) { | 281 | if i < len(h.upperBounds) { |
281 | atomic.AddUint64(&hotCounts.buckets[i], 1) | 282 | atomic.AddUint64(&hotCounts.buckets[i], 1) |
@@ -293,72 +294,43 @@ func (h *histogram) Observe(v float64) { | |||
293 | } | 294 | } |
294 | 295 | ||
295 | func (h *histogram) Write(out *dto.Metric) error { | 296 | func (h *histogram) Write(out *dto.Metric) error { |
296 | var ( | 297 | // For simplicity, we protect this whole method by a mutex. It is not in |
297 | his = &dto.Histogram{} | 298 | // the hot path, i.e. Observe is called much more often than Write. The |
298 | buckets = make([]*dto.Bucket, len(h.upperBounds)) | 299 | // complication of making Write lock-free isn't worth it, if possible at |
299 | hotCounts, coldCounts *histogramCounts | 300 | // all. |
300 | count uint64 | ||
301 | ) | ||
302 | |||
303 | // For simplicity, we mutex the rest of this method. It is not in the | ||
304 | // hot path, i.e. Observe is called much more often than Write. The | ||
305 | // complication of making Write lock-free isn't worth it. | ||
306 | h.writeMtx.Lock() | 301 | h.writeMtx.Lock() |
307 | defer h.writeMtx.Unlock() | 302 | defer h.writeMtx.Unlock() |
308 | 303 | ||
309 | // This is a bit arcane, which is why the following spells out this if | 304 | // Adding 1<<63 switches the hot index (from 0 to 1 or from 1 to 0) |
310 | // clause in English: | 305 | // without touching the count bits. See the struct comments for a full |
311 | // | 306 | // description of the algorithm. |
312 | // If the currently-hot counts struct is #0, we atomically increment | 307 | n := atomic.AddUint64(&h.countAndHotIdx, 1<<63) |
313 | // h.countAndHotIdx by 1 so that from now on Observe will use the counts | 308 | // count is contained unchanged in the lower 63 bits. |
314 | // struct #1. Furthermore, the atomic increment gives us the new value, | 309 | count := n & ((1 << 63) - 1) |
315 | // which, in its most significant 63 bits, tells us the count of | 310 | // The most significant bit tells us which counts is hot. The complement |
316 | // observations done so far up to and including currently ongoing | 311 | // is thus the cold one. |
317 | // observations still using the counts struct just changed from hot to | 312 | hotCounts := h.counts[n>>63] |
318 | // cold. To have a normal uint64 for the count, we bitshift by 1 and | 313 | coldCounts := h.counts[(^n)>>63] |
319 | // save the result in count. We also set h.hotIdx to 1 for the next | 314 | |
320 | // Write call, and we will refer to counts #1 as hotCounts and to counts | 315 | // Await cooldown. |
321 | // #0 as coldCounts. | 316 | for count != atomic.LoadUint64(&coldCounts.count) { |
322 | // | ||
323 | // If the currently-hot counts struct is #1, we do the corresponding | ||
324 | // things the other way round. We have to _decrement_ h.countAndHotIdx | ||
325 | // (which is a bit arcane in itself, as we have to express -1 with an | ||
326 | // unsigned int...). | ||
327 | if h.hotIdx == 0 { | ||
328 | count = atomic.AddUint64(&h.countAndHotIdx, 1) >> 1 | ||
329 | h.hotIdx = 1 | ||
330 | hotCounts = h.counts[1] | ||
331 | coldCounts = h.counts[0] | ||
332 | } else { | ||
333 | count = atomic.AddUint64(&h.countAndHotIdx, ^uint64(0)) >> 1 // Decrement. | ||
334 | h.hotIdx = 0 | ||
335 | hotCounts = h.counts[0] | ||
336 | coldCounts = h.counts[1] | ||
337 | } | ||
338 | |||
339 | // Now we have to wait for the now-declared-cold counts to actually cool | ||
340 | // down, i.e. wait for all observations still using it to finish. That's | ||
341 | // the case once the count in the cold counts struct is the same as the | ||
342 | // one atomically retrieved from the upper 63bits of h.countAndHotIdx. | ||
343 | for { | ||
344 | if count == atomic.LoadUint64(&coldCounts.count) { | ||
345 | break | ||
346 | } | ||
347 | runtime.Gosched() // Let observations get work done. | 317 | runtime.Gosched() // Let observations get work done. |
348 | } | 318 | } |
349 | 319 | ||
350 | his.SampleCount = proto.Uint64(count) | 320 | his := &dto.Histogram{ |
351 | his.SampleSum = proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))) | 321 | Bucket: make([]*dto.Bucket, len(h.upperBounds)), |
322 | SampleCount: proto.Uint64(count), | ||
323 | SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), | ||
324 | } | ||
352 | var cumCount uint64 | 325 | var cumCount uint64 |
353 | for i, upperBound := range h.upperBounds { | 326 | for i, upperBound := range h.upperBounds { |
354 | cumCount += atomic.LoadUint64(&coldCounts.buckets[i]) | 327 | cumCount += atomic.LoadUint64(&coldCounts.buckets[i]) |
355 | buckets[i] = &dto.Bucket{ | 328 | his.Bucket[i] = &dto.Bucket{ |
356 | CumulativeCount: proto.Uint64(cumCount), | 329 | CumulativeCount: proto.Uint64(cumCount), |
357 | UpperBound: proto.Float64(upperBound), | 330 | UpperBound: proto.Float64(upperBound), |
358 | } | 331 | } |
359 | } | 332 | } |
360 | 333 | ||
361 | his.Bucket = buckets | ||
362 | out.Histogram = his | 334 | out.Histogram = his |
363 | out.Label = h.labelPairs | 335 | out.Label = h.labelPairs |
364 | 336 | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/http.go b/vendor/github.com/prometheus/client_golang/prometheus/http.go deleted file mode 100644 index 9f0875b..0000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/http.go +++ /dev/null | |||
@@ -1,504 +0,0 @@ | |||
1 | // Copyright 2014 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | package prometheus | ||
15 | |||
16 | import ( | ||
17 | "bufio" | ||
18 | "compress/gzip" | ||
19 | "io" | ||
20 | "net" | ||
21 | "net/http" | ||
22 | "strconv" | ||
23 | "strings" | ||
24 | "sync" | ||
25 | "time" | ||
26 | |||
27 | "github.com/prometheus/common/expfmt" | ||
28 | ) | ||
29 | |||
30 | // TODO(beorn7): Remove this whole file. It is a partial mirror of | ||
31 | // promhttp/http.go (to avoid circular import chains) where everything HTTP | ||
32 | // related should live. The functions here are just for avoiding | ||
33 | // breakage. Everything is deprecated. | ||
34 | |||
35 | const ( | ||
36 | contentTypeHeader = "Content-Type" | ||
37 | contentLengthHeader = "Content-Length" | ||
38 | contentEncodingHeader = "Content-Encoding" | ||
39 | acceptEncodingHeader = "Accept-Encoding" | ||
40 | ) | ||
41 | |||
42 | var gzipPool = sync.Pool{ | ||
43 | New: func() interface{} { | ||
44 | return gzip.NewWriter(nil) | ||
45 | }, | ||
46 | } | ||
47 | |||
48 | // Handler returns an HTTP handler for the DefaultGatherer. It is | ||
49 | // already instrumented with InstrumentHandler (using "prometheus" as handler | ||
50 | // name). | ||
51 | // | ||
52 | // Deprecated: Please note the issues described in the doc comment of | ||
53 | // InstrumentHandler. You might want to consider using promhttp.Handler instead. | ||
54 | func Handler() http.Handler { | ||
55 | return InstrumentHandler("prometheus", UninstrumentedHandler()) | ||
56 | } | ||
57 | |||
58 | // UninstrumentedHandler returns an HTTP handler for the DefaultGatherer. | ||
59 | // | ||
60 | // Deprecated: Use promhttp.HandlerFor(DefaultGatherer, promhttp.HandlerOpts{}) | ||
61 | // instead. See there for further documentation. | ||
62 | func UninstrumentedHandler() http.Handler { | ||
63 | return http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) { | ||
64 | mfs, err := DefaultGatherer.Gather() | ||
65 | if err != nil { | ||
66 | httpError(rsp, err) | ||
67 | return | ||
68 | } | ||
69 | |||
70 | contentType := expfmt.Negotiate(req.Header) | ||
71 | header := rsp.Header() | ||
72 | header.Set(contentTypeHeader, string(contentType)) | ||
73 | |||
74 | w := io.Writer(rsp) | ||
75 | if gzipAccepted(req.Header) { | ||
76 | header.Set(contentEncodingHeader, "gzip") | ||
77 | gz := gzipPool.Get().(*gzip.Writer) | ||
78 | defer gzipPool.Put(gz) | ||
79 | |||
80 | gz.Reset(w) | ||
81 | defer gz.Close() | ||
82 | |||
83 | w = gz | ||
84 | } | ||
85 | |||
86 | enc := expfmt.NewEncoder(w, contentType) | ||
87 | |||
88 | for _, mf := range mfs { | ||
89 | if err := enc.Encode(mf); err != nil { | ||
90 | httpError(rsp, err) | ||
91 | return | ||
92 | } | ||
93 | } | ||
94 | }) | ||
95 | } | ||
96 | |||
97 | var instLabels = []string{"method", "code"} | ||
98 | |||
99 | type nower interface { | ||
100 | Now() time.Time | ||
101 | } | ||
102 | |||
103 | type nowFunc func() time.Time | ||
104 | |||
105 | func (n nowFunc) Now() time.Time { | ||
106 | return n() | ||
107 | } | ||
108 | |||
109 | var now nower = nowFunc(func() time.Time { | ||
110 | return time.Now() | ||
111 | }) | ||
112 | |||
113 | // InstrumentHandler wraps the given HTTP handler for instrumentation. It | ||
114 | // registers four metric collectors (if not already done) and reports HTTP | ||
115 | // metrics to the (newly or already) registered collectors: http_requests_total | ||
116 | // (CounterVec), http_request_duration_microseconds (Summary), | ||
117 | // http_request_size_bytes (Summary), http_response_size_bytes (Summary). Each | ||
118 | // has a constant label named "handler" with the provided handlerName as | ||
119 | // value. http_requests_total is a metric vector partitioned by HTTP method | ||
120 | // (label name "method") and HTTP status code (label name "code"). | ||
121 | // | ||
122 | // Deprecated: InstrumentHandler has several issues. Use the tooling provided in | ||
123 | // package promhttp instead. The issues are the following: (1) It uses Summaries | ||
124 | // rather than Histograms. Summaries are not useful if aggregation across | ||
125 | // multiple instances is required. (2) It uses microseconds as unit, which is | ||
126 | // deprecated and should be replaced by seconds. (3) The size of the request is | ||
127 | // calculated in a separate goroutine. Since this calculator requires access to | ||
128 | // the request header, it creates a race with any writes to the header performed | ||
129 | // during request handling. httputil.ReverseProxy is a prominent example for a | ||
130 | // handler performing such writes. (4) It has additional issues with HTTP/2, cf. | ||
131 | // https://github.com/prometheus/client_golang/issues/272. | ||
132 | func InstrumentHandler(handlerName string, handler http.Handler) http.HandlerFunc { | ||
133 | return InstrumentHandlerFunc(handlerName, handler.ServeHTTP) | ||
134 | } | ||
135 | |||
136 | // InstrumentHandlerFunc wraps the given function for instrumentation. It | ||
137 | // otherwise works in the same way as InstrumentHandler (and shares the same | ||
138 | // issues). | ||
139 | // | ||
140 | // Deprecated: InstrumentHandlerFunc is deprecated for the same reasons as | ||
141 | // InstrumentHandler is. Use the tooling provided in package promhttp instead. | ||
142 | func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc { | ||
143 | return InstrumentHandlerFuncWithOpts( | ||
144 | SummaryOpts{ | ||
145 | Subsystem: "http", | ||
146 | ConstLabels: Labels{"handler": handlerName}, | ||
147 | Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, | ||
148 | }, | ||
149 | handlerFunc, | ||
150 | ) | ||
151 | } | ||
152 | |||
153 | // InstrumentHandlerWithOpts works like InstrumentHandler (and shares the same | ||
154 | // issues) but provides more flexibility (at the cost of a more complex call | ||
155 | // syntax). As InstrumentHandler, this function registers four metric | ||
156 | // collectors, but it uses the provided SummaryOpts to create them. However, the | ||
157 | // fields "Name" and "Help" in the SummaryOpts are ignored. "Name" is replaced | ||
158 | // by "requests_total", "request_duration_microseconds", "request_size_bytes", | ||
159 | // and "response_size_bytes", respectively. "Help" is replaced by an appropriate | ||
160 | // help string. The names of the variable labels of the http_requests_total | ||
161 | // CounterVec are "method" (get, post, etc.), and "code" (HTTP status code). | ||
162 | // | ||
163 | // If InstrumentHandlerWithOpts is called as follows, it mimics exactly the | ||
164 | // behavior of InstrumentHandler: | ||
165 | // | ||
166 | // prometheus.InstrumentHandlerWithOpts( | ||
167 | // prometheus.SummaryOpts{ | ||
168 | // Subsystem: "http", | ||
169 | // ConstLabels: prometheus.Labels{"handler": handlerName}, | ||
170 | // }, | ||
171 | // handler, | ||
172 | // ) | ||
173 | // | ||
174 | // Technical detail: "requests_total" is a CounterVec, not a SummaryVec, so it | ||
175 | // cannot use SummaryOpts. Instead, a CounterOpts struct is created internally, | ||
176 | // and all its fields are set to the equally named fields in the provided | ||
177 | // SummaryOpts. | ||
178 | // | ||
179 | // Deprecated: InstrumentHandlerWithOpts is deprecated for the same reasons as | ||
180 | // InstrumentHandler is. Use the tooling provided in package promhttp instead. | ||
181 | func InstrumentHandlerWithOpts(opts SummaryOpts, handler http.Handler) http.HandlerFunc { | ||
182 | return InstrumentHandlerFuncWithOpts(opts, handler.ServeHTTP) | ||
183 | } | ||
184 | |||
185 | // InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc (and shares | ||
186 | // the same issues) but provides more flexibility (at the cost of a more complex | ||
187 | // call syntax). See InstrumentHandlerWithOpts for details how the provided | ||
188 | // SummaryOpts are used. | ||
189 | // | ||
190 | // Deprecated: InstrumentHandlerFuncWithOpts is deprecated for the same reasons | ||
191 | // as InstrumentHandler is. Use the tooling provided in package promhttp instead. | ||
192 | func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc { | ||
193 | reqCnt := NewCounterVec( | ||
194 | CounterOpts{ | ||
195 | Namespace: opts.Namespace, | ||
196 | Subsystem: opts.Subsystem, | ||
197 | Name: "requests_total", | ||
198 | Help: "Total number of HTTP requests made.", | ||
199 | ConstLabels: opts.ConstLabels, | ||
200 | }, | ||
201 | instLabels, | ||
202 | ) | ||
203 | if err := Register(reqCnt); err != nil { | ||
204 | if are, ok := err.(AlreadyRegisteredError); ok { | ||
205 | reqCnt = are.ExistingCollector.(*CounterVec) | ||
206 | } else { | ||
207 | panic(err) | ||
208 | } | ||
209 | } | ||
210 | |||
211 | opts.Name = "request_duration_microseconds" | ||
212 | opts.Help = "The HTTP request latencies in microseconds." | ||
213 | reqDur := NewSummary(opts) | ||
214 | if err := Register(reqDur); err != nil { | ||
215 | if are, ok := err.(AlreadyRegisteredError); ok { | ||
216 | reqDur = are.ExistingCollector.(Summary) | ||
217 | } else { | ||
218 | panic(err) | ||
219 | } | ||
220 | } | ||
221 | |||
222 | opts.Name = "request_size_bytes" | ||
223 | opts.Help = "The HTTP request sizes in bytes." | ||
224 | reqSz := NewSummary(opts) | ||
225 | if err := Register(reqSz); err != nil { | ||
226 | if are, ok := err.(AlreadyRegisteredError); ok { | ||
227 | reqSz = are.ExistingCollector.(Summary) | ||
228 | } else { | ||
229 | panic(err) | ||
230 | } | ||
231 | } | ||
232 | |||
233 | opts.Name = "response_size_bytes" | ||
234 | opts.Help = "The HTTP response sizes in bytes." | ||
235 | resSz := NewSummary(opts) | ||
236 | if err := Register(resSz); err != nil { | ||
237 | if are, ok := err.(AlreadyRegisteredError); ok { | ||
238 | resSz = are.ExistingCollector.(Summary) | ||
239 | } else { | ||
240 | panic(err) | ||
241 | } | ||
242 | } | ||
243 | |||
244 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
245 | now := time.Now() | ||
246 | |||
247 | delegate := &responseWriterDelegator{ResponseWriter: w} | ||
248 | out := computeApproximateRequestSize(r) | ||
249 | |||
250 | _, cn := w.(http.CloseNotifier) | ||
251 | _, fl := w.(http.Flusher) | ||
252 | _, hj := w.(http.Hijacker) | ||
253 | _, rf := w.(io.ReaderFrom) | ||
254 | var rw http.ResponseWriter | ||
255 | if cn && fl && hj && rf { | ||
256 | rw = &fancyResponseWriterDelegator{delegate} | ||
257 | } else { | ||
258 | rw = delegate | ||
259 | } | ||
260 | handlerFunc(rw, r) | ||
261 | |||
262 | elapsed := float64(time.Since(now)) / float64(time.Microsecond) | ||
263 | |||
264 | method := sanitizeMethod(r.Method) | ||
265 | code := sanitizeCode(delegate.status) | ||
266 | reqCnt.WithLabelValues(method, code).Inc() | ||
267 | reqDur.Observe(elapsed) | ||
268 | resSz.Observe(float64(delegate.written)) | ||
269 | reqSz.Observe(float64(<-out)) | ||
270 | }) | ||
271 | } | ||
272 | |||
273 | func computeApproximateRequestSize(r *http.Request) <-chan int { | ||
274 | // Get URL length in current goroutine for avoiding a race condition. | ||
275 | // HandlerFunc that runs in parallel may modify the URL. | ||
276 | s := 0 | ||
277 | if r.URL != nil { | ||
278 | s += len(r.URL.String()) | ||
279 | } | ||
280 | |||
281 | out := make(chan int, 1) | ||
282 | |||
283 | go func() { | ||
284 | s += len(r.Method) | ||
285 | s += len(r.Proto) | ||
286 | for name, values := range r.Header { | ||
287 | s += len(name) | ||
288 | for _, value := range values { | ||
289 | s += len(value) | ||
290 | } | ||
291 | } | ||
292 | s += len(r.Host) | ||
293 | |||
294 | // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. | ||
295 | |||
296 | if r.ContentLength != -1 { | ||
297 | s += int(r.ContentLength) | ||
298 | } | ||
299 | out <- s | ||
300 | close(out) | ||
301 | }() | ||
302 | |||
303 | return out | ||
304 | } | ||
305 | |||
306 | type responseWriterDelegator struct { | ||
307 | http.ResponseWriter | ||
308 | |||
309 | status int | ||
310 | written int64 | ||
311 | wroteHeader bool | ||
312 | } | ||
313 | |||
314 | func (r *responseWriterDelegator) WriteHeader(code int) { | ||
315 | r.status = code | ||
316 | r.wroteHeader = true | ||
317 | r.ResponseWriter.WriteHeader(code) | ||
318 | } | ||
319 | |||
320 | func (r *responseWriterDelegator) Write(b []byte) (int, error) { | ||
321 | if !r.wroteHeader { | ||
322 | r.WriteHeader(http.StatusOK) | ||
323 | } | ||
324 | n, err := r.ResponseWriter.Write(b) | ||
325 | r.written += int64(n) | ||
326 | return n, err | ||
327 | } | ||
328 | |||
329 | type fancyResponseWriterDelegator struct { | ||
330 | *responseWriterDelegator | ||
331 | } | ||
332 | |||
333 | func (f *fancyResponseWriterDelegator) CloseNotify() <-chan bool { | ||
334 | return f.ResponseWriter.(http.CloseNotifier).CloseNotify() | ||
335 | } | ||
336 | |||
337 | func (f *fancyResponseWriterDelegator) Flush() { | ||
338 | f.ResponseWriter.(http.Flusher).Flush() | ||
339 | } | ||
340 | |||
341 | func (f *fancyResponseWriterDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) { | ||
342 | return f.ResponseWriter.(http.Hijacker).Hijack() | ||
343 | } | ||
344 | |||
345 | func (f *fancyResponseWriterDelegator) ReadFrom(r io.Reader) (int64, error) { | ||
346 | if !f.wroteHeader { | ||
347 | f.WriteHeader(http.StatusOK) | ||
348 | } | ||
349 | n, err := f.ResponseWriter.(io.ReaderFrom).ReadFrom(r) | ||
350 | f.written += n | ||
351 | return n, err | ||
352 | } | ||
353 | |||
354 | func sanitizeMethod(m string) string { | ||
355 | switch m { | ||
356 | case "GET", "get": | ||
357 | return "get" | ||
358 | case "PUT", "put": | ||
359 | return "put" | ||
360 | case "HEAD", "head": | ||
361 | return "head" | ||
362 | case "POST", "post": | ||
363 | return "post" | ||
364 | case "DELETE", "delete": | ||
365 | return "delete" | ||
366 | case "CONNECT", "connect": | ||
367 | return "connect" | ||
368 | case "OPTIONS", "options": | ||
369 | return "options" | ||
370 | case "NOTIFY", "notify": | ||
371 | return "notify" | ||
372 | default: | ||
373 | return strings.ToLower(m) | ||
374 | } | ||
375 | } | ||
376 | |||
377 | func sanitizeCode(s int) string { | ||
378 | switch s { | ||
379 | case 100: | ||
380 | return "100" | ||
381 | case 101: | ||
382 | return "101" | ||
383 | |||
384 | case 200: | ||
385 | return "200" | ||
386 | case 201: | ||
387 | return "201" | ||
388 | case 202: | ||
389 | return "202" | ||
390 | case 203: | ||
391 | return "203" | ||
392 | case 204: | ||
393 | return "204" | ||
394 | case 205: | ||
395 | return "205" | ||
396 | case 206: | ||
397 | return "206" | ||
398 | |||
399 | case 300: | ||
400 | return "300" | ||
401 | case 301: | ||
402 | return "301" | ||
403 | case 302: | ||
404 | return "302" | ||
405 | case 304: | ||
406 | return "304" | ||
407 | case 305: | ||
408 | return "305" | ||
409 | case 307: | ||
410 | return "307" | ||
411 | |||
412 | case 400: | ||
413 | return "400" | ||
414 | case 401: | ||
415 | return "401" | ||
416 | case 402: | ||
417 | return "402" | ||
418 | case 403: | ||
419 | return "403" | ||
420 | case 404: | ||
421 | return "404" | ||
422 | case 405: | ||
423 | return "405" | ||
424 | case 406: | ||
425 | return "406" | ||
426 | case 407: | ||
427 | return "407" | ||
428 | case 408: | ||
429 | return "408" | ||
430 | case 409: | ||
431 | return "409" | ||
432 | case 410: | ||
433 | return "410" | ||
434 | case 411: | ||
435 | return "411" | ||
436 | case 412: | ||
437 | return "412" | ||
438 | case 413: | ||
439 | return "413" | ||
440 | case 414: | ||
441 | return "414" | ||
442 | case 415: | ||
443 | return "415" | ||
444 | case 416: | ||
445 | return "416" | ||
446 | case 417: | ||
447 | return "417" | ||
448 | case 418: | ||
449 | return "418" | ||
450 | |||
451 | case 500: | ||
452 | return "500" | ||
453 | case 501: | ||
454 | return "501" | ||
455 | case 502: | ||
456 | return "502" | ||
457 | case 503: | ||
458 | return "503" | ||
459 | case 504: | ||
460 | return "504" | ||
461 | case 505: | ||
462 | return "505" | ||
463 | |||
464 | case 428: | ||
465 | return "428" | ||
466 | case 429: | ||
467 | return "429" | ||
468 | case 431: | ||
469 | return "431" | ||
470 | case 511: | ||
471 | return "511" | ||
472 | |||
473 | default: | ||
474 | return strconv.Itoa(s) | ||
475 | } | ||
476 | } | ||
477 | |||
478 | // gzipAccepted returns whether the client will accept gzip-encoded content. | ||
479 | func gzipAccepted(header http.Header) bool { | ||
480 | a := header.Get(acceptEncodingHeader) | ||
481 | parts := strings.Split(a, ",") | ||
482 | for _, part := range parts { | ||
483 | part = strings.TrimSpace(part) | ||
484 | if part == "gzip" || strings.HasPrefix(part, "gzip;") { | ||
485 | return true | ||
486 | } | ||
487 | } | ||
488 | return false | ||
489 | } | ||
490 | |||
491 | // httpError removes any content-encoding header and then calls http.Error with | ||
492 | // the provided error and http.StatusInternalServerErrer. Error contents is | ||
493 | // supposed to be uncompressed plain text. However, same as with a plain | ||
494 | // http.Error, any header settings will be void if the header has already been | ||
495 | // sent. The error message will still be written to the writer, but it will | ||
496 | // probably be of limited use. | ||
497 | func httpError(rsp http.ResponseWriter, err error) { | ||
498 | rsp.Header().Del(contentEncodingHeader) | ||
499 | http.Error( | ||
500 | rsp, | ||
501 | "An error has occurred while serving metrics:\n\n"+err.Error(), | ||
502 | http.StatusInternalServerError, | ||
503 | ) | ||
504 | } | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go index 55176d5..9b80979 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go | |||
@@ -16,8 +16,6 @@ package prometheus | |||
16 | import ( | 16 | import ( |
17 | "errors" | 17 | "errors" |
18 | "os" | 18 | "os" |
19 | |||
20 | "github.com/prometheus/procfs" | ||
21 | ) | 19 | ) |
22 | 20 | ||
23 | type processCollector struct { | 21 | type processCollector struct { |
@@ -59,20 +57,9 @@ type ProcessCollectorOpts struct { | |||
59 | // collector for the current process with an empty namespace string and no error | 57 | // collector for the current process with an empty namespace string and no error |
60 | // reporting. | 58 | // reporting. |
61 | // | 59 | // |
62 | // Currently, the collector depends on a Linux-style proc filesystem and | 60 | // The collector only works on operating systems with a Linux-style proc |
63 | // therefore only exports metrics for Linux. | 61 | // filesystem and on Microsoft Windows. On other operating systems, it will not |
64 | // | 62 | // collect any metrics. |
65 | // Note: An older version of this function had the following signature: | ||
66 | // | ||
67 | // NewProcessCollector(pid int, namespace string) Collector | ||
68 | // | ||
69 | // Most commonly, it was called as | ||
70 | // | ||
71 | // NewProcessCollector(os.Getpid(), "") | ||
72 | // | ||
73 | // The following call of the current version is equivalent to the above: | ||
74 | // | ||
75 | // NewProcessCollector(ProcessCollectorOpts{}) | ||
76 | func NewProcessCollector(opts ProcessCollectorOpts) Collector { | 63 | func NewProcessCollector(opts ProcessCollectorOpts) Collector { |
77 | ns := "" | 64 | ns := "" |
78 | if len(opts.Namespace) > 0 { | 65 | if len(opts.Namespace) > 0 { |
@@ -126,7 +113,7 @@ func NewProcessCollector(opts ProcessCollectorOpts) Collector { | |||
126 | } | 113 | } |
127 | 114 | ||
128 | // Set up process metric collection if supported by the runtime. | 115 | // Set up process metric collection if supported by the runtime. |
129 | if _, err := procfs.NewStat(); err == nil { | 116 | if canCollectProcess() { |
130 | c.collectFn = c.processCollect | 117 | c.collectFn = c.processCollect |
131 | } else { | 118 | } else { |
132 | c.collectFn = func(ch chan<- Metric) { | 119 | c.collectFn = func(ch chan<- Metric) { |
@@ -153,46 +140,6 @@ func (c *processCollector) Collect(ch chan<- Metric) { | |||
153 | c.collectFn(ch) | 140 | c.collectFn(ch) |
154 | } | 141 | } |
155 | 142 | ||
156 | func (c *processCollector) processCollect(ch chan<- Metric) { | ||
157 | pid, err := c.pidFn() | ||
158 | if err != nil { | ||
159 | c.reportError(ch, nil, err) | ||
160 | return | ||
161 | } | ||
162 | |||
163 | p, err := procfs.NewProc(pid) | ||
164 | if err != nil { | ||
165 | c.reportError(ch, nil, err) | ||
166 | return | ||
167 | } | ||
168 | |||
169 | if stat, err := p.NewStat(); err == nil { | ||
170 | ch <- MustNewConstMetric(c.cpuTotal, CounterValue, stat.CPUTime()) | ||
171 | ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(stat.VirtualMemory())) | ||
172 | ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory())) | ||
173 | if startTime, err := stat.StartTime(); err == nil { | ||
174 | ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime) | ||
175 | } else { | ||
176 | c.reportError(ch, c.startTime, err) | ||
177 | } | ||
178 | } else { | ||
179 | c.reportError(ch, nil, err) | ||
180 | } | ||
181 | |||
182 | if fds, err := p.FileDescriptorsLen(); err == nil { | ||
183 | ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds)) | ||
184 | } else { | ||
185 | c.reportError(ch, c.openFDs, err) | ||
186 | } | ||
187 | |||
188 | if limits, err := p.NewLimits(); err == nil { | ||
189 | ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles)) | ||
190 | ch <- MustNewConstMetric(c.maxVsize, GaugeValue, float64(limits.AddressSpace)) | ||
191 | } else { | ||
192 | c.reportError(ch, nil, err) | ||
193 | } | ||
194 | } | ||
195 | |||
196 | func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) { | 143 | func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) { |
197 | if !c.reportErrors { | 144 | if !c.reportErrors { |
198 | return | 145 | return |
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go new file mode 100644 index 0000000..3117461 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go | |||
@@ -0,0 +1,65 @@ | |||
1 | // Copyright 2019 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | // +build !windows | ||
15 | |||
16 | package prometheus | ||
17 | |||
18 | import ( | ||
19 | "github.com/prometheus/procfs" | ||
20 | ) | ||
21 | |||
22 | func canCollectProcess() bool { | ||
23 | _, err := procfs.NewDefaultFS() | ||
24 | return err == nil | ||
25 | } | ||
26 | |||
27 | func (c *processCollector) processCollect(ch chan<- Metric) { | ||
28 | pid, err := c.pidFn() | ||
29 | if err != nil { | ||
30 | c.reportError(ch, nil, err) | ||
31 | return | ||
32 | } | ||
33 | |||
34 | p, err := procfs.NewProc(pid) | ||
35 | if err != nil { | ||
36 | c.reportError(ch, nil, err) | ||
37 | return | ||
38 | } | ||
39 | |||
40 | if stat, err := p.Stat(); err == nil { | ||
41 | ch <- MustNewConstMetric(c.cpuTotal, CounterValue, stat.CPUTime()) | ||
42 | ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(stat.VirtualMemory())) | ||
43 | ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory())) | ||
44 | if startTime, err := stat.StartTime(); err == nil { | ||
45 | ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime) | ||
46 | } else { | ||
47 | c.reportError(ch, c.startTime, err) | ||
48 | } | ||
49 | } else { | ||
50 | c.reportError(ch, nil, err) | ||
51 | } | ||
52 | |||
53 | if fds, err := p.FileDescriptorsLen(); err == nil { | ||
54 | ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds)) | ||
55 | } else { | ||
56 | c.reportError(ch, c.openFDs, err) | ||
57 | } | ||
58 | |||
59 | if limits, err := p.Limits(); err == nil { | ||
60 | ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles)) | ||
61 | ch <- MustNewConstMetric(c.maxVsize, GaugeValue, float64(limits.AddressSpace)) | ||
62 | } else { | ||
63 | c.reportError(ch, nil, err) | ||
64 | } | ||
65 | } | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go new file mode 100644 index 0000000..e0b935d --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go | |||
@@ -0,0 +1,112 @@ | |||
1 | // Copyright 2019 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | package prometheus | ||
15 | |||
16 | import ( | ||
17 | "syscall" | ||
18 | "unsafe" | ||
19 | |||
20 | "golang.org/x/sys/windows" | ||
21 | ) | ||
22 | |||
23 | func canCollectProcess() bool { | ||
24 | return true | ||
25 | } | ||
26 | |||
27 | var ( | ||
28 | modpsapi = syscall.NewLazyDLL("psapi.dll") | ||
29 | modkernel32 = syscall.NewLazyDLL("kernel32.dll") | ||
30 | |||
31 | procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo") | ||
32 | procGetProcessHandleCount = modkernel32.NewProc("GetProcessHandleCount") | ||
33 | ) | ||
34 | |||
35 | type processMemoryCounters struct { | ||
36 | // https://docs.microsoft.com/en-us/windows/desktop/api/psapi/ns-psapi-_process_memory_counters_ex | ||
37 | _ uint32 | ||
38 | PageFaultCount uint32 | ||
39 | PeakWorkingSetSize uint64 | ||
40 | WorkingSetSize uint64 | ||
41 | QuotaPeakPagedPoolUsage uint64 | ||
42 | QuotaPagedPoolUsage uint64 | ||
43 | QuotaPeakNonPagedPoolUsage uint64 | ||
44 | QuotaNonPagedPoolUsage uint64 | ||
45 | PagefileUsage uint64 | ||
46 | PeakPagefileUsage uint64 | ||
47 | PrivateUsage uint64 | ||
48 | } | ||
49 | |||
50 | func getProcessMemoryInfo(handle windows.Handle) (processMemoryCounters, error) { | ||
51 | mem := processMemoryCounters{} | ||
52 | r1, _, err := procGetProcessMemoryInfo.Call( | ||
53 | uintptr(handle), | ||
54 | uintptr(unsafe.Pointer(&mem)), | ||
55 | uintptr(unsafe.Sizeof(mem)), | ||
56 | ) | ||
57 | if r1 != 1 { | ||
58 | return mem, err | ||
59 | } else { | ||
60 | return mem, nil | ||
61 | } | ||
62 | } | ||
63 | |||
64 | func getProcessHandleCount(handle windows.Handle) (uint32, error) { | ||
65 | var count uint32 | ||
66 | r1, _, err := procGetProcessHandleCount.Call( | ||
67 | uintptr(handle), | ||
68 | uintptr(unsafe.Pointer(&count)), | ||
69 | ) | ||
70 | if r1 != 1 { | ||
71 | return 0, err | ||
72 | } else { | ||
73 | return count, nil | ||
74 | } | ||
75 | } | ||
76 | |||
77 | func (c *processCollector) processCollect(ch chan<- Metric) { | ||
78 | h, err := windows.GetCurrentProcess() | ||
79 | if err != nil { | ||
80 | c.reportError(ch, nil, err) | ||
81 | return | ||
82 | } | ||
83 | |||
84 | var startTime, exitTime, kernelTime, userTime windows.Filetime | ||
85 | err = windows.GetProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime) | ||
86 | if err != nil { | ||
87 | c.reportError(ch, nil, err) | ||
88 | return | ||
89 | } | ||
90 | ch <- MustNewConstMetric(c.startTime, GaugeValue, float64(startTime.Nanoseconds()/1e9)) | ||
91 | ch <- MustNewConstMetric(c.cpuTotal, CounterValue, fileTimeToSeconds(kernelTime)+fileTimeToSeconds(userTime)) | ||
92 | |||
93 | mem, err := getProcessMemoryInfo(h) | ||
94 | if err != nil { | ||
95 | c.reportError(ch, nil, err) | ||
96 | return | ||
97 | } | ||
98 | ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(mem.PrivateUsage)) | ||
99 | ch <- MustNewConstMetric(c.rss, GaugeValue, float64(mem.WorkingSetSize)) | ||
100 | |||
101 | handles, err := getProcessHandleCount(h) | ||
102 | if err != nil { | ||
103 | c.reportError(ch, nil, err) | ||
104 | return | ||
105 | } | ||
106 | ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(handles)) | ||
107 | ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(16*1024*1024)) // Windows has a hard-coded max limit, not per-process. | ||
108 | } | ||
109 | |||
110 | func fileTimeToSeconds(ft windows.Filetime) float64 { | ||
111 | return float64(uint64(ft.HighDateTime)<<32+uint64(ft.LowDateTime)) / 1e7 | ||
112 | } | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go index 67b56d3..fa53568 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go | |||
@@ -38,7 +38,6 @@ type delegator interface { | |||
38 | type responseWriterDelegator struct { | 38 | type responseWriterDelegator struct { |
39 | http.ResponseWriter | 39 | http.ResponseWriter |
40 | 40 | ||
41 | handler, method string | ||
42 | status int | 41 | status int |
43 | written int64 | 42 | written int64 |
44 | wroteHeader bool | 43 | wroteHeader bool |
@@ -75,8 +74,11 @@ type closeNotifierDelegator struct{ *responseWriterDelegator } | |||
75 | type flusherDelegator struct{ *responseWriterDelegator } | 74 | type flusherDelegator struct{ *responseWriterDelegator } |
76 | type hijackerDelegator struct{ *responseWriterDelegator } | 75 | type hijackerDelegator struct{ *responseWriterDelegator } |
77 | type readerFromDelegator struct{ *responseWriterDelegator } | 76 | type readerFromDelegator struct{ *responseWriterDelegator } |
77 | type pusherDelegator struct{ *responseWriterDelegator } | ||
78 | 78 | ||
79 | func (d closeNotifierDelegator) CloseNotify() <-chan bool { | 79 | func (d closeNotifierDelegator) CloseNotify() <-chan bool { |
80 | //lint:ignore SA1019 http.CloseNotifier is deprecated but we don't want to | ||
81 | //remove support from client_golang yet. | ||
80 | return d.ResponseWriter.(http.CloseNotifier).CloseNotify() | 82 | return d.ResponseWriter.(http.CloseNotifier).CloseNotify() |
81 | } | 83 | } |
82 | func (d flusherDelegator) Flush() { | 84 | func (d flusherDelegator) Flush() { |
@@ -93,6 +95,9 @@ func (d readerFromDelegator) ReadFrom(re io.Reader) (int64, error) { | |||
93 | d.written += n | 95 | d.written += n |
94 | return n, err | 96 | return n, err |
95 | } | 97 | } |
98 | func (d pusherDelegator) Push(target string, opts *http.PushOptions) error { | ||
99 | return d.ResponseWriter.(http.Pusher).Push(target, opts) | ||
100 | } | ||
96 | 101 | ||
97 | var pickDelegator = make([]func(*responseWriterDelegator) delegator, 32) | 102 | var pickDelegator = make([]func(*responseWriterDelegator) delegator, 32) |
98 | 103 | ||
@@ -196,4 +201,157 @@ func init() { | |||
196 | http.CloseNotifier | 201 | http.CloseNotifier |
197 | }{d, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} | 202 | }{d, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} |
198 | } | 203 | } |
204 | pickDelegator[pusher] = func(d *responseWriterDelegator) delegator { // 16 | ||
205 | return pusherDelegator{d} | ||
206 | } | ||
207 | pickDelegator[pusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 17 | ||
208 | return struct { | ||
209 | *responseWriterDelegator | ||
210 | http.Pusher | ||
211 | http.CloseNotifier | ||
212 | }{d, pusherDelegator{d}, closeNotifierDelegator{d}} | ||
213 | } | ||
214 | pickDelegator[pusher+flusher] = func(d *responseWriterDelegator) delegator { // 18 | ||
215 | return struct { | ||
216 | *responseWriterDelegator | ||
217 | http.Pusher | ||
218 | http.Flusher | ||
219 | }{d, pusherDelegator{d}, flusherDelegator{d}} | ||
220 | } | ||
221 | pickDelegator[pusher+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 19 | ||
222 | return struct { | ||
223 | *responseWriterDelegator | ||
224 | http.Pusher | ||
225 | http.Flusher | ||
226 | http.CloseNotifier | ||
227 | }{d, pusherDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} | ||
228 | } | ||
229 | pickDelegator[pusher+hijacker] = func(d *responseWriterDelegator) delegator { // 20 | ||
230 | return struct { | ||
231 | *responseWriterDelegator | ||
232 | http.Pusher | ||
233 | http.Hijacker | ||
234 | }{d, pusherDelegator{d}, hijackerDelegator{d}} | ||
235 | } | ||
236 | pickDelegator[pusher+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 21 | ||
237 | return struct { | ||
238 | *responseWriterDelegator | ||
239 | http.Pusher | ||
240 | http.Hijacker | ||
241 | http.CloseNotifier | ||
242 | }{d, pusherDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}} | ||
243 | } | ||
244 | pickDelegator[pusher+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 22 | ||
245 | return struct { | ||
246 | *responseWriterDelegator | ||
247 | http.Pusher | ||
248 | http.Hijacker | ||
249 | http.Flusher | ||
250 | }{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}} | ||
251 | } | ||
252 | pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { //23 | ||
253 | return struct { | ||
254 | *responseWriterDelegator | ||
255 | http.Pusher | ||
256 | http.Hijacker | ||
257 | http.Flusher | ||
258 | http.CloseNotifier | ||
259 | }{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} | ||
260 | } | ||
261 | pickDelegator[pusher+readerFrom] = func(d *responseWriterDelegator) delegator { // 24 | ||
262 | return struct { | ||
263 | *responseWriterDelegator | ||
264 | http.Pusher | ||
265 | io.ReaderFrom | ||
266 | }{d, pusherDelegator{d}, readerFromDelegator{d}} | ||
267 | } | ||
268 | pickDelegator[pusher+readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 25 | ||
269 | return struct { | ||
270 | *responseWriterDelegator | ||
271 | http.Pusher | ||
272 | io.ReaderFrom | ||
273 | http.CloseNotifier | ||
274 | }{d, pusherDelegator{d}, readerFromDelegator{d}, closeNotifierDelegator{d}} | ||
275 | } | ||
276 | pickDelegator[pusher+readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 26 | ||
277 | return struct { | ||
278 | *responseWriterDelegator | ||
279 | http.Pusher | ||
280 | io.ReaderFrom | ||
281 | http.Flusher | ||
282 | }{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}} | ||
283 | } | ||
284 | pickDelegator[pusher+readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 27 | ||
285 | return struct { | ||
286 | *responseWriterDelegator | ||
287 | http.Pusher | ||
288 | io.ReaderFrom | ||
289 | http.Flusher | ||
290 | http.CloseNotifier | ||
291 | }{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} | ||
292 | } | ||
293 | pickDelegator[pusher+readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 28 | ||
294 | return struct { | ||
295 | *responseWriterDelegator | ||
296 | http.Pusher | ||
297 | io.ReaderFrom | ||
298 | http.Hijacker | ||
299 | }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}} | ||
300 | } | ||
301 | pickDelegator[pusher+readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 29 | ||
302 | return struct { | ||
303 | *responseWriterDelegator | ||
304 | http.Pusher | ||
305 | io.ReaderFrom | ||
306 | http.Hijacker | ||
307 | http.CloseNotifier | ||
308 | }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}} | ||
309 | } | ||
310 | pickDelegator[pusher+readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 30 | ||
311 | return struct { | ||
312 | *responseWriterDelegator | ||
313 | http.Pusher | ||
314 | io.ReaderFrom | ||
315 | http.Hijacker | ||
316 | http.Flusher | ||
317 | }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}} | ||
318 | } | ||
319 | pickDelegator[pusher+readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 31 | ||
320 | return struct { | ||
321 | *responseWriterDelegator | ||
322 | http.Pusher | ||
323 | io.ReaderFrom | ||
324 | http.Hijacker | ||
325 | http.Flusher | ||
326 | http.CloseNotifier | ||
327 | }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} | ||
328 | } | ||
329 | } | ||
330 | |||
331 | func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator { | ||
332 | d := &responseWriterDelegator{ | ||
333 | ResponseWriter: w, | ||
334 | observeWriteHeader: observeWriteHeaderFunc, | ||
335 | } | ||
336 | |||
337 | id := 0 | ||
338 | //lint:ignore SA1019 http.CloseNotifier is deprecated but we don't want to | ||
339 | //remove support from client_golang yet. | ||
340 | if _, ok := w.(http.CloseNotifier); ok { | ||
341 | id += closeNotifier | ||
342 | } | ||
343 | if _, ok := w.(http.Flusher); ok { | ||
344 | id += flusher | ||
345 | } | ||
346 | if _, ok := w.(http.Hijacker); ok { | ||
347 | id += hijacker | ||
348 | } | ||
349 | if _, ok := w.(io.ReaderFrom); ok { | ||
350 | id += readerFrom | ||
351 | } | ||
352 | if _, ok := w.(http.Pusher); ok { | ||
353 | id += pusher | ||
354 | } | ||
355 | |||
356 | return pickDelegator[id](d) | ||
199 | } | 357 | } |
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go deleted file mode 100644 index 31a7069..0000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go +++ /dev/null | |||
@@ -1,181 +0,0 @@ | |||
1 | // Copyright 2017 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | // +build go1.8 | ||
15 | |||
16 | package promhttp | ||
17 | |||
18 | import ( | ||
19 | "io" | ||
20 | "net/http" | ||
21 | ) | ||
22 | |||
23 | type pusherDelegator struct{ *responseWriterDelegator } | ||
24 | |||
25 | func (d pusherDelegator) Push(target string, opts *http.PushOptions) error { | ||
26 | return d.ResponseWriter.(http.Pusher).Push(target, opts) | ||
27 | } | ||
28 | |||
29 | func init() { | ||
30 | pickDelegator[pusher] = func(d *responseWriterDelegator) delegator { // 16 | ||
31 | return pusherDelegator{d} | ||
32 | } | ||
33 | pickDelegator[pusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 17 | ||
34 | return struct { | ||
35 | *responseWriterDelegator | ||
36 | http.Pusher | ||
37 | http.CloseNotifier | ||
38 | }{d, pusherDelegator{d}, closeNotifierDelegator{d}} | ||
39 | } | ||
40 | pickDelegator[pusher+flusher] = func(d *responseWriterDelegator) delegator { // 18 | ||
41 | return struct { | ||
42 | *responseWriterDelegator | ||
43 | http.Pusher | ||
44 | http.Flusher | ||
45 | }{d, pusherDelegator{d}, flusherDelegator{d}} | ||
46 | } | ||
47 | pickDelegator[pusher+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 19 | ||
48 | return struct { | ||
49 | *responseWriterDelegator | ||
50 | http.Pusher | ||
51 | http.Flusher | ||
52 | http.CloseNotifier | ||
53 | }{d, pusherDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} | ||
54 | } | ||
55 | pickDelegator[pusher+hijacker] = func(d *responseWriterDelegator) delegator { // 20 | ||
56 | return struct { | ||
57 | *responseWriterDelegator | ||
58 | http.Pusher | ||
59 | http.Hijacker | ||
60 | }{d, pusherDelegator{d}, hijackerDelegator{d}} | ||
61 | } | ||
62 | pickDelegator[pusher+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 21 | ||
63 | return struct { | ||
64 | *responseWriterDelegator | ||
65 | http.Pusher | ||
66 | http.Hijacker | ||
67 | http.CloseNotifier | ||
68 | }{d, pusherDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}} | ||
69 | } | ||
70 | pickDelegator[pusher+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 22 | ||
71 | return struct { | ||
72 | *responseWriterDelegator | ||
73 | http.Pusher | ||
74 | http.Hijacker | ||
75 | http.Flusher | ||
76 | }{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}} | ||
77 | } | ||
78 | pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { //23 | ||
79 | return struct { | ||
80 | *responseWriterDelegator | ||
81 | http.Pusher | ||
82 | http.Hijacker | ||
83 | http.Flusher | ||
84 | http.CloseNotifier | ||
85 | }{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} | ||
86 | } | ||
87 | pickDelegator[pusher+readerFrom] = func(d *responseWriterDelegator) delegator { // 24 | ||
88 | return struct { | ||
89 | *responseWriterDelegator | ||
90 | http.Pusher | ||
91 | io.ReaderFrom | ||
92 | }{d, pusherDelegator{d}, readerFromDelegator{d}} | ||
93 | } | ||
94 | pickDelegator[pusher+readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 25 | ||
95 | return struct { | ||
96 | *responseWriterDelegator | ||
97 | http.Pusher | ||
98 | io.ReaderFrom | ||
99 | http.CloseNotifier | ||
100 | }{d, pusherDelegator{d}, readerFromDelegator{d}, closeNotifierDelegator{d}} | ||
101 | } | ||
102 | pickDelegator[pusher+readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 26 | ||
103 | return struct { | ||
104 | *responseWriterDelegator | ||
105 | http.Pusher | ||
106 | io.ReaderFrom | ||
107 | http.Flusher | ||
108 | }{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}} | ||
109 | } | ||
110 | pickDelegator[pusher+readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 27 | ||
111 | return struct { | ||
112 | *responseWriterDelegator | ||
113 | http.Pusher | ||
114 | io.ReaderFrom | ||
115 | http.Flusher | ||
116 | http.CloseNotifier | ||
117 | }{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} | ||
118 | } | ||
119 | pickDelegator[pusher+readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 28 | ||
120 | return struct { | ||
121 | *responseWriterDelegator | ||
122 | http.Pusher | ||
123 | io.ReaderFrom | ||
124 | http.Hijacker | ||
125 | }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}} | ||
126 | } | ||
127 | pickDelegator[pusher+readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 29 | ||
128 | return struct { | ||
129 | *responseWriterDelegator | ||
130 | http.Pusher | ||
131 | io.ReaderFrom | ||
132 | http.Hijacker | ||
133 | http.CloseNotifier | ||
134 | }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}} | ||
135 | } | ||
136 | pickDelegator[pusher+readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 30 | ||
137 | return struct { | ||
138 | *responseWriterDelegator | ||
139 | http.Pusher | ||
140 | io.ReaderFrom | ||
141 | http.Hijacker | ||
142 | http.Flusher | ||
143 | }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}} | ||
144 | } | ||
145 | pickDelegator[pusher+readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 31 | ||
146 | return struct { | ||
147 | *responseWriterDelegator | ||
148 | http.Pusher | ||
149 | io.ReaderFrom | ||
150 | http.Hijacker | ||
151 | http.Flusher | ||
152 | http.CloseNotifier | ||
153 | }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} | ||
154 | } | ||
155 | } | ||
156 | |||
157 | func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator { | ||
158 | d := &responseWriterDelegator{ | ||
159 | ResponseWriter: w, | ||
160 | observeWriteHeader: observeWriteHeaderFunc, | ||
161 | } | ||
162 | |||
163 | id := 0 | ||
164 | if _, ok := w.(http.CloseNotifier); ok { | ||
165 | id += closeNotifier | ||
166 | } | ||
167 | if _, ok := w.(http.Flusher); ok { | ||
168 | id += flusher | ||
169 | } | ||
170 | if _, ok := w.(http.Hijacker); ok { | ||
171 | id += hijacker | ||
172 | } | ||
173 | if _, ok := w.(io.ReaderFrom); ok { | ||
174 | id += readerFrom | ||
175 | } | ||
176 | if _, ok := w.(http.Pusher); ok { | ||
177 | id += pusher | ||
178 | } | ||
179 | |||
180 | return pickDelegator[id](d) | ||
181 | } | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go deleted file mode 100644 index 8bb9b8b..0000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | // Copyright 2017 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | // +build !go1.8 | ||
15 | |||
16 | package promhttp | ||
17 | |||
18 | import ( | ||
19 | "io" | ||
20 | "net/http" | ||
21 | ) | ||
22 | |||
23 | func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator { | ||
24 | d := &responseWriterDelegator{ | ||
25 | ResponseWriter: w, | ||
26 | observeWriteHeader: observeWriteHeaderFunc, | ||
27 | } | ||
28 | |||
29 | id := 0 | ||
30 | if _, ok := w.(http.CloseNotifier); ok { | ||
31 | id += closeNotifier | ||
32 | } | ||
33 | if _, ok := w.(http.Flusher); ok { | ||
34 | id += flusher | ||
35 | } | ||
36 | if _, ok := w.(http.Hijacker); ok { | ||
37 | id += hijacker | ||
38 | } | ||
39 | if _, ok := w.(io.ReaderFrom); ok { | ||
40 | id += readerFrom | ||
41 | } | ||
42 | |||
43 | return pickDelegator[id](d) | ||
44 | } | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go index 668eb6b..cea5a90 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go | |||
@@ -47,7 +47,6 @@ import ( | |||
47 | 47 | ||
48 | const ( | 48 | const ( |
49 | contentTypeHeader = "Content-Type" | 49 | contentTypeHeader = "Content-Type" |
50 | contentLengthHeader = "Content-Length" | ||
51 | contentEncodingHeader = "Content-Encoding" | 50 | contentEncodingHeader = "Content-Encoding" |
52 | acceptEncodingHeader = "Accept-Encoding" | 51 | acceptEncodingHeader = "Accept-Encoding" |
53 | ) | 52 | ) |
@@ -85,10 +84,32 @@ func Handler() http.Handler { | |||
85 | // instrumentation. Use the InstrumentMetricHandler function to apply the same | 84 | // instrumentation. Use the InstrumentMetricHandler function to apply the same |
86 | // kind of instrumentation as it is used by the Handler function. | 85 | // kind of instrumentation as it is used by the Handler function. |
87 | func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { | 86 | func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { |
88 | var inFlightSem chan struct{} | 87 | var ( |
88 | inFlightSem chan struct{} | ||
89 | errCnt = prometheus.NewCounterVec( | ||
90 | prometheus.CounterOpts{ | ||
91 | Name: "promhttp_metric_handler_errors_total", | ||
92 | Help: "Total number of internal errors encountered by the promhttp metric handler.", | ||
93 | }, | ||
94 | []string{"cause"}, | ||
95 | ) | ||
96 | ) | ||
97 | |||
89 | if opts.MaxRequestsInFlight > 0 { | 98 | if opts.MaxRequestsInFlight > 0 { |
90 | inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight) | 99 | inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight) |
91 | } | 100 | } |
101 | if opts.Registry != nil { | ||
102 | // Initialize all possibilites that can occur below. | ||
103 | errCnt.WithLabelValues("gathering") | ||
104 | errCnt.WithLabelValues("encoding") | ||
105 | if err := opts.Registry.Register(errCnt); err != nil { | ||
106 | if are, ok := err.(prometheus.AlreadyRegisteredError); ok { | ||
107 | errCnt = are.ExistingCollector.(*prometheus.CounterVec) | ||
108 | } else { | ||
109 | panic(err) | ||
110 | } | ||
111 | } | ||
112 | } | ||
92 | 113 | ||
93 | h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) { | 114 | h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) { |
94 | if inFlightSem != nil { | 115 | if inFlightSem != nil { |
@@ -107,6 +128,7 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { | |||
107 | if opts.ErrorLog != nil { | 128 | if opts.ErrorLog != nil { |
108 | opts.ErrorLog.Println("error gathering metrics:", err) | 129 | opts.ErrorLog.Println("error gathering metrics:", err) |
109 | } | 130 | } |
131 | errCnt.WithLabelValues("gathering").Inc() | ||
110 | switch opts.ErrorHandling { | 132 | switch opts.ErrorHandling { |
111 | case PanicOnError: | 133 | case PanicOnError: |
112 | panic(err) | 134 | panic(err) |
@@ -147,6 +169,7 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { | |||
147 | if opts.ErrorLog != nil { | 169 | if opts.ErrorLog != nil { |
148 | opts.ErrorLog.Println("error encoding and sending metric family:", err) | 170 | opts.ErrorLog.Println("error encoding and sending metric family:", err) |
149 | } | 171 | } |
172 | errCnt.WithLabelValues("encoding").Inc() | ||
150 | switch opts.ErrorHandling { | 173 | switch opts.ErrorHandling { |
151 | case PanicOnError: | 174 | case PanicOnError: |
152 | panic(err) | 175 | panic(err) |
@@ -237,9 +260,12 @@ const ( | |||
237 | // Ignore errors and try to serve as many metrics as possible. However, | 260 | // Ignore errors and try to serve as many metrics as possible. However, |
238 | // if no metrics can be served, serve an HTTP status code 500 and the | 261 | // if no metrics can be served, serve an HTTP status code 500 and the |
239 | // last error message in the body. Only use this in deliberate "best | 262 | // last error message in the body. Only use this in deliberate "best |
240 | // effort" metrics collection scenarios. It is recommended to at least | 263 | // effort" metrics collection scenarios. In this case, it is highly |
241 | // log errors (by providing an ErrorLog in HandlerOpts) to not mask | 264 | // recommended to provide other means of detecting errors: By setting an |
242 | // errors completely. | 265 | // ErrorLog in HandlerOpts, the errors are logged. By providing a |
266 | // Registry in HandlerOpts, the exposed metrics include an error counter | ||
267 | // "promhttp_metric_handler_errors_total", which can be used for | ||
268 | // alerts. | ||
243 | ContinueOnError | 269 | ContinueOnError |
244 | // Panic upon the first error encountered (useful for "crash only" apps). | 270 | // Panic upon the first error encountered (useful for "crash only" apps). |
245 | PanicOnError | 271 | PanicOnError |
@@ -262,6 +288,18 @@ type HandlerOpts struct { | |||
262 | // logged regardless of the configured ErrorHandling provided ErrorLog | 288 | // logged regardless of the configured ErrorHandling provided ErrorLog |
263 | // is not nil. | 289 | // is not nil. |
264 | ErrorHandling HandlerErrorHandling | 290 | ErrorHandling HandlerErrorHandling |
291 | // If Registry is not nil, it is used to register a metric | ||
292 | // "promhttp_metric_handler_errors_total", partitioned by "cause". A | ||
293 | // failed registration causes a panic. Note that this error counter is | ||
294 | // different from the instrumentation you get from the various | ||
295 | // InstrumentHandler... helpers. It counts errors that don't necessarily | ||
296 | // result in a non-2xx HTTP status code. There are two typical cases: | ||
297 | // (1) Encoding errors that only happen after streaming of the HTTP body | ||
298 | // has already started (and the status code 200 has been sent). This | ||
299 | // should only happen with custom collectors. (2) Collection errors with | ||
300 | // no effect on the HTTP status code because ErrorHandling is set to | ||
301 | // ContinueOnError. | ||
302 | Registry prometheus.Registerer | ||
265 | // If DisableCompression is true, the handler will never compress the | 303 | // If DisableCompression is true, the handler will never compress the |
266 | // response, even if requested by the client. | 304 | // response, even if requested by the client. |
267 | DisableCompression bool | 305 | DisableCompression bool |
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go index 86fd564..83c49b6 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go | |||
@@ -14,7 +14,9 @@ | |||
14 | package promhttp | 14 | package promhttp |
15 | 15 | ||
16 | import ( | 16 | import ( |
17 | "crypto/tls" | ||
17 | "net/http" | 18 | "net/http" |
19 | "net/http/httptrace" | ||
18 | "time" | 20 | "time" |
19 | 21 | ||
20 | "github.com/prometheus/client_golang/prometheus" | 22 | "github.com/prometheus/client_golang/prometheus" |
@@ -95,3 +97,123 @@ func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundT | |||
95 | return resp, err | 97 | return resp, err |
96 | }) | 98 | }) |
97 | } | 99 | } |
100 | |||
101 | // InstrumentTrace is used to offer flexibility in instrumenting the available | ||
102 | // httptrace.ClientTrace hook functions. Each function is passed a float64 | ||
103 | // representing the time in seconds since the start of the http request. A user | ||
104 | // may choose to use separately buckets Histograms, or implement custom | ||
105 | // instance labels on a per function basis. | ||
106 | type InstrumentTrace struct { | ||
107 | GotConn func(float64) | ||
108 | PutIdleConn func(float64) | ||
109 | GotFirstResponseByte func(float64) | ||
110 | Got100Continue func(float64) | ||
111 | DNSStart func(float64) | ||
112 | DNSDone func(float64) | ||
113 | ConnectStart func(float64) | ||
114 | ConnectDone func(float64) | ||
115 | TLSHandshakeStart func(float64) | ||
116 | TLSHandshakeDone func(float64) | ||
117 | WroteHeaders func(float64) | ||
118 | Wait100Continue func(float64) | ||
119 | WroteRequest func(float64) | ||
120 | } | ||
121 | |||
122 | // InstrumentRoundTripperTrace is a middleware that wraps the provided | ||
123 | // RoundTripper and reports times to hook functions provided in the | ||
124 | // InstrumentTrace struct. Hook functions that are not present in the provided | ||
125 | // InstrumentTrace struct are ignored. Times reported to the hook functions are | ||
126 | // time since the start of the request. Only with Go1.9+, those times are | ||
127 | // guaranteed to never be negative. (Earlier Go versions are not using a | ||
128 | // monotonic clock.) Note that partitioning of Histograms is expensive and | ||
129 | // should be used judiciously. | ||
130 | // | ||
131 | // For hook functions that receive an error as an argument, no observations are | ||
132 | // made in the event of a non-nil error value. | ||
133 | // | ||
134 | // See the example for ExampleInstrumentRoundTripperDuration for example usage. | ||
135 | func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) RoundTripperFunc { | ||
136 | return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { | ||
137 | start := time.Now() | ||
138 | |||
139 | trace := &httptrace.ClientTrace{ | ||
140 | GotConn: func(_ httptrace.GotConnInfo) { | ||
141 | if it.GotConn != nil { | ||
142 | it.GotConn(time.Since(start).Seconds()) | ||
143 | } | ||
144 | }, | ||
145 | PutIdleConn: func(err error) { | ||
146 | if err != nil { | ||
147 | return | ||
148 | } | ||
149 | if it.PutIdleConn != nil { | ||
150 | it.PutIdleConn(time.Since(start).Seconds()) | ||
151 | } | ||
152 | }, | ||
153 | DNSStart: func(_ httptrace.DNSStartInfo) { | ||
154 | if it.DNSStart != nil { | ||
155 | it.DNSStart(time.Since(start).Seconds()) | ||
156 | } | ||
157 | }, | ||
158 | DNSDone: func(_ httptrace.DNSDoneInfo) { | ||
159 | if it.DNSDone != nil { | ||
160 | it.DNSDone(time.Since(start).Seconds()) | ||
161 | } | ||
162 | }, | ||
163 | ConnectStart: func(_, _ string) { | ||
164 | if it.ConnectStart != nil { | ||
165 | it.ConnectStart(time.Since(start).Seconds()) | ||
166 | } | ||
167 | }, | ||
168 | ConnectDone: func(_, _ string, err error) { | ||
169 | if err != nil { | ||
170 | return | ||
171 | } | ||
172 | if it.ConnectDone != nil { | ||
173 | it.ConnectDone(time.Since(start).Seconds()) | ||
174 | } | ||
175 | }, | ||
176 | GotFirstResponseByte: func() { | ||
177 | if it.GotFirstResponseByte != nil { | ||
178 | it.GotFirstResponseByte(time.Since(start).Seconds()) | ||
179 | } | ||
180 | }, | ||
181 | Got100Continue: func() { | ||
182 | if it.Got100Continue != nil { | ||
183 | it.Got100Continue(time.Since(start).Seconds()) | ||
184 | } | ||
185 | }, | ||
186 | TLSHandshakeStart: func() { | ||
187 | if it.TLSHandshakeStart != nil { | ||
188 | it.TLSHandshakeStart(time.Since(start).Seconds()) | ||
189 | } | ||
190 | }, | ||
191 | TLSHandshakeDone: func(_ tls.ConnectionState, err error) { | ||
192 | if err != nil { | ||
193 | return | ||
194 | } | ||
195 | if it.TLSHandshakeDone != nil { | ||
196 | it.TLSHandshakeDone(time.Since(start).Seconds()) | ||
197 | } | ||
198 | }, | ||
199 | WroteHeaders: func() { | ||
200 | if it.WroteHeaders != nil { | ||
201 | it.WroteHeaders(time.Since(start).Seconds()) | ||
202 | } | ||
203 | }, | ||
204 | Wait100Continue: func() { | ||
205 | if it.Wait100Continue != nil { | ||
206 | it.Wait100Continue(time.Since(start).Seconds()) | ||
207 | } | ||
208 | }, | ||
209 | WroteRequest: func(_ httptrace.WroteRequestInfo) { | ||
210 | if it.WroteRequest != nil { | ||
211 | it.WroteRequest(time.Since(start).Seconds()) | ||
212 | } | ||
213 | }, | ||
214 | } | ||
215 | r = r.WithContext(httptrace.WithClientTrace(r.Context(), trace)) | ||
216 | |||
217 | return next.RoundTrip(r) | ||
218 | }) | ||
219 | } | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go deleted file mode 100644 index a034d1e..0000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go +++ /dev/null | |||
@@ -1,144 +0,0 @@ | |||
1 | // Copyright 2017 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | // +build go1.8 | ||
15 | |||
16 | package promhttp | ||
17 | |||
18 | import ( | ||
19 | "context" | ||
20 | "crypto/tls" | ||
21 | "net/http" | ||
22 | "net/http/httptrace" | ||
23 | "time" | ||
24 | ) | ||
25 | |||
26 | // InstrumentTrace is used to offer flexibility in instrumenting the available | ||
27 | // httptrace.ClientTrace hook functions. Each function is passed a float64 | ||
28 | // representing the time in seconds since the start of the http request. A user | ||
29 | // may choose to use separately buckets Histograms, or implement custom | ||
30 | // instance labels on a per function basis. | ||
31 | type InstrumentTrace struct { | ||
32 | GotConn func(float64) | ||
33 | PutIdleConn func(float64) | ||
34 | GotFirstResponseByte func(float64) | ||
35 | Got100Continue func(float64) | ||
36 | DNSStart func(float64) | ||
37 | DNSDone func(float64) | ||
38 | ConnectStart func(float64) | ||
39 | ConnectDone func(float64) | ||
40 | TLSHandshakeStart func(float64) | ||
41 | TLSHandshakeDone func(float64) | ||
42 | WroteHeaders func(float64) | ||
43 | Wait100Continue func(float64) | ||
44 | WroteRequest func(float64) | ||
45 | } | ||
46 | |||
47 | // InstrumentRoundTripperTrace is a middleware that wraps the provided | ||
48 | // RoundTripper and reports times to hook functions provided in the | ||
49 | // InstrumentTrace struct. Hook functions that are not present in the provided | ||
50 | // InstrumentTrace struct are ignored. Times reported to the hook functions are | ||
51 | // time since the start of the request. Only with Go1.9+, those times are | ||
52 | // guaranteed to never be negative. (Earlier Go versions are not using a | ||
53 | // monotonic clock.) Note that partitioning of Histograms is expensive and | ||
54 | // should be used judiciously. | ||
55 | // | ||
56 | // For hook functions that receive an error as an argument, no observations are | ||
57 | // made in the event of a non-nil error value. | ||
58 | // | ||
59 | // See the example for ExampleInstrumentRoundTripperDuration for example usage. | ||
60 | func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) RoundTripperFunc { | ||
61 | return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { | ||
62 | start := time.Now() | ||
63 | |||
64 | trace := &httptrace.ClientTrace{ | ||
65 | GotConn: func(_ httptrace.GotConnInfo) { | ||
66 | if it.GotConn != nil { | ||
67 | it.GotConn(time.Since(start).Seconds()) | ||
68 | } | ||
69 | }, | ||
70 | PutIdleConn: func(err error) { | ||
71 | if err != nil { | ||
72 | return | ||
73 | } | ||
74 | if it.PutIdleConn != nil { | ||
75 | it.PutIdleConn(time.Since(start).Seconds()) | ||
76 | } | ||
77 | }, | ||
78 | DNSStart: func(_ httptrace.DNSStartInfo) { | ||
79 | if it.DNSStart != nil { | ||
80 | it.DNSStart(time.Since(start).Seconds()) | ||
81 | } | ||
82 | }, | ||
83 | DNSDone: func(_ httptrace.DNSDoneInfo) { | ||
84 | if it.DNSDone != nil { | ||
85 | it.DNSDone(time.Since(start).Seconds()) | ||
86 | } | ||
87 | }, | ||
88 | ConnectStart: func(_, _ string) { | ||
89 | if it.ConnectStart != nil { | ||
90 | it.ConnectStart(time.Since(start).Seconds()) | ||
91 | } | ||
92 | }, | ||
93 | ConnectDone: func(_, _ string, err error) { | ||
94 | if err != nil { | ||
95 | return | ||
96 | } | ||
97 | if it.ConnectDone != nil { | ||
98 | it.ConnectDone(time.Since(start).Seconds()) | ||
99 | } | ||
100 | }, | ||
101 | GotFirstResponseByte: func() { | ||
102 | if it.GotFirstResponseByte != nil { | ||
103 | it.GotFirstResponseByte(time.Since(start).Seconds()) | ||
104 | } | ||
105 | }, | ||
106 | Got100Continue: func() { | ||
107 | if it.Got100Continue != nil { | ||
108 | it.Got100Continue(time.Since(start).Seconds()) | ||
109 | } | ||
110 | }, | ||
111 | TLSHandshakeStart: func() { | ||
112 | if it.TLSHandshakeStart != nil { | ||
113 | it.TLSHandshakeStart(time.Since(start).Seconds()) | ||
114 | } | ||
115 | }, | ||
116 | TLSHandshakeDone: func(_ tls.ConnectionState, err error) { | ||
117 | if err != nil { | ||
118 | return | ||
119 | } | ||
120 | if it.TLSHandshakeDone != nil { | ||
121 | it.TLSHandshakeDone(time.Since(start).Seconds()) | ||
122 | } | ||
123 | }, | ||
124 | WroteHeaders: func() { | ||
125 | if it.WroteHeaders != nil { | ||
126 | it.WroteHeaders(time.Since(start).Seconds()) | ||
127 | } | ||
128 | }, | ||
129 | Wait100Continue: func() { | ||
130 | if it.Wait100Continue != nil { | ||
131 | it.Wait100Continue(time.Since(start).Seconds()) | ||
132 | } | ||
133 | }, | ||
134 | WroteRequest: func(_ httptrace.WroteRequestInfo) { | ||
135 | if it.WroteRequest != nil { | ||
136 | it.WroteRequest(time.Since(start).Seconds()) | ||
137 | } | ||
138 | }, | ||
139 | } | ||
140 | r = r.WithContext(httptrace.WithClientTrace(context.Background(), trace)) | ||
141 | |||
142 | return next.RoundTrip(r) | ||
143 | }) | ||
144 | } | ||
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry.go b/vendor/github.com/prometheus/client_golang/prometheus/registry.go index b5e70b9..6c32516 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/registry.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/registry.go | |||
@@ -325,9 +325,17 @@ func (r *Registry) Register(c Collector) error { | |||
325 | return nil | 325 | return nil |
326 | } | 326 | } |
327 | if existing, exists := r.collectorsByID[collectorID]; exists { | 327 | if existing, exists := r.collectorsByID[collectorID]; exists { |
328 | return AlreadyRegisteredError{ | 328 | switch e := existing.(type) { |
329 | ExistingCollector: existing, | 329 | case *wrappingCollector: |
330 | NewCollector: c, | 330 | return AlreadyRegisteredError{ |
331 | ExistingCollector: e.unwrapRecursively(), | ||
332 | NewCollector: c, | ||
333 | } | ||
334 | default: | ||
335 | return AlreadyRegisteredError{ | ||
336 | ExistingCollector: e, | ||
337 | NewCollector: c, | ||
338 | } | ||
331 | } | 339 | } |
332 | } | 340 | } |
333 | // If the collectorID is new, but at least one of the descs existed | 341 | // If the collectorID is new, but at least one of the descs existed |
@@ -680,7 +688,7 @@ func processMetric( | |||
680 | // Gatherers is a slice of Gatherer instances that implements the Gatherer | 688 | // Gatherers is a slice of Gatherer instances that implements the Gatherer |
681 | // interface itself. Its Gather method calls Gather on all Gatherers in the | 689 | // interface itself. Its Gather method calls Gather on all Gatherers in the |
682 | // slice in order and returns the merged results. Errors returned from the | 690 | // slice in order and returns the merged results. Errors returned from the |
683 | // Gather calles are all returned in a flattened MultiError. Duplicate and | 691 | // Gather calls are all returned in a flattened MultiError. Duplicate and |
684 | // inconsistent Metrics are skipped (first occurrence in slice order wins) and | 692 | // inconsistent Metrics are skipped (first occurrence in slice order wins) and |
685 | // reported in the returned error. | 693 | // reported in the returned error. |
686 | // | 694 | // |
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go index 2980614..c970fde 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/summary.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/summary.go | |||
@@ -16,8 +16,10 @@ package prometheus | |||
16 | import ( | 16 | import ( |
17 | "fmt" | 17 | "fmt" |
18 | "math" | 18 | "math" |
19 | "runtime" | ||
19 | "sort" | 20 | "sort" |
20 | "sync" | 21 | "sync" |
22 | "sync/atomic" | ||
21 | "time" | 23 | "time" |
22 | 24 | ||
23 | "github.com/beorn7/perks/quantile" | 25 | "github.com/beorn7/perks/quantile" |
@@ -37,7 +39,7 @@ const quantileLabel = "quantile" | |||
37 | // A typical use-case is the observation of request latencies. By default, a | 39 | // A typical use-case is the observation of request latencies. By default, a |
38 | // Summary provides the median, the 90th and the 99th percentile of the latency | 40 | // Summary provides the median, the 90th and the 99th percentile of the latency |
39 | // as rank estimations. However, the default behavior will change in the | 41 | // as rank estimations. However, the default behavior will change in the |
40 | // upcoming v0.10 of the library. There will be no rank estimations at all by | 42 | // upcoming v1.0.0 of the library. There will be no rank estimations at all by |
41 | // default. For a sane transition, it is recommended to set the desired rank | 43 | // default. For a sane transition, it is recommended to set the desired rank |
42 | // estimations explicitly. | 44 | // estimations explicitly. |
43 | // | 45 | // |
@@ -56,16 +58,8 @@ type Summary interface { | |||
56 | Observe(float64) | 58 | Observe(float64) |
57 | } | 59 | } |
58 | 60 | ||
59 | // DefObjectives are the default Summary quantile values. | 61 | var errQuantileLabelNotAllowed = fmt.Errorf( |
60 | // | 62 | "%q is not allowed as label name in summaries", quantileLabel, |
61 | // Deprecated: DefObjectives will not be used as the default objectives in | ||
62 | // v0.10 of the library. The default Summary will have no quantiles then. | ||
63 | var ( | ||
64 | DefObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001} | ||
65 | |||
66 | errQuantileLabelNotAllowed = fmt.Errorf( | ||
67 | "%q is not allowed as label name in summaries", quantileLabel, | ||
68 | ) | ||
69 | ) | 63 | ) |
70 | 64 | ||
71 | // Default values for SummaryOpts. | 65 | // Default values for SummaryOpts. |
@@ -84,7 +78,7 @@ const ( | |||
84 | // mandatory to set Name to a non-empty string. While all other fields are | 78 | // mandatory to set Name to a non-empty string. While all other fields are |
85 | // optional and can safely be left at their zero value, it is recommended to set | 79 | // optional and can safely be left at their zero value, it is recommended to set |
86 | // a help string and to explicitly set the Objectives field to the desired value | 80 | // a help string and to explicitly set the Objectives field to the desired value |
87 | // as the default value will change in the upcoming v0.10 of the library. | 81 | // as the default value will change in the upcoming v1.0.0 of the library. |
88 | type SummaryOpts struct { | 82 | type SummaryOpts struct { |
89 | // Namespace, Subsystem, and Name are components of the fully-qualified | 83 | // Namespace, Subsystem, and Name are components of the fully-qualified |
90 | // name of the Summary (created by joining these components with | 84 | // name of the Summary (created by joining these components with |
@@ -121,13 +115,8 @@ type SummaryOpts struct { | |||
121 | // Objectives defines the quantile rank estimates with their respective | 115 | // Objectives defines the quantile rank estimates with their respective |
122 | // absolute error. If Objectives[q] = e, then the value reported for q | 116 | // absolute error. If Objectives[q] = e, then the value reported for q |
123 | // will be the φ-quantile value for some φ between q-e and q+e. The | 117 | // will be the φ-quantile value for some φ between q-e and q+e. The |
124 | // default value is DefObjectives. It is used if Objectives is left at | 118 | // default value is an empty map, resulting in a summary without |
125 | // its zero value (i.e. nil). To create a Summary without Objectives, | 119 | // quantiles. |
126 | // set it to an empty map (i.e. map[float64]float64{}). | ||
127 | // | ||
128 | // Deprecated: Note that the current value of DefObjectives is | ||
129 | // deprecated. It will be replaced by an empty map in v0.10 of the | ||
130 | // library. Please explicitly set Objectives to the desired value. | ||
131 | Objectives map[float64]float64 | 120 | Objectives map[float64]float64 |
132 | 121 | ||
133 | // MaxAge defines the duration for which an observation stays relevant | 122 | // MaxAge defines the duration for which an observation stays relevant |
@@ -151,7 +140,7 @@ type SummaryOpts struct { | |||
151 | BufCap uint32 | 140 | BufCap uint32 |
152 | } | 141 | } |
153 | 142 | ||
154 | // Great fuck-up with the sliding-window decay algorithm... The Merge method of | 143 | // Problem with the sliding-window decay algorithm... The Merge method of |
155 | // perk/quantile is actually not working as advertised - and it might be | 144 | // perk/quantile is actually not working as advertised - and it might be |
156 | // unfixable, as the underlying algorithm is apparently not capable of merging | 145 | // unfixable, as the underlying algorithm is apparently not capable of merging |
157 | // summaries in the first place. To avoid using Merge, we are currently adding | 146 | // summaries in the first place. To avoid using Merge, we are currently adding |
@@ -196,7 +185,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { | |||
196 | } | 185 | } |
197 | 186 | ||
198 | if opts.Objectives == nil { | 187 | if opts.Objectives == nil { |
199 | opts.Objectives = DefObjectives | 188 | opts.Objectives = map[float64]float64{} |
200 | } | 189 | } |
201 | 190 | ||
202 | if opts.MaxAge < 0 { | 191 | if opts.MaxAge < 0 { |
@@ -214,6 +203,17 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { | |||
214 | opts.BufCap = DefBufCap | 203 | opts.BufCap = DefBufCap |
215 | } | 204 | } |
216 | 205 | ||
206 | if len(opts.Objectives) == 0 { | ||
207 | // Use the lock-free implementation of a Summary without objectives. | ||
208 | s := &noObjectivesSummary{ | ||
209 | desc: desc, | ||
210 | labelPairs: makeLabelPairs(desc, labelValues), | ||
211 | counts: [2]*summaryCounts{&summaryCounts{}, &summaryCounts{}}, | ||
212 | } | ||
213 | s.init(s) // Init self-collection. | ||
214 | return s | ||
215 | } | ||
216 | |||
217 | s := &summary{ | 217 | s := &summary{ |
218 | desc: desc, | 218 | desc: desc, |
219 | 219 | ||
@@ -382,6 +382,116 @@ func (s *summary) swapBufs(now time.Time) { | |||
382 | } | 382 | } |
383 | } | 383 | } |
384 | 384 | ||
385 | type summaryCounts struct { | ||
386 | // sumBits contains the bits of the float64 representing the sum of all | ||
387 | // observations. sumBits and count have to go first in the struct to | ||
388 | // guarantee alignment for atomic operations. | ||
389 | // http://golang.org/pkg/sync/atomic/#pkg-note-BUG | ||
390 | sumBits uint64 | ||
391 | count uint64 | ||
392 | } | ||
393 | |||
394 | type noObjectivesSummary struct { | ||
395 | // countAndHotIdx enables lock-free writes with use of atomic updates. | ||
396 | // The most significant bit is the hot index [0 or 1] of the count field | ||
397 | // below. Observe calls update the hot one. All remaining bits count the | ||
398 | // number of Observe calls. Observe starts by incrementing this counter, | ||
399 | // and finish by incrementing the count field in the respective | ||
400 | // summaryCounts, as a marker for completion. | ||
401 | // | ||
402 | // Calls of the Write method (which are non-mutating reads from the | ||
403 | // perspective of the summary) swap the hot–cold under the writeMtx | ||
404 | // lock. A cooldown is awaited (while locked) by comparing the number of | ||
405 | // observations with the initiation count. Once they match, then the | ||
406 | // last observation on the now cool one has completed. All cool fields must | ||
407 | // be merged into the new hot before releasing writeMtx. | ||
408 | |||
409 | // Fields with atomic access first! See alignment constraint: | ||
410 | // http://golang.org/pkg/sync/atomic/#pkg-note-BUG | ||
411 | countAndHotIdx uint64 | ||
412 | |||
413 | selfCollector | ||
414 | desc *Desc | ||
415 | writeMtx sync.Mutex // Only used in the Write method. | ||
416 | |||
417 | // Two counts, one is "hot" for lock-free observations, the other is | ||
418 | // "cold" for writing out a dto.Metric. It has to be an array of | ||
419 | // pointers to guarantee 64bit alignment of the histogramCounts, see | ||
420 | // http://golang.org/pkg/sync/atomic/#pkg-note-BUG. | ||
421 | counts [2]*summaryCounts | ||
422 | |||
423 | labelPairs []*dto.LabelPair | ||
424 | } | ||
425 | |||
426 | func (s *noObjectivesSummary) Desc() *Desc { | ||
427 | return s.desc | ||
428 | } | ||
429 | |||
430 | func (s *noObjectivesSummary) Observe(v float64) { | ||
431 | // We increment h.countAndHotIdx so that the counter in the lower | ||
432 | // 63 bits gets incremented. At the same time, we get the new value | ||
433 | // back, which we can use to find the currently-hot counts. | ||
434 | n := atomic.AddUint64(&s.countAndHotIdx, 1) | ||
435 | hotCounts := s.counts[n>>63] | ||
436 | |||
437 | for { | ||
438 | oldBits := atomic.LoadUint64(&hotCounts.sumBits) | ||
439 | newBits := math.Float64bits(math.Float64frombits(oldBits) + v) | ||
440 | if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) { | ||
441 | break | ||
442 | } | ||
443 | } | ||
444 | // Increment count last as we take it as a signal that the observation | ||
445 | // is complete. | ||
446 | atomic.AddUint64(&hotCounts.count, 1) | ||
447 | } | ||
448 | |||
449 | func (s *noObjectivesSummary) Write(out *dto.Metric) error { | ||
450 | // For simplicity, we protect this whole method by a mutex. It is not in | ||
451 | // the hot path, i.e. Observe is called much more often than Write. The | ||
452 | // complication of making Write lock-free isn't worth it, if possible at | ||
453 | // all. | ||
454 | s.writeMtx.Lock() | ||
455 | defer s.writeMtx.Unlock() | ||
456 | |||
457 | // Adding 1<<63 switches the hot index (from 0 to 1 or from 1 to 0) | ||
458 | // without touching the count bits. See the struct comments for a full | ||
459 | // description of the algorithm. | ||
460 | n := atomic.AddUint64(&s.countAndHotIdx, 1<<63) | ||
461 | // count is contained unchanged in the lower 63 bits. | ||
462 | count := n & ((1 << 63) - 1) | ||
463 | // The most significant bit tells us which counts is hot. The complement | ||
464 | // is thus the cold one. | ||
465 | hotCounts := s.counts[n>>63] | ||
466 | coldCounts := s.counts[(^n)>>63] | ||
467 | |||
468 | // Await cooldown. | ||
469 | for count != atomic.LoadUint64(&coldCounts.count) { | ||
470 | runtime.Gosched() // Let observations get work done. | ||
471 | } | ||
472 | |||
473 | sum := &dto.Summary{ | ||
474 | SampleCount: proto.Uint64(count), | ||
475 | SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), | ||
476 | } | ||
477 | |||
478 | out.Summary = sum | ||
479 | out.Label = s.labelPairs | ||
480 | |||
481 | // Finally add all the cold counts to the new hot counts and reset the cold counts. | ||
482 | atomic.AddUint64(&hotCounts.count, count) | ||
483 | atomic.StoreUint64(&coldCounts.count, 0) | ||
484 | for { | ||
485 | oldBits := atomic.LoadUint64(&hotCounts.sumBits) | ||
486 | newBits := math.Float64bits(math.Float64frombits(oldBits) + sum.GetSampleSum()) | ||
487 | if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) { | ||
488 | atomic.StoreUint64(&coldCounts.sumBits, 0) | ||
489 | break | ||
490 | } | ||
491 | } | ||
492 | return nil | ||
493 | } | ||
494 | |||
385 | type quantSort []*dto.Quantile | 495 | type quantSort []*dto.Quantile |
386 | 496 | ||
387 | func (s quantSort) Len() int { | 497 | func (s quantSort) Len() int { |
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go index 49159bf..e303eef 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go | |||
@@ -32,6 +32,12 @@ import ( | |||
32 | // WrapRegistererWith provides a way to add fixed labels to a subset of | 32 | // WrapRegistererWith provides a way to add fixed labels to a subset of |
33 | // Collectors. It should not be used to add fixed labels to all metrics exposed. | 33 | // Collectors. It should not be used to add fixed labels to all metrics exposed. |
34 | // | 34 | // |
35 | // Conflicts between Collectors registered through the original Registerer with | ||
36 | // Collectors registered through the wrapping Registerer will still be | ||
37 | // detected. Any AlreadyRegisteredError returned by the Register method of | ||
38 | // either Registerer will contain the ExistingCollector in the form it was | ||
39 | // provided to the respective registry. | ||
40 | // | ||
35 | // The Collector example demonstrates a use of WrapRegistererWith. | 41 | // The Collector example demonstrates a use of WrapRegistererWith. |
36 | func WrapRegistererWith(labels Labels, reg Registerer) Registerer { | 42 | func WrapRegistererWith(labels Labels, reg Registerer) Registerer { |
37 | return &wrappingRegisterer{ | 43 | return &wrappingRegisterer{ |
@@ -54,6 +60,12 @@ func WrapRegistererWith(labels Labels, reg Registerer) Registerer { | |||
54 | // (see NewGoCollector) and the process collector (see NewProcessCollector). (In | 60 | // (see NewGoCollector) and the process collector (see NewProcessCollector). (In |
55 | // fact, those metrics are already prefixed with “go_” or “process_”, | 61 | // fact, those metrics are already prefixed with “go_” or “process_”, |
56 | // respectively.) | 62 | // respectively.) |
63 | // | ||
64 | // Conflicts between Collectors registered through the original Registerer with | ||
65 | // Collectors registered through the wrapping Registerer will still be | ||
66 | // detected. Any AlreadyRegisteredError returned by the Register method of | ||
67 | // either Registerer will contain the ExistingCollector in the form it was | ||
68 | // provided to the respective registry. | ||
57 | func WrapRegistererWithPrefix(prefix string, reg Registerer) Registerer { | 69 | func WrapRegistererWithPrefix(prefix string, reg Registerer) Registerer { |
58 | return &wrappingRegisterer{ | 70 | return &wrappingRegisterer{ |
59 | wrappedRegisterer: reg, | 71 | wrappedRegisterer: reg, |
@@ -123,6 +135,15 @@ func (c *wrappingCollector) Describe(ch chan<- *Desc) { | |||
123 | } | 135 | } |
124 | } | 136 | } |
125 | 137 | ||
138 | func (c *wrappingCollector) unwrapRecursively() Collector { | ||
139 | switch wc := c.wrappedCollector.(type) { | ||
140 | case *wrappingCollector: | ||
141 | return wc.unwrapRecursively() | ||
142 | default: | ||
143 | return wc | ||
144 | } | ||
145 | } | ||
146 | |||
126 | type wrappingMetric struct { | 147 | type wrappingMetric struct { |
127 | wrappedMetric Metric | 148 | wrappedMetric Metric |
128 | prefix string | 149 | prefix string |
diff --git a/vendor/github.com/prometheus/common/model/time.go b/vendor/github.com/prometheus/common/model/time.go index 46259b1..7b0064f 100644 --- a/vendor/github.com/prometheus/common/model/time.go +++ b/vendor/github.com/prometheus/common/model/time.go | |||
@@ -150,7 +150,13 @@ func (t *Time) UnmarshalJSON(b []byte) error { | |||
150 | return err | 150 | return err |
151 | } | 151 | } |
152 | 152 | ||
153 | *t = Time(v + va) | 153 | // If the value was something like -0.1 the negative is lost in the |
154 | // parsing because of the leading zero, this ensures that we capture it. | ||
155 | if len(p[0]) > 0 && p[0][0] == '-' && v+va > 0 { | ||
156 | *t = Time(v+va) * -1 | ||
157 | } else { | ||
158 | *t = Time(v + va) | ||
159 | } | ||
154 | 160 | ||
155 | default: | 161 | default: |
156 | return fmt.Errorf("invalid time %q", string(b)) | 162 | return fmt.Errorf("invalid time %q", string(b)) |
diff --git a/vendor/modules.txt b/vendor/modules.txt index 0227700..4204734 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt | |||
@@ -33,13 +33,13 @@ github.com/mdlayher/netlink/nlenc | |||
33 | # github.com/mdlayher/wifi v0.0.0-20180727163819-efdf3f4195d9 | 33 | # github.com/mdlayher/wifi v0.0.0-20180727163819-efdf3f4195d9 |
34 | github.com/mdlayher/wifi | 34 | github.com/mdlayher/wifi |
35 | github.com/mdlayher/wifi/internal/nl80211 | 35 | github.com/mdlayher/wifi/internal/nl80211 |
36 | # github.com/prometheus/client_golang v0.9.2 | 36 | # github.com/prometheus/client_golang v1.0.0 |
37 | github.com/prometheus/client_golang/prometheus | 37 | github.com/prometheus/client_golang/prometheus |
38 | github.com/prometheus/client_golang/prometheus/promhttp | 38 | github.com/prometheus/client_golang/prometheus/promhttp |
39 | github.com/prometheus/client_golang/prometheus/internal | 39 | github.com/prometheus/client_golang/prometheus/internal |
40 | # github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 | 40 | # github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 |
41 | github.com/prometheus/client_model/go | 41 | github.com/prometheus/client_model/go |
42 | # github.com/prometheus/common v0.3.0 | 42 | # github.com/prometheus/common v0.4.1 |
43 | github.com/prometheus/common/log | 43 | github.com/prometheus/common/log |
44 | github.com/prometheus/common/version | 44 | github.com/prometheus/common/version |
45 | github.com/prometheus/common/expfmt | 45 | github.com/prometheus/common/expfmt |
@@ -72,8 +72,8 @@ golang.org/x/net/internal/socket | |||
72 | golang.org/x/sync/errgroup | 72 | golang.org/x/sync/errgroup |
73 | # golang.org/x/sys v0.0.0-20190610081024-1e42afee0f76 | 73 | # golang.org/x/sys v0.0.0-20190610081024-1e42afee0f76 |
74 | golang.org/x/sys/unix | 74 | golang.org/x/sys/unix |
75 | golang.org/x/sys/windows/svc/eventlog | ||
76 | golang.org/x/sys/windows | 75 | golang.org/x/sys/windows |
76 | golang.org/x/sys/windows/svc/eventlog | ||
77 | golang.org/x/sys/windows/registry | 77 | golang.org/x/sys/windows/registry |
78 | # gopkg.in/alecthomas/kingpin.v2 v2.2.6 | 78 | # gopkg.in/alecthomas/kingpin.v2 v2.2.6 |
79 | gopkg.in/alecthomas/kingpin.v2 | 79 | gopkg.in/alecthomas/kingpin.v2 |