Browse code

vendor: bump prometheus/client_golang v1.1.0

full diff: https://github.com/prometheus/client_golang/compare/v0.9.4...v1.1.0

Using v1.1.0, because version v1.2.0 and up use versioned import paths for the
github.com/cespare/xxhash/v2 dependency (prometheus/client_golang#657), which
causes vendoring with vndr to break due to the v2 in the import-path.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2020/01/09 09:39:55
Showing 11 changed files
... ...
@@ -143,7 +143,10 @@ github.com/coreos/pkg                               3ac0863d7acf3bc44daf49afef89
143 143
 code.cloudfoundry.org/clock                         02e53af36e6c978af692887ed449b74026d76fec
144 144
 
145 145
 # prometheus
146
-github.com/prometheus/client_golang                 2641b987480bca71fb39738eb8c8b0d577cb1d76 # v0.9.4
146
+# Using v1.1.0, because version v1.2.0 and up use versioned import paths for the
147
+# github.com/cespare/xxhash/v2 dependency (prometheus/client_golang#657), which
148
+# causes vendoring with vndr to break due to the v2 in the import-path.
149
+github.com/prometheus/client_golang                 170205fb58decfd011f1550d4cfb737230d7ae4f # v1.1.0
147 150
 github.com/beorn7/perks                             37c8de3658fcb183f997c4e13e8337516ab753e6 # v1.0.1
148 151
 github.com/prometheus/client_model                  d1d2010b5beead3fa1c5f271a5cf626e40b3ad6e # v0.1.0
149 152
 github.com/prometheus/common                        287d3e634a1e550c9e463dd7e5a75a422c614505 # v0.7.0
... ...
@@ -11,41 +11,23 @@ Prometheus HTTP API.
11 11
 
12 12
 __This library requires Go1.9 or later.__
13 13
 
14
-## Important note about releases, versioning, tagging, and stability
15
-
16
-In this repository, we used to mostly ignore the many coming and going
17
-dependency management tools for Go and instead wait for a tool that most of the
18
-community would converge on. Our bet is that this tool has arrived now in the
19
-form of [Go
20
-Modules](https://github.com/golang/go/wiki/Modules#how-to-upgrade-and-downgrade-dependencies).
21
-
22
-To make full use of what Go Modules are offering, the previous versioning
23
-roadmap for this repository had to be changed. In particular, Go Modules
24
-finally provide a way for incompatible versions of the same package to coexist
25
-in the same binary. For that, however, the versions must be tagged with
26
-different major versions of 1 or greater (following [Semantic
27
-Versioning](https://semver.org/)). Thus, we decided to abandon the original
28
-plan of introducing a lot of breaking changes _before_ releasing v1 of this
29
-repository, mostly driven by the widespread use this repository already has and
30
-the relatively stable state it is in.
31
-
32
-To leverage the mechanism Go Modules offers for a transition between major
33
-version, the current plan is the following:
34
-
35
-- The v0.9.x series of releases will see a small number of bugfix releases to
36
-  deal with a few remaining minor issues (#543, #542, #539).
37
-- After that, all features currently marked as _deprecated_ will be removed,
38
-  and the result will be released as v1.0.0.
39
-- The planned breaking changes previously gathered as part of the v0.10
40
-  milestone will now go into the v2 milestone. The v2 development happens in a
41
-  [separate branch](https://github.com/prometheus/client_golang/tree/dev-v2)
42
-  for the time being. v2 releases off that branch will happen once sufficient
43
-  stability is reached. v1 and v2 will coexist for a while to enable a
44
-  convenient transition.
45
-- The API client in prometheus/client_golang/api/… is still considered
46
-  experimental. While it will be tagged alongside the rest of the code
47
-  according to the plan above, we cannot strictly guarantee semver semantics
48
-  for it.
14
+## Important note about releases and stability
15
+
16
+This repository generally follows [Semantic
17
+Versioning](https://semver.org/). However, the API client in
18
+prometheus/client_golang/api/… is still considered experimental. Breaking
19
+changes of the API client will _not_ trigger a new major release. The same is
20
+true for selected other new features explicitly marked as **EXPERIMENTAL** in
21
+CHANGELOG.md.
22
+
23
+Features that require breaking changes in the stable parts of the repository
24
+are being batched up and tracked in the [v2
25
+milestone](https://github.com/prometheus/client_golang/milestone/2). The v2
26
+development happens in a [separate
27
+branch](https://github.com/prometheus/client_golang/tree/dev-v2) for the time
28
+being. v2 releases off that branch will happen once sufficient stability is
29
+reached. In view of the widespread use of this repository, v1 and v2 will
30
+coexist for a while to enable a convenient transition.
49 31
 
50 32
 ## Instrumenting applications
51 33
 
... ...
@@ -1,13 +1,11 @@
1 1
 module github.com/prometheus/client_golang
2 2
 
3 3
 require (
4
-	github.com/beorn7/perks v1.0.0
5
-	github.com/golang/protobuf v1.3.1
6
-	github.com/json-iterator/go v1.1.6
7
-	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
8
-	github.com/modern-go/reflect2 v1.0.1 // indirect
4
+	github.com/beorn7/perks v1.0.1
5
+	github.com/golang/protobuf v1.3.2
6
+	github.com/json-iterator/go v1.1.7
9 7
 	github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90
10
-	github.com/prometheus/common v0.4.1
11
-	github.com/prometheus/procfs v0.0.2
12
-	github.com/stretchr/testify v1.3.0 // indirect
8
+	github.com/prometheus/common v0.6.0
9
+	github.com/prometheus/procfs v0.0.3
10
+	golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3
13 11
 )
... ...
@@ -183,7 +183,6 @@
183 183
 // method can then expose the gathered metrics in some way. Usually, the metrics
184 184
 // are served via HTTP on the /metrics endpoint. That's happening in the example
185 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 187
 // Pushing to the Pushgateway
189 188
 //
190 189
deleted file mode 100644
... ...
@@ -1,505 +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
-	contentEncodingHeader = "Content-Encoding"
38
-	acceptEncodingHeader  = "Accept-Encoding"
39
-)
40
-
41
-var gzipPool = sync.Pool{
42
-	New: func() interface{} {
43
-		return gzip.NewWriter(nil)
44
-	},
45
-}
46
-
47
-// Handler returns an HTTP handler for the DefaultGatherer. It is
48
-// already instrumented with InstrumentHandler (using "prometheus" as handler
49
-// name).
50
-//
51
-// Deprecated: Please note the issues described in the doc comment of
52
-// InstrumentHandler. You might want to consider using promhttp.Handler instead.
53
-func Handler() http.Handler {
54
-	return InstrumentHandler("prometheus", UninstrumentedHandler())
55
-}
56
-
57
-// UninstrumentedHandler returns an HTTP handler for the DefaultGatherer.
58
-//
59
-// Deprecated: Use promhttp.HandlerFor(DefaultGatherer, promhttp.HandlerOpts{})
60
-// instead. See there for further documentation.
61
-func UninstrumentedHandler() http.Handler {
62
-	return http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) {
63
-		mfs, err := DefaultGatherer.Gather()
64
-		if err != nil {
65
-			httpError(rsp, err)
66
-			return
67
-		}
68
-
69
-		contentType := expfmt.Negotiate(req.Header)
70
-		header := rsp.Header()
71
-		header.Set(contentTypeHeader, string(contentType))
72
-
73
-		w := io.Writer(rsp)
74
-		if gzipAccepted(req.Header) {
75
-			header.Set(contentEncodingHeader, "gzip")
76
-			gz := gzipPool.Get().(*gzip.Writer)
77
-			defer gzipPool.Put(gz)
78
-
79
-			gz.Reset(w)
80
-			defer gz.Close()
81
-
82
-			w = gz
83
-		}
84
-
85
-		enc := expfmt.NewEncoder(w, contentType)
86
-
87
-		for _, mf := range mfs {
88
-			if err := enc.Encode(mf); err != nil {
89
-				httpError(rsp, err)
90
-				return
91
-			}
92
-		}
93
-	})
94
-}
95
-
96
-var instLabels = []string{"method", "code"}
97
-
98
-type nower interface {
99
-	Now() time.Time
100
-}
101
-
102
-type nowFunc func() time.Time
103
-
104
-func (n nowFunc) Now() time.Time {
105
-	return n()
106
-}
107
-
108
-var now nower = nowFunc(func() time.Time {
109
-	return time.Now()
110
-})
111
-
112
-// InstrumentHandler wraps the given HTTP handler for instrumentation. It
113
-// registers four metric collectors (if not already done) and reports HTTP
114
-// metrics to the (newly or already) registered collectors: http_requests_total
115
-// (CounterVec), http_request_duration_microseconds (Summary),
116
-// http_request_size_bytes (Summary), http_response_size_bytes (Summary). Each
117
-// has a constant label named "handler" with the provided handlerName as
118
-// value. http_requests_total is a metric vector partitioned by HTTP method
119
-// (label name "method") and HTTP status code (label name "code").
120
-//
121
-// Deprecated: InstrumentHandler has several issues. Use the tooling provided in
122
-// package promhttp instead. The issues are the following: (1) It uses Summaries
123
-// rather than Histograms. Summaries are not useful if aggregation across
124
-// multiple instances is required. (2) It uses microseconds as unit, which is
125
-// deprecated and should be replaced by seconds. (3) The size of the request is
126
-// calculated in a separate goroutine. Since this calculator requires access to
127
-// the request header, it creates a race with any writes to the header performed
128
-// during request handling.  httputil.ReverseProxy is a prominent example for a
129
-// handler performing such writes. (4) It has additional issues with HTTP/2, cf.
130
-// https://github.com/prometheus/client_golang/issues/272.
131
-func InstrumentHandler(handlerName string, handler http.Handler) http.HandlerFunc {
132
-	return InstrumentHandlerFunc(handlerName, handler.ServeHTTP)
133
-}
134
-
135
-// InstrumentHandlerFunc wraps the given function for instrumentation. It
136
-// otherwise works in the same way as InstrumentHandler (and shares the same
137
-// issues).
138
-//
139
-// Deprecated: InstrumentHandlerFunc is deprecated for the same reasons as
140
-// InstrumentHandler is. Use the tooling provided in package promhttp instead.
141
-func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
142
-	return InstrumentHandlerFuncWithOpts(
143
-		SummaryOpts{
144
-			Subsystem:   "http",
145
-			ConstLabels: Labels{"handler": handlerName},
146
-			Objectives:  map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
147
-		},
148
-		handlerFunc,
149
-	)
150
-}
151
-
152
-// InstrumentHandlerWithOpts works like InstrumentHandler (and shares the same
153
-// issues) but provides more flexibility (at the cost of a more complex call
154
-// syntax). As InstrumentHandler, this function registers four metric
155
-// collectors, but it uses the provided SummaryOpts to create them. However, the
156
-// fields "Name" and "Help" in the SummaryOpts are ignored. "Name" is replaced
157
-// by "requests_total", "request_duration_microseconds", "request_size_bytes",
158
-// and "response_size_bytes", respectively. "Help" is replaced by an appropriate
159
-// help string. The names of the variable labels of the http_requests_total
160
-// CounterVec are "method" (get, post, etc.), and "code" (HTTP status code).
161
-//
162
-// If InstrumentHandlerWithOpts is called as follows, it mimics exactly the
163
-// behavior of InstrumentHandler:
164
-//
165
-//     prometheus.InstrumentHandlerWithOpts(
166
-//         prometheus.SummaryOpts{
167
-//              Subsystem:   "http",
168
-//              ConstLabels: prometheus.Labels{"handler": handlerName},
169
-//         },
170
-//         handler,
171
-//     )
172
-//
173
-// Technical detail: "requests_total" is a CounterVec, not a SummaryVec, so it
174
-// cannot use SummaryOpts. Instead, a CounterOpts struct is created internally,
175
-// and all its fields are set to the equally named fields in the provided
176
-// SummaryOpts.
177
-//
178
-// Deprecated: InstrumentHandlerWithOpts is deprecated for the same reasons as
179
-// InstrumentHandler is. Use the tooling provided in package promhttp instead.
180
-func InstrumentHandlerWithOpts(opts SummaryOpts, handler http.Handler) http.HandlerFunc {
181
-	return InstrumentHandlerFuncWithOpts(opts, handler.ServeHTTP)
182
-}
183
-
184
-// InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc (and shares
185
-// the same issues) but provides more flexibility (at the cost of a more complex
186
-// call syntax). See InstrumentHandlerWithOpts for details how the provided
187
-// SummaryOpts are used.
188
-//
189
-// Deprecated: InstrumentHandlerFuncWithOpts is deprecated for the same reasons
190
-// as InstrumentHandler is. Use the tooling provided in package promhttp instead.
191
-func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
192
-	reqCnt := NewCounterVec(
193
-		CounterOpts{
194
-			Namespace:   opts.Namespace,
195
-			Subsystem:   opts.Subsystem,
196
-			Name:        "requests_total",
197
-			Help:        "Total number of HTTP requests made.",
198
-			ConstLabels: opts.ConstLabels,
199
-		},
200
-		instLabels,
201
-	)
202
-	if err := Register(reqCnt); err != nil {
203
-		if are, ok := err.(AlreadyRegisteredError); ok {
204
-			reqCnt = are.ExistingCollector.(*CounterVec)
205
-		} else {
206
-			panic(err)
207
-		}
208
-	}
209
-
210
-	opts.Name = "request_duration_microseconds"
211
-	opts.Help = "The HTTP request latencies in microseconds."
212
-	reqDur := NewSummary(opts)
213
-	if err := Register(reqDur); err != nil {
214
-		if are, ok := err.(AlreadyRegisteredError); ok {
215
-			reqDur = are.ExistingCollector.(Summary)
216
-		} else {
217
-			panic(err)
218
-		}
219
-	}
220
-
221
-	opts.Name = "request_size_bytes"
222
-	opts.Help = "The HTTP request sizes in bytes."
223
-	reqSz := NewSummary(opts)
224
-	if err := Register(reqSz); err != nil {
225
-		if are, ok := err.(AlreadyRegisteredError); ok {
226
-			reqSz = are.ExistingCollector.(Summary)
227
-		} else {
228
-			panic(err)
229
-		}
230
-	}
231
-
232
-	opts.Name = "response_size_bytes"
233
-	opts.Help = "The HTTP response sizes in bytes."
234
-	resSz := NewSummary(opts)
235
-	if err := Register(resSz); err != nil {
236
-		if are, ok := err.(AlreadyRegisteredError); ok {
237
-			resSz = are.ExistingCollector.(Summary)
238
-		} else {
239
-			panic(err)
240
-		}
241
-	}
242
-
243
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
244
-		now := time.Now()
245
-
246
-		delegate := &responseWriterDelegator{ResponseWriter: w}
247
-		out := computeApproximateRequestSize(r)
248
-
249
-		_, cn := w.(http.CloseNotifier)
250
-		_, fl := w.(http.Flusher)
251
-		_, hj := w.(http.Hijacker)
252
-		_, rf := w.(io.ReaderFrom)
253
-		var rw http.ResponseWriter
254
-		if cn && fl && hj && rf {
255
-			rw = &fancyResponseWriterDelegator{delegate}
256
-		} else {
257
-			rw = delegate
258
-		}
259
-		handlerFunc(rw, r)
260
-
261
-		elapsed := float64(time.Since(now)) / float64(time.Microsecond)
262
-
263
-		method := sanitizeMethod(r.Method)
264
-		code := sanitizeCode(delegate.status)
265
-		reqCnt.WithLabelValues(method, code).Inc()
266
-		reqDur.Observe(elapsed)
267
-		resSz.Observe(float64(delegate.written))
268
-		reqSz.Observe(float64(<-out))
269
-	})
270
-}
271
-
272
-func computeApproximateRequestSize(r *http.Request) <-chan int {
273
-	// Get URL length in current goroutine for avoiding a race condition.
274
-	// HandlerFunc that runs in parallel may modify the URL.
275
-	s := 0
276
-	if r.URL != nil {
277
-		s += len(r.URL.String())
278
-	}
279
-
280
-	out := make(chan int, 1)
281
-
282
-	go func() {
283
-		s += len(r.Method)
284
-		s += len(r.Proto)
285
-		for name, values := range r.Header {
286
-			s += len(name)
287
-			for _, value := range values {
288
-				s += len(value)
289
-			}
290
-		}
291
-		s += len(r.Host)
292
-
293
-		// N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.
294
-
295
-		if r.ContentLength != -1 {
296
-			s += int(r.ContentLength)
297
-		}
298
-		out <- s
299
-		close(out)
300
-	}()
301
-
302
-	return out
303
-}
304
-
305
-type responseWriterDelegator struct {
306
-	http.ResponseWriter
307
-
308
-	status      int
309
-	written     int64
310
-	wroteHeader bool
311
-}
312
-
313
-func (r *responseWriterDelegator) WriteHeader(code int) {
314
-	r.status = code
315
-	r.wroteHeader = true
316
-	r.ResponseWriter.WriteHeader(code)
317
-}
318
-
319
-func (r *responseWriterDelegator) Write(b []byte) (int, error) {
320
-	if !r.wroteHeader {
321
-		r.WriteHeader(http.StatusOK)
322
-	}
323
-	n, err := r.ResponseWriter.Write(b)
324
-	r.written += int64(n)
325
-	return n, err
326
-}
327
-
328
-type fancyResponseWriterDelegator struct {
329
-	*responseWriterDelegator
330
-}
331
-
332
-func (f *fancyResponseWriterDelegator) CloseNotify() <-chan bool {
333
-	//lint:ignore SA1019 http.CloseNotifier is deprecated but we don't want to
334
-	//remove support from client_golang yet.
335
-	return f.ResponseWriter.(http.CloseNotifier).CloseNotify()
336
-}
337
-
338
-func (f *fancyResponseWriterDelegator) Flush() {
339
-	f.ResponseWriter.(http.Flusher).Flush()
340
-}
341
-
342
-func (f *fancyResponseWriterDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
343
-	return f.ResponseWriter.(http.Hijacker).Hijack()
344
-}
345
-
346
-func (f *fancyResponseWriterDelegator) ReadFrom(r io.Reader) (int64, error) {
347
-	if !f.wroteHeader {
348
-		f.WriteHeader(http.StatusOK)
349
-	}
350
-	n, err := f.ResponseWriter.(io.ReaderFrom).ReadFrom(r)
351
-	f.written += n
352
-	return n, err
353
-}
354
-
355
-func sanitizeMethod(m string) string {
356
-	switch m {
357
-	case "GET", "get":
358
-		return "get"
359
-	case "PUT", "put":
360
-		return "put"
361
-	case "HEAD", "head":
362
-		return "head"
363
-	case "POST", "post":
364
-		return "post"
365
-	case "DELETE", "delete":
366
-		return "delete"
367
-	case "CONNECT", "connect":
368
-		return "connect"
369
-	case "OPTIONS", "options":
370
-		return "options"
371
-	case "NOTIFY", "notify":
372
-		return "notify"
373
-	default:
374
-		return strings.ToLower(m)
375
-	}
376
-}
377
-
378
-func sanitizeCode(s int) string {
379
-	switch s {
380
-	case 100:
381
-		return "100"
382
-	case 101:
383
-		return "101"
384
-
385
-	case 200:
386
-		return "200"
387
-	case 201:
388
-		return "201"
389
-	case 202:
390
-		return "202"
391
-	case 203:
392
-		return "203"
393
-	case 204:
394
-		return "204"
395
-	case 205:
396
-		return "205"
397
-	case 206:
398
-		return "206"
399
-
400
-	case 300:
401
-		return "300"
402
-	case 301:
403
-		return "301"
404
-	case 302:
405
-		return "302"
406
-	case 304:
407
-		return "304"
408
-	case 305:
409
-		return "305"
410
-	case 307:
411
-		return "307"
412
-
413
-	case 400:
414
-		return "400"
415
-	case 401:
416
-		return "401"
417
-	case 402:
418
-		return "402"
419
-	case 403:
420
-		return "403"
421
-	case 404:
422
-		return "404"
423
-	case 405:
424
-		return "405"
425
-	case 406:
426
-		return "406"
427
-	case 407:
428
-		return "407"
429
-	case 408:
430
-		return "408"
431
-	case 409:
432
-		return "409"
433
-	case 410:
434
-		return "410"
435
-	case 411:
436
-		return "411"
437
-	case 412:
438
-		return "412"
439
-	case 413:
440
-		return "413"
441
-	case 414:
442
-		return "414"
443
-	case 415:
444
-		return "415"
445
-	case 416:
446
-		return "416"
447
-	case 417:
448
-		return "417"
449
-	case 418:
450
-		return "418"
451
-
452
-	case 500:
453
-		return "500"
454
-	case 501:
455
-		return "501"
456
-	case 502:
457
-		return "502"
458
-	case 503:
459
-		return "503"
460
-	case 504:
461
-		return "504"
462
-	case 505:
463
-		return "505"
464
-
465
-	case 428:
466
-		return "428"
467
-	case 429:
468
-		return "429"
469
-	case 431:
470
-		return "431"
471
-	case 511:
472
-		return "511"
473
-
474
-	default:
475
-		return strconv.Itoa(s)
476
-	}
477
-}
478
-
479
-// gzipAccepted returns whether the client will accept gzip-encoded content.
480
-func gzipAccepted(header http.Header) bool {
481
-	a := header.Get(acceptEncodingHeader)
482
-	parts := strings.Split(a, ",")
483
-	for _, part := range parts {
484
-		part = strings.TrimSpace(part)
485
-		if part == "gzip" || strings.HasPrefix(part, "gzip;") {
486
-			return true
487
-		}
488
-	}
489
-	return false
490
-}
491
-
492
-// httpError removes any content-encoding header and then calls http.Error with
493
-// the provided error and http.StatusInternalServerErrer. Error contents is
494
-// supposed to be uncompressed plain text. However, same as with a plain
495
-// http.Error, any header settings will be void if the header has already been
496
-// sent. The error message will still be written to the writer, but it will
497
-// probably be of limited use.
498
-func httpError(rsp http.ResponseWriter, err error) {
499
-	rsp.Header().Del(contentEncodingHeader)
500
-	http.Error(
501
-		rsp,
502
-		"An error has occurred while serving metrics:\n\n"+err.Error(),
503
-		http.StatusInternalServerError,
504
-	)
505
-}
... ...
@@ -16,8 +16,6 @@ package prometheus
16 16
 import (
17 17
 	"errors"
18 18
 	"os"
19
-
20
-	"github.com/prometheus/procfs"
21 19
 )
22 20
 
23 21
 type processCollector struct {
... ...
@@ -59,20 +57,9 @@ type ProcessCollectorOpts struct {
59 59
 // collector for the current process with an empty namespace string and no error
60 60
 // reporting.
61 61
 //
62
-// Currently, the collector depends on a Linux-style proc filesystem and
63
-// therefore only exports metrics for Linux.
64
-//
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{})
62
+// The collector only works on operating systems with a Linux-style proc
63
+// filesystem and on Microsoft Windows. On other operating systems, it will not
64
+// collect any metrics.
76 65
 func NewProcessCollector(opts ProcessCollectorOpts) Collector {
77 66
 	ns := ""
78 67
 	if len(opts.Namespace) > 0 {
... ...
@@ -126,7 +113,7 @@ func NewProcessCollector(opts ProcessCollectorOpts) Collector {
126 126
 	}
127 127
 
128 128
 	// Set up process metric collection if supported by the runtime.
129
-	if _, err := procfs.NewDefaultFS(); err == nil {
129
+	if canCollectProcess() {
130 130
 		c.collectFn = c.processCollect
131 131
 	} else {
132 132
 		c.collectFn = func(ch chan<- Metric) {
... ...
@@ -153,46 +140,6 @@ func (c *processCollector) Collect(ch chan<- Metric) {
153 153
 	c.collectFn(ch)
154 154
 }
155 155
 
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.Stat(); 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.Limits(); 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 156
 func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) {
197 157
 	if !c.reportErrors {
198 158
 		return
199 159
new file mode 100644
... ...
@@ -0,0 +1,65 @@
0
+// Copyright 2019 The Prometheus Authors
1
+// Licensed under the Apache License, Version 2.0 (the "License");
2
+// you may not use this file except in compliance with the License.
3
+// You may obtain a copy of the License at
4
+//
5
+// http://www.apache.org/licenses/LICENSE-2.0
6
+//
7
+// Unless required by applicable law or agreed to in writing, software
8
+// distributed under the License is distributed on an "AS IS" BASIS,
9
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+// See the License for the specific language governing permissions and
11
+// limitations under the License.
12
+
13
+// +build !windows
14
+
15
+package prometheus
16
+
17
+import (
18
+	"github.com/prometheus/procfs"
19
+)
20
+
21
+func canCollectProcess() bool {
22
+	_, err := procfs.NewDefaultFS()
23
+	return err == nil
24
+}
25
+
26
+func (c *processCollector) processCollect(ch chan<- Metric) {
27
+	pid, err := c.pidFn()
28
+	if err != nil {
29
+		c.reportError(ch, nil, err)
30
+		return
31
+	}
32
+
33
+	p, err := procfs.NewProc(pid)
34
+	if err != nil {
35
+		c.reportError(ch, nil, err)
36
+		return
37
+	}
38
+
39
+	if stat, err := p.Stat(); err == nil {
40
+		ch <- MustNewConstMetric(c.cpuTotal, CounterValue, stat.CPUTime())
41
+		ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(stat.VirtualMemory()))
42
+		ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory()))
43
+		if startTime, err := stat.StartTime(); err == nil {
44
+			ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime)
45
+		} else {
46
+			c.reportError(ch, c.startTime, err)
47
+		}
48
+	} else {
49
+		c.reportError(ch, nil, err)
50
+	}
51
+
52
+	if fds, err := p.FileDescriptorsLen(); err == nil {
53
+		ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds))
54
+	} else {
55
+		c.reportError(ch, c.openFDs, err)
56
+	}
57
+
58
+	if limits, err := p.Limits(); err == nil {
59
+		ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles))
60
+		ch <- MustNewConstMetric(c.maxVsize, GaugeValue, float64(limits.AddressSpace))
61
+	} else {
62
+		c.reportError(ch, nil, err)
63
+	}
64
+}
0 65
new file mode 100644
... ...
@@ -0,0 +1,112 @@
0
+// Copyright 2019 The Prometheus Authors
1
+// Licensed under the Apache License, Version 2.0 (the "License");
2
+// you may not use this file except in compliance with the License.
3
+// You may obtain a copy of the License at
4
+//
5
+// http://www.apache.org/licenses/LICENSE-2.0
6
+//
7
+// Unless required by applicable law or agreed to in writing, software
8
+// distributed under the License is distributed on an "AS IS" BASIS,
9
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+// See the License for the specific language governing permissions and
11
+// limitations under the License.
12
+
13
+package prometheus
14
+
15
+import (
16
+	"syscall"
17
+	"unsafe"
18
+
19
+	"golang.org/x/sys/windows"
20
+)
21
+
22
+func canCollectProcess() bool {
23
+	return true
24
+}
25
+
26
+var (
27
+	modpsapi    = syscall.NewLazyDLL("psapi.dll")
28
+	modkernel32 = syscall.NewLazyDLL("kernel32.dll")
29
+
30
+	procGetProcessMemoryInfo  = modpsapi.NewProc("GetProcessMemoryInfo")
31
+	procGetProcessHandleCount = modkernel32.NewProc("GetProcessHandleCount")
32
+)
33
+
34
+type processMemoryCounters struct {
35
+	// https://docs.microsoft.com/en-us/windows/desktop/api/psapi/ns-psapi-_process_memory_counters_ex
36
+	_                          uint32
37
+	PageFaultCount             uint32
38
+	PeakWorkingSetSize         uint64
39
+	WorkingSetSize             uint64
40
+	QuotaPeakPagedPoolUsage    uint64
41
+	QuotaPagedPoolUsage        uint64
42
+	QuotaPeakNonPagedPoolUsage uint64
43
+	QuotaNonPagedPoolUsage     uint64
44
+	PagefileUsage              uint64
45
+	PeakPagefileUsage          uint64
46
+	PrivateUsage               uint64
47
+}
48
+
49
+func getProcessMemoryInfo(handle windows.Handle) (processMemoryCounters, error) {
50
+	mem := processMemoryCounters{}
51
+	r1, _, err := procGetProcessMemoryInfo.Call(
52
+		uintptr(handle),
53
+		uintptr(unsafe.Pointer(&mem)),
54
+		uintptr(unsafe.Sizeof(mem)),
55
+	)
56
+	if r1 != 1 {
57
+		return mem, err
58
+	} else {
59
+		return mem, nil
60
+	}
61
+}
62
+
63
+func getProcessHandleCount(handle windows.Handle) (uint32, error) {
64
+	var count uint32
65
+	r1, _, err := procGetProcessHandleCount.Call(
66
+		uintptr(handle),
67
+		uintptr(unsafe.Pointer(&count)),
68
+	)
69
+	if r1 != 1 {
70
+		return 0, err
71
+	} else {
72
+		return count, nil
73
+	}
74
+}
75
+
76
+func (c *processCollector) processCollect(ch chan<- Metric) {
77
+	h, err := windows.GetCurrentProcess()
78
+	if err != nil {
79
+		c.reportError(ch, nil, err)
80
+		return
81
+	}
82
+
83
+	var startTime, exitTime, kernelTime, userTime windows.Filetime
84
+	err = windows.GetProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime)
85
+	if err != nil {
86
+		c.reportError(ch, nil, err)
87
+		return
88
+	}
89
+	ch <- MustNewConstMetric(c.startTime, GaugeValue, float64(startTime.Nanoseconds()/1e9))
90
+	ch <- MustNewConstMetric(c.cpuTotal, CounterValue, fileTimeToSeconds(kernelTime)+fileTimeToSeconds(userTime))
91
+
92
+	mem, err := getProcessMemoryInfo(h)
93
+	if err != nil {
94
+		c.reportError(ch, nil, err)
95
+		return
96
+	}
97
+	ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(mem.PrivateUsage))
98
+	ch <- MustNewConstMetric(c.rss, GaugeValue, float64(mem.WorkingSetSize))
99
+
100
+	handles, err := getProcessHandleCount(h)
101
+	if err != nil {
102
+		c.reportError(ch, nil, err)
103
+		return
104
+	}
105
+	ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(handles))
106
+	ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(16*1024*1024)) // Windows has a hard-coded max limit, not per-process.
107
+}
108
+
109
+func fileTimeToSeconds(ft windows.Filetime) float64 {
110
+	return float64(uint64(ft.HighDateTime)<<32+uint64(ft.LowDateTime)) / 1e7
111
+}
... ...
@@ -325,9 +325,17 @@ func (r *Registry) Register(c Collector) error {
325 325
 		return nil
326 326
 	}
327 327
 	if existing, exists := r.collectorsByID[collectorID]; exists {
328
-		return AlreadyRegisteredError{
329
-			ExistingCollector: existing,
330
-			NewCollector:      c,
328
+		switch e := existing.(type) {
329
+		case *wrappingCollector:
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 341
 	// If the collectorID is new, but at least one of the descs existed
... ...
@@ -58,16 +58,8 @@ type Summary interface {
58 58
 	Observe(float64)
59 59
 }
60 60
 
61
-// DefObjectives are the default Summary quantile values.
62
-//
63
-// Deprecated: DefObjectives will not be used as the default objectives in
64
-// v1.0.0 of the library. The default Summary will have no quantiles then.
65
-var (
66
-	DefObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}
67
-
68
-	errQuantileLabelNotAllowed = fmt.Errorf(
69
-		"%q is not allowed as label name in summaries", quantileLabel,
70
-	)
61
+var errQuantileLabelNotAllowed = fmt.Errorf(
62
+	"%q is not allowed as label name in summaries", quantileLabel,
71 63
 )
72 64
 
73 65
 // Default values for SummaryOpts.
... ...
@@ -123,14 +115,8 @@ type SummaryOpts struct {
123 123
 	// Objectives defines the quantile rank estimates with their respective
124 124
 	// absolute error. If Objectives[q] = e, then the value reported for q
125 125
 	// will be the φ-quantile value for some φ between q-e and q+e.  The
126
-	// default value is DefObjectives. It is used if Objectives is left at
127
-	// its zero value (i.e. nil). To create a Summary without Objectives,
128
-	// set it to an empty map (i.e. map[float64]float64{}).
129
-	//
130
-	// Note that the current value of DefObjectives is deprecated. It will
131
-	// be replaced by an empty map in v1.0.0 of the library. Please
132
-	// explicitly set Objectives to the desired value to avoid problems
133
-	// during the transition.
126
+	// default value is an empty map, resulting in a summary without
127
+	// quantiles.
134 128
 	Objectives map[float64]float64
135 129
 
136 130
 	// MaxAge defines the duration for which an observation stays relevant
... ...
@@ -199,7 +185,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
199 199
 	}
200 200
 
201 201
 	if opts.Objectives == nil {
202
-		opts.Objectives = DefObjectives
202
+		opts.Objectives = map[float64]float64{}
203 203
 	}
204 204
 
205 205
 	if opts.MaxAge < 0 {
... ...
@@ -32,6 +32,12 @@ import (
32 32
 // WrapRegistererWith provides a way to add fixed labels to a subset of
33 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 41
 // The Collector example demonstrates a use of WrapRegistererWith.
36 42
 func WrapRegistererWith(labels Labels, reg Registerer) Registerer {
37 43
 	return &wrappingRegisterer{
... ...
@@ -54,6 +60,12 @@ func WrapRegistererWith(labels Labels, reg Registerer) Registerer {
54 54
 // (see NewGoCollector) and the process collector (see NewProcessCollector). (In
55 55
 // fact, those metrics are already prefixed with “go_” or “process_”,
56 56
 // respectively.)
57
+//
58
+// Conflicts between Collectors registered through the original Registerer with
59
+// Collectors registered through the wrapping Registerer will still be
60
+// detected. Any AlreadyRegisteredError returned by the Register method of
61
+// either Registerer will contain the ExistingCollector in the form it was
62
+// provided to the respective registry.
57 63
 func WrapRegistererWithPrefix(prefix string, reg Registerer) Registerer {
58 64
 	return &wrappingRegisterer{
59 65
 		wrappedRegisterer: reg,
... ...
@@ -123,6 +135,15 @@ func (c *wrappingCollector) Describe(ch chan<- *Desc) {
123 123
 	}
124 124
 }
125 125
 
126
+func (c *wrappingCollector) unwrapRecursively() Collector {
127
+	switch wc := c.wrappedCollector.(type) {
128
+	case *wrappingCollector:
129
+		return wc.unwrapRecursively()
130
+	default:
131
+		return wc
132
+	}
133
+}
134
+
126 135
 type wrappingMetric struct {
127 136
 	wrappedMetric Metric
128 137
 	prefix        string