Update vendoring of Prometheus Go client (#4283)

This is to pickup changes from
https://github.com/prometheus/client_golang/pull/414. It leads to
better error output in promtool.

Signed-off-by: Sneha Inguva <singuva@digitalocean.com>
This commit is contained in:
Sneha Inguva 2018-07-17 22:08:38 -06:00 committed by Brian Brazil
parent 219e477272
commit 295a95329e
10 changed files with 71 additions and 97 deletions

View file

@ -455,6 +455,11 @@ type apiResponse struct {
Error string `json:"error"`
}
func apiError(code int) bool {
// These are the codes that Prometheus sends when it returns an error.
return code == statusAPIError || code == http.StatusBadRequest
}
func (c apiClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, error) {
resp, body, err := c.Client.Do(ctx, req)
if err != nil {
@ -463,7 +468,7 @@ func (c apiClient) Do(ctx context.Context, req *http.Request) (*http.Response, [
code := resp.StatusCode
if code/100 != 2 && code != statusAPIError {
if code/100 != 2 && !apiError(code) {
return resp, body, &Error{
Type: ErrBadResponse,
Msg: fmt.Sprintf("bad response code %d", resp.StatusCode),
@ -479,14 +484,14 @@ func (c apiClient) Do(ctx context.Context, req *http.Request) (*http.Response, [
}
}
if (code == statusAPIError) != (result.Status == "error") {
if apiError(code) != (result.Status == "error") {
err = &Error{
Type: ErrBadResponse,
Msg: "inconsistent body for response code",
}
}
if code == statusAPIError && result.Status == "error" {
if apiError(code) && result.Status == "error" {
err = &Error{
Type: result.ErrorType,
Msg: result.Error,

View file

@ -17,8 +17,12 @@ type goCollector struct {
metrics memStatsMetrics
}
// NewGoCollector returns a collector which exports metrics about the current
// go process.
// NewGoCollector returns a collector which exports metrics about the current Go
// process. This includes memory stats. To collect those, runtime.ReadMemStats
// is called. This causes a stop-the-world, which is very short with Go1.9+
// (~25µs). However, with older Go versions, the stop-the-world duration depends
// on the heap size and can be quite significant (~1.7 ms/GiB as per
// https://go-review.googlesource.com/c/go/+/34937).
func NewGoCollector() Collector {
return &goCollector{
goroutinesDesc: NewDesc(
@ -265,7 +269,7 @@ func (c *goCollector) Collect(ch chan<- Metric) {
quantiles[float64(idx+1)/float64(len(stats.PauseQuantiles)-1)] = pq.Seconds()
}
quantiles[0.0] = stats.PauseQuantiles[0].Seconds()
ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles)
ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), stats.PauseTotal.Seconds(), quantiles)
ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1)

View file

@ -115,7 +115,7 @@ func decorateWriter(request *http.Request, writer io.Writer) (io.Writer, string)
header := request.Header.Get(acceptEncodingHeader)
parts := strings.Split(header, ",")
for _, part := range parts {
part := strings.TrimSpace(part)
part = strings.TrimSpace(part)
if part == "gzip" || strings.HasPrefix(part, "gzip;") {
return gzip.NewWriter(writer), "gzip"
}
@ -139,16 +139,6 @@ var now nower = nowFunc(func() time.Time {
return time.Now()
})
func nowSeries(t ...time.Time) nower {
return nowFunc(func() time.Time {
defer func() {
t = t[1:]
}()
return t[0]
})
}
// InstrumentHandler wraps the given HTTP handler for instrumentation. It
// registers four metric collectors (if not already done) and reports HTTP
// metrics to the (newly or already) registered collectors: http_requests_total
@ -352,10 +342,9 @@ func computeApproximateRequestSize(r *http.Request) <-chan int {
type responseWriterDelegator struct {
http.ResponseWriter
handler, method string
status int
written int64
wroteHeader bool
status int
written int64
wroteHeader bool
}
func (r *responseWriterDelegator) WriteHeader(code int) {

View file

@ -127,20 +127,6 @@ func (s LabelPairSorter) Less(i, j int) bool {
return s[i].GetName() < s[j].GetName()
}
type hashSorter []uint64
func (s hashSorter) Len() int {
return len(s)
}
func (s hashSorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s hashSorter) Less(i, j int) bool {
return s[i] < s[j]
}
type invalidMetric struct {
desc *Desc
err error

View file

@ -16,7 +16,6 @@ package prometheus
import "github.com/prometheus/procfs"
type processCollector struct {
pid int
collectFn func(chan<- Metric)
pidFn func() (int, error)
cpuTotal *Desc

View file

@ -302,7 +302,7 @@ func decorateWriter(request *http.Request, writer io.Writer, compressionDisabled
header := request.Header.Get(acceptEncodingHeader)
parts := strings.Split(header, ",")
for _, part := range parts {
part := strings.TrimSpace(part)
part = strings.TrimSpace(part)
if part == "gzip" || strings.HasPrefix(part, "gzip;") {
return gzip.NewWriter(writer), "gzip"
}

View file

@ -38,12 +38,13 @@ const (
// Registerer and Gatherer interface a number of convenience functions in this
// package act on. Initially, both variables point to the same Registry, which
// has a process collector (currently on Linux only, see NewProcessCollector)
// and a Go collector (see NewGoCollector) already registered. This approach to
// keep default instances as global state mirrors the approach of other packages
// in the Go standard library. Note that there are caveats. Change the variables
// with caution and only if you understand the consequences. Users who want to
// avoid global state altogether should not use the convenience functions and
// act on custom instances instead.
// and a Go collector (see NewGoCollector, in particular the note about
// stop-the-world implication with Go versions older than 1.9) already
// registered. This approach to keep default instances as global state mirrors
// the approach of other packages in the Go standard library. Note that there
// are caveats. Change the variables with caution and only if you understand the
// consequences. Users who want to avoid global state altogether should not use
// the convenience functions and act on custom instances instead.
var (
defaultRegistry = NewRegistry()
DefaultRegisterer Registerer = defaultRegistry
@ -125,15 +126,23 @@ type Registerer interface {
type Gatherer interface {
// Gather calls the Collect method of the registered Collectors and then
// gathers the collected metrics into a lexicographically sorted slice
// of MetricFamily protobufs. Even if an error occurs, Gather attempts
// to gather as many metrics as possible. Hence, if a non-nil error is
// returned, the returned MetricFamily slice could be nil (in case of a
// fatal error that prevented any meaningful metric collection) or
// contain a number of MetricFamily protobufs, some of which might be
// incomplete, and some might be missing altogether. The returned error
// (which might be a MultiError) explains the details. In scenarios
// where complete collection is critical, the returned MetricFamily
// protobufs should be disregarded if the returned error is non-nil.
// of uniquely named MetricFamily protobufs. Gather ensures that the
// returned slice is valid and self-consistent so that it can be used
// for valid exposition. As an exception to the strict consistency
// requirements described for metric.Desc, Gather will tolerate
// different sets of label names for metrics of the same metric family.
//
// Even if an error occurs, Gather attempts to gather as many metrics as
// possible. Hence, if a non-nil error is returned, the returned
// MetricFamily slice could be nil (in case of a fatal error that
// prevented any meaningful metric collection) or contain a number of
// MetricFamily protobufs, some of which might be incomplete, and some
// might be missing altogether. The returned error (which might be a
// MultiError) explains the details. Note that this is mostly useful for
// debugging purposes. If the gathered protobufs are to be used for
// exposition in actual monitoring, it is almost always better to not
// expose an incomplete result and instead disregard the returned
// MetricFamily protobufs in case the returned error is non-nil.
Gather() ([]*dto.MetricFamily, error)
}
@ -369,7 +378,6 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
var (
metricChan = make(chan Metric, capMetricChan)
metricHashes = map[uint64]struct{}{}
dimHashes = map[string]uint64{}
wg sync.WaitGroup
errs MultiError // The collected errors to return in the end.
registeredDescIDs map[uint64]struct{} // Only used for pedantic checks
@ -432,19 +440,19 @@ collectLoop:
}
errs.Append(processMetric(
metric, metricFamiliesByName,
metricHashes, dimHashes,
metricHashes,
registeredDescIDs,
))
default:
if goroutineBudget <= 0 || len(collectors) == 0 {
// All collectors are aleady being worked on or
// All collectors are already being worked on or
// we have already as many goroutines started as
// there are collectors. Just process metrics
// from now on.
for metric := range metricChan {
errs.Append(processMetric(
metric, metricFamiliesByName,
metricHashes, dimHashes,
metricHashes,
registeredDescIDs,
))
}
@ -464,7 +472,6 @@ func processMetric(
metric Metric,
metricFamiliesByName map[string]*dto.MetricFamily,
metricHashes map[uint64]struct{},
dimHashes map[string]uint64,
registeredDescIDs map[uint64]struct{},
) error {
desc := metric.Desc()
@ -541,7 +548,7 @@ func processMetric(
}
metricFamiliesByName[desc.fqName] = metricFamily
}
if err := checkMetricConsistency(metricFamily, dtoMetric, metricHashes, dimHashes); err != nil {
if err := checkMetricConsistency(metricFamily, dtoMetric, metricHashes); err != nil {
return err
}
if registeredDescIDs != nil {
@ -583,7 +590,6 @@ func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) {
var (
metricFamiliesByName = map[string]*dto.MetricFamily{}
metricHashes = map[uint64]struct{}{}
dimHashes = map[string]uint64{}
errs MultiError // The collected errors to return in the end.
)
@ -623,7 +629,7 @@ func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) {
metricFamiliesByName[mf.GetName()] = existingMF
}
for _, m := range mf.Metric {
if err := checkMetricConsistency(existingMF, m, metricHashes, dimHashes); err != nil {
if err := checkMetricConsistency(existingMF, m, metricHashes); err != nil {
errs = append(errs, err)
continue
}
@ -700,18 +706,13 @@ func normalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily)
}
// checkMetricConsistency checks if the provided Metric is consistent with the
// provided MetricFamily. It also hashed the Metric labels and the MetricFamily
// provided MetricFamily. It also hashes the Metric labels and the MetricFamily
// name. If the resulting hash is already in the provided metricHashes, an error
// is returned. If not, it is added to metricHashes. The provided dimHashes maps
// MetricFamily names to their dimHash (hashed sorted label names). If dimHashes
// doesn't yet contain a hash for the provided MetricFamily, it is
// added. Otherwise, an error is returned if the existing dimHashes in not equal
// the calculated dimHash.
// is returned. If not, it is added to metricHashes.
func checkMetricConsistency(
metricFamily *dto.MetricFamily,
dtoMetric *dto.Metric,
metricHashes map[uint64]struct{},
dimHashes map[string]uint64,
) error {
// Type consistency with metric family.
if metricFamily.GetType() == dto.MetricType_GAUGE && dtoMetric.Gauge == nil ||
@ -726,24 +727,23 @@ func checkMetricConsistency(
}
for _, labelPair := range dtoMetric.GetLabel() {
if !utf8.ValidString(*labelPair.Value) {
return fmt.Errorf("collected metric's label %s is not utf8: %#v", *labelPair.Name, *labelPair.Value)
if !utf8.ValidString(labelPair.GetValue()) {
return fmt.Errorf("collected metric's label %s is not utf8: %#v", labelPair.GetName(), labelPair.GetValue())
}
}
// Is the metric unique (i.e. no other metric with the same name and the same label values)?
// Is the metric unique (i.e. no other metric with the same name and the same labels)?
h := hashNew()
h = hashAdd(h, metricFamily.GetName())
h = hashAddByte(h, separatorByte)
dh := hashNew()
// Make sure label pairs are sorted. We depend on it for the consistency
// check.
sort.Sort(LabelPairSorter(dtoMetric.Label))
for _, lp := range dtoMetric.Label {
h = hashAdd(h, lp.GetName())
h = hashAddByte(h, separatorByte)
h = hashAdd(h, lp.GetValue())
h = hashAddByte(h, separatorByte)
dh = hashAdd(dh, lp.GetName())
dh = hashAddByte(dh, separatorByte)
}
if _, exists := metricHashes[h]; exists {
return fmt.Errorf(
@ -751,16 +751,6 @@ func checkMetricConsistency(
metricFamily.GetName(), dtoMetric,
)
}
if dimHash, ok := dimHashes[metricFamily.GetName()]; ok {
if dimHash != dh {
return fmt.Errorf(
"collected metric %s %s has label dimensions inconsistent with previously collected metrics in the same metric family",
metricFamily.GetName(), dtoMetric,
)
}
} else {
dimHashes[metricFamily.GetName()] = dh
}
metricHashes[h] = struct{}{}
return nil
}

View file

@ -152,9 +152,7 @@ func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
Value: proto.String(labelValues[i]),
})
}
for _, lp := range desc.constLabelPairs {
labelPairs = append(labelPairs, lp)
}
labelPairs = append(labelPairs, desc.constLabelPairs...)
sort.Sort(LabelPairSorter(labelPairs))
return labelPairs
}

View file

@ -277,6 +277,9 @@ func (m *metricMap) deleteByHashWithLabelValues(
func (m *metricMap) deleteByHashWithLabels(
h uint64, labels Labels, curry []curriedLabelValue,
) bool {
m.mtx.Lock()
defer m.mtx.Unlock()
metrics, ok := m.metrics[h]
if !ok {
return false

22
vendor/vendor.json vendored
View file

@ -738,26 +738,26 @@
{
"checksumSHA1": "4VppKBbzCSmoFfQxGNUm0TYiFCA=",
"path": "github.com/prometheus/client_golang/api",
"revision": "82f5ff156b29e276022b1a958f7d385870fb9814",
"revisionTime": "2018-04-16T23:38:56Z"
"revision": "faf4ec335fe01ae5a6a0eaa34a5a9333bfbd1a30",
"revisionTime": "2018-06-07T12:36:07Z"
},
{
"checksumSHA1": "b+vg1vscoxR9FbKlKBR+2/HmWfA=",
"checksumSHA1": "83pGB3cRG5uqx9O5d+7MCB+TFT4=",
"path": "github.com/prometheus/client_golang/api/prometheus/v1",
"revision": "82f5ff156b29e276022b1a958f7d385870fb9814",
"revisionTime": "2018-04-16T23:38:56Z"
"revision": "faf4ec335fe01ae5a6a0eaa34a5a9333bfbd1a30",
"revisionTime": "2018-06-07T12:36:07Z"
},
{
"checksumSHA1": "I87tkF1e/hrl4d/XIKFfkPRq1ww=",
"checksumSHA1": "WVgL9pNO2RZCCcaXfSYSNEPgtCo=",
"path": "github.com/prometheus/client_golang/prometheus",
"revision": "f504d69affe11ec1ccb2e5948127f86878c9fd57",
"revisionTime": "2018-03-28T13:04:30Z"
"revision": "faf4ec335fe01ae5a6a0eaa34a5a9333bfbd1a30",
"revisionTime": "2018-06-07T12:36:07Z"
},
{
"checksumSHA1": "BM771aKU6hC+5rap48aqvMXczII=",
"checksumSHA1": "MYqKV5uVTfCxP9zBug7naBQ1vr8=",
"path": "github.com/prometheus/client_golang/prometheus/promhttp",
"revision": "f504d69affe11ec1ccb2e5948127f86878c9fd57",
"revisionTime": "2018-03-28T13:04:30Z"
"revision": "faf4ec335fe01ae5a6a0eaa34a5a9333bfbd1a30",
"revisionTime": "2018-06-07T12:36:07Z"
},
{
"checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=",