update vendor
Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
parent
19a32db84d
commit
94d1cfbfbf
10501 changed files with 2307943 additions and 29279 deletions
11
vendor/github.com/prometheus/client_golang/.travis.yml
generated
vendored
11
vendor/github.com/prometheus/client_golang/.travis.yml
generated
vendored
|
@ -2,9 +2,12 @@ sudo: false
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
- 1.7.x # See README.md for current minimum version.
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
|
||||
script:
|
||||
- go test -short ./...
|
||||
- make check_license style unused test-short
|
||||
- if [[ ! $TRAVIS_GO_VERSION =~ ^1\.(7|8|9)\.[x0-9]+$ ]]; then make staticcheck; fi
|
||||
|
|
2
vendor/github.com/prometheus/client_golang/CONTRIBUTING.md
generated
vendored
2
vendor/github.com/prometheus/client_golang/CONTRIBUTING.md
generated
vendored
|
@ -16,3 +16,5 @@ Prometheus uses GitHub to manage reviews of pull requests.
|
|||
and the _Formatting and style_ section of Peter Bourgon's [Go: Best
|
||||
Practices for Production
|
||||
Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style).
|
||||
|
||||
* Be sure to sign off on the [DCO](https://github.com/probot/dco#how-it-works)
|
||||
|
|
23
vendor/github.com/prometheus/client_golang/Dockerfile
generated
vendored
Normal file
23
vendor/github.com/prometheus/client_golang/Dockerfile
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
# This Dockerfile builds an image for a client_golang example.
|
||||
#
|
||||
# Use as (from the root for the client_golang repository):
|
||||
# docker build -f examples/$name/Dockerfile -t prometheus/golang-example-$name .
|
||||
|
||||
# Builder image, where we build the example.
|
||||
FROM golang:1 AS builder
|
||||
WORKDIR /go/src/github.com/prometheus/client_golang
|
||||
COPY . .
|
||||
WORKDIR /go/src/github.com/prometheus/client_golang/prometheus
|
||||
RUN go get -d
|
||||
WORKDIR /go/src/github.com/prometheus/client_golang/examples/random
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -tags netgo -ldflags '-w'
|
||||
WORKDIR /go/src/github.com/prometheus/client_golang/examples/simple
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -tags netgo -ldflags '-w'
|
||||
|
||||
# Final image.
|
||||
FROM prom/busybox
|
||||
LABEL maintainer="The Prometheus Authors <prometheus-developers@googlegroups.com>"
|
||||
COPY --from=builder /go/src/github.com/prometheus/client_golang/examples/random \
|
||||
/go/src/github.com/prometheus/client_golang/examples/simple ./
|
||||
EXPOSE 8080
|
||||
CMD echo Please run an example. Either /random or /simple
|
3
vendor/github.com/prometheus/client_golang/MAINTAINERS.md
generated
vendored
3
vendor/github.com/prometheus/client_golang/MAINTAINERS.md
generated
vendored
|
@ -1 +1,2 @@
|
|||
* Björn Rabenstein <beorn@soundcloud.com>
|
||||
* Krasi Georgiev <kgeorgie@redhat.com> for `api/...`
|
||||
* Björn Rabenstein <beorn@soundcloud.com> for everything else
|
||||
|
|
32
vendor/github.com/prometheus/client_golang/Makefile
generated
vendored
Normal file
32
vendor/github.com/prometheus/client_golang/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Copyright 2018 The Prometheus Authors
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
include Makefile.common
|
||||
|
||||
# http.CloseNotifier is deprecated but we don't want to remove support
|
||||
# from client_golang to not break anybody still using it.
|
||||
STATICCHECK_IGNORE = \
|
||||
github.com/prometheus/client_golang/prometheus/promhttp/delegator*.go:SA1019 \
|
||||
github.com/prometheus/client_golang/prometheus/promhttp/instrument_server_test.go:SA1019 \
|
||||
github.com/prometheus/client_golang/prometheus/http.go:SA1019
|
||||
|
||||
.PHONY: get_dep
|
||||
get_dep:
|
||||
@echo ">> getting dependencies"
|
||||
$(GO) get -t ./...
|
||||
|
||||
.PHONY: test
|
||||
test: get_dep common-test
|
||||
|
||||
.PHONY: test-short
|
||||
test-short: get_dep common-test-short
|
132
vendor/github.com/prometheus/client_golang/Makefile.common
generated
vendored
Normal file
132
vendor/github.com/prometheus/client_golang/Makefile.common
generated
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
# Copyright 2018 The Prometheus Authors
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
# A common Makefile that includes rules to be reused in different prometheus projects.
|
||||
# !!! Open PRs only against the prometheus/prometheus/Makefile.common repository!
|
||||
|
||||
# Example usage :
|
||||
# Create the main Makefile in the root project directory.
|
||||
# include Makefile.common
|
||||
# customTarget:
|
||||
# @echo ">> Running customTarget"
|
||||
#
|
||||
|
||||
# Ensure GOBIN is not set during build so that promu is installed to the correct path
|
||||
unexport GOBIN
|
||||
|
||||
GO ?= go
|
||||
GOFMT ?= $(GO)fmt
|
||||
FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH)))
|
||||
PROMU := $(FIRST_GOPATH)/bin/promu
|
||||
STATICCHECK := $(FIRST_GOPATH)/bin/staticcheck
|
||||
GOVENDOR := $(FIRST_GOPATH)/bin/govendor
|
||||
pkgs = ./...
|
||||
|
||||
PREFIX ?= $(shell pwd)
|
||||
BIN_DIR ?= $(shell pwd)
|
||||
DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD))
|
||||
DOCKER_REPO ?= prom
|
||||
|
||||
.PHONY: all
|
||||
all: style staticcheck unused build test
|
||||
|
||||
# This rule is used to forward a target like "build" to "common-build". This
|
||||
# allows a new "build" target to be defined in a Makefile which includes this
|
||||
# one and override "common-build" without override warnings.
|
||||
%: common-% ;
|
||||
|
||||
.PHONY: common-style
|
||||
common-style:
|
||||
@echo ">> checking code style"
|
||||
@fmtRes=$$($(GOFMT) -d $$(find . -path ./vendor -prune -o -name '*.go' -print)); \
|
||||
if [ -n "$${fmtRes}" ]; then \
|
||||
echo "gofmt checking failed!"; echo "$${fmtRes}"; echo; \
|
||||
echo "Please ensure you are using $$($(GO) version) for formatting code."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: common-check_license
|
||||
common-check_license:
|
||||
@echo ">> checking license header"
|
||||
@licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \
|
||||
awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \
|
||||
done); \
|
||||
if [ -n "$${licRes}" ]; then \
|
||||
echo "license header checking failed:"; echo "$${licRes}"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: common-test-short
|
||||
common-test-short:
|
||||
@echo ">> running short tests"
|
||||
$(GO) test -short $(pkgs)
|
||||
|
||||
.PHONY: common-test
|
||||
common-test:
|
||||
@echo ">> running all tests"
|
||||
$(GO) test -race $(pkgs)
|
||||
|
||||
.PHONY: common-format
|
||||
common-format:
|
||||
@echo ">> formatting code"
|
||||
$(GO) fmt $(pkgs)
|
||||
|
||||
.PHONY: common-vet
|
||||
common-vet:
|
||||
@echo ">> vetting code"
|
||||
$(GO) vet $(pkgs)
|
||||
|
||||
.PHONY: common-staticcheck
|
||||
common-staticcheck: $(STATICCHECK)
|
||||
@echo ">> running staticcheck"
|
||||
$(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs)
|
||||
|
||||
.PHONY: common-unused
|
||||
common-unused: $(GOVENDOR)
|
||||
@echo ">> running check for unused packages"
|
||||
@$(GOVENDOR) list +unused | grep . && exit 1 || echo 'No unused packages'
|
||||
|
||||
.PHONY: common-build
|
||||
common-build: promu
|
||||
@echo ">> building binaries"
|
||||
$(PROMU) build --prefix $(PREFIX)
|
||||
|
||||
.PHONY: common-tarball
|
||||
common-tarball: promu
|
||||
@echo ">> building release tarball"
|
||||
$(PROMU) tarball --prefix $(PREFIX) $(BIN_DIR)
|
||||
|
||||
.PHONY: common-docker
|
||||
common-docker:
|
||||
docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" .
|
||||
|
||||
.PHONY: common-docker-publish
|
||||
common-docker-publish:
|
||||
docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)"
|
||||
|
||||
.PHONY: common-docker-tag-latest
|
||||
common-docker-tag-latest:
|
||||
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):latest"
|
||||
|
||||
.PHONY: promu
|
||||
promu:
|
||||
GOOS= GOARCH= $(GO) get -u github.com/prometheus/promu
|
||||
|
||||
.PHONY: $(STATICCHECK)
|
||||
$(STATICCHECK):
|
||||
GOOS= GOARCH= $(GO) get -u honnef.co/go/tools/cmd/staticcheck
|
||||
|
||||
.PHONY: $(GOVENDOR)
|
||||
$(GOVENDOR):
|
||||
GOOS= GOARCH= $(GO) get -u github.com/kardianos/govendor
|
131
vendor/github.com/prometheus/client_golang/api/client.go
generated
vendored
Normal file
131
vendor/github.com/prometheus/client_golang/api/client.go
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
// Copyright 2015 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
// Package api provides clients for the HTTP APIs.
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultRoundTripper is used if no RoundTripper is set in Config.
|
||||
var DefaultRoundTripper http.RoundTripper = &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
// Config defines configuration parameters for a new client.
|
||||
type Config struct {
|
||||
// The address of the Prometheus to connect to.
|
||||
Address string
|
||||
|
||||
// RoundTripper is used by the Client to drive HTTP requests. If not
|
||||
// provided, DefaultRoundTripper will be used.
|
||||
RoundTripper http.RoundTripper
|
||||
}
|
||||
|
||||
func (cfg *Config) roundTripper() http.RoundTripper {
|
||||
if cfg.RoundTripper == nil {
|
||||
return DefaultRoundTripper
|
||||
}
|
||||
return cfg.RoundTripper
|
||||
}
|
||||
|
||||
// Client is the interface for an API client.
|
||||
type Client interface {
|
||||
URL(ep string, args map[string]string) *url.URL
|
||||
Do(context.Context, *http.Request) (*http.Response, []byte, error)
|
||||
}
|
||||
|
||||
// NewClient returns a new Client.
|
||||
//
|
||||
// It is safe to use the returned Client from multiple goroutines.
|
||||
func NewClient(cfg Config) (Client, error) {
|
||||
u, err := url.Parse(cfg.Address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u.Path = strings.TrimRight(u.Path, "/")
|
||||
|
||||
return &httpClient{
|
||||
endpoint: u,
|
||||
client: http.Client{Transport: cfg.roundTripper()},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type httpClient struct {
|
||||
endpoint *url.URL
|
||||
client http.Client
|
||||
}
|
||||
|
||||
func (c *httpClient) URL(ep string, args map[string]string) *url.URL {
|
||||
p := path.Join(c.endpoint.Path, ep)
|
||||
|
||||
for arg, val := range args {
|
||||
arg = ":" + arg
|
||||
p = strings.Replace(p, arg, val, -1)
|
||||
}
|
||||
|
||||
u := *c.endpoint
|
||||
u.Path = p
|
||||
|
||||
return &u
|
||||
}
|
||||
|
||||
func (c *httpClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, error) {
|
||||
if ctx != nil {
|
||||
req = req.WithContext(ctx)
|
||||
}
|
||||
resp, err := c.client.Do(req)
|
||||
defer func() {
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var body []byte
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
body, err = ioutil.ReadAll(resp.Body)
|
||||
close(done)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
err = resp.Body.Close()
|
||||
<-done
|
||||
if err == nil {
|
||||
err = ctx.Err()
|
||||
}
|
||||
case <-done:
|
||||
}
|
||||
|
||||
return resp, body, err
|
||||
}
|
115
vendor/github.com/prometheus/client_golang/api/client_test.go
generated
vendored
Normal file
115
vendor/github.com/prometheus/client_golang/api/client_test.go
generated
vendored
Normal file
|
@ -0,0 +1,115 @@
|
|||
// Copyright 2015 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
c := Config{}
|
||||
if c.roundTripper() != DefaultRoundTripper {
|
||||
t.Fatalf("expected default roundtripper for nil RoundTripper field")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
address string
|
||||
endpoint string
|
||||
args map[string]string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
address: "http://localhost:9090",
|
||||
endpoint: "/test",
|
||||
expected: "http://localhost:9090/test",
|
||||
},
|
||||
{
|
||||
address: "http://localhost",
|
||||
endpoint: "/test",
|
||||
expected: "http://localhost/test",
|
||||
},
|
||||
{
|
||||
address: "http://localhost:9090",
|
||||
endpoint: "test",
|
||||
expected: "http://localhost:9090/test",
|
||||
},
|
||||
{
|
||||
address: "http://localhost:9090/prefix",
|
||||
endpoint: "/test",
|
||||
expected: "http://localhost:9090/prefix/test",
|
||||
},
|
||||
{
|
||||
address: "https://localhost:9090/",
|
||||
endpoint: "/test/",
|
||||
expected: "https://localhost:9090/test",
|
||||
},
|
||||
{
|
||||
address: "http://localhost:9090",
|
||||
endpoint: "/test/:param",
|
||||
args: map[string]string{
|
||||
"param": "content",
|
||||
},
|
||||
expected: "http://localhost:9090/test/content",
|
||||
},
|
||||
{
|
||||
address: "http://localhost:9090",
|
||||
endpoint: "/test/:param/more/:param",
|
||||
args: map[string]string{
|
||||
"param": "content",
|
||||
},
|
||||
expected: "http://localhost:9090/test/content/more/content",
|
||||
},
|
||||
{
|
||||
address: "http://localhost:9090",
|
||||
endpoint: "/test/:param/more/:foo",
|
||||
args: map[string]string{
|
||||
"param": "content",
|
||||
"foo": "bar",
|
||||
},
|
||||
expected: "http://localhost:9090/test/content/more/bar",
|
||||
},
|
||||
{
|
||||
address: "http://localhost:9090",
|
||||
endpoint: "/test/:param",
|
||||
args: map[string]string{
|
||||
"nonexistent": "content",
|
||||
},
|
||||
expected: "http://localhost:9090/test/:param",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
ep, err := url.Parse(test.address)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hclient := &httpClient{
|
||||
endpoint: ep,
|
||||
client: http.Client{Transport: DefaultRoundTripper},
|
||||
}
|
||||
|
||||
u := hclient.URL(test.endpoint, test.args)
|
||||
if u.String() != test.expected {
|
||||
t.Errorf("unexpected result: got %s, want %s", u, test.expected)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
502
vendor/github.com/prometheus/client_golang/api/prometheus/v1/api.go
generated
vendored
Normal file
502
vendor/github.com/prometheus/client_golang/api/prometheus/v1/api.go
generated
vendored
Normal file
|
@ -0,0 +1,502 @@
|
|||
// Copyright 2017 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
// Package v1 provides bindings to the Prometheus HTTP API v1:
|
||||
// http://prometheus.io/docs/querying/api/
|
||||
package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/api"
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
const (
|
||||
statusAPIError = 422
|
||||
|
||||
apiPrefix = "/api/v1"
|
||||
|
||||
epAlertManagers = apiPrefix + "/alertmanagers"
|
||||
epQuery = apiPrefix + "/query"
|
||||
epQueryRange = apiPrefix + "/query_range"
|
||||
epLabelValues = apiPrefix + "/label/:name/values"
|
||||
epSeries = apiPrefix + "/series"
|
||||
epTargets = apiPrefix + "/targets"
|
||||
epSnapshot = apiPrefix + "/admin/tsdb/snapshot"
|
||||
epDeleteSeries = apiPrefix + "/admin/tsdb/delete_series"
|
||||
epCleanTombstones = apiPrefix + "/admin/tsdb/clean_tombstones"
|
||||
epConfig = apiPrefix + "/status/config"
|
||||
epFlags = apiPrefix + "/status/flags"
|
||||
)
|
||||
|
||||
// ErrorType models the different API error types.
|
||||
type ErrorType string
|
||||
|
||||
// HealthStatus models the health status of a scrape target.
|
||||
type HealthStatus string
|
||||
|
||||
const (
|
||||
// Possible values for ErrorType.
|
||||
ErrBadData ErrorType = "bad_data"
|
||||
ErrTimeout = "timeout"
|
||||
ErrCanceled = "canceled"
|
||||
ErrExec = "execution"
|
||||
ErrBadResponse = "bad_response"
|
||||
|
||||
// Possible values for HealthStatus.
|
||||
HealthGood HealthStatus = "up"
|
||||
HealthUnknown HealthStatus = "unknown"
|
||||
HealthBad HealthStatus = "down"
|
||||
)
|
||||
|
||||
// Error is an error returned by the API.
|
||||
type Error struct {
|
||||
Type ErrorType
|
||||
Msg string
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Type, e.Msg)
|
||||
}
|
||||
|
||||
// Range represents a sliced time range.
|
||||
type Range struct {
|
||||
// The boundaries of the time range.
|
||||
Start, End time.Time
|
||||
// The maximum time between two slices within the boundaries.
|
||||
Step time.Duration
|
||||
}
|
||||
|
||||
// API provides bindings for Prometheus's v1 API.
|
||||
type API interface {
|
||||
// AlertManagers returns an overview of the current state of the Prometheus alert manager discovery.
|
||||
AlertManagers(ctx context.Context) (AlertManagersResult, error)
|
||||
// CleanTombstones removes the deleted data from disk and cleans up the existing tombstones.
|
||||
CleanTombstones(ctx context.Context) error
|
||||
// Config returns the current Prometheus configuration.
|
||||
Config(ctx context.Context) (ConfigResult, error)
|
||||
// DeleteSeries deletes data for a selection of series in a time range.
|
||||
DeleteSeries(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) error
|
||||
// Flags returns the flag values that Prometheus was launched with.
|
||||
Flags(ctx context.Context) (FlagsResult, error)
|
||||
// LabelValues performs a query for the values of the given label.
|
||||
LabelValues(ctx context.Context, label string) (model.LabelValues, error)
|
||||
// Query performs a query for the given time.
|
||||
Query(ctx context.Context, query string, ts time.Time) (model.Value, error)
|
||||
// QueryRange performs a query for the given range.
|
||||
QueryRange(ctx context.Context, query string, r Range) (model.Value, error)
|
||||
// Series finds series by label matchers.
|
||||
Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, error)
|
||||
// Snapshot creates a snapshot of all current data into snapshots/<datetime>-<rand>
|
||||
// under the TSDB's data directory and returns the directory as response.
|
||||
Snapshot(ctx context.Context, skipHead bool) (SnapshotResult, error)
|
||||
// Targets returns an overview of the current state of the Prometheus target discovery.
|
||||
Targets(ctx context.Context) (TargetsResult, error)
|
||||
}
|
||||
|
||||
// AlertManagersResult contains the result from querying the alertmanagers endpoint.
|
||||
type AlertManagersResult struct {
|
||||
Active []AlertManager `json:"activeAlertManagers"`
|
||||
Dropped []AlertManager `json:"droppedAlertManagers"`
|
||||
}
|
||||
|
||||
// AlertManager models a configured Alert Manager.
|
||||
type AlertManager struct {
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// ConfigResult contains the result from querying the config endpoint.
|
||||
type ConfigResult struct {
|
||||
YAML string `json:"yaml"`
|
||||
}
|
||||
|
||||
// FlagsResult contains the result from querying the flag endpoint.
|
||||
type FlagsResult map[string]string
|
||||
|
||||
// SnapshotResult contains the result from querying the snapshot endpoint.
|
||||
type SnapshotResult struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// TargetsResult contains the result from querying the targets endpoint.
|
||||
type TargetsResult struct {
|
||||
Active []ActiveTarget `json:"activeTargets"`
|
||||
Dropped []DroppedTarget `json:"droppedTargets"`
|
||||
}
|
||||
|
||||
// ActiveTarget models an active Prometheus scrape target.
|
||||
type ActiveTarget struct {
|
||||
DiscoveredLabels model.LabelSet `json:"discoveredLabels"`
|
||||
Labels model.LabelSet `json:"labels"`
|
||||
ScrapeURL string `json:"scrapeUrl"`
|
||||
LastError string `json:"lastError"`
|
||||
LastScrape time.Time `json:"lastScrape"`
|
||||
Health HealthStatus `json:"health"`
|
||||
}
|
||||
|
||||
// DroppedTarget models a dropped Prometheus scrape target.
|
||||
type DroppedTarget struct {
|
||||
DiscoveredLabels model.LabelSet `json:"discoveredLabels"`
|
||||
}
|
||||
|
||||
// queryResult contains result data for a query.
|
||||
type queryResult struct {
|
||||
Type model.ValueType `json:"resultType"`
|
||||
Result interface{} `json:"result"`
|
||||
|
||||
// The decoded value.
|
||||
v model.Value
|
||||
}
|
||||
|
||||
func (qr *queryResult) UnmarshalJSON(b []byte) error {
|
||||
v := struct {
|
||||
Type model.ValueType `json:"resultType"`
|
||||
Result json.RawMessage `json:"result"`
|
||||
}{}
|
||||
|
||||
err := json.Unmarshal(b, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch v.Type {
|
||||
case model.ValScalar:
|
||||
var sv model.Scalar
|
||||
err = json.Unmarshal(v.Result, &sv)
|
||||
qr.v = &sv
|
||||
|
||||
case model.ValVector:
|
||||
var vv model.Vector
|
||||
err = json.Unmarshal(v.Result, &vv)
|
||||
qr.v = vv
|
||||
|
||||
case model.ValMatrix:
|
||||
var mv model.Matrix
|
||||
err = json.Unmarshal(v.Result, &mv)
|
||||
qr.v = mv
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("unexpected value type %q", v.Type)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// NewAPI returns a new API for the client.
|
||||
//
|
||||
// It is safe to use the returned API from multiple goroutines.
|
||||
func NewAPI(c api.Client) API {
|
||||
return &httpAPI{client: apiClient{c}}
|
||||
}
|
||||
|
||||
type httpAPI struct {
|
||||
client api.Client
|
||||
}
|
||||
|
||||
func (h *httpAPI) AlertManagers(ctx context.Context) (AlertManagersResult, error) {
|
||||
u := h.client.URL(epAlertManagers, nil)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return AlertManagersResult{}, err
|
||||
}
|
||||
|
||||
_, body, err := h.client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return AlertManagersResult{}, err
|
||||
}
|
||||
|
||||
var res AlertManagersResult
|
||||
err = json.Unmarshal(body, &res)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (h *httpAPI) CleanTombstones(ctx context.Context) error {
|
||||
u := h.client.URL(epCleanTombstones, nil)
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, u.String(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = h.client.Do(ctx, req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *httpAPI) Config(ctx context.Context) (ConfigResult, error) {
|
||||
u := h.client.URL(epConfig, nil)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return ConfigResult{}, err
|
||||
}
|
||||
|
||||
_, body, err := h.client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return ConfigResult{}, err
|
||||
}
|
||||
|
||||
var res ConfigResult
|
||||
err = json.Unmarshal(body, &res)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (h *httpAPI) DeleteSeries(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) error {
|
||||
u := h.client.URL(epDeleteSeries, nil)
|
||||
q := u.Query()
|
||||
|
||||
for _, m := range matches {
|
||||
q.Add("match[]", m)
|
||||
}
|
||||
|
||||
q.Set("start", startTime.Format(time.RFC3339Nano))
|
||||
q.Set("end", endTime.Format(time.RFC3339Nano))
|
||||
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, u.String(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = h.client.Do(ctx, req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *httpAPI) Flags(ctx context.Context) (FlagsResult, error) {
|
||||
u := h.client.URL(epFlags, nil)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return FlagsResult{}, err
|
||||
}
|
||||
|
||||
_, body, err := h.client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return FlagsResult{}, err
|
||||
}
|
||||
|
||||
var res FlagsResult
|
||||
err = json.Unmarshal(body, &res)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (h *httpAPI) LabelValues(ctx context.Context, label string) (model.LabelValues, error) {
|
||||
u := h.client.URL(epLabelValues, map[string]string{"name": label})
|
||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, body, err := h.client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var labelValues model.LabelValues
|
||||
err = json.Unmarshal(body, &labelValues)
|
||||
return labelValues, err
|
||||
}
|
||||
|
||||
func (h *httpAPI) Query(ctx context.Context, query string, ts time.Time) (model.Value, error) {
|
||||
u := h.client.URL(epQuery, nil)
|
||||
q := u.Query()
|
||||
|
||||
q.Set("query", query)
|
||||
if !ts.IsZero() {
|
||||
q.Set("time", ts.Format(time.RFC3339Nano))
|
||||
}
|
||||
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, body, err := h.client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var qres queryResult
|
||||
err = json.Unmarshal(body, &qres)
|
||||
|
||||
return model.Value(qres.v), err
|
||||
}
|
||||
|
||||
func (h *httpAPI) QueryRange(ctx context.Context, query string, r Range) (model.Value, error) {
|
||||
u := h.client.URL(epQueryRange, nil)
|
||||
q := u.Query()
|
||||
|
||||
var (
|
||||
start = r.Start.Format(time.RFC3339Nano)
|
||||
end = r.End.Format(time.RFC3339Nano)
|
||||
step = strconv.FormatFloat(r.Step.Seconds(), 'f', 3, 64)
|
||||
)
|
||||
|
||||
q.Set("query", query)
|
||||
q.Set("start", start)
|
||||
q.Set("end", end)
|
||||
q.Set("step", step)
|
||||
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, body, err := h.client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var qres queryResult
|
||||
err = json.Unmarshal(body, &qres)
|
||||
|
||||
return model.Value(qres.v), err
|
||||
}
|
||||
|
||||
func (h *httpAPI) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, error) {
|
||||
u := h.client.URL(epSeries, nil)
|
||||
q := u.Query()
|
||||
|
||||
for _, m := range matches {
|
||||
q.Add("match[]", m)
|
||||
}
|
||||
|
||||
q.Set("start", startTime.Format(time.RFC3339Nano))
|
||||
q.Set("end", endTime.Format(time.RFC3339Nano))
|
||||
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, body, err := h.client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var mset []model.LabelSet
|
||||
err = json.Unmarshal(body, &mset)
|
||||
return mset, err
|
||||
}
|
||||
|
||||
func (h *httpAPI) Snapshot(ctx context.Context, skipHead bool) (SnapshotResult, error) {
|
||||
u := h.client.URL(epSnapshot, nil)
|
||||
q := u.Query()
|
||||
|
||||
q.Set("skip_head", strconv.FormatBool(skipHead))
|
||||
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, u.String(), nil)
|
||||
if err != nil {
|
||||
return SnapshotResult{}, err
|
||||
}
|
||||
|
||||
_, body, err := h.client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return SnapshotResult{}, err
|
||||
}
|
||||
|
||||
var res SnapshotResult
|
||||
err = json.Unmarshal(body, &res)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (h *httpAPI) Targets(ctx context.Context) (TargetsResult, error) {
|
||||
u := h.client.URL(epTargets, nil)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return TargetsResult{}, err
|
||||
}
|
||||
|
||||
_, body, err := h.client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return TargetsResult{}, err
|
||||
}
|
||||
|
||||
var res TargetsResult
|
||||
err = json.Unmarshal(body, &res)
|
||||
return res, err
|
||||
}
|
||||
|
||||
// apiClient wraps a regular client and processes successful API responses.
|
||||
// Successful also includes responses that errored at the API level.
|
||||
type apiClient struct {
|
||||
api.Client
|
||||
}
|
||||
|
||||
type apiResponse struct {
|
||||
Status string `json:"status"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
ErrorType ErrorType `json:"errorType"`
|
||||
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 {
|
||||
return resp, body, err
|
||||
}
|
||||
|
||||
code := resp.StatusCode
|
||||
|
||||
if code/100 != 2 && !apiError(code) {
|
||||
return resp, body, &Error{
|
||||
Type: ErrBadResponse,
|
||||
Msg: fmt.Sprintf("bad response code %d", resp.StatusCode),
|
||||
}
|
||||
}
|
||||
|
||||
var result apiResponse
|
||||
|
||||
if err = json.Unmarshal(body, &result); err != nil {
|
||||
return resp, body, &Error{
|
||||
Type: ErrBadResponse,
|
||||
Msg: err.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
if apiError(code) != (result.Status == "error") {
|
||||
err = &Error{
|
||||
Type: ErrBadResponse,
|
||||
Msg: "inconsistent body for response code",
|
||||
}
|
||||
}
|
||||
|
||||
if apiError(code) && result.Status == "error" {
|
||||
err = &Error{
|
||||
Type: result.ErrorType,
|
||||
Msg: result.Error,
|
||||
}
|
||||
}
|
||||
|
||||
return resp, []byte(result.Data), err
|
||||
}
|
706
vendor/github.com/prometheus/client_golang/api/prometheus/v1/api_test.go
generated
vendored
Normal file
706
vendor/github.com/prometheus/client_golang/api/prometheus/v1/api_test.go
generated
vendored
Normal file
|
@ -0,0 +1,706 @@
|
|||
// Copyright 2017 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
type apiTest struct {
|
||||
do func() (interface{}, error)
|
||||
inErr error
|
||||
inRes interface{}
|
||||
|
||||
reqPath string
|
||||
reqParam url.Values
|
||||
reqMethod string
|
||||
res interface{}
|
||||
err error
|
||||
}
|
||||
|
||||
type apiTestClient struct {
|
||||
*testing.T
|
||||
curTest apiTest
|
||||
}
|
||||
|
||||
func (c *apiTestClient) URL(ep string, args map[string]string) *url.URL {
|
||||
path := ep
|
||||
for k, v := range args {
|
||||
path = strings.Replace(path, ":"+k, v, -1)
|
||||
}
|
||||
u := &url.URL{
|
||||
Host: "test:9090",
|
||||
Path: path,
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
func (c *apiTestClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, error) {
|
||||
|
||||
test := c.curTest
|
||||
|
||||
if req.URL.Path != test.reqPath {
|
||||
c.Errorf("unexpected request path: want %s, got %s", test.reqPath, req.URL.Path)
|
||||
}
|
||||
if req.Method != test.reqMethod {
|
||||
c.Errorf("unexpected request method: want %s, got %s", test.reqMethod, req.Method)
|
||||
}
|
||||
|
||||
b, err := json.Marshal(test.inRes)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
resp := &http.Response{}
|
||||
if test.inErr != nil {
|
||||
resp.StatusCode = statusAPIError
|
||||
} else {
|
||||
resp.StatusCode = http.StatusOK
|
||||
}
|
||||
|
||||
return resp, b, test.inErr
|
||||
}
|
||||
|
||||
func TestAPIs(t *testing.T) {
|
||||
|
||||
testTime := time.Now()
|
||||
|
||||
client := &apiTestClient{T: t}
|
||||
|
||||
promAPI := &httpAPI{
|
||||
client: client,
|
||||
}
|
||||
|
||||
doAlertManagers := func() func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return promAPI.AlertManagers(context.Background())
|
||||
}
|
||||
}
|
||||
|
||||
doCleanTombstones := func() func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return nil, promAPI.CleanTombstones(context.Background())
|
||||
}
|
||||
}
|
||||
|
||||
doConfig := func() func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return promAPI.Config(context.Background())
|
||||
}
|
||||
}
|
||||
|
||||
doDeleteSeries := func(matcher string, startTime time.Time, endTime time.Time) func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return nil, promAPI.DeleteSeries(context.Background(), []string{matcher}, startTime, endTime)
|
||||
}
|
||||
}
|
||||
|
||||
doFlags := func() func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return promAPI.Flags(context.Background())
|
||||
}
|
||||
}
|
||||
|
||||
doLabelValues := func(label string) func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return promAPI.LabelValues(context.Background(), label)
|
||||
}
|
||||
}
|
||||
|
||||
doQuery := func(q string, ts time.Time) func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return promAPI.Query(context.Background(), q, ts)
|
||||
}
|
||||
}
|
||||
|
||||
doQueryRange := func(q string, rng Range) func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return promAPI.QueryRange(context.Background(), q, rng)
|
||||
}
|
||||
}
|
||||
|
||||
doSeries := func(matcher string, startTime time.Time, endTime time.Time) func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return promAPI.Series(context.Background(), []string{matcher}, startTime, endTime)
|
||||
}
|
||||
}
|
||||
|
||||
doSnapshot := func(skipHead bool) func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return promAPI.Snapshot(context.Background(), skipHead)
|
||||
}
|
||||
}
|
||||
|
||||
doTargets := func() func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
return promAPI.Targets(context.Background())
|
||||
}
|
||||
}
|
||||
|
||||
queryTests := []apiTest{
|
||||
{
|
||||
do: doQuery("2", testTime),
|
||||
inRes: &queryResult{
|
||||
Type: model.ValScalar,
|
||||
Result: &model.Scalar{
|
||||
Value: 2,
|
||||
Timestamp: model.TimeFromUnix(testTime.Unix()),
|
||||
},
|
||||
},
|
||||
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/query",
|
||||
reqParam: url.Values{
|
||||
"query": []string{"2"},
|
||||
"time": []string{testTime.Format(time.RFC3339Nano)},
|
||||
},
|
||||
res: &model.Scalar{
|
||||
Value: 2,
|
||||
Timestamp: model.TimeFromUnix(testTime.Unix()),
|
||||
},
|
||||
},
|
||||
{
|
||||
do: doQuery("2", testTime),
|
||||
inErr: fmt.Errorf("some error"),
|
||||
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/query",
|
||||
reqParam: url.Values{
|
||||
"query": []string{"2"},
|
||||
"time": []string{testTime.Format(time.RFC3339Nano)},
|
||||
},
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
|
||||
{
|
||||
do: doQueryRange("2", Range{
|
||||
Start: testTime.Add(-time.Minute),
|
||||
End: testTime,
|
||||
Step: time.Minute,
|
||||
}),
|
||||
inErr: fmt.Errorf("some error"),
|
||||
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/query_range",
|
||||
reqParam: url.Values{
|
||||
"query": []string{"2"},
|
||||
"start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)},
|
||||
"end": []string{testTime.Format(time.RFC3339Nano)},
|
||||
"step": []string{time.Minute.String()},
|
||||
},
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
|
||||
{
|
||||
do: doLabelValues("mylabel"),
|
||||
inRes: []string{"val1", "val2"},
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/label/mylabel/values",
|
||||
res: model.LabelValues{"val1", "val2"},
|
||||
},
|
||||
|
||||
{
|
||||
do: doLabelValues("mylabel"),
|
||||
inErr: fmt.Errorf("some error"),
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/label/mylabel/values",
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
|
||||
{
|
||||
do: doSeries("up", testTime.Add(-time.Minute), testTime),
|
||||
inRes: []map[string]string{
|
||||
{
|
||||
"__name__": "up",
|
||||
"job": "prometheus",
|
||||
"instance": "localhost:9090"},
|
||||
},
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/series",
|
||||
reqParam: url.Values{
|
||||
"match": []string{"up"},
|
||||
"start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)},
|
||||
"end": []string{testTime.Format(time.RFC3339Nano)},
|
||||
},
|
||||
res: []model.LabelSet{
|
||||
model.LabelSet{
|
||||
"__name__": "up",
|
||||
"job": "prometheus",
|
||||
"instance": "localhost:9090",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
do: doSeries("up", testTime.Add(-time.Minute), testTime),
|
||||
inErr: fmt.Errorf("some error"),
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/series",
|
||||
reqParam: url.Values{
|
||||
"match": []string{"up"},
|
||||
"start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)},
|
||||
"end": []string{testTime.Format(time.RFC3339Nano)},
|
||||
},
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
|
||||
{
|
||||
do: doSnapshot(true),
|
||||
inRes: map[string]string{
|
||||
"name": "20171210T211224Z-2be650b6d019eb54",
|
||||
},
|
||||
reqMethod: "POST",
|
||||
reqPath: "/api/v1/admin/tsdb/snapshot",
|
||||
reqParam: url.Values{
|
||||
"skip_head": []string{"true"},
|
||||
},
|
||||
res: SnapshotResult{
|
||||
Name: "20171210T211224Z-2be650b6d019eb54",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
do: doSnapshot(true),
|
||||
inErr: fmt.Errorf("some error"),
|
||||
reqMethod: "POST",
|
||||
reqPath: "/api/v1/admin/tsdb/snapshot",
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
|
||||
{
|
||||
do: doCleanTombstones(),
|
||||
reqMethod: "POST",
|
||||
reqPath: "/api/v1/admin/tsdb/clean_tombstones",
|
||||
},
|
||||
|
||||
{
|
||||
do: doCleanTombstones(),
|
||||
inErr: fmt.Errorf("some error"),
|
||||
reqMethod: "POST",
|
||||
reqPath: "/api/v1/admin/tsdb/clean_tombstones",
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
|
||||
{
|
||||
do: doDeleteSeries("up", testTime.Add(-time.Minute), testTime),
|
||||
inRes: []map[string]string{
|
||||
{
|
||||
"__name__": "up",
|
||||
"job": "prometheus",
|
||||
"instance": "localhost:9090"},
|
||||
},
|
||||
reqMethod: "POST",
|
||||
reqPath: "/api/v1/admin/tsdb/delete_series",
|
||||
reqParam: url.Values{
|
||||
"match": []string{"up"},
|
||||
"start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)},
|
||||
"end": []string{testTime.Format(time.RFC3339Nano)},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
do: doDeleteSeries("up", testTime.Add(-time.Minute), testTime),
|
||||
inErr: fmt.Errorf("some error"),
|
||||
reqMethod: "POST",
|
||||
reqPath: "/api/v1/admin/tsdb/delete_series",
|
||||
reqParam: url.Values{
|
||||
"match": []string{"up"},
|
||||
"start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)},
|
||||
"end": []string{testTime.Format(time.RFC3339Nano)},
|
||||
},
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
|
||||
{
|
||||
do: doConfig(),
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/status/config",
|
||||
inRes: map[string]string{
|
||||
"yaml": "<content of the loaded config file in YAML>",
|
||||
},
|
||||
res: ConfigResult{
|
||||
YAML: "<content of the loaded config file in YAML>",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
do: doConfig(),
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/status/config",
|
||||
inErr: fmt.Errorf("some error"),
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
|
||||
{
|
||||
do: doFlags(),
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/status/flags",
|
||||
inRes: map[string]string{
|
||||
"alertmanager.notification-queue-capacity": "10000",
|
||||
"alertmanager.timeout": "10s",
|
||||
"log.level": "info",
|
||||
"query.lookback-delta": "5m",
|
||||
"query.max-concurrency": "20",
|
||||
},
|
||||
res: FlagsResult{
|
||||
"alertmanager.notification-queue-capacity": "10000",
|
||||
"alertmanager.timeout": "10s",
|
||||
"log.level": "info",
|
||||
"query.lookback-delta": "5m",
|
||||
"query.max-concurrency": "20",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
do: doFlags(),
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/status/flags",
|
||||
inErr: fmt.Errorf("some error"),
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
|
||||
{
|
||||
do: doAlertManagers(),
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/alertmanagers",
|
||||
inRes: map[string]interface{}{
|
||||
"activeAlertManagers": []map[string]string{
|
||||
{
|
||||
"url": "http://127.0.0.1:9091/api/v1/alerts",
|
||||
},
|
||||
},
|
||||
"droppedAlertManagers": []map[string]string{
|
||||
{
|
||||
"url": "http://127.0.0.1:9092/api/v1/alerts",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: AlertManagersResult{
|
||||
Active: []AlertManager{
|
||||
{
|
||||
URL: "http://127.0.0.1:9091/api/v1/alerts",
|
||||
},
|
||||
},
|
||||
Dropped: []AlertManager{
|
||||
{
|
||||
URL: "http://127.0.0.1:9092/api/v1/alerts",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
do: doAlertManagers(),
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/alertmanagers",
|
||||
inErr: fmt.Errorf("some error"),
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
|
||||
{
|
||||
do: doTargets(),
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/targets",
|
||||
inRes: map[string]interface{}{
|
||||
"activeTargets": []map[string]interface{}{
|
||||
{
|
||||
"discoveredLabels": map[string]string{
|
||||
"__address__": "127.0.0.1:9090",
|
||||
"__metrics_path__": "/metrics",
|
||||
"__scheme__": "http",
|
||||
"job": "prometheus",
|
||||
},
|
||||
"labels": map[string]string{
|
||||
"instance": "127.0.0.1:9090",
|
||||
"job": "prometheus",
|
||||
},
|
||||
"scrapeUrl": "http://127.0.0.1:9090",
|
||||
"lastError": "error while scraping target",
|
||||
"lastScrape": testTime.UTC().Format(time.RFC3339Nano),
|
||||
"health": "up",
|
||||
},
|
||||
},
|
||||
"droppedTargets": []map[string]interface{}{
|
||||
{
|
||||
"discoveredLabels": map[string]string{
|
||||
"__address__": "127.0.0.1:9100",
|
||||
"__metrics_path__": "/metrics",
|
||||
"__scheme__": "http",
|
||||
"job": "node",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: TargetsResult{
|
||||
Active: []ActiveTarget{
|
||||
{
|
||||
DiscoveredLabels: model.LabelSet{
|
||||
"__address__": "127.0.0.1:9090",
|
||||
"__metrics_path__": "/metrics",
|
||||
"__scheme__": "http",
|
||||
"job": "prometheus",
|
||||
},
|
||||
Labels: model.LabelSet{
|
||||
"instance": "127.0.0.1:9090",
|
||||
"job": "prometheus",
|
||||
},
|
||||
ScrapeURL: "http://127.0.0.1:9090",
|
||||
LastError: "error while scraping target",
|
||||
LastScrape: testTime.UTC(),
|
||||
Health: HealthGood,
|
||||
},
|
||||
},
|
||||
Dropped: []DroppedTarget{
|
||||
{
|
||||
DiscoveredLabels: model.LabelSet{
|
||||
"__address__": "127.0.0.1:9100",
|
||||
"__metrics_path__": "/metrics",
|
||||
"__scheme__": "http",
|
||||
"job": "node",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
do: doTargets(),
|
||||
reqMethod: "GET",
|
||||
reqPath: "/api/v1/targets",
|
||||
inErr: fmt.Errorf("some error"),
|
||||
err: fmt.Errorf("some error"),
|
||||
},
|
||||
}
|
||||
|
||||
var tests []apiTest
|
||||
tests = append(tests, queryTests...)
|
||||
|
||||
for _, test := range tests {
|
||||
client.curTest = test
|
||||
|
||||
res, err := test.do()
|
||||
|
||||
if test.err != nil {
|
||||
if err == nil {
|
||||
t.Errorf("expected error %q but got none", test.err)
|
||||
continue
|
||||
}
|
||||
if err.Error() != test.err.Error() {
|
||||
t.Errorf("unexpected error: want %s, got %s", test.err, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(res, test.res) {
|
||||
t.Errorf("unexpected result: want %v, got %v", test.res, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type testClient struct {
|
||||
*testing.T
|
||||
|
||||
ch chan apiClientTest
|
||||
req *http.Request
|
||||
}
|
||||
|
||||
type apiClientTest struct {
|
||||
code int
|
||||
response interface{}
|
||||
expected string
|
||||
err *Error
|
||||
}
|
||||
|
||||
func (c *testClient) URL(ep string, args map[string]string) *url.URL {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *testClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, error) {
|
||||
if ctx == nil {
|
||||
c.Fatalf("context was not passed down")
|
||||
}
|
||||
if req != c.req {
|
||||
c.Fatalf("request was not passed down")
|
||||
}
|
||||
|
||||
test := <-c.ch
|
||||
|
||||
var b []byte
|
||||
var err error
|
||||
|
||||
switch v := test.response.(type) {
|
||||
case string:
|
||||
b = []byte(v)
|
||||
default:
|
||||
b, err = json.Marshal(v)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
resp := &http.Response{
|
||||
StatusCode: test.code,
|
||||
}
|
||||
|
||||
return resp, b, nil
|
||||
}
|
||||
|
||||
func TestAPIClientDo(t *testing.T) {
|
||||
tests := []apiClientTest{
|
||||
{
|
||||
response: &apiResponse{
|
||||
Status: "error",
|
||||
Data: json.RawMessage(`null`),
|
||||
ErrorType: ErrBadData,
|
||||
Error: "failed",
|
||||
},
|
||||
err: &Error{
|
||||
Type: ErrBadData,
|
||||
Msg: "failed",
|
||||
},
|
||||
code: statusAPIError,
|
||||
expected: `null`,
|
||||
},
|
||||
{
|
||||
response: &apiResponse{
|
||||
Status: "error",
|
||||
Data: json.RawMessage(`"test"`),
|
||||
ErrorType: ErrTimeout,
|
||||
Error: "timed out",
|
||||
},
|
||||
err: &Error{
|
||||
Type: ErrTimeout,
|
||||
Msg: "timed out",
|
||||
},
|
||||
code: statusAPIError,
|
||||
expected: `test`,
|
||||
},
|
||||
{
|
||||
response: "bad json",
|
||||
err: &Error{
|
||||
Type: ErrBadResponse,
|
||||
Msg: "bad response code 500",
|
||||
},
|
||||
code: http.StatusInternalServerError,
|
||||
},
|
||||
{
|
||||
response: &apiResponse{
|
||||
Status: "error",
|
||||
Data: json.RawMessage(`null`),
|
||||
ErrorType: ErrBadData,
|
||||
Error: "end timestamp must not be before start time",
|
||||
},
|
||||
err: &Error{
|
||||
Type: ErrBadData,
|
||||
Msg: "end timestamp must not be before start time",
|
||||
},
|
||||
code: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
response: "bad json",
|
||||
err: &Error{
|
||||
Type: ErrBadResponse,
|
||||
Msg: "invalid character 'b' looking for beginning of value",
|
||||
},
|
||||
code: statusAPIError,
|
||||
},
|
||||
{
|
||||
response: &apiResponse{
|
||||
Status: "success",
|
||||
Data: json.RawMessage(`"test"`),
|
||||
},
|
||||
err: &Error{
|
||||
Type: ErrBadResponse,
|
||||
Msg: "inconsistent body for response code",
|
||||
},
|
||||
code: statusAPIError,
|
||||
},
|
||||
{
|
||||
response: &apiResponse{
|
||||
Status: "success",
|
||||
Data: json.RawMessage(`"test"`),
|
||||
ErrorType: ErrTimeout,
|
||||
Error: "timed out",
|
||||
},
|
||||
err: &Error{
|
||||
Type: ErrBadResponse,
|
||||
Msg: "inconsistent body for response code",
|
||||
},
|
||||
code: statusAPIError,
|
||||
},
|
||||
{
|
||||
response: &apiResponse{
|
||||
Status: "error",
|
||||
Data: json.RawMessage(`"test"`),
|
||||
ErrorType: ErrTimeout,
|
||||
Error: "timed out",
|
||||
},
|
||||
err: &Error{
|
||||
Type: ErrBadResponse,
|
||||
Msg: "inconsistent body for response code",
|
||||
},
|
||||
code: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
tc := &testClient{
|
||||
T: t,
|
||||
ch: make(chan apiClientTest, 1),
|
||||
req: &http.Request{},
|
||||
}
|
||||
client := &apiClient{tc}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
tc.ch <- test
|
||||
|
||||
_, body, err := client.Do(context.Background(), tc.req)
|
||||
|
||||
if test.err != nil {
|
||||
if err == nil {
|
||||
t.Errorf("expected error %q but got none", test.err)
|
||||
continue
|
||||
}
|
||||
if test.err.Error() != err.Error() {
|
||||
t.Errorf("unexpected error: want %q, got %q", test.err, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("unexpeceted error %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
want, got := test.expected, string(body)
|
||||
if want != got {
|
||||
t.Errorf("unexpected body: want %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
}
|
106
vendor/github.com/prometheus/client_golang/examples/random/main.go
generated
vendored
Normal file
106
vendor/github.com/prometheus/client_golang/examples/random/main.go
generated
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Copyright 2015 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// A simple example exposing fictional RPC latencies with different types of
|
||||
// random distributions (uniform, normal, and exponential) as Prometheus
|
||||
// metrics.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
var (
|
||||
addr = flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.")
|
||||
uniformDomain = flag.Float64("uniform.domain", 0.0002, "The domain for the uniform distribution.")
|
||||
normDomain = flag.Float64("normal.domain", 0.0002, "The domain for the normal distribution.")
|
||||
normMean = flag.Float64("normal.mean", 0.00001, "The mean for the normal distribution.")
|
||||
oscillationPeriod = flag.Duration("oscillation-period", 10*time.Minute, "The duration of the rate oscillation period.")
|
||||
)
|
||||
|
||||
var (
|
||||
// Create a summary to track fictional interservice RPC latencies for three
|
||||
// distinct services with different latency distributions. These services are
|
||||
// differentiated via a "service" label.
|
||||
rpcDurations = prometheus.NewSummaryVec(
|
||||
prometheus.SummaryOpts{
|
||||
Name: "rpc_durations_seconds",
|
||||
Help: "RPC latency distributions.",
|
||||
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
|
||||
},
|
||||
[]string{"service"},
|
||||
)
|
||||
// The same as above, but now as a histogram, and only for the normal
|
||||
// distribution. The buckets are targeted to the parameters of the
|
||||
// normal distribution, with 20 buckets centered on the mean, each
|
||||
// half-sigma wide.
|
||||
rpcDurationsHistogram = prometheus.NewHistogram(prometheus.HistogramOpts{
|
||||
Name: "rpc_durations_histogram_seconds",
|
||||
Help: "RPC latency distributions.",
|
||||
Buckets: prometheus.LinearBuckets(*normMean-5**normDomain, .5**normDomain, 20),
|
||||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Register the summary and the histogram with Prometheus's default registry.
|
||||
prometheus.MustRegister(rpcDurations)
|
||||
prometheus.MustRegister(rpcDurationsHistogram)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
start := time.Now()
|
||||
|
||||
oscillationFactor := func() float64 {
|
||||
return 2 + math.Sin(math.Sin(2*math.Pi*float64(time.Since(start))/float64(*oscillationPeriod)))
|
||||
}
|
||||
|
||||
// Periodically record some sample latencies for the three services.
|
||||
go func() {
|
||||
for {
|
||||
v := rand.Float64() * *uniformDomain
|
||||
rpcDurations.WithLabelValues("uniform").Observe(v)
|
||||
time.Sleep(time.Duration(100*oscillationFactor()) * time.Millisecond)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
v := (rand.NormFloat64() * *normDomain) + *normMean
|
||||
rpcDurations.WithLabelValues("normal").Observe(v)
|
||||
rpcDurationsHistogram.Observe(v)
|
||||
time.Sleep(time.Duration(75*oscillationFactor()) * time.Millisecond)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
v := rand.ExpFloat64() / 1e6
|
||||
rpcDurations.WithLabelValues("exponential").Observe(v)
|
||||
time.Sleep(time.Duration(50*oscillationFactor()) * time.Millisecond)
|
||||
}
|
||||
}()
|
||||
|
||||
// Expose the registered metrics via HTTP.
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
log.Fatal(http.ListenAndServe(*addr, nil))
|
||||
}
|
31
vendor/github.com/prometheus/client_golang/examples/simple/main.go
generated
vendored
Normal file
31
vendor/github.com/prometheus/client_golang/examples/simple/main.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2015 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// A minimal example of how to include Prometheus instrumentation.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
var addr = flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
log.Fatal(http.ListenAndServe(*addr, nil))
|
||||
}
|
72
vendor/github.com/prometheus/client_golang/prometheus/collector.go
generated
vendored
72
vendor/github.com/prometheus/client_golang/prometheus/collector.go
generated
vendored
|
@ -29,27 +29,71 @@ type Collector interface {
|
|||
// collected by this Collector to the provided channel and returns once
|
||||
// the last descriptor has been sent. The sent descriptors fulfill the
|
||||
// consistency and uniqueness requirements described in the Desc
|
||||
// documentation. (It is valid if one and the same Collector sends
|
||||
// duplicate descriptors. Those duplicates are simply ignored. However,
|
||||
// two different Collectors must not send duplicate descriptors.) This
|
||||
// method idempotently sends the same descriptors throughout the
|
||||
// lifetime of the Collector. If a Collector encounters an error while
|
||||
// executing this method, it must send an invalid descriptor (created
|
||||
// with NewInvalidDesc) to signal the error to the registry.
|
||||
// documentation.
|
||||
//
|
||||
// It is valid if one and the same Collector sends duplicate
|
||||
// descriptors. Those duplicates are simply ignored. However, two
|
||||
// different Collectors must not send duplicate descriptors.
|
||||
//
|
||||
// Sending no descriptor at all marks the Collector as “unchecked”,
|
||||
// i.e. no checks will be performed at registration time, and the
|
||||
// Collector may yield any Metric it sees fit in its Collect method.
|
||||
//
|
||||
// This method idempotently sends the same descriptors throughout the
|
||||
// lifetime of the Collector.
|
||||
//
|
||||
// If a Collector encounters an error while executing this method, it
|
||||
// must send an invalid descriptor (created with NewInvalidDesc) to
|
||||
// signal the error to the registry.
|
||||
Describe(chan<- *Desc)
|
||||
// Collect is called by the Prometheus registry when collecting
|
||||
// metrics. The implementation sends each collected metric via the
|
||||
// provided channel and returns once the last metric has been sent. The
|
||||
// descriptor of each sent metric is one of those returned by
|
||||
// Describe. Returned metrics that share the same descriptor must differ
|
||||
// in their variable label values. This method may be called
|
||||
// concurrently and must therefore be implemented in a concurrency safe
|
||||
// way. Blocking occurs at the expense of total performance of rendering
|
||||
// all registered metrics. Ideally, Collector implementations support
|
||||
// concurrent readers.
|
||||
// descriptor of each sent metric is one of those returned by Describe
|
||||
// (unless the Collector is unchecked, see above). Returned metrics that
|
||||
// share the same descriptor must differ in their variable label
|
||||
// values.
|
||||
//
|
||||
// This method may be called concurrently and must therefore be
|
||||
// implemented in a concurrency safe way. Blocking occurs at the expense
|
||||
// of total performance of rendering all registered metrics. Ideally,
|
||||
// Collector implementations support concurrent readers.
|
||||
Collect(chan<- Metric)
|
||||
}
|
||||
|
||||
// DescribeByCollect is a helper to implement the Describe method of a custom
|
||||
// Collector. It collects the metrics from the provided Collector and sends
|
||||
// their descriptors to the provided channel.
|
||||
//
|
||||
// If a Collector collects the same metrics throughout its lifetime, its
|
||||
// Describe method can simply be implemented as:
|
||||
//
|
||||
// func (c customCollector) Describe(ch chan<- *Desc) {
|
||||
// DescribeByCollect(c, ch)
|
||||
// }
|
||||
//
|
||||
// However, this will not work if the metrics collected change dynamically over
|
||||
// the lifetime of the Collector in a way that their combined set of descriptors
|
||||
// changes as well. The shortcut implementation will then violate the contract
|
||||
// of the Describe method. If a Collector sometimes collects no metrics at all
|
||||
// (for example vectors like CounterVec, GaugeVec, etc., which only collect
|
||||
// metrics after a metric with a fully specified label set has been accessed),
|
||||
// it might even get registered as an unchecked Collecter (cf. the Register
|
||||
// method of the Registerer interface). Hence, only use this shortcut
|
||||
// implementation of Describe if you are certain to fulfill the contract.
|
||||
//
|
||||
// The Collector example demonstrates a use of DescribeByCollect.
|
||||
func DescribeByCollect(c Collector, descs chan<- *Desc) {
|
||||
metrics := make(chan Metric)
|
||||
go func() {
|
||||
c.Collect(metrics)
|
||||
close(metrics)
|
||||
}()
|
||||
for m := range metrics {
|
||||
descs <- m.Desc()
|
||||
}
|
||||
}
|
||||
|
||||
// selfCollector implements Collector for a single Metric so that the Metric
|
||||
// collects itself. Add it as an anonymous field to a struct that implements
|
||||
// Metric, and call init with the Metric itself as an argument.
|
||||
|
|
62
vendor/github.com/prometheus/client_golang/prometheus/collector_test.go
generated
vendored
Normal file
62
vendor/github.com/prometheus/client_golang/prometheus/collector_test.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import "testing"
|
||||
|
||||
type collectorDescribedByCollect struct {
|
||||
cnt Counter
|
||||
gge Gauge
|
||||
}
|
||||
|
||||
func (c collectorDescribedByCollect) Collect(ch chan<- Metric) {
|
||||
ch <- c.cnt
|
||||
ch <- c.gge
|
||||
}
|
||||
|
||||
func (c collectorDescribedByCollect) Describe(ch chan<- *Desc) {
|
||||
DescribeByCollect(c, ch)
|
||||
}
|
||||
|
||||
func TestDescribeByCollect(t *testing.T) {
|
||||
|
||||
goodCollector := collectorDescribedByCollect{
|
||||
cnt: NewCounter(CounterOpts{Name: "c1", Help: "help c1"}),
|
||||
gge: NewGauge(GaugeOpts{Name: "g1", Help: "help g1"}),
|
||||
}
|
||||
collidingCollector := collectorDescribedByCollect{
|
||||
cnt: NewCounter(CounterOpts{Name: "c2", Help: "help c2"}),
|
||||
gge: NewGauge(GaugeOpts{Name: "g1", Help: "help g1"}),
|
||||
}
|
||||
inconsistentCollector := collectorDescribedByCollect{
|
||||
cnt: NewCounter(CounterOpts{Name: "c3", Help: "help c3"}),
|
||||
gge: NewGauge(GaugeOpts{Name: "c3", Help: "help inconsistent"}),
|
||||
}
|
||||
|
||||
reg := NewPedanticRegistry()
|
||||
|
||||
if err := reg.Register(goodCollector); err != nil {
|
||||
t.Error("registration failed:", err)
|
||||
}
|
||||
if err := reg.Register(collidingCollector); err == nil {
|
||||
t.Error("registration unexpectedly succeeded")
|
||||
}
|
||||
if err := reg.Register(inconsistentCollector); err == nil {
|
||||
t.Error("registration unexpectedly succeeded")
|
||||
}
|
||||
|
||||
if _, err := reg.Gather(); err != nil {
|
||||
t.Error("gathering failed:", err)
|
||||
}
|
||||
}
|
8
vendor/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
8
vendor/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
|
@ -67,7 +67,7 @@ type Desc struct {
|
|||
|
||||
// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc
|
||||
// and will be reported on registration time. variableLabels and constLabels can
|
||||
// be nil if no such labels should be set. fqName and help must not be empty.
|
||||
// be nil if no such labels should be set. fqName must not be empty.
|
||||
//
|
||||
// variableLabels only contain the label names. Their label values are variable
|
||||
// and therefore not part of the Desc. (They are managed within the Metric.)
|
||||
|
@ -80,10 +80,6 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
|
|||
help: help,
|
||||
variableLabels: variableLabels,
|
||||
}
|
||||
if help == "" {
|
||||
d.err = errors.New("empty help string")
|
||||
return d
|
||||
}
|
||||
if !model.IsValidMetricName(model.LabelValue(fqName)) {
|
||||
d.err = fmt.Errorf("%q is not a valid metric name", fqName)
|
||||
return d
|
||||
|
@ -156,7 +152,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
|
|||
Value: proto.String(v),
|
||||
})
|
||||
}
|
||||
sort.Sort(LabelPairSorter(d.constLabelPairs))
|
||||
sort.Sort(labelPairSorter(d.constLabelPairs))
|
||||
return d
|
||||
}
|
||||
|
||||
|
|
13
vendor/github.com/prometheus/client_golang/prometheus/desc_test.go
generated
vendored
13
vendor/github.com/prometheus/client_golang/prometheus/desc_test.go
generated
vendored
|
@ -1,3 +1,16 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
|
|
12
vendor/github.com/prometheus/client_golang/prometheus/doc.go
generated
vendored
12
vendor/github.com/prometheus/client_golang/prometheus/doc.go
generated
vendored
|
@ -121,7 +121,17 @@
|
|||
// NewConstSummary (and their respective Must… versions). That will happen in
|
||||
// the Collect method. The Describe method has to return separate Desc
|
||||
// instances, representative of the “throw-away” metrics to be created later.
|
||||
// NewDesc comes in handy to create those Desc instances.
|
||||
// NewDesc comes in handy to create those Desc instances. Alternatively, you
|
||||
// could return no Desc at all, which will marke the Collector “unchecked”. No
|
||||
// checks are porformed at registration time, but metric consistency will still
|
||||
// be ensured at scrape time, i.e. any inconsistencies will lead to scrape
|
||||
// errors. Thus, with unchecked Collectors, the responsibility to not collect
|
||||
// metrics that lead to inconsistencies in the total scrape result lies with the
|
||||
// implementer of the Collector. While this is not a desirable state, it is
|
||||
// sometimes necessary. The typical use case is a situatios where the exact
|
||||
// metrics to be returned by a Collector cannot be predicted at registration
|
||||
// time, but the implementer has sufficient knowledge of the whole system to
|
||||
// guarantee metric consistency.
|
||||
//
|
||||
// The Collector example illustrates the use case. You can also look at the
|
||||
// source code of the processCollector (mirroring process metrics), the
|
||||
|
|
93
vendor/github.com/prometheus/client_golang/prometheus/example_clustermanager_test.go
generated
vendored
93
vendor/github.com/prometheus/client_golang/prometheus/example_clustermanager_test.go
generated
vendored
|
@ -17,18 +17,18 @@ import "github.com/prometheus/client_golang/prometheus"
|
|||
|
||||
// ClusterManager is an example for a system that might have been built without
|
||||
// Prometheus in mind. It models a central manager of jobs running in a
|
||||
// cluster. To turn it into something that collects Prometheus metrics, we
|
||||
// simply add the two methods required for the Collector interface.
|
||||
// cluster. Thus, we implement a custom Collector called
|
||||
// ClusterManagerCollector, which collects information from a ClusterManager
|
||||
// using its provided methods and turns them into Prometheus Metrics for
|
||||
// collection.
|
||||
//
|
||||
// An additional challenge is that multiple instances of the ClusterManager are
|
||||
// run within the same binary, each in charge of a different zone. We need to
|
||||
// make use of ConstLabels to be able to register each ClusterManager instance
|
||||
// with Prometheus.
|
||||
// make use of wrapping Registerers to be able to register each
|
||||
// ClusterManagerCollector instance with Prometheus.
|
||||
type ClusterManager struct {
|
||||
Zone string
|
||||
OOMCountDesc *prometheus.Desc
|
||||
RAMUsageDesc *prometheus.Desc
|
||||
// ... many more fields
|
||||
Zone string
|
||||
// Contains many more fields not listed in this example.
|
||||
}
|
||||
|
||||
// ReallyExpensiveAssessmentOfTheSystemState is a mock for the data gathering a
|
||||
|
@ -50,10 +50,30 @@ func (c *ClusterManager) ReallyExpensiveAssessmentOfTheSystemState() (
|
|||
return
|
||||
}
|
||||
|
||||
// Describe simply sends the two Descs in the struct to the channel.
|
||||
func (c *ClusterManager) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- c.OOMCountDesc
|
||||
ch <- c.RAMUsageDesc
|
||||
// ClusterManagerCollector implements the Collector interface.
|
||||
type ClusterManagerCollector struct {
|
||||
ClusterManager *ClusterManager
|
||||
}
|
||||
|
||||
// Descriptors used by the ClusterManagerCollector below.
|
||||
var (
|
||||
oomCountDesc = prometheus.NewDesc(
|
||||
"clustermanager_oom_crashes_total",
|
||||
"Number of OOM crashes.",
|
||||
[]string{"host"}, nil,
|
||||
)
|
||||
ramUsageDesc = prometheus.NewDesc(
|
||||
"clustermanager_ram_usage_bytes",
|
||||
"RAM usage as reported to the cluster manager.",
|
||||
[]string{"host"}, nil,
|
||||
)
|
||||
)
|
||||
|
||||
// Describe is implemented with DescribeByCollect. That's possible because the
|
||||
// Collect method will always return the same two metrics with the same two
|
||||
// descriptors.
|
||||
func (cc ClusterManagerCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
prometheus.DescribeByCollect(cc, ch)
|
||||
}
|
||||
|
||||
// Collect first triggers the ReallyExpensiveAssessmentOfTheSystemState. Then it
|
||||
|
@ -61,11 +81,11 @@ func (c *ClusterManager) Describe(ch chan<- *prometheus.Desc) {
|
|||
//
|
||||
// Note that Collect could be called concurrently, so we depend on
|
||||
// ReallyExpensiveAssessmentOfTheSystemState to be concurrency-safe.
|
||||
func (c *ClusterManager) Collect(ch chan<- prometheus.Metric) {
|
||||
oomCountByHost, ramUsageByHost := c.ReallyExpensiveAssessmentOfTheSystemState()
|
||||
func (cc ClusterManagerCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
oomCountByHost, ramUsageByHost := cc.ClusterManager.ReallyExpensiveAssessmentOfTheSystemState()
|
||||
for host, oomCount := range oomCountByHost {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.OOMCountDesc,
|
||||
oomCountDesc,
|
||||
prometheus.CounterValue,
|
||||
float64(oomCount),
|
||||
host,
|
||||
|
@ -73,7 +93,7 @@ func (c *ClusterManager) Collect(ch chan<- prometheus.Metric) {
|
|||
}
|
||||
for host, ramUsage := range ramUsageByHost {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.RAMUsageDesc,
|
||||
ramUsageDesc,
|
||||
prometheus.GaugeValue,
|
||||
ramUsage,
|
||||
host,
|
||||
|
@ -81,38 +101,27 @@ func (c *ClusterManager) Collect(ch chan<- prometheus.Metric) {
|
|||
}
|
||||
}
|
||||
|
||||
// NewClusterManager creates the two Descs OOMCountDesc and RAMUsageDesc. Note
|
||||
// that the zone is set as a ConstLabel. (It's different in each instance of the
|
||||
// ClusterManager, but constant over the lifetime of an instance.) Then there is
|
||||
// a variable label "host", since we want to partition the collected metrics by
|
||||
// host. Since all Descs created in this way are consistent across instances,
|
||||
// with a guaranteed distinction by the "zone" label, we can register different
|
||||
// ClusterManager instances with the same registry.
|
||||
func NewClusterManager(zone string) *ClusterManager {
|
||||
return &ClusterManager{
|
||||
// NewClusterManager first creates a Prometheus-ignorant ClusterManager
|
||||
// instance. Then, it creates a ClusterManagerCollector for the just created
|
||||
// ClusterManager. Finally, it registers the ClusterManagerCollector with a
|
||||
// wrapping Registerer that adds the zone as a label. In this way, the metrics
|
||||
// collected by different ClusterManagerCollectors do not collide.
|
||||
func NewClusterManager(zone string, reg prometheus.Registerer) *ClusterManager {
|
||||
c := &ClusterManager{
|
||||
Zone: zone,
|
||||
OOMCountDesc: prometheus.NewDesc(
|
||||
"clustermanager_oom_crashes_total",
|
||||
"Number of OOM crashes.",
|
||||
[]string{"host"},
|
||||
prometheus.Labels{"zone": zone},
|
||||
),
|
||||
RAMUsageDesc: prometheus.NewDesc(
|
||||
"clustermanager_ram_usage_bytes",
|
||||
"RAM usage as reported to the cluster manager.",
|
||||
[]string{"host"},
|
||||
prometheus.Labels{"zone": zone},
|
||||
),
|
||||
}
|
||||
cc := ClusterManagerCollector{ClusterManager: c}
|
||||
prometheus.WrapRegistererWith(prometheus.Labels{"zone": zone}, reg).MustRegister(cc)
|
||||
return c
|
||||
}
|
||||
|
||||
func ExampleCollector() {
|
||||
workerDB := NewClusterManager("db")
|
||||
workerCA := NewClusterManager("ca")
|
||||
|
||||
// Since we are dealing with custom Collector implementations, it might
|
||||
// be a good idea to try it out with a pedantic registry.
|
||||
reg := prometheus.NewPedanticRegistry()
|
||||
reg.MustRegister(workerDB)
|
||||
reg.MustRegister(workerCA)
|
||||
|
||||
// Construct cluster managers. In real code, we would assign them to
|
||||
// variables to then do something with them.
|
||||
NewClusterManager("db", reg)
|
||||
NewClusterManager("ca", reg)
|
||||
}
|
||||
|
|
92
vendor/github.com/prometheus/client_golang/prometheus/examples_test.go
generated
vendored
92
vendor/github.com/prometheus/client_golang/prometheus/examples_test.go
generated
vendored
|
@ -19,13 +19,13 @@ import (
|
|||
"math"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"github.com/prometheus/common/expfmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/prometheus/common/expfmt"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
@ -89,37 +89,6 @@ func ExampleGaugeFunc() {
|
|||
// GaugeFunc 'goroutines_count' registered.
|
||||
}
|
||||
|
||||
func ExampleCounter() {
|
||||
pushCounter := prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "repository_pushes", // Note: No help string...
|
||||
})
|
||||
err := prometheus.Register(pushCounter) // ... so this will return an error.
|
||||
if err != nil {
|
||||
fmt.Println("Push counter couldn't be registered, no counting will happen:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Try it once more, this time with a help string.
|
||||
pushCounter = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "repository_pushes",
|
||||
Help: "Number of pushes to external repository.",
|
||||
})
|
||||
err = prometheus.Register(pushCounter)
|
||||
if err != nil {
|
||||
fmt.Println("Push counter couldn't be registered AGAIN, no counting will happen:", err)
|
||||
return
|
||||
}
|
||||
|
||||
pushComplete := make(chan struct{})
|
||||
// TODO: Start a goroutine that performs repository pushes and reports
|
||||
// each completion via the channel.
|
||||
for range pushComplete {
|
||||
pushCounter.Inc()
|
||||
}
|
||||
// Output:
|
||||
// Push counter couldn't be registered, no counting will happen: descriptor Desc{fqName: "repository_pushes", help: "", constLabels: {}, variableLabels: []} is invalid: empty help string
|
||||
}
|
||||
|
||||
func ExampleCounterVec() {
|
||||
httpReqs := prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
|
@ -167,19 +136,6 @@ func ExampleInstrumentHandler() {
|
|||
))
|
||||
}
|
||||
|
||||
func ExampleLabelPairSorter() {
|
||||
labelPairs := []*dto.LabelPair{
|
||||
{Name: proto.String("status"), Value: proto.String("404")},
|
||||
{Name: proto.String("method"), Value: proto.String("get")},
|
||||
}
|
||||
|
||||
sort.Sort(prometheus.LabelPairSorter(labelPairs))
|
||||
|
||||
fmt.Println(labelPairs)
|
||||
// Output:
|
||||
// [name:"method" value:"get" name:"status" value:"404" ]
|
||||
}
|
||||
|
||||
func ExampleRegister() {
|
||||
// Imagine you have a worker pool and want to count the tasks completed.
|
||||
taskCounter := prometheus.NewCounter(prometheus.CounterOpts{
|
||||
|
@ -712,7 +668,7 @@ humidity_percent{location="inside"} 33.2
|
|||
# HELP temperature_kelvin Temperature in Kelvin.
|
||||
# Duplicate metric:
|
||||
temperature_kelvin{location="outside"} 265.3
|
||||
# Wrong labels:
|
||||
# Missing location label (note that this is undesirable but valid):
|
||||
temperature_kelvin 4.5
|
||||
`
|
||||
|
||||
|
@ -740,15 +696,47 @@ temperature_kelvin 4.5
|
|||
// temperature_kelvin{location="outside"} 273.14
|
||||
// temperature_kelvin{location="somewhere else"} 4.5
|
||||
// ----------
|
||||
// 2 error(s) occurred:
|
||||
// * collected metric temperature_kelvin label:<name:"location" value:"outside" > gauge:<value:265.3 > was collected before with the same name and label values
|
||||
// * collected metric temperature_kelvin gauge:<value:4.5 > has label dimensions inconsistent with previously collected metrics in the same metric family
|
||||
// collected metric "temperature_kelvin" { label:<name:"location" value:"outside" > gauge:<value:265.3 > } was collected before with the same name and label values
|
||||
// # HELP humidity_percent Humidity in %.
|
||||
// # TYPE humidity_percent gauge
|
||||
// humidity_percent{location="inside"} 33.2
|
||||
// humidity_percent{location="outside"} 45.4
|
||||
// # HELP temperature_kelvin Temperature in Kelvin.
|
||||
// # TYPE temperature_kelvin gauge
|
||||
// temperature_kelvin 4.5
|
||||
// temperature_kelvin{location="inside"} 298.44
|
||||
// temperature_kelvin{location="outside"} 273.14
|
||||
}
|
||||
|
||||
func ExampleNewMetricWithTimestamp() {
|
||||
desc := prometheus.NewDesc(
|
||||
"temperature_kelvin",
|
||||
"Current temperature in Kelvin.",
|
||||
nil, nil,
|
||||
)
|
||||
|
||||
// Create a constant gauge from values we got from an external
|
||||
// temperature reporting system. Those values are reported with a slight
|
||||
// delay, so we want to add the timestamp of the actual measurement.
|
||||
temperatureReportedByExternalSystem := 298.15
|
||||
timeReportedByExternalSystem := time.Date(2009, time.November, 10, 23, 0, 0, 12345678, time.UTC)
|
||||
s := prometheus.NewMetricWithTimestamp(
|
||||
timeReportedByExternalSystem,
|
||||
prometheus.MustNewConstMetric(
|
||||
desc, prometheus.GaugeValue, temperatureReportedByExternalSystem,
|
||||
),
|
||||
)
|
||||
|
||||
// Just for demonstration, let's check the state of the gauge by
|
||||
// (ab)using its Write method (which is usually only used by Prometheus
|
||||
// internally).
|
||||
metric := &dto.Metric{}
|
||||
s.Write(metric)
|
||||
fmt.Println(proto.MarshalTextString(metric))
|
||||
|
||||
// Output:
|
||||
// gauge: <
|
||||
// value: 298.15
|
||||
// >
|
||||
// timestamp_ms: 1257894000012
|
||||
}
|
||||
|
|
2
vendor/github.com/prometheus/client_golang/prometheus/expvar_collector_test.go
generated
vendored
2
vendor/github.com/prometheus/client_golang/prometheus/expvar_collector_test.go
generated
vendored
|
@ -78,7 +78,7 @@ func ExampleNewExpvarCollector() {
|
|||
close(metricChan)
|
||||
}()
|
||||
for m := range metricChan {
|
||||
if strings.Index(m.Desc().String(), "expvar_memstats") == -1 {
|
||||
if !strings.Contains(m.Desc().String(), "expvar_memstats") {
|
||||
metric.Reset()
|
||||
m.Write(&metric)
|
||||
metricStrings = append(metricStrings, metric.String())
|
||||
|
|
13
vendor/github.com/prometheus/client_golang/prometheus/fnv.go
generated
vendored
13
vendor/github.com/prometheus/client_golang/prometheus/fnv.go
generated
vendored
|
@ -1,3 +1,16 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
// Inline and byte-free variant of hash/fnv's fnv64a.
|
||||
|
|
23
vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
generated
vendored
23
vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
generated
vendored
|
@ -1,3 +1,16 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
|
@ -17,8 +30,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 +282,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)
|
||||
|
||||
|
|
13
vendor/github.com/prometheus/client_golang/prometheus/go_collector_test.go
generated
vendored
13
vendor/github.com/prometheus/client_golang/prometheus/go_collector_test.go
generated
vendored
|
@ -1,3 +1,16 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
|
|
282
vendor/github.com/prometheus/client_golang/prometheus/graphite/bridge.go
generated
vendored
Normal file
282
vendor/github.com/prometheus/client_golang/prometheus/graphite/bridge.go
generated
vendored
Normal file
|
@ -0,0 +1,282 @@
|
|||
// Copyright 2016 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package graphite provides a bridge to push Prometheus metrics to a Graphite
|
||||
// server.
|
||||
package graphite
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/common/expfmt"
|
||||
"github.com/prometheus/common/model"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultInterval = 15 * time.Second
|
||||
millisecondsPerSecond = 1000
|
||||
)
|
||||
|
||||
// HandlerErrorHandling defines how a Handler serving metrics will handle
|
||||
// errors.
|
||||
type HandlerErrorHandling int
|
||||
|
||||
// These constants cause handlers serving metrics to behave as described if
|
||||
// errors are encountered.
|
||||
const (
|
||||
// Ignore errors and try to push as many metrics to Graphite as possible.
|
||||
ContinueOnError HandlerErrorHandling = iota
|
||||
|
||||
// Abort the push to Graphite upon the first error encountered.
|
||||
AbortOnError
|
||||
)
|
||||
|
||||
// Config defines the Graphite bridge config.
|
||||
type Config struct {
|
||||
// The url to push data to. Required.
|
||||
URL string
|
||||
|
||||
// The prefix for the pushed Graphite metrics. Defaults to empty string.
|
||||
Prefix string
|
||||
|
||||
// The interval to use for pushing data to Graphite. Defaults to 15 seconds.
|
||||
Interval time.Duration
|
||||
|
||||
// The timeout for pushing metrics to Graphite. Defaults to 15 seconds.
|
||||
Timeout time.Duration
|
||||
|
||||
// The Gatherer to use for metrics. Defaults to prometheus.DefaultGatherer.
|
||||
Gatherer prometheus.Gatherer
|
||||
|
||||
// The logger that messages are written to. Defaults to no logging.
|
||||
Logger Logger
|
||||
|
||||
// ErrorHandling defines how errors are handled. Note that errors are
|
||||
// logged regardless of the configured ErrorHandling provided Logger
|
||||
// is not nil.
|
||||
ErrorHandling HandlerErrorHandling
|
||||
}
|
||||
|
||||
// Bridge pushes metrics to the configured Graphite server.
|
||||
type Bridge struct {
|
||||
url string
|
||||
prefix string
|
||||
interval time.Duration
|
||||
timeout time.Duration
|
||||
|
||||
errorHandling HandlerErrorHandling
|
||||
logger Logger
|
||||
|
||||
g prometheus.Gatherer
|
||||
}
|
||||
|
||||
// Logger is the minimal interface Bridge needs for logging. Note that
|
||||
// log.Logger from the standard library implements this interface, and it is
|
||||
// easy to implement by custom loggers, if they don't do so already anyway.
|
||||
type Logger interface {
|
||||
Println(v ...interface{})
|
||||
}
|
||||
|
||||
// NewBridge returns a pointer to a new Bridge struct.
|
||||
func NewBridge(c *Config) (*Bridge, error) {
|
||||
b := &Bridge{}
|
||||
|
||||
if c.URL == "" {
|
||||
return nil, errors.New("missing URL")
|
||||
}
|
||||
b.url = c.URL
|
||||
|
||||
if c.Gatherer == nil {
|
||||
b.g = prometheus.DefaultGatherer
|
||||
} else {
|
||||
b.g = c.Gatherer
|
||||
}
|
||||
|
||||
if c.Logger != nil {
|
||||
b.logger = c.Logger
|
||||
}
|
||||
|
||||
if c.Prefix != "" {
|
||||
b.prefix = c.Prefix
|
||||
}
|
||||
|
||||
var z time.Duration
|
||||
if c.Interval == z {
|
||||
b.interval = defaultInterval
|
||||
} else {
|
||||
b.interval = c.Interval
|
||||
}
|
||||
|
||||
if c.Timeout == z {
|
||||
b.timeout = defaultInterval
|
||||
} else {
|
||||
b.timeout = c.Timeout
|
||||
}
|
||||
|
||||
b.errorHandling = c.ErrorHandling
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Run starts the event loop that pushes Prometheus metrics to Graphite at the
|
||||
// configured interval.
|
||||
func (b *Bridge) Run(ctx context.Context) {
|
||||
ticker := time.NewTicker(b.interval)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if err := b.Push(); err != nil && b.logger != nil {
|
||||
b.logger.Println("error pushing to Graphite:", err)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push pushes Prometheus metrics to the configured Graphite server.
|
||||
func (b *Bridge) Push() error {
|
||||
mfs, err := b.g.Gather()
|
||||
if err != nil || len(mfs) == 0 {
|
||||
switch b.errorHandling {
|
||||
case AbortOnError:
|
||||
return err
|
||||
case ContinueOnError:
|
||||
if b.logger != nil {
|
||||
b.logger.Println("continue on error:", err)
|
||||
}
|
||||
default:
|
||||
panic("unrecognized error handling value")
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := net.DialTimeout("tcp", b.url, b.timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
return writeMetrics(conn, mfs, b.prefix, model.Now())
|
||||
}
|
||||
|
||||
func writeMetrics(w io.Writer, mfs []*dto.MetricFamily, prefix string, now model.Time) error {
|
||||
vec, err := expfmt.ExtractSamples(&expfmt.DecodeOptions{
|
||||
Timestamp: now,
|
||||
}, mfs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := bufio.NewWriter(w)
|
||||
for _, s := range vec {
|
||||
for _, c := range prefix {
|
||||
if _, err := buf.WriteRune(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := buf.WriteByte('.'); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeMetric(buf, s.Metric); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := fmt.Fprintf(buf, " %g %d\n", s.Value, int64(s.Timestamp)/millisecondsPerSecond); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := buf.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeMetric(buf *bufio.Writer, m model.Metric) error {
|
||||
metricName, hasName := m[model.MetricNameLabel]
|
||||
numLabels := len(m) - 1
|
||||
if !hasName {
|
||||
numLabels = len(m)
|
||||
}
|
||||
|
||||
labelStrings := make([]string, 0, numLabels)
|
||||
for label, value := range m {
|
||||
if label != model.MetricNameLabel {
|
||||
labelStrings = append(labelStrings, fmt.Sprintf("%s %s", string(label), string(value)))
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
switch numLabels {
|
||||
case 0:
|
||||
if hasName {
|
||||
return writeSanitized(buf, string(metricName))
|
||||
}
|
||||
default:
|
||||
sort.Strings(labelStrings)
|
||||
if err = writeSanitized(buf, string(metricName)); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range labelStrings {
|
||||
if err = buf.WriteByte('.'); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = writeSanitized(buf, s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeSanitized(buf *bufio.Writer, s string) error {
|
||||
prevUnderscore := false
|
||||
|
||||
for _, c := range s {
|
||||
c = replaceInvalidRune(c)
|
||||
if c == '_' {
|
||||
if prevUnderscore {
|
||||
continue
|
||||
}
|
||||
prevUnderscore = true
|
||||
} else {
|
||||
prevUnderscore = false
|
||||
}
|
||||
if _, err := buf.WriteRune(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func replaceInvalidRune(c rune) rune {
|
||||
if c == ' ' {
|
||||
return '.'
|
||||
}
|
||||
if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == ':' || c == '-' || (c >= '0' && c <= '9')) {
|
||||
return '_'
|
||||
}
|
||||
return c
|
||||
}
|
338
vendor/github.com/prometheus/client_golang/prometheus/graphite/bridge_test.go
generated
vendored
Normal file
338
vendor/github.com/prometheus/client_golang/prometheus/graphite/bridge_test.go
generated
vendored
Normal file
|
@ -0,0 +1,338 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package graphite
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func TestSanitize(t *testing.T) {
|
||||
testCases := []struct {
|
||||
in, out string
|
||||
}{
|
||||
{in: "hello", out: "hello"},
|
||||
{in: "hE/l1o", out: "hE_l1o"},
|
||||
{in: "he,*ll(.o", out: "he_ll_o"},
|
||||
{in: "hello_there%^&", out: "hello_there_"},
|
||||
{in: "hell-.o", out: "hell-_o"},
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
for i, tc := range testCases {
|
||||
if err := writeSanitized(w, tc.in); err != nil {
|
||||
t.Fatalf("write failed: %v", err)
|
||||
}
|
||||
if err := w.Flush(); err != nil {
|
||||
t.Fatalf("flush failed: %v", err)
|
||||
}
|
||||
|
||||
if want, got := tc.out, buf.String(); want != got {
|
||||
t.Fatalf("test case index %d: got sanitized string %s, want %s", i, got, want)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteSummary(t *testing.T) {
|
||||
sumVec := prometheus.NewSummaryVec(
|
||||
prometheus.SummaryOpts{
|
||||
Name: "name",
|
||||
Help: "docstring",
|
||||
ConstLabels: prometheus.Labels{"constname": "constvalue"},
|
||||
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
|
||||
},
|
||||
[]string{"labelname"},
|
||||
)
|
||||
|
||||
sumVec.WithLabelValues("val1").Observe(float64(10))
|
||||
sumVec.WithLabelValues("val1").Observe(float64(20))
|
||||
sumVec.WithLabelValues("val1").Observe(float64(30))
|
||||
sumVec.WithLabelValues("val2").Observe(float64(20))
|
||||
sumVec.WithLabelValues("val2").Observe(float64(30))
|
||||
sumVec.WithLabelValues("val2").Observe(float64(40))
|
||||
|
||||
reg := prometheus.NewRegistry()
|
||||
reg.MustRegister(sumVec)
|
||||
|
||||
mfs, err := reg.Gather()
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
prefix string
|
||||
}{
|
||||
{prefix: "prefix"},
|
||||
{prefix: "pre/fix"},
|
||||
{prefix: "pre.fix"},
|
||||
}
|
||||
|
||||
const want = `%s.name.constname.constvalue.labelname.val1.quantile.0_5 20 1477043
|
||||
%s.name.constname.constvalue.labelname.val1.quantile.0_9 30 1477043
|
||||
%s.name.constname.constvalue.labelname.val1.quantile.0_99 30 1477043
|
||||
%s.name_sum.constname.constvalue.labelname.val1 60 1477043
|
||||
%s.name_count.constname.constvalue.labelname.val1 3 1477043
|
||||
%s.name.constname.constvalue.labelname.val2.quantile.0_5 30 1477043
|
||||
%s.name.constname.constvalue.labelname.val2.quantile.0_9 40 1477043
|
||||
%s.name.constname.constvalue.labelname.val2.quantile.0_99 40 1477043
|
||||
%s.name_sum.constname.constvalue.labelname.val2 90 1477043
|
||||
%s.name_count.constname.constvalue.labelname.val2 3 1477043
|
||||
`
|
||||
for i, tc := range testCases {
|
||||
|
||||
now := model.Time(1477043083)
|
||||
var buf bytes.Buffer
|
||||
err = writeMetrics(&buf, mfs, tc.prefix, now)
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
wantWithPrefix := fmt.Sprintf(want,
|
||||
tc.prefix, tc.prefix, tc.prefix, tc.prefix, tc.prefix,
|
||||
tc.prefix, tc.prefix, tc.prefix, tc.prefix, tc.prefix,
|
||||
)
|
||||
if got := buf.String(); wantWithPrefix != got {
|
||||
t.Fatalf("test case index %d: wanted \n%s\n, got \n%s\n", i, wantWithPrefix, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteHistogram(t *testing.T) {
|
||||
histVec := prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "name",
|
||||
Help: "docstring",
|
||||
ConstLabels: prometheus.Labels{"constname": "constvalue"},
|
||||
Buckets: []float64{0.01, 0.02, 0.05, 0.1},
|
||||
},
|
||||
[]string{"labelname"},
|
||||
)
|
||||
|
||||
histVec.WithLabelValues("val1").Observe(float64(10))
|
||||
histVec.WithLabelValues("val1").Observe(float64(20))
|
||||
histVec.WithLabelValues("val1").Observe(float64(30))
|
||||
histVec.WithLabelValues("val2").Observe(float64(20))
|
||||
histVec.WithLabelValues("val2").Observe(float64(30))
|
||||
histVec.WithLabelValues("val2").Observe(float64(40))
|
||||
|
||||
reg := prometheus.NewRegistry()
|
||||
reg.MustRegister(histVec)
|
||||
|
||||
mfs, err := reg.Gather()
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
now := model.Time(1477043083)
|
||||
var buf bytes.Buffer
|
||||
err = writeMetrics(&buf, mfs, "prefix", now)
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
want := `prefix.name_bucket.constname.constvalue.labelname.val1.le.0_01 0 1477043
|
||||
prefix.name_bucket.constname.constvalue.labelname.val1.le.0_02 0 1477043
|
||||
prefix.name_bucket.constname.constvalue.labelname.val1.le.0_05 0 1477043
|
||||
prefix.name_bucket.constname.constvalue.labelname.val1.le.0_1 0 1477043
|
||||
prefix.name_sum.constname.constvalue.labelname.val1 60 1477043
|
||||
prefix.name_count.constname.constvalue.labelname.val1 3 1477043
|
||||
prefix.name_bucket.constname.constvalue.labelname.val1.le._Inf 3 1477043
|
||||
prefix.name_bucket.constname.constvalue.labelname.val2.le.0_01 0 1477043
|
||||
prefix.name_bucket.constname.constvalue.labelname.val2.le.0_02 0 1477043
|
||||
prefix.name_bucket.constname.constvalue.labelname.val2.le.0_05 0 1477043
|
||||
prefix.name_bucket.constname.constvalue.labelname.val2.le.0_1 0 1477043
|
||||
prefix.name_sum.constname.constvalue.labelname.val2 90 1477043
|
||||
prefix.name_count.constname.constvalue.labelname.val2 3 1477043
|
||||
prefix.name_bucket.constname.constvalue.labelname.val2.le._Inf 3 1477043
|
||||
`
|
||||
if got := buf.String(); want != got {
|
||||
t.Fatalf("wanted \n%s\n, got \n%s\n", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToReader(t *testing.T) {
|
||||
cntVec := prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "name",
|
||||
Help: "docstring",
|
||||
ConstLabels: prometheus.Labels{"constname": "constvalue"},
|
||||
},
|
||||
[]string{"labelname"},
|
||||
)
|
||||
cntVec.WithLabelValues("val1").Inc()
|
||||
cntVec.WithLabelValues("val2").Inc()
|
||||
|
||||
reg := prometheus.NewRegistry()
|
||||
reg.MustRegister(cntVec)
|
||||
|
||||
want := `prefix.name.constname.constvalue.labelname.val1 1 1477043
|
||||
prefix.name.constname.constvalue.labelname.val2 1 1477043
|
||||
`
|
||||
mfs, err := reg.Gather()
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
now := model.Time(1477043083)
|
||||
var buf bytes.Buffer
|
||||
err = writeMetrics(&buf, mfs, "prefix", now)
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
if got := buf.String(); want != got {
|
||||
t.Fatalf("wanted \n%s\n, got \n%s\n", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPush(t *testing.T) {
|
||||
reg := prometheus.NewRegistry()
|
||||
cntVec := prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "name",
|
||||
Help: "docstring",
|
||||
ConstLabels: prometheus.Labels{"constname": "constvalue"},
|
||||
},
|
||||
[]string{"labelname"},
|
||||
)
|
||||
cntVec.WithLabelValues("val1").Inc()
|
||||
cntVec.WithLabelValues("val2").Inc()
|
||||
reg.MustRegister(cntVec)
|
||||
|
||||
host := "localhost"
|
||||
port := ":56789"
|
||||
b, err := NewBridge(&Config{
|
||||
URL: host + port,
|
||||
Gatherer: reg,
|
||||
Prefix: "prefix",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("error creating bridge: %v", err)
|
||||
}
|
||||
|
||||
nmg, err := newMockGraphite(port)
|
||||
if err != nil {
|
||||
t.Fatalf("error creating mock graphite: %v", err)
|
||||
}
|
||||
defer nmg.Close()
|
||||
|
||||
err = b.Push()
|
||||
if err != nil {
|
||||
t.Fatalf("error pushing: %v", err)
|
||||
}
|
||||
|
||||
wants := []string{
|
||||
"prefix.name.constname.constvalue.labelname.val1 1",
|
||||
"prefix.name.constname.constvalue.labelname.val2 1",
|
||||
}
|
||||
|
||||
select {
|
||||
case got := <-nmg.readc:
|
||||
for _, want := range wants {
|
||||
matched, err := regexp.MatchString(want, got)
|
||||
if err != nil {
|
||||
t.Fatalf("error pushing: %v", err)
|
||||
}
|
||||
if !matched {
|
||||
t.Fatalf("missing metric:\nno match for %s received by server:\n%s", want, got)
|
||||
}
|
||||
}
|
||||
return
|
||||
case err := <-nmg.errc:
|
||||
t.Fatalf("error reading push: %v", err)
|
||||
case <-time.After(50 * time.Millisecond):
|
||||
t.Fatalf("no result from graphite server")
|
||||
}
|
||||
}
|
||||
|
||||
func newMockGraphite(port string) (*mockGraphite, error) {
|
||||
readc := make(chan string)
|
||||
errc := make(chan error)
|
||||
ln, err := net.Listen("tcp", port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
errc <- err
|
||||
}
|
||||
var b bytes.Buffer
|
||||
io.Copy(&b, conn)
|
||||
readc <- b.String()
|
||||
}()
|
||||
|
||||
return &mockGraphite{
|
||||
readc: readc,
|
||||
errc: errc,
|
||||
Listener: ln,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type mockGraphite struct {
|
||||
readc chan string
|
||||
errc chan error
|
||||
|
||||
net.Listener
|
||||
}
|
||||
|
||||
func ExampleBridge() {
|
||||
b, err := NewBridge(&Config{
|
||||
URL: "graphite.example.org:3099",
|
||||
Gatherer: prometheus.DefaultGatherer,
|
||||
Prefix: "prefix",
|
||||
Interval: 15 * time.Second,
|
||||
Timeout: 10 * time.Second,
|
||||
ErrorHandling: AbortOnError,
|
||||
Logger: log.New(os.Stdout, "graphite bridge: ", log.Lshortfile),
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
// Start something in a goroutine that uses metrics.
|
||||
}()
|
||||
|
||||
// Push initial metrics to Graphite. Fail fast if the push fails.
|
||||
if err := b.Push(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create a Context to control stopping the Run() loop that pushes
|
||||
// metrics to Graphite.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// Start pushing metrics to Graphite in the Run() loop.
|
||||
b.Run(ctx)
|
||||
}
|
155
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
155
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
|
@ -16,7 +16,9 @@ package prometheus
|
|||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
@ -108,8 +110,9 @@ func ExponentialBuckets(start, factor float64, count int) []float64 {
|
|||
}
|
||||
|
||||
// HistogramOpts bundles the options for creating a Histogram metric. It is
|
||||
// mandatory to set Name and Help to a non-empty string. All other fields are
|
||||
// optional and can safely be left at their zero value.
|
||||
// mandatory to set Name to a non-empty string. All other fields are optional
|
||||
// and can safely be left at their zero value, although it is strongly
|
||||
// encouraged to set a Help string.
|
||||
type HistogramOpts struct {
|
||||
// Namespace, Subsystem, and Name are components of the fully-qualified
|
||||
// name of the Histogram (created by joining these components with
|
||||
|
@ -120,7 +123,7 @@ type HistogramOpts struct {
|
|||
Subsystem string
|
||||
Name string
|
||||
|
||||
// Help provides information about this Histogram. Mandatory!
|
||||
// Help provides information about this Histogram.
|
||||
//
|
||||
// Metrics with the same fully-qualified name must have the same Help
|
||||
// string.
|
||||
|
@ -184,6 +187,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
|
|||
desc: desc,
|
||||
upperBounds: opts.Buckets,
|
||||
labelPairs: makeLabelPairs(desc, labelValues),
|
||||
counts: [2]*histogramCounts{&histogramCounts{}, &histogramCounts{}},
|
||||
}
|
||||
for i, upperBound := range h.upperBounds {
|
||||
if i < len(h.upperBounds)-1 {
|
||||
|
@ -200,28 +204,53 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
|
|||
}
|
||||
}
|
||||
}
|
||||
// Finally we know the final length of h.upperBounds and can make counts.
|
||||
h.counts = make([]uint64, len(h.upperBounds))
|
||||
// Finally we know the final length of h.upperBounds and can make counts
|
||||
// for both states:
|
||||
h.counts[0].buckets = make([]uint64, len(h.upperBounds))
|
||||
h.counts[1].buckets = make([]uint64, len(h.upperBounds))
|
||||
|
||||
h.init(h) // Init self-collection.
|
||||
return h
|
||||
}
|
||||
|
||||
type histogram struct {
|
||||
type histogramCounts struct {
|
||||
// sumBits contains the bits of the float64 representing the sum of all
|
||||
// observations. sumBits and count have to go first in the struct to
|
||||
// guarantee alignment for atomic operations.
|
||||
// http://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
||||
sumBits uint64
|
||||
count uint64
|
||||
buckets []uint64
|
||||
}
|
||||
|
||||
type histogram struct {
|
||||
// countAndHotIdx is a complicated one. For lock-free yet atomic
|
||||
// observations, we need to save the total count of observations again,
|
||||
// combined with the index of the currently-hot counts struct, so that
|
||||
// we can perform the operation on both values atomically. The least
|
||||
// significant bit defines the hot counts struct. The remaining 63 bits
|
||||
// represent the total count of observations. This happens under the
|
||||
// assumption that the 63bit count will never overflow. Rationale: An
|
||||
// observations takes about 30ns. Let's assume it could happen in
|
||||
// 10ns. Overflowing the counter will then take at least (2^63)*10ns,
|
||||
// which is about 3000 years.
|
||||
//
|
||||
// This has to be first in the struct for 64bit alignment. See
|
||||
// http://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
||||
countAndHotIdx uint64
|
||||
|
||||
selfCollector
|
||||
// Note that there is no mutex required.
|
||||
|
||||
desc *Desc
|
||||
desc *Desc
|
||||
writeMtx sync.Mutex // Only used in the Write method.
|
||||
|
||||
upperBounds []float64
|
||||
counts []uint64
|
||||
|
||||
// Two counts, one is "hot" for lock-free observations, the other is
|
||||
// "cold" for writing out a dto.Metric. It has to be an array of
|
||||
// pointers to guarantee 64bit alignment of the histogramCounts, see
|
||||
// http://golang.org/pkg/sync/atomic/#pkg-note-BUG.
|
||||
counts [2]*histogramCounts
|
||||
hotIdx int // Index of currently-hot counts. Only used within Write.
|
||||
|
||||
labelPairs []*dto.LabelPair
|
||||
}
|
||||
|
@ -241,36 +270,113 @@ func (h *histogram) Observe(v float64) {
|
|||
// 100 buckets: 78.1 ns/op linear - binary 54.9 ns/op
|
||||
// 300 buckets: 154 ns/op linear - binary 61.6 ns/op
|
||||
i := sort.SearchFloat64s(h.upperBounds, v)
|
||||
if i < len(h.counts) {
|
||||
atomic.AddUint64(&h.counts[i], 1)
|
||||
|
||||
// We increment h.countAndHotIdx by 2 so that the counter in the upper
|
||||
// 63 bits gets incremented by 1. At the same time, we get the new value
|
||||
// back, which we can use to find the currently-hot counts.
|
||||
n := atomic.AddUint64(&h.countAndHotIdx, 2)
|
||||
hotCounts := h.counts[n%2]
|
||||
|
||||
if i < len(h.upperBounds) {
|
||||
atomic.AddUint64(&hotCounts.buckets[i], 1)
|
||||
}
|
||||
atomic.AddUint64(&h.count, 1)
|
||||
for {
|
||||
oldBits := atomic.LoadUint64(&h.sumBits)
|
||||
oldBits := atomic.LoadUint64(&hotCounts.sumBits)
|
||||
newBits := math.Float64bits(math.Float64frombits(oldBits) + v)
|
||||
if atomic.CompareAndSwapUint64(&h.sumBits, oldBits, newBits) {
|
||||
if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) {
|
||||
break
|
||||
}
|
||||
}
|
||||
// Increment count last as we take it as a signal that the observation
|
||||
// is complete.
|
||||
atomic.AddUint64(&hotCounts.count, 1)
|
||||
}
|
||||
|
||||
func (h *histogram) Write(out *dto.Metric) error {
|
||||
his := &dto.Histogram{}
|
||||
buckets := make([]*dto.Bucket, len(h.upperBounds))
|
||||
var (
|
||||
his = &dto.Histogram{}
|
||||
buckets = make([]*dto.Bucket, len(h.upperBounds))
|
||||
hotCounts, coldCounts *histogramCounts
|
||||
count uint64
|
||||
)
|
||||
|
||||
his.SampleSum = proto.Float64(math.Float64frombits(atomic.LoadUint64(&h.sumBits)))
|
||||
his.SampleCount = proto.Uint64(atomic.LoadUint64(&h.count))
|
||||
var count uint64
|
||||
// For simplicity, we mutex the rest of this method. It is not in the
|
||||
// hot path, i.e. Observe is called much more often than Write. The
|
||||
// complication of making Write lock-free isn't worth it.
|
||||
h.writeMtx.Lock()
|
||||
defer h.writeMtx.Unlock()
|
||||
|
||||
// This is a bit arcane, which is why the following spells out this if
|
||||
// clause in English:
|
||||
//
|
||||
// If the currently-hot counts struct is #0, we atomically increment
|
||||
// h.countAndHotIdx by 1 so that from now on Observe will use the counts
|
||||
// struct #1. Furthermore, the atomic increment gives us the new value,
|
||||
// which, in its most significant 63 bits, tells us the count of
|
||||
// observations done so far up to and including currently ongoing
|
||||
// observations still using the counts struct just changed from hot to
|
||||
// cold. To have a normal uint64 for the count, we bitshift by 1 and
|
||||
// save the result in count. We also set h.hotIdx to 1 for the next
|
||||
// Write call, and we will refer to counts #1 as hotCounts and to counts
|
||||
// #0 as coldCounts.
|
||||
//
|
||||
// If the currently-hot counts struct is #1, we do the corresponding
|
||||
// things the other way round. We have to _decrement_ h.countAndHotIdx
|
||||
// (which is a bit arcane in itself, as we have to express -1 with an
|
||||
// unsigned int...).
|
||||
if h.hotIdx == 0 {
|
||||
count = atomic.AddUint64(&h.countAndHotIdx, 1) >> 1
|
||||
h.hotIdx = 1
|
||||
hotCounts = h.counts[1]
|
||||
coldCounts = h.counts[0]
|
||||
} else {
|
||||
count = atomic.AddUint64(&h.countAndHotIdx, ^uint64(0)) >> 1 // Decrement.
|
||||
h.hotIdx = 0
|
||||
hotCounts = h.counts[0]
|
||||
coldCounts = h.counts[1]
|
||||
}
|
||||
|
||||
// Now we have to wait for the now-declared-cold counts to actually cool
|
||||
// down, i.e. wait for all observations still using it to finish. That's
|
||||
// the case once the count in the cold counts struct is the same as the
|
||||
// one atomically retrieved from the upper 63bits of h.countAndHotIdx.
|
||||
for {
|
||||
if count == atomic.LoadUint64(&coldCounts.count) {
|
||||
break
|
||||
}
|
||||
runtime.Gosched() // Let observations get work done.
|
||||
}
|
||||
|
||||
his.SampleCount = proto.Uint64(count)
|
||||
his.SampleSum = proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits)))
|
||||
var cumCount uint64
|
||||
for i, upperBound := range h.upperBounds {
|
||||
count += atomic.LoadUint64(&h.counts[i])
|
||||
cumCount += atomic.LoadUint64(&coldCounts.buckets[i])
|
||||
buckets[i] = &dto.Bucket{
|
||||
CumulativeCount: proto.Uint64(count),
|
||||
CumulativeCount: proto.Uint64(cumCount),
|
||||
UpperBound: proto.Float64(upperBound),
|
||||
}
|
||||
}
|
||||
|
||||
his.Bucket = buckets
|
||||
out.Histogram = his
|
||||
out.Label = h.labelPairs
|
||||
|
||||
// Finally add all the cold counts to the new hot counts and reset the cold counts.
|
||||
atomic.AddUint64(&hotCounts.count, count)
|
||||
atomic.StoreUint64(&coldCounts.count, 0)
|
||||
for {
|
||||
oldBits := atomic.LoadUint64(&hotCounts.sumBits)
|
||||
newBits := math.Float64bits(math.Float64frombits(oldBits) + his.GetSampleSum())
|
||||
if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) {
|
||||
atomic.StoreUint64(&coldCounts.sumBits, 0)
|
||||
break
|
||||
}
|
||||
}
|
||||
for i := range h.upperBounds {
|
||||
atomic.AddUint64(&hotCounts.buckets[i], atomic.LoadUint64(&coldCounts.buckets[i]))
|
||||
atomic.StoreUint64(&coldCounts.buckets[i], 0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -454,7 +560,7 @@ func (h *constHistogram) Write(out *dto.Metric) error {
|
|||
// bucket.
|
||||
//
|
||||
// NewConstHistogram returns an error if the length of labelValues is not
|
||||
// consistent with the variable labels in Desc.
|
||||
// consistent with the variable labels in Desc or if Desc is invalid.
|
||||
func NewConstHistogram(
|
||||
desc *Desc,
|
||||
count uint64,
|
||||
|
@ -462,6 +568,9 @@ func NewConstHistogram(
|
|||
buckets map[float64]uint64,
|
||||
labelValues ...string,
|
||||
) (Metric, error) {
|
||||
if desc.err != nil {
|
||||
return nil, desc.err
|
||||
}
|
||||
if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
45
vendor/github.com/prometheus/client_golang/prometheus/histogram_test.go
generated
vendored
45
vendor/github.com/prometheus/client_golang/prometheus/histogram_test.go
generated
vendored
|
@ -17,6 +17,7 @@ import (
|
|||
"math"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
"testing"
|
||||
|
@ -346,3 +347,47 @@ func TestBuckets(t *testing.T) {
|
|||
t.Errorf("linear buckets: got %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistogramAtomicObserve(t *testing.T) {
|
||||
var (
|
||||
quit = make(chan struct{})
|
||||
his = NewHistogram(HistogramOpts{
|
||||
Buckets: []float64{0.5, 10, 20},
|
||||
})
|
||||
)
|
||||
|
||||
defer func() { close(quit) }()
|
||||
|
||||
observe := func() {
|
||||
for {
|
||||
select {
|
||||
case <-quit:
|
||||
return
|
||||
default:
|
||||
his.Observe(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go observe()
|
||||
go observe()
|
||||
go observe()
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
m := &dto.Metric{}
|
||||
if err := his.Write(m); err != nil {
|
||||
t.Fatal("unexpected error writing histogram:", err)
|
||||
}
|
||||
h := m.GetHistogram()
|
||||
if h.GetSampleCount() != uint64(h.GetSampleSum()) ||
|
||||
h.GetSampleCount() != h.GetBucket()[1].GetCumulativeCount() ||
|
||||
h.GetSampleCount() != h.GetBucket()[2].GetCumulativeCount() {
|
||||
t.Fatalf(
|
||||
"inconsistent counts in histogram: count=%d sum=%f buckets=[%d, %d]",
|
||||
h.GetSampleCount(), h.GetSampleSum(),
|
||||
h.GetBucket()[1].GetCumulativeCount(), h.GetBucket()[2].GetCumulativeCount(),
|
||||
)
|
||||
}
|
||||
runtime.Gosched()
|
||||
}
|
||||
}
|
||||
|
|
50
vendor/github.com/prometheus/client_golang/prometheus/http.go
generated
vendored
50
vendor/github.com/prometheus/client_golang/prometheus/http.go
generated
vendored
|
@ -61,15 +61,15 @@ func giveBuf(buf *bytes.Buffer) {
|
|||
// name).
|
||||
//
|
||||
// Deprecated: Please note the issues described in the doc comment of
|
||||
// InstrumentHandler. You might want to consider using
|
||||
// promhttp.InstrumentedHandler instead.
|
||||
// InstrumentHandler. You might want to consider using promhttp.Handler instead.
|
||||
func Handler() http.Handler {
|
||||
return InstrumentHandler("prometheus", UninstrumentedHandler())
|
||||
}
|
||||
|
||||
// UninstrumentedHandler returns an HTTP handler for the DefaultGatherer.
|
||||
//
|
||||
// Deprecated: Use promhttp.Handler instead. See there for further documentation.
|
||||
// Deprecated: Use promhttp.HandlerFor(DefaultGatherer, promhttp.HandlerOpts{})
|
||||
// instead. See there for further documentation.
|
||||
func UninstrumentedHandler() http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
mfs, err := DefaultGatherer.Gather()
|
||||
|
@ -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
|
||||
|
@ -159,21 +149,14 @@ func nowSeries(t ...time.Time) nower {
|
|||
// (label name "method") and HTTP status code (label name "code").
|
||||
//
|
||||
// Deprecated: InstrumentHandler has several issues. Use the tooling provided in
|
||||
// package promhttp instead. The issues are the following:
|
||||
//
|
||||
// - It uses Summaries rather than Histograms. Summaries are not useful if
|
||||
// aggregation across multiple instances is required.
|
||||
//
|
||||
// - It uses microseconds as unit, which is deprecated and should be replaced by
|
||||
// seconds.
|
||||
//
|
||||
// - The size of the request is calculated in a separate goroutine. Since this
|
||||
// calculator requires access to the request header, it creates a race with
|
||||
// any writes to the header performed during request handling.
|
||||
// httputil.ReverseProxy is a prominent example for a handler
|
||||
// performing such writes.
|
||||
//
|
||||
// - It has additional issues with HTTP/2, cf.
|
||||
// package promhttp instead. The issues are the following: (1) It uses Summaries
|
||||
// rather than Histograms. Summaries are not useful if aggregation across
|
||||
// multiple instances is required. (2) It uses microseconds as unit, which is
|
||||
// deprecated and should be replaced by seconds. (3) The size of the request is
|
||||
// calculated in a separate goroutine. Since this calculator requires access to
|
||||
// the request header, it creates a race with any writes to the header performed
|
||||
// during request handling. httputil.ReverseProxy is a prominent example for a
|
||||
// handler performing such writes. (4) It has additional issues with HTTP/2, cf.
|
||||
// https://github.com/prometheus/client_golang/issues/272.
|
||||
func InstrumentHandler(handlerName string, handler http.Handler) http.HandlerFunc {
|
||||
return InstrumentHandlerFunc(handlerName, handler.ServeHTTP)
|
||||
|
@ -317,7 +300,7 @@ func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.Respo
|
|||
}
|
||||
|
||||
func computeApproximateRequestSize(r *http.Request) <-chan int {
|
||||
// Get URL length in current go routine for avoiding a race condition.
|
||||
// Get URL length in current goroutine for avoiding a race condition.
|
||||
// HandlerFunc that runs in parallel may modify the URL.
|
||||
s := 0
|
||||
if r.URL != nil {
|
||||
|
@ -352,10 +335,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) {
|
||||
|
|
18
vendor/github.com/prometheus/client_golang/prometheus/http_test.go
generated
vendored
18
vendor/github.com/prometheus/client_golang/prometheus/http_test.go
generated
vendored
|
@ -29,6 +29,16 @@ func (b respBody) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
w.Write([]byte(b))
|
||||
}
|
||||
|
||||
func nowSeries(t ...time.Time) nower {
|
||||
return nowFunc(func() time.Time {
|
||||
defer func() {
|
||||
t = t[1:]
|
||||
}()
|
||||
|
||||
return t[0]
|
||||
})
|
||||
}
|
||||
|
||||
func TestInstrumentHandler(t *testing.T) {
|
||||
defer func(n nower) {
|
||||
now = n.(nower)
|
||||
|
@ -37,9 +47,9 @@ func TestInstrumentHandler(t *testing.T) {
|
|||
instant := time.Now()
|
||||
end := instant.Add(30 * time.Second)
|
||||
now = nowSeries(instant, end)
|
||||
respBody := respBody("Howdy there!")
|
||||
body := respBody("Howdy there!")
|
||||
|
||||
hndlr := InstrumentHandler("test-handler", respBody)
|
||||
hndlr := InstrumentHandler("test-handler", body)
|
||||
|
||||
opts := SummaryOpts{
|
||||
Subsystem: "http",
|
||||
|
@ -114,8 +124,8 @@ func TestInstrumentHandler(t *testing.T) {
|
|||
if resp.Code != http.StatusTeapot {
|
||||
t.Fatalf("expected status %d, got %d", http.StatusTeapot, resp.Code)
|
||||
}
|
||||
if string(resp.Body.Bytes()) != "Howdy there!" {
|
||||
t.Fatalf("expected body %s, got %s", "Howdy there!", string(resp.Body.Bytes()))
|
||||
if resp.Body.String() != "Howdy there!" {
|
||||
t.Fatalf("expected body %s, got %s", "Howdy there!", resp.Body.String())
|
||||
}
|
||||
|
||||
out := &dto.Metric{}
|
||||
|
|
85
vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go
generated
vendored
Normal file
85
vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
// metricSorter is a sortable slice of *dto.Metric.
|
||||
type metricSorter []*dto.Metric
|
||||
|
||||
func (s metricSorter) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s metricSorter) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s metricSorter) Less(i, j int) bool {
|
||||
if len(s[i].Label) != len(s[j].Label) {
|
||||
// This should not happen. The metrics are
|
||||
// inconsistent. However, we have to deal with the fact, as
|
||||
// people might use custom collectors or metric family injection
|
||||
// to create inconsistent metrics. So let's simply compare the
|
||||
// number of labels in this case. That will still yield
|
||||
// reproducible sorting.
|
||||
return len(s[i].Label) < len(s[j].Label)
|
||||
}
|
||||
for n, lp := range s[i].Label {
|
||||
vi := lp.GetValue()
|
||||
vj := s[j].Label[n].GetValue()
|
||||
if vi != vj {
|
||||
return vi < vj
|
||||
}
|
||||
}
|
||||
|
||||
// We should never arrive here. Multiple metrics with the same
|
||||
// label set in the same scrape will lead to undefined ingestion
|
||||
// behavior. However, as above, we have to provide stable sorting
|
||||
// here, even for inconsistent metrics. So sort equal metrics
|
||||
// by their timestamp, with missing timestamps (implying "now")
|
||||
// coming last.
|
||||
if s[i].TimestampMs == nil {
|
||||
return false
|
||||
}
|
||||
if s[j].TimestampMs == nil {
|
||||
return true
|
||||
}
|
||||
return s[i].GetTimestampMs() < s[j].GetTimestampMs()
|
||||
}
|
||||
|
||||
// NormalizeMetricFamilies returns a MetricFamily slice with empty
|
||||
// MetricFamilies pruned and the remaining MetricFamilies sorted by name within
|
||||
// the slice, with the contained Metrics sorted within each MetricFamily.
|
||||
func NormalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily {
|
||||
for _, mf := range metricFamiliesByName {
|
||||
sort.Sort(metricSorter(mf.Metric))
|
||||
}
|
||||
names := make([]string, 0, len(metricFamiliesByName))
|
||||
for name, mf := range metricFamiliesByName {
|
||||
if len(mf.Metric) > 0 {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
sort.Strings(names)
|
||||
result := make([]*dto.MetricFamily, 0, len(names))
|
||||
for _, name := range names {
|
||||
result = append(result, metricFamiliesByName[name])
|
||||
}
|
||||
return result
|
||||
}
|
13
vendor/github.com/prometheus/client_golang/prometheus/labels.go
generated
vendored
13
vendor/github.com/prometheus/client_golang/prometheus/labels.go
generated
vendored
|
@ -1,3 +1,16 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
|
|
70
vendor/github.com/prometheus/client_golang/prometheus/metric.go
generated
vendored
70
vendor/github.com/prometheus/client_golang/prometheus/metric.go
generated
vendored
|
@ -15,6 +15,9 @@ package prometheus
|
|||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
@ -43,9 +46,8 @@ type Metric interface {
|
|||
// While populating dto.Metric, it is the responsibility of the
|
||||
// implementation to ensure validity of the Metric protobuf (like valid
|
||||
// UTF-8 strings or syntactically valid metric and label names). It is
|
||||
// recommended to sort labels lexicographically. (Implementers may find
|
||||
// LabelPairSorter useful for that.) Callers of Write should still make
|
||||
// sure of sorting if they depend on it.
|
||||
// recommended to sort labels lexicographically. Callers of Write should
|
||||
// still make sure of sorting if they depend on it.
|
||||
Write(*dto.Metric) error
|
||||
// TODO(beorn7): The original rationale of passing in a pre-allocated
|
||||
// dto.Metric protobuf to save allocations has disappeared. The
|
||||
|
@ -57,8 +59,9 @@ type Metric interface {
|
|||
// implementation XXX has its own XXXOpts type, but in most cases, it is just be
|
||||
// an alias of this type (which might change when the requirement arises.)
|
||||
//
|
||||
// It is mandatory to set Name and Help to a non-empty string. All other fields
|
||||
// are optional and can safely be left at their zero value.
|
||||
// It is mandatory to set Name to a non-empty string. All other fields are
|
||||
// optional and can safely be left at their zero value, although it is strongly
|
||||
// encouraged to set a Help string.
|
||||
type Opts struct {
|
||||
// Namespace, Subsystem, and Name are components of the fully-qualified
|
||||
// name of the Metric (created by joining these components with
|
||||
|
@ -69,7 +72,7 @@ type Opts struct {
|
|||
Subsystem string
|
||||
Name string
|
||||
|
||||
// Help provides information about this metric. Mandatory!
|
||||
// Help provides information about this metric.
|
||||
//
|
||||
// Metrics with the same fully-qualified name must have the same Help
|
||||
// string.
|
||||
|
@ -110,37 +113,22 @@ func BuildFQName(namespace, subsystem, name string) string {
|
|||
return name
|
||||
}
|
||||
|
||||
// LabelPairSorter implements sort.Interface. It is used to sort a slice of
|
||||
// dto.LabelPair pointers. This is useful for implementing the Write method of
|
||||
// custom metrics.
|
||||
type LabelPairSorter []*dto.LabelPair
|
||||
// labelPairSorter implements sort.Interface. It is used to sort a slice of
|
||||
// dto.LabelPair pointers.
|
||||
type labelPairSorter []*dto.LabelPair
|
||||
|
||||
func (s LabelPairSorter) Len() int {
|
||||
func (s labelPairSorter) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s LabelPairSorter) Swap(i, j int) {
|
||||
func (s labelPairSorter) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s LabelPairSorter) Less(i, j int) bool {
|
||||
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
|
||||
|
@ -156,3 +144,31 @@ func NewInvalidMetric(desc *Desc, err error) Metric {
|
|||
func (m *invalidMetric) Desc() *Desc { return m.desc }
|
||||
|
||||
func (m *invalidMetric) Write(*dto.Metric) error { return m.err }
|
||||
|
||||
type timestampedMetric struct {
|
||||
Metric
|
||||
t time.Time
|
||||
}
|
||||
|
||||
func (m timestampedMetric) Write(pb *dto.Metric) error {
|
||||
e := m.Metric.Write(pb)
|
||||
pb.TimestampMs = proto.Int64(m.t.Unix()*1000 + int64(m.t.Nanosecond()/1000000))
|
||||
return e
|
||||
}
|
||||
|
||||
// NewMetricWithTimestamp returns a new Metric wrapping the provided Metric in a
|
||||
// way that it has an explicit timestamp set to the provided Time. This is only
|
||||
// useful in rare cases as the timestamp of a Prometheus metric should usually
|
||||
// be set by the Prometheus server during scraping. Exceptions include mirroring
|
||||
// metrics with given timestamps from other metric
|
||||
// sources.
|
||||
//
|
||||
// NewMetricWithTimestamp works best with MustNewConstMetric,
|
||||
// MustNewConstHistogram, and MustNewConstSummary, see example.
|
||||
//
|
||||
// Currently, the exposition formats used by Prometheus are limited to
|
||||
// millisecond resolution. Thus, the provided time will be rounded down to the
|
||||
// next full millisecond value.
|
||||
func NewMetricWithTimestamp(t time.Time, m Metric) Metric {
|
||||
return timestampedMetric{Metric: m, t: t}
|
||||
}
|
||||
|
|
116
vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
generated
vendored
116
vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
generated
vendored
|
@ -13,46 +13,74 @@
|
|||
|
||||
package prometheus
|
||||
|
||||
import "github.com/prometheus/procfs"
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/prometheus/procfs"
|
||||
)
|
||||
|
||||
type processCollector struct {
|
||||
pid int
|
||||
collectFn func(chan<- Metric)
|
||||
pidFn func() (int, error)
|
||||
reportErrors bool
|
||||
cpuTotal *Desc
|
||||
openFDs, maxFDs *Desc
|
||||
vsize, rss *Desc
|
||||
vsize, maxVsize *Desc
|
||||
rss *Desc
|
||||
startTime *Desc
|
||||
}
|
||||
|
||||
// ProcessCollectorOpts defines the behavior of a process metrics collector
|
||||
// created with NewProcessCollector.
|
||||
type ProcessCollectorOpts struct {
|
||||
// PidFn returns the PID of the process the collector collects metrics
|
||||
// for. It is called upon each collection. By default, the PID of the
|
||||
// current process is used, as determined on construction time by
|
||||
// calling os.Getpid().
|
||||
PidFn func() (int, error)
|
||||
// If non-empty, each of the collected metrics is prefixed by the
|
||||
// provided string and an underscore ("_").
|
||||
Namespace string
|
||||
// If true, any error encountered during collection is reported as an
|
||||
// invalid metric (see NewInvalidMetric). Otherwise, errors are ignored
|
||||
// and the collected metrics will be incomplete. (Possibly, no metrics
|
||||
// will be collected at all.) While that's usually not desired, it is
|
||||
// appropriate for the common "mix-in" of process metrics, where process
|
||||
// metrics are nice to have, but failing to collect them should not
|
||||
// disrupt the collection of the remaining metrics.
|
||||
ReportErrors bool
|
||||
}
|
||||
|
||||
// NewProcessCollector returns a collector which exports the current state of
|
||||
// process metrics including CPU, memory and file descriptor usage as well as
|
||||
// the process start time for the given process ID under the given namespace.
|
||||
// the process start time. The detailed behavior is defined by the provided
|
||||
// ProcessCollectorOpts. The zero value of ProcessCollectorOpts creates a
|
||||
// collector for the current process with an empty namespace string and no error
|
||||
// reporting.
|
||||
//
|
||||
// Currently, the collector depends on a Linux-style proc filesystem and
|
||||
// therefore only exports metrics for Linux.
|
||||
func NewProcessCollector(pid int, namespace string) Collector {
|
||||
return NewProcessCollectorPIDFn(
|
||||
func() (int, error) { return pid, nil },
|
||||
namespace,
|
||||
)
|
||||
}
|
||||
|
||||
// NewProcessCollectorPIDFn works like NewProcessCollector but the process ID is
|
||||
// determined on each collect anew by calling the given pidFn function.
|
||||
func NewProcessCollectorPIDFn(
|
||||
pidFn func() (int, error),
|
||||
namespace string,
|
||||
) Collector {
|
||||
//
|
||||
// Note: An older version of this function had the following signature:
|
||||
//
|
||||
// NewProcessCollector(pid int, namespace string) Collector
|
||||
//
|
||||
// Most commonly, it was called as
|
||||
//
|
||||
// NewProcessCollector(os.Getpid(), "")
|
||||
//
|
||||
// The following call of the current version is equivalent to the above:
|
||||
//
|
||||
// NewProcessCollector(ProcessCollectorOpts{})
|
||||
func NewProcessCollector(opts ProcessCollectorOpts) Collector {
|
||||
ns := ""
|
||||
if len(namespace) > 0 {
|
||||
ns = namespace + "_"
|
||||
if len(opts.Namespace) > 0 {
|
||||
ns = opts.Namespace + "_"
|
||||
}
|
||||
|
||||
c := processCollector{
|
||||
pidFn: pidFn,
|
||||
collectFn: func(chan<- Metric) {},
|
||||
|
||||
c := &processCollector{
|
||||
reportErrors: opts.ReportErrors,
|
||||
cpuTotal: NewDesc(
|
||||
ns+"process_cpu_seconds_total",
|
||||
"Total user and system CPU time spent in seconds.",
|
||||
|
@ -73,6 +101,11 @@ func NewProcessCollectorPIDFn(
|
|||
"Virtual memory size in bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
maxVsize: NewDesc(
|
||||
ns+"process_virtual_memory_max_bytes",
|
||||
"Maximum amount of virtual memory available in bytes.",
|
||||
nil, nil,
|
||||
),
|
||||
rss: NewDesc(
|
||||
ns+"process_resident_memory_bytes",
|
||||
"Resident memory size in bytes.",
|
||||
|
@ -85,12 +118,23 @@ func NewProcessCollectorPIDFn(
|
|||
),
|
||||
}
|
||||
|
||||
if opts.PidFn == nil {
|
||||
pid := os.Getpid()
|
||||
c.pidFn = func() (int, error) { return pid, nil }
|
||||
} else {
|
||||
c.pidFn = opts.PidFn
|
||||
}
|
||||
|
||||
// Set up process metric collection if supported by the runtime.
|
||||
if _, err := procfs.NewStat(); err == nil {
|
||||
c.collectFn = c.processCollect
|
||||
} else {
|
||||
c.collectFn = func(ch chan<- Metric) {
|
||||
c.reportError(ch, nil, errors.New("process metrics not supported on this platform"))
|
||||
}
|
||||
}
|
||||
|
||||
return &c
|
||||
return c
|
||||
}
|
||||
|
||||
// Describe returns all descriptions of the collector.
|
||||
|
@ -99,6 +143,7 @@ func (c *processCollector) Describe(ch chan<- *Desc) {
|
|||
ch <- c.openFDs
|
||||
ch <- c.maxFDs
|
||||
ch <- c.vsize
|
||||
ch <- c.maxVsize
|
||||
ch <- c.rss
|
||||
ch <- c.startTime
|
||||
}
|
||||
|
@ -108,16 +153,16 @@ func (c *processCollector) Collect(ch chan<- Metric) {
|
|||
c.collectFn(ch)
|
||||
}
|
||||
|
||||
// TODO(ts): Bring back error reporting by reverting 7faf9e7 as soon as the
|
||||
// client allows users to configure the error behavior.
|
||||
func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||
pid, err := c.pidFn()
|
||||
if err != nil {
|
||||
c.reportError(ch, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
p, err := procfs.NewProc(pid)
|
||||
if err != nil {
|
||||
c.reportError(ch, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -127,14 +172,33 @@ func (c *processCollector) processCollect(ch chan<- Metric) {
|
|||
ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory()))
|
||||
if startTime, err := stat.StartTime(); err == nil {
|
||||
ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime)
|
||||
} else {
|
||||
c.reportError(ch, c.startTime, err)
|
||||
}
|
||||
} else {
|
||||
c.reportError(ch, nil, err)
|
||||
}
|
||||
|
||||
if fds, err := p.FileDescriptorsLen(); err == nil {
|
||||
ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds))
|
||||
} else {
|
||||
c.reportError(ch, c.openFDs, err)
|
||||
}
|
||||
|
||||
if limits, err := p.NewLimits(); err == nil {
|
||||
ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles))
|
||||
ch <- MustNewConstMetric(c.maxVsize, GaugeValue, float64(limits.AddressSpace))
|
||||
} else {
|
||||
c.reportError(ch, nil, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) {
|
||||
if !c.reportErrors {
|
||||
return
|
||||
}
|
||||
if desc == nil {
|
||||
desc = NewInvalidDesc(err)
|
||||
}
|
||||
ch <- NewInvalidMetric(desc, err)
|
||||
}
|
||||
|
|
53
vendor/github.com/prometheus/client_golang/prometheus/process_collector_test.go
generated
vendored
53
vendor/github.com/prometheus/client_golang/prometheus/process_collector_test.go
generated
vendored
|
@ -1,13 +1,31 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/common/expfmt"
|
||||
"github.com/prometheus/procfs"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
func TestProcessCollector(t *testing.T) {
|
||||
|
@ -16,12 +34,14 @@ func TestProcessCollector(t *testing.T) {
|
|||
}
|
||||
|
||||
registry := NewRegistry()
|
||||
if err := registry.Register(NewProcessCollector(os.Getpid(), "")); err != nil {
|
||||
if err := registry.Register(NewProcessCollector(ProcessCollectorOpts{})); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := registry.Register(NewProcessCollectorPIDFn(
|
||||
func() (int, error) { return os.Getpid(), nil }, "foobar"),
|
||||
); err != nil {
|
||||
if err := registry.Register(NewProcessCollector(ProcessCollectorOpts{
|
||||
PidFn: func() (int, error) { return os.Getpid(), nil },
|
||||
Namespace: "foobar",
|
||||
ReportErrors: true, // No errors expected, just to see if none are reported.
|
||||
})); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -41,12 +61,14 @@ func TestProcessCollector(t *testing.T) {
|
|||
regexp.MustCompile("\nprocess_cpu_seconds_total [0-9]"),
|
||||
regexp.MustCompile("\nprocess_max_fds [1-9]"),
|
||||
regexp.MustCompile("\nprocess_open_fds [1-9]"),
|
||||
regexp.MustCompile("\nprocess_virtual_memory_max_bytes (-1|[1-9])"),
|
||||
regexp.MustCompile("\nprocess_virtual_memory_bytes [1-9]"),
|
||||
regexp.MustCompile("\nprocess_resident_memory_bytes [1-9]"),
|
||||
regexp.MustCompile("\nprocess_start_time_seconds [0-9.]{10,}"),
|
||||
regexp.MustCompile("\nfoobar_process_cpu_seconds_total [0-9]"),
|
||||
regexp.MustCompile("\nfoobar_process_max_fds [1-9]"),
|
||||
regexp.MustCompile("\nfoobar_process_open_fds [1-9]"),
|
||||
regexp.MustCompile("\nfoobar_process_virtual_memory_max_bytes (-1|[1-9])"),
|
||||
regexp.MustCompile("\nfoobar_process_virtual_memory_bytes [1-9]"),
|
||||
regexp.MustCompile("\nfoobar_process_resident_memory_bytes [1-9]"),
|
||||
regexp.MustCompile("\nfoobar_process_start_time_seconds [0-9.]{10,}"),
|
||||
|
@ -55,4 +77,27 @@ func TestProcessCollector(t *testing.T) {
|
|||
t.Errorf("want body to match %s\n%s", re, buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
brokenProcessCollector := NewProcessCollector(ProcessCollectorOpts{
|
||||
PidFn: func() (int, error) { return 0, errors.New("boo") },
|
||||
ReportErrors: true,
|
||||
})
|
||||
|
||||
ch := make(chan Metric)
|
||||
go func() {
|
||||
brokenProcessCollector.Collect(ch)
|
||||
close(ch)
|
||||
}()
|
||||
n := 0
|
||||
for m := range ch {
|
||||
n++
|
||||
pb := &dto.Metric{}
|
||||
err := m.Write(pb)
|
||||
if err == nil {
|
||||
t.Error("metric collected from broken process collector is unexpectedly valid")
|
||||
}
|
||||
}
|
||||
if n != 1 {
|
||||
t.Errorf("%d metrics collected, want 1", n)
|
||||
}
|
||||
}
|
||||
|
|
223
vendor/github.com/prometheus/client_golang/prometheus/promauto/auto.go
generated
vendored
Normal file
223
vendor/github.com/prometheus/client_golang/prometheus/promauto/auto.go
generated
vendored
Normal file
|
@ -0,0 +1,223 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package promauto provides constructors for the usual Prometheus metrics that
|
||||
// return them already registered with the global registry
|
||||
// (prometheus.DefaultRegisterer). This allows very compact code, avoiding any
|
||||
// references to the registry altogether, but all the constructors in this
|
||||
// package will panic if the registration fails.
|
||||
//
|
||||
// The following example is a complete program to create a histogram of normally
|
||||
// distributed random numbers from the math/rand package:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import (
|
||||
// "math/rand"
|
||||
// "net/http"
|
||||
//
|
||||
// "github.com/prometheus/client_golang/prometheus"
|
||||
// "github.com/prometheus/client_golang/prometheus/promauto"
|
||||
// "github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
// )
|
||||
//
|
||||
// var histogram = promauto.NewHistogram(prometheus.HistogramOpts{
|
||||
// Name: "random_numbers",
|
||||
// Help: "A histogram of normally distributed random numbers.",
|
||||
// Buckets: prometheus.LinearBuckets(-3, .1, 61),
|
||||
// })
|
||||
//
|
||||
// func Random() {
|
||||
// for {
|
||||
// histogram.Observe(rand.NormFloat64())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func main() {
|
||||
// go Random()
|
||||
// http.Handle("/metrics", promhttp.Handler())
|
||||
// http.ListenAndServe(":1971", nil)
|
||||
// }
|
||||
//
|
||||
// Prometheus's version of a minimal hello-world program:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import (
|
||||
// "fmt"
|
||||
// "net/http"
|
||||
//
|
||||
// "github.com/prometheus/client_golang/prometheus"
|
||||
// "github.com/prometheus/client_golang/prometheus/promauto"
|
||||
// "github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
// http.Handle("/", promhttp.InstrumentHandlerCounter(
|
||||
// promauto.NewCounterVec(
|
||||
// prometheus.CounterOpts{
|
||||
// Name: "hello_requests_total",
|
||||
// Help: "Total number of hello-world requests by HTTP code.",
|
||||
// },
|
||||
// []string{"code"},
|
||||
// ),
|
||||
// http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// fmt.Fprint(w, "Hello, world!")
|
||||
// }),
|
||||
// ))
|
||||
// http.Handle("/metrics", promhttp.Handler())
|
||||
// http.ListenAndServe(":1971", nil)
|
||||
// }
|
||||
//
|
||||
// This appears very handy. So why are these constructors locked away in a
|
||||
// separate package? There are two caveats:
|
||||
//
|
||||
// First, in more complex programs, global state is often quite problematic.
|
||||
// That's the reason why the metrics constructors in the prometheus package do
|
||||
// not interact with the global prometheus.DefaultRegisterer on their own. You
|
||||
// are free to use the Register or MustRegister functions to register them with
|
||||
// the global prometheus.DefaultRegisterer, but you could as well choose a local
|
||||
// Registerer (usually created with prometheus.NewRegistry, but there are other
|
||||
// scenarios, e.g. testing).
|
||||
//
|
||||
// The second issue is that registration may fail, e.g. if a metric inconsistent
|
||||
// with the newly to be registered one is already registered. But how to signal
|
||||
// and handle a panic in the automatic registration with the default registry?
|
||||
// The only way is panicking. While panicking on invalid input provided by the
|
||||
// programmer is certainly fine, things are a bit more subtle in this case: You
|
||||
// might just add another package to the program, and that package (in its init
|
||||
// function) happens to register a metric with the same name as your code. Now,
|
||||
// all of a sudden, either your code or the code of the newly imported package
|
||||
// panics, depending on initialization order, without any opportunity to handle
|
||||
// the case gracefully. Even worse is a scenario where registration happens
|
||||
// later during the runtime (e.g. upon loading some kind of plugin), where the
|
||||
// panic could be triggered long after the code has been deployed to
|
||||
// production. A possibility to panic should be explicitly called out by the
|
||||
// Must… idiom, cf. prometheus.MustRegister. But adding a separate set of
|
||||
// constructors in the prometheus package called MustRegisterNewCounterVec or
|
||||
// similar would be quite unwieldy. Adding an extra MustRegister method to each
|
||||
// metric, returning the registered metric, would result in nice code for those
|
||||
// using the method, but would pollute every single metric interface for
|
||||
// everybody avoiding the global registry.
|
||||
//
|
||||
// To address both issues, the problematic auto-registering and possibly
|
||||
// panicking constructors are all in this package with a clear warning
|
||||
// ahead. And whoever cares about avoiding global state and possibly panicking
|
||||
// function calls can simply ignore the existence of the promauto package
|
||||
// altogether.
|
||||
//
|
||||
// A final note: There is a similar case in the net/http package of the standard
|
||||
// library. It has DefaultServeMux as a global instance of ServeMux, and the
|
||||
// Handle function acts on it, panicking if a handler for the same pattern has
|
||||
// already been registered. However, one might argue that the whole HTTP routing
|
||||
// is usually set up closely together in the same package or file, while
|
||||
// Prometheus metrics tend to be spread widely over the codebase, increasing the
|
||||
// chance of surprising registration failures. Furthermore, the use of global
|
||||
// state in net/http has been criticized widely, and some avoid it altogether.
|
||||
package promauto
|
||||
|
||||
import "github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
// NewCounter works like the function of the same name in the prometheus package
|
||||
// but it automatically registers the Counter with the
|
||||
// prometheus.DefaultRegisterer. If the registration fails, NewCounter panics.
|
||||
func NewCounter(opts prometheus.CounterOpts) prometheus.Counter {
|
||||
c := prometheus.NewCounter(opts)
|
||||
prometheus.MustRegister(c)
|
||||
return c
|
||||
}
|
||||
|
||||
// NewCounterVec works like the function of the same name in the prometheus
|
||||
// package but it automatically registers the CounterVec with the
|
||||
// prometheus.DefaultRegisterer. If the registration fails, NewCounterVec
|
||||
// panics.
|
||||
func NewCounterVec(opts prometheus.CounterOpts, labelNames []string) *prometheus.CounterVec {
|
||||
c := prometheus.NewCounterVec(opts, labelNames)
|
||||
prometheus.MustRegister(c)
|
||||
return c
|
||||
}
|
||||
|
||||
// NewCounterFunc works like the function of the same name in the prometheus
|
||||
// package but it automatically registers the CounterFunc with the
|
||||
// prometheus.DefaultRegisterer. If the registration fails, NewCounterFunc
|
||||
// panics.
|
||||
func NewCounterFunc(opts prometheus.CounterOpts, function func() float64) prometheus.CounterFunc {
|
||||
g := prometheus.NewCounterFunc(opts, function)
|
||||
prometheus.MustRegister(g)
|
||||
return g
|
||||
}
|
||||
|
||||
// NewGauge works like the function of the same name in the prometheus package
|
||||
// but it automatically registers the Gauge with the
|
||||
// prometheus.DefaultRegisterer. If the registration fails, NewGauge panics.
|
||||
func NewGauge(opts prometheus.GaugeOpts) prometheus.Gauge {
|
||||
g := prometheus.NewGauge(opts)
|
||||
prometheus.MustRegister(g)
|
||||
return g
|
||||
}
|
||||
|
||||
// NewGaugeVec works like the function of the same name in the prometheus
|
||||
// package but it automatically registers the GaugeVec with the
|
||||
// prometheus.DefaultRegisterer. If the registration fails, NewGaugeVec panics.
|
||||
func NewGaugeVec(opts prometheus.GaugeOpts, labelNames []string) *prometheus.GaugeVec {
|
||||
g := prometheus.NewGaugeVec(opts, labelNames)
|
||||
prometheus.MustRegister(g)
|
||||
return g
|
||||
}
|
||||
|
||||
// NewGaugeFunc works like the function of the same name in the prometheus
|
||||
// package but it automatically registers the GaugeFunc with the
|
||||
// prometheus.DefaultRegisterer. If the registration fails, NewGaugeFunc panics.
|
||||
func NewGaugeFunc(opts prometheus.GaugeOpts, function func() float64) prometheus.GaugeFunc {
|
||||
g := prometheus.NewGaugeFunc(opts, function)
|
||||
prometheus.MustRegister(g)
|
||||
return g
|
||||
}
|
||||
|
||||
// NewSummary works like the function of the same name in the prometheus package
|
||||
// but it automatically registers the Summary with the
|
||||
// prometheus.DefaultRegisterer. If the registration fails, NewSummary panics.
|
||||
func NewSummary(opts prometheus.SummaryOpts) prometheus.Summary {
|
||||
s := prometheus.NewSummary(opts)
|
||||
prometheus.MustRegister(s)
|
||||
return s
|
||||
}
|
||||
|
||||
// NewSummaryVec works like the function of the same name in the prometheus
|
||||
// package but it automatically registers the SummaryVec with the
|
||||
// prometheus.DefaultRegisterer. If the registration fails, NewSummaryVec
|
||||
// panics.
|
||||
func NewSummaryVec(opts prometheus.SummaryOpts, labelNames []string) *prometheus.SummaryVec {
|
||||
s := prometheus.NewSummaryVec(opts, labelNames)
|
||||
prometheus.MustRegister(s)
|
||||
return s
|
||||
}
|
||||
|
||||
// NewHistogram works like the function of the same name in the prometheus
|
||||
// package but it automatically registers the Histogram with the
|
||||
// prometheus.DefaultRegisterer. If the registration fails, NewHistogram panics.
|
||||
func NewHistogram(opts prometheus.HistogramOpts) prometheus.Histogram {
|
||||
h := prometheus.NewHistogram(opts)
|
||||
prometheus.MustRegister(h)
|
||||
return h
|
||||
}
|
||||
|
||||
// NewHistogramVec works like the function of the same name in the prometheus
|
||||
// package but it automatically registers the HistogramVec with the
|
||||
// prometheus.DefaultRegisterer. If the registration fails, NewHistogramVec
|
||||
// panics.
|
||||
func NewHistogramVec(opts prometheus.HistogramOpts, labelNames []string) *prometheus.HistogramVec {
|
||||
h := prometheus.NewHistogramVec(opts, labelNames)
|
||||
prometheus.MustRegister(h)
|
||||
return h
|
||||
}
|
36
vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go
generated
vendored
36
vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go
generated
vendored
|
@ -76,16 +76,16 @@ type flusherDelegator struct{ *responseWriterDelegator }
|
|||
type hijackerDelegator struct{ *responseWriterDelegator }
|
||||
type readerFromDelegator struct{ *responseWriterDelegator }
|
||||
|
||||
func (d *closeNotifierDelegator) CloseNotify() <-chan bool {
|
||||
func (d closeNotifierDelegator) CloseNotify() <-chan bool {
|
||||
return d.ResponseWriter.(http.CloseNotifier).CloseNotify()
|
||||
}
|
||||
func (d *flusherDelegator) Flush() {
|
||||
func (d flusherDelegator) Flush() {
|
||||
d.ResponseWriter.(http.Flusher).Flush()
|
||||
}
|
||||
func (d *hijackerDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
func (d hijackerDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
return d.ResponseWriter.(http.Hijacker).Hijack()
|
||||
}
|
||||
func (d *readerFromDelegator) ReadFrom(re io.Reader) (int64, error) {
|
||||
func (d readerFromDelegator) ReadFrom(re io.Reader) (int64, error) {
|
||||
if !d.wroteHeader {
|
||||
d.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
@ -102,34 +102,34 @@ func init() {
|
|||
return d
|
||||
}
|
||||
pickDelegator[closeNotifier] = func(d *responseWriterDelegator) delegator { // 1
|
||||
return &closeNotifierDelegator{d}
|
||||
return closeNotifierDelegator{d}
|
||||
}
|
||||
pickDelegator[flusher] = func(d *responseWriterDelegator) delegator { // 2
|
||||
return &flusherDelegator{d}
|
||||
return flusherDelegator{d}
|
||||
}
|
||||
pickDelegator[flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 3
|
||||
return struct {
|
||||
*responseWriterDelegator
|
||||
http.Flusher
|
||||
http.CloseNotifier
|
||||
}{d, &flusherDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, flusherDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[hijacker] = func(d *responseWriterDelegator) delegator { // 4
|
||||
return &hijackerDelegator{d}
|
||||
return hijackerDelegator{d}
|
||||
}
|
||||
pickDelegator[hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 5
|
||||
return struct {
|
||||
*responseWriterDelegator
|
||||
http.Hijacker
|
||||
http.CloseNotifier
|
||||
}{d, &hijackerDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, hijackerDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 6
|
||||
return struct {
|
||||
*responseWriterDelegator
|
||||
http.Hijacker
|
||||
http.Flusher
|
||||
}{d, &hijackerDelegator{d}, &flusherDelegator{d}}
|
||||
}{d, hijackerDelegator{d}, flusherDelegator{d}}
|
||||
}
|
||||
pickDelegator[hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 7
|
||||
return struct {
|
||||
|
@ -137,7 +137,7 @@ func init() {
|
|||
http.Hijacker
|
||||
http.Flusher
|
||||
http.CloseNotifier
|
||||
}{d, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[readerFrom] = func(d *responseWriterDelegator) delegator { // 8
|
||||
return readerFromDelegator{d}
|
||||
|
@ -147,14 +147,14 @@ func init() {
|
|||
*responseWriterDelegator
|
||||
io.ReaderFrom
|
||||
http.CloseNotifier
|
||||
}{d, &readerFromDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, readerFromDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 10
|
||||
return struct {
|
||||
*responseWriterDelegator
|
||||
io.ReaderFrom
|
||||
http.Flusher
|
||||
}{d, &readerFromDelegator{d}, &flusherDelegator{d}}
|
||||
}{d, readerFromDelegator{d}, flusherDelegator{d}}
|
||||
}
|
||||
pickDelegator[readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 11
|
||||
return struct {
|
||||
|
@ -162,14 +162,14 @@ func init() {
|
|||
io.ReaderFrom
|
||||
http.Flusher
|
||||
http.CloseNotifier
|
||||
}{d, &readerFromDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, readerFromDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 12
|
||||
return struct {
|
||||
*responseWriterDelegator
|
||||
io.ReaderFrom
|
||||
http.Hijacker
|
||||
}{d, &readerFromDelegator{d}, &hijackerDelegator{d}}
|
||||
}{d, readerFromDelegator{d}, hijackerDelegator{d}}
|
||||
}
|
||||
pickDelegator[readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 13
|
||||
return struct {
|
||||
|
@ -177,7 +177,7 @@ func init() {
|
|||
io.ReaderFrom
|
||||
http.Hijacker
|
||||
http.CloseNotifier
|
||||
}{d, &readerFromDelegator{d}, &hijackerDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, readerFromDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 14
|
||||
return struct {
|
||||
|
@ -185,7 +185,7 @@ func init() {
|
|||
io.ReaderFrom
|
||||
http.Hijacker
|
||||
http.Flusher
|
||||
}{d, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}}
|
||||
}{d, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}}
|
||||
}
|
||||
pickDelegator[readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 15
|
||||
return struct {
|
||||
|
@ -194,6 +194,6 @@ func init() {
|
|||
http.Hijacker
|
||||
http.Flusher
|
||||
http.CloseNotifier
|
||||
}{d, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
}
|
||||
|
|
34
vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go
generated
vendored
34
vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go
generated
vendored
|
@ -22,27 +22,27 @@ import (
|
|||
|
||||
type pusherDelegator struct{ *responseWriterDelegator }
|
||||
|
||||
func (d *pusherDelegator) Push(target string, opts *http.PushOptions) error {
|
||||
func (d pusherDelegator) Push(target string, opts *http.PushOptions) error {
|
||||
return d.ResponseWriter.(http.Pusher).Push(target, opts)
|
||||
}
|
||||
|
||||
func init() {
|
||||
pickDelegator[pusher] = func(d *responseWriterDelegator) delegator { // 16
|
||||
return &pusherDelegator{d}
|
||||
return pusherDelegator{d}
|
||||
}
|
||||
pickDelegator[pusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 17
|
||||
return struct {
|
||||
*responseWriterDelegator
|
||||
http.Pusher
|
||||
http.CloseNotifier
|
||||
}{d, &pusherDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, pusherDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+flusher] = func(d *responseWriterDelegator) delegator { // 18
|
||||
return struct {
|
||||
*responseWriterDelegator
|
||||
http.Pusher
|
||||
http.Flusher
|
||||
}{d, &pusherDelegator{d}, &flusherDelegator{d}}
|
||||
}{d, pusherDelegator{d}, flusherDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 19
|
||||
return struct {
|
||||
|
@ -50,14 +50,14 @@ func init() {
|
|||
http.Pusher
|
||||
http.Flusher
|
||||
http.CloseNotifier
|
||||
}{d, &pusherDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, pusherDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+hijacker] = func(d *responseWriterDelegator) delegator { // 20
|
||||
return struct {
|
||||
*responseWriterDelegator
|
||||
http.Pusher
|
||||
http.Hijacker
|
||||
}{d, &pusherDelegator{d}, &hijackerDelegator{d}}
|
||||
}{d, pusherDelegator{d}, hijackerDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 21
|
||||
return struct {
|
||||
|
@ -65,7 +65,7 @@ func init() {
|
|||
http.Pusher
|
||||
http.Hijacker
|
||||
http.CloseNotifier
|
||||
}{d, &pusherDelegator{d}, &hijackerDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, pusherDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 22
|
||||
return struct {
|
||||
|
@ -73,7 +73,7 @@ func init() {
|
|||
http.Pusher
|
||||
http.Hijacker
|
||||
http.Flusher
|
||||
}{d, &pusherDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}}
|
||||
}{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { //23
|
||||
return struct {
|
||||
|
@ -82,14 +82,14 @@ func init() {
|
|||
http.Hijacker
|
||||
http.Flusher
|
||||
http.CloseNotifier
|
||||
}{d, &pusherDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+readerFrom] = func(d *responseWriterDelegator) delegator { // 24
|
||||
return struct {
|
||||
*responseWriterDelegator
|
||||
http.Pusher
|
||||
io.ReaderFrom
|
||||
}{d, &pusherDelegator{d}, &readerFromDelegator{d}}
|
||||
}{d, pusherDelegator{d}, readerFromDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 25
|
||||
return struct {
|
||||
|
@ -97,7 +97,7 @@ func init() {
|
|||
http.Pusher
|
||||
io.ReaderFrom
|
||||
http.CloseNotifier
|
||||
}{d, &pusherDelegator{d}, &readerFromDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, pusherDelegator{d}, readerFromDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 26
|
||||
return struct {
|
||||
|
@ -105,7 +105,7 @@ func init() {
|
|||
http.Pusher
|
||||
io.ReaderFrom
|
||||
http.Flusher
|
||||
}{d, &pusherDelegator{d}, &readerFromDelegator{d}, &flusherDelegator{d}}
|
||||
}{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 27
|
||||
return struct {
|
||||
|
@ -114,7 +114,7 @@ func init() {
|
|||
io.ReaderFrom
|
||||
http.Flusher
|
||||
http.CloseNotifier
|
||||
}{d, &pusherDelegator{d}, &readerFromDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 28
|
||||
return struct {
|
||||
|
@ -122,7 +122,7 @@ func init() {
|
|||
http.Pusher
|
||||
io.ReaderFrom
|
||||
http.Hijacker
|
||||
}{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}}
|
||||
}{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 29
|
||||
return struct {
|
||||
|
@ -131,7 +131,7 @@ func init() {
|
|||
io.ReaderFrom
|
||||
http.Hijacker
|
||||
http.CloseNotifier
|
||||
}{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 30
|
||||
return struct {
|
||||
|
@ -140,7 +140,7 @@ func init() {
|
|||
io.ReaderFrom
|
||||
http.Hijacker
|
||||
http.Flusher
|
||||
}{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}}
|
||||
}{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}}
|
||||
}
|
||||
pickDelegator[pusher+readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 31
|
||||
return struct {
|
||||
|
@ -150,7 +150,7 @@ func init() {
|
|||
http.Hijacker
|
||||
http.Flusher
|
||||
http.CloseNotifier
|
||||
}{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
|
||||
}{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
generated
vendored
2
vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
generated
vendored
|
@ -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"
|
||||
}
|
||||
|
|
2
vendor/github.com/prometheus/client_golang/prometheus/promhttp/http_test.go
generated
vendored
2
vendor/github.com/prometheus/client_golang/prometheus/promhttp/http_test.go
generated
vendored
|
@ -121,7 +121,7 @@ the_count 0
|
|||
t.Errorf("got HTTP status code %d, want %d", got, want)
|
||||
}
|
||||
if got := logBuf.String(); got != wantMsg {
|
||||
t.Errorf("got log message:\n%s\nwant log mesage:\n%s\n", got, wantMsg)
|
||||
t.Errorf("got log message:\n%s\nwant log message:\n%s\n", got, wantMsg)
|
||||
}
|
||||
if got := writer.Body.String(); got != wantErrorBody {
|
||||
t.Errorf("got body:\n%s\nwant body:\n%s\n", got, wantErrorBody)
|
||||
|
|
|
@ -81,8 +81,8 @@ func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) Ro
|
|||
}
|
||||
},
|
||||
DNSDone: func(_ httptrace.DNSDoneInfo) {
|
||||
if it.DNSStart != nil {
|
||||
it.DNSStart(time.Since(start).Seconds())
|
||||
if it.DNSDone != nil {
|
||||
it.DNSDone(time.Since(start).Seconds())
|
||||
}
|
||||
},
|
||||
ConnectStart: func(_, _ string) {
|
||||
|
|
172
vendor/github.com/prometheus/client_golang/prometheus/push/deprecated.go
generated
vendored
Normal file
172
vendor/github.com/prometheus/client_golang/prometheus/push/deprecated.go
generated
vendored
Normal file
|
@ -0,0 +1,172 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package push
|
||||
|
||||
// This file contains only deprecated code. Remove after v0.9 is released.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/common/expfmt"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// FromGatherer triggers a metric collection by the provided Gatherer (which is
|
||||
// usually implemented by a prometheus.Registry) and pushes all gathered metrics
|
||||
// to the Pushgateway specified by url, using the provided job name and the
|
||||
// (optional) further grouping labels (the grouping map may be nil). See the
|
||||
// Pushgateway documentation for detailed implications of the job and other
|
||||
// grouping labels. Neither the job name nor any grouping label value may
|
||||
// contain a "/". The metrics pushed must not contain a job label of their own
|
||||
// nor any of the grouping labels.
|
||||
//
|
||||
// You can use just host:port or ip:port as url, in which case 'http://' is
|
||||
// added automatically. You can also include the schema in the URL. However, do
|
||||
// not include the '/metrics/jobs/...' part.
|
||||
//
|
||||
// Note that all previously pushed metrics with the same job and other grouping
|
||||
// labels will be replaced with the metrics pushed by this call. (It uses HTTP
|
||||
// method 'PUT' to push to the Pushgateway.)
|
||||
//
|
||||
// Deprecated: Please use a Pusher created with New instead.
|
||||
func FromGatherer(job string, grouping map[string]string, url string, g prometheus.Gatherer) error {
|
||||
return push(job, grouping, url, g, "PUT")
|
||||
}
|
||||
|
||||
// AddFromGatherer works like FromGatherer, but only previously pushed metrics
|
||||
// with the same name (and the same job and other grouping labels) will be
|
||||
// replaced. (It uses HTTP method 'POST' to push to the Pushgateway.)
|
||||
//
|
||||
// Deprecated: Please use a Pusher created with New instead.
|
||||
func AddFromGatherer(job string, grouping map[string]string, url string, g prometheus.Gatherer) error {
|
||||
return push(job, grouping, url, g, "POST")
|
||||
}
|
||||
|
||||
func push(job string, grouping map[string]string, pushURL string, g prometheus.Gatherer, method string) error {
|
||||
if !strings.Contains(pushURL, "://") {
|
||||
pushURL = "http://" + pushURL
|
||||
}
|
||||
if strings.HasSuffix(pushURL, "/") {
|
||||
pushURL = pushURL[:len(pushURL)-1]
|
||||
}
|
||||
|
||||
if strings.Contains(job, "/") {
|
||||
return fmt.Errorf("job contains '/': %s", job)
|
||||
}
|
||||
urlComponents := []string{url.QueryEscape(job)}
|
||||
for ln, lv := range grouping {
|
||||
if !model.LabelName(ln).IsValid() {
|
||||
return fmt.Errorf("grouping label has invalid name: %s", ln)
|
||||
}
|
||||
if strings.Contains(lv, "/") {
|
||||
return fmt.Errorf("value of grouping label %s contains '/': %s", ln, lv)
|
||||
}
|
||||
urlComponents = append(urlComponents, ln, lv)
|
||||
}
|
||||
pushURL = fmt.Sprintf("%s/metrics/job/%s", pushURL, strings.Join(urlComponents, "/"))
|
||||
|
||||
mfs, err := g.Gather()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
enc := expfmt.NewEncoder(buf, expfmt.FmtProtoDelim)
|
||||
// Check for pre-existing grouping labels:
|
||||
for _, mf := range mfs {
|
||||
for _, m := range mf.GetMetric() {
|
||||
for _, l := range m.GetLabel() {
|
||||
if l.GetName() == "job" {
|
||||
return fmt.Errorf("pushed metric %s (%s) already contains a job label", mf.GetName(), m)
|
||||
}
|
||||
if _, ok := grouping[l.GetName()]; ok {
|
||||
return fmt.Errorf(
|
||||
"pushed metric %s (%s) already contains grouping label %s",
|
||||
mf.GetName(), m, l.GetName(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
enc.Encode(mf)
|
||||
}
|
||||
req, err := http.NewRequest(method, pushURL, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set(contentTypeHeader, string(expfmt.FmtProtoDelim))
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 202 {
|
||||
body, _ := ioutil.ReadAll(resp.Body) // Ignore any further error as this is for an error message only.
|
||||
return fmt.Errorf("unexpected status code %d while pushing to %s: %s", resp.StatusCode, pushURL, body)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Collectors works like FromGatherer, but it does not use a Gatherer. Instead,
|
||||
// it collects from the provided collectors directly. It is a convenient way to
|
||||
// push only a few metrics.
|
||||
//
|
||||
// Deprecated: Please use a Pusher created with New instead.
|
||||
func Collectors(job string, grouping map[string]string, url string, collectors ...prometheus.Collector) error {
|
||||
return pushCollectors(job, grouping, url, "PUT", collectors...)
|
||||
}
|
||||
|
||||
// AddCollectors works like AddFromGatherer, but it does not use a Gatherer.
|
||||
// Instead, it collects from the provided collectors directly. It is a
|
||||
// convenient way to push only a few metrics.
|
||||
//
|
||||
// Deprecated: Please use a Pusher created with New instead.
|
||||
func AddCollectors(job string, grouping map[string]string, url string, collectors ...prometheus.Collector) error {
|
||||
return pushCollectors(job, grouping, url, "POST", collectors...)
|
||||
}
|
||||
|
||||
func pushCollectors(job string, grouping map[string]string, url, method string, collectors ...prometheus.Collector) error {
|
||||
r := prometheus.NewRegistry()
|
||||
for _, collector := range collectors {
|
||||
if err := r.Register(collector); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return push(job, grouping, url, r, method)
|
||||
}
|
||||
|
||||
// HostnameGroupingKey returns a label map with the only entry
|
||||
// {instance="<hostname>"}. This can be conveniently used as the grouping
|
||||
// parameter if metrics should be pushed with the hostname as label. The
|
||||
// returned map is created upon each call so that the caller is free to add more
|
||||
// labels to the map.
|
||||
//
|
||||
// Deprecated: Usually, metrics pushed to the Pushgateway should not be
|
||||
// host-centric. (You would use https://github.com/prometheus/node_exporter in
|
||||
// that case.) If you have the need to add the hostname to the grouping key, you
|
||||
// are probably doing something wrong. See
|
||||
// https://prometheus.io/docs/practices/pushing/ for details.
|
||||
func HostnameGroupingKey() map[string]string {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return map[string]string{"instance": "unknown"}
|
||||
}
|
||||
return map[string]string{"instance": hostname}
|
||||
}
|
80
vendor/github.com/prometheus/client_golang/prometheus/push/example_add_from_gatherer_test.go
generated
vendored
Normal file
80
vendor/github.com/prometheus/client_golang/prometheus/push/example_add_from_gatherer_test.go
generated
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
// Copyright 2016 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package push_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/push"
|
||||
)
|
||||
|
||||
var (
|
||||
completionTime = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "db_backup_last_completion_timestamp_seconds",
|
||||
Help: "The timestamp of the last completion of a DB backup, successful or not.",
|
||||
})
|
||||
successTime = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "db_backup_last_success_timestamp_seconds",
|
||||
Help: "The timestamp of the last successful completion of a DB backup.",
|
||||
})
|
||||
duration = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "db_backup_duration_seconds",
|
||||
Help: "The duration of the last DB backup in seconds.",
|
||||
})
|
||||
records = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "db_backup_records_processed",
|
||||
Help: "The number of records processed in the last DB backup.",
|
||||
})
|
||||
)
|
||||
|
||||
func performBackup() (int, error) {
|
||||
// Perform the backup and return the number of backed up records and any
|
||||
// applicable error.
|
||||
// ...
|
||||
return 42, nil
|
||||
}
|
||||
|
||||
func ExamplePusher_Add() {
|
||||
// We use a registry here to benefit from the consistency checks that
|
||||
// happen during registration.
|
||||
registry := prometheus.NewRegistry()
|
||||
registry.MustRegister(completionTime, duration, records)
|
||||
// Note that successTime is not registered.
|
||||
|
||||
pusher := push.New("http://pushgateway:9091", "db_backup").Gatherer(registry)
|
||||
|
||||
start := time.Now()
|
||||
n, err := performBackup()
|
||||
records.Set(float64(n))
|
||||
// Note that time.Since only uses a monotonic clock in Go1.9+.
|
||||
duration.Set(time.Since(start).Seconds())
|
||||
completionTime.SetToCurrentTime()
|
||||
if err != nil {
|
||||
fmt.Println("DB backup failed:", err)
|
||||
} else {
|
||||
// Add successTime to pusher only in case of success.
|
||||
// We could as well register it with the registry.
|
||||
// This example, however, demonstrates that you can
|
||||
// mix Gatherers and Collectors when handling a Pusher.
|
||||
pusher.Collector(successTime)
|
||||
successTime.SetToCurrentTime()
|
||||
}
|
||||
// Add is used here rather than Push to not delete a previously pushed
|
||||
// success timestamp in case of a failure of this backup.
|
||||
if err := pusher.Add(); err != nil {
|
||||
fmt.Println("Could not push to Pushgateway:", err)
|
||||
}
|
||||
}
|
35
vendor/github.com/prometheus/client_golang/prometheus/push/examples_test.go
generated
vendored
Normal file
35
vendor/github.com/prometheus/client_golang/prometheus/push/examples_test.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2016 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package push_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/push"
|
||||
)
|
||||
|
||||
func ExamplePusher_Push() {
|
||||
completionTime := prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "db_backup_last_completion_timestamp_seconds",
|
||||
Help: "The timestamp of the last successful completion of a DB backup.",
|
||||
})
|
||||
completionTime.SetToCurrentTime()
|
||||
if err := push.New("http://pushgateway:9091", "db_backup").
|
||||
Collector(completionTime).
|
||||
Grouping("db", "customers").
|
||||
Push(); err != nil {
|
||||
fmt.Println("Could not push completion time to Pushgateway:", err)
|
||||
}
|
||||
}
|
236
vendor/github.com/prometheus/client_golang/prometheus/push/push.go
generated
vendored
Normal file
236
vendor/github.com/prometheus/client_golang/prometheus/push/push.go
generated
vendored
Normal file
|
@ -0,0 +1,236 @@
|
|||
// Copyright 2015 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package push provides functions to push metrics to a Pushgateway. It uses a
|
||||
// builder approach. Create a Pusher with New and then add the various options
|
||||
// by using its methods, finally calling Add or Push, like this:
|
||||
//
|
||||
// // Easy case:
|
||||
// push.New("http://example.org/metrics", "my_job").Gatherer(myRegistry).Push()
|
||||
//
|
||||
// // Complex case:
|
||||
// push.New("http://example.org/metrics", "my_job").
|
||||
// Collector(myCollector1).
|
||||
// Collector(myCollector2).
|
||||
// Grouping("zone", "xy").
|
||||
// Client(&myHTTPClient).
|
||||
// BasicAuth("top", "secret").
|
||||
// Add()
|
||||
//
|
||||
// See the examples section for more detailed examples.
|
||||
//
|
||||
// See the documentation of the Pushgateway to understand the meaning of
|
||||
// the grouping key and the differences between Push and Add:
|
||||
// https://github.com/prometheus/pushgateway
|
||||
package push
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/common/expfmt"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const contentTypeHeader = "Content-Type"
|
||||
|
||||
// Pusher manages a push to the Pushgateway. Use New to create one, configure it
|
||||
// with its methods, and finally use the Add or Push method to push.
|
||||
type Pusher struct {
|
||||
error error
|
||||
|
||||
url, job string
|
||||
grouping map[string]string
|
||||
|
||||
gatherers prometheus.Gatherers
|
||||
registerer prometheus.Registerer
|
||||
|
||||
client *http.Client
|
||||
useBasicAuth bool
|
||||
username, password string
|
||||
}
|
||||
|
||||
// New creates a new Pusher to push to the provided URL with the provided job
|
||||
// name. You can use just host:port or ip:port as url, in which case “http://”
|
||||
// is added automatically. Alternatively, include the schema in the
|
||||
// URL. However, do not include the “/metrics/jobs/…” part.
|
||||
//
|
||||
// Note that until https://github.com/prometheus/pushgateway/issues/97 is
|
||||
// resolved, a “/” character in the job name is prohibited.
|
||||
func New(url, job string) *Pusher {
|
||||
var (
|
||||
reg = prometheus.NewRegistry()
|
||||
err error
|
||||
)
|
||||
if !strings.Contains(url, "://") {
|
||||
url = "http://" + url
|
||||
}
|
||||
if strings.HasSuffix(url, "/") {
|
||||
url = url[:len(url)-1]
|
||||
}
|
||||
if strings.Contains(job, "/") {
|
||||
err = fmt.Errorf("job contains '/': %s", job)
|
||||
}
|
||||
|
||||
return &Pusher{
|
||||
error: err,
|
||||
url: url,
|
||||
job: job,
|
||||
grouping: map[string]string{},
|
||||
gatherers: prometheus.Gatherers{reg},
|
||||
registerer: reg,
|
||||
client: &http.Client{},
|
||||
}
|
||||
}
|
||||
|
||||
// Push collects/gathers all metrics from all Collectors and Gatherers added to
|
||||
// this Pusher. Then, it pushes them to the Pushgateway configured while
|
||||
// creating this Pusher, using the configured job name and any added grouping
|
||||
// labels as grouping key. All previously pushed metrics with the same job and
|
||||
// other grouping labels will be replaced with the metrics pushed by this
|
||||
// call. (It uses HTTP method “PUT” to push to the Pushgateway.)
|
||||
//
|
||||
// Push returns the first error encountered by any method call (including this
|
||||
// one) in the lifetime of the Pusher.
|
||||
func (p *Pusher) Push() error {
|
||||
return p.push("PUT")
|
||||
}
|
||||
|
||||
// Add works like push, but only previously pushed metrics with the same name
|
||||
// (and the same job and other grouping labels) will be replaced. (It uses HTTP
|
||||
// method “POST” to push to the Pushgateway.)
|
||||
func (p *Pusher) Add() error {
|
||||
return p.push("POST")
|
||||
}
|
||||
|
||||
// Gatherer adds a Gatherer to the Pusher, from which metrics will be gathered
|
||||
// to push them to the Pushgateway. The gathered metrics must not contain a job
|
||||
// label of their own.
|
||||
//
|
||||
// For convenience, this method returns a pointer to the Pusher itself.
|
||||
func (p *Pusher) Gatherer(g prometheus.Gatherer) *Pusher {
|
||||
p.gatherers = append(p.gatherers, g)
|
||||
return p
|
||||
}
|
||||
|
||||
// Collector adds a Collector to the Pusher, from which metrics will be
|
||||
// collected to push them to the Pushgateway. The collected metrics must not
|
||||
// contain a job label of their own.
|
||||
//
|
||||
// For convenience, this method returns a pointer to the Pusher itself.
|
||||
func (p *Pusher) Collector(c prometheus.Collector) *Pusher {
|
||||
if p.error == nil {
|
||||
p.error = p.registerer.Register(c)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Grouping adds a label pair to the grouping key of the Pusher, replacing any
|
||||
// previously added label pair with the same label name. Note that setting any
|
||||
// labels in the grouping key that are already contained in the metrics to push
|
||||
// will lead to an error.
|
||||
//
|
||||
// For convenience, this method returns a pointer to the Pusher itself.
|
||||
//
|
||||
// Note that until https://github.com/prometheus/pushgateway/issues/97 is
|
||||
// resolved, this method does not allow a “/” character in the label value.
|
||||
func (p *Pusher) Grouping(name, value string) *Pusher {
|
||||
if p.error == nil {
|
||||
if !model.LabelName(name).IsValid() {
|
||||
p.error = fmt.Errorf("grouping label has invalid name: %s", name)
|
||||
return p
|
||||
}
|
||||
if strings.Contains(value, "/") {
|
||||
p.error = fmt.Errorf("value of grouping label %s contains '/': %s", name, value)
|
||||
return p
|
||||
}
|
||||
p.grouping[name] = value
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Client sets a custom HTTP client for the Pusher. For convenience, this method
|
||||
// returns a pointer to the Pusher itself.
|
||||
func (p *Pusher) Client(c *http.Client) *Pusher {
|
||||
p.client = c
|
||||
return p
|
||||
}
|
||||
|
||||
// BasicAuth configures the Pusher to use HTTP Basic Authentication with the
|
||||
// provided username and password. For convenience, this method returns a
|
||||
// pointer to the Pusher itself.
|
||||
func (p *Pusher) BasicAuth(username, password string) *Pusher {
|
||||
p.useBasicAuth = true
|
||||
p.username = username
|
||||
p.password = password
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Pusher) push(method string) error {
|
||||
if p.error != nil {
|
||||
return p.error
|
||||
}
|
||||
urlComponents := []string{url.QueryEscape(p.job)}
|
||||
for ln, lv := range p.grouping {
|
||||
urlComponents = append(urlComponents, ln, lv)
|
||||
}
|
||||
pushURL := fmt.Sprintf("%s/metrics/job/%s", p.url, strings.Join(urlComponents, "/"))
|
||||
|
||||
mfs, err := p.gatherers.Gather()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
enc := expfmt.NewEncoder(buf, expfmt.FmtProtoDelim)
|
||||
// Check for pre-existing grouping labels:
|
||||
for _, mf := range mfs {
|
||||
for _, m := range mf.GetMetric() {
|
||||
for _, l := range m.GetLabel() {
|
||||
if l.GetName() == "job" {
|
||||
return fmt.Errorf("pushed metric %s (%s) already contains a job label", mf.GetName(), m)
|
||||
}
|
||||
if _, ok := p.grouping[l.GetName()]; ok {
|
||||
return fmt.Errorf(
|
||||
"pushed metric %s (%s) already contains grouping label %s",
|
||||
mf.GetName(), m, l.GetName(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
enc.Encode(mf)
|
||||
}
|
||||
req, err := http.NewRequest(method, pushURL, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if p.useBasicAuth {
|
||||
req.SetBasicAuth(p.username, p.password)
|
||||
}
|
||||
req.Header.Set(contentTypeHeader, string(expfmt.FmtProtoDelim))
|
||||
resp, err := p.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 202 {
|
||||
body, _ := ioutil.ReadAll(resp.Body) // Ignore any further error as this is for an error message only.
|
||||
return fmt.Errorf("unexpected status code %d while pushing to %s: %s", resp.StatusCode, pushURL, body)
|
||||
}
|
||||
return nil
|
||||
}
|
194
vendor/github.com/prometheus/client_golang/prometheus/push/push_test.go
generated
vendored
Normal file
194
vendor/github.com/prometheus/client_golang/prometheus/push/push_test.go
generated
vendored
Normal file
|
@ -0,0 +1,194 @@
|
|||
// Copyright 2016 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package push
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/common/expfmt"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func TestPush(t *testing.T) {
|
||||
|
||||
var (
|
||||
lastMethod string
|
||||
lastBody []byte
|
||||
lastPath string
|
||||
)
|
||||
|
||||
// Fake a Pushgateway that always responds with 202.
|
||||
pgwOK := httptest.NewServer(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
lastMethod = r.Method
|
||||
var err error
|
||||
lastBody, err = ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lastPath = r.URL.EscapedPath()
|
||||
w.Header().Set("Content-Type", `text/plain; charset=utf-8`)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
}),
|
||||
)
|
||||
defer pgwOK.Close()
|
||||
|
||||
// Fake a Pushgateway that always responds with 500.
|
||||
pgwErr := httptest.NewServer(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "fake error", http.StatusInternalServerError)
|
||||
}),
|
||||
)
|
||||
defer pgwErr.Close()
|
||||
|
||||
metric1 := prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "testname1",
|
||||
Help: "testhelp1",
|
||||
})
|
||||
metric2 := prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "testname2",
|
||||
Help: "testhelp2",
|
||||
ConstLabels: prometheus.Labels{"foo": "bar", "dings": "bums"},
|
||||
})
|
||||
|
||||
reg := prometheus.NewRegistry()
|
||||
reg.MustRegister(metric1)
|
||||
reg.MustRegister(metric2)
|
||||
|
||||
mfs, err := reg.Gather()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
enc := expfmt.NewEncoder(buf, expfmt.FmtProtoDelim)
|
||||
|
||||
for _, mf := range mfs {
|
||||
if err := enc.Encode(mf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
wantBody := buf.Bytes()
|
||||
|
||||
// Push some Collectors, all good.
|
||||
if err := New(pgwOK.URL, "testjob").
|
||||
Collector(metric1).
|
||||
Collector(metric2).
|
||||
Push(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if lastMethod != "PUT" {
|
||||
t.Error("want method PUT for Push, got", lastMethod)
|
||||
}
|
||||
if bytes.Compare(lastBody, wantBody) != 0 {
|
||||
t.Errorf("got body %v, want %v", lastBody, wantBody)
|
||||
}
|
||||
if lastPath != "/metrics/job/testjob" {
|
||||
t.Error("unexpected path:", lastPath)
|
||||
}
|
||||
|
||||
// Add some Collectors, with nil grouping, all good.
|
||||
if err := New(pgwOK.URL, "testjob").
|
||||
Collector(metric1).
|
||||
Collector(metric2).
|
||||
Add(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if lastMethod != "POST" {
|
||||
t.Error("want method POST for Add, got", lastMethod)
|
||||
}
|
||||
if bytes.Compare(lastBody, wantBody) != 0 {
|
||||
t.Errorf("got body %v, want %v", lastBody, wantBody)
|
||||
}
|
||||
if lastPath != "/metrics/job/testjob" {
|
||||
t.Error("unexpected path:", lastPath)
|
||||
}
|
||||
|
||||
// Push some Collectors with a broken PGW.
|
||||
if err := New(pgwErr.URL, "testjob").
|
||||
Collector(metric1).
|
||||
Collector(metric2).
|
||||
Push(); err == nil {
|
||||
t.Error("push to broken Pushgateway succeeded")
|
||||
} else {
|
||||
if got, want := err.Error(), "unexpected status code 500 while pushing to "+pgwErr.URL+"/metrics/job/testjob: fake error\n"; got != want {
|
||||
t.Errorf("got error %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// Push some Collectors with invalid grouping or job.
|
||||
if err := New(pgwOK.URL, "testjob").
|
||||
Grouping("foo", "bums").
|
||||
Collector(metric1).
|
||||
Collector(metric2).
|
||||
Push(); err == nil {
|
||||
t.Error("push with grouping contained in metrics succeeded")
|
||||
}
|
||||
if err := New(pgwOK.URL, "test/job").
|
||||
Collector(metric1).
|
||||
Collector(metric2).
|
||||
Push(); err == nil {
|
||||
t.Error("push with invalid job value succeeded")
|
||||
}
|
||||
if err := New(pgwOK.URL, "testjob").
|
||||
Grouping("foobar", "bu/ms").
|
||||
Collector(metric1).
|
||||
Collector(metric2).
|
||||
Push(); err == nil {
|
||||
t.Error("push with invalid grouping succeeded")
|
||||
}
|
||||
if err := New(pgwOK.URL, "testjob").
|
||||
Grouping("foo-bar", "bums").
|
||||
Collector(metric1).
|
||||
Collector(metric2).
|
||||
Push(); err == nil {
|
||||
t.Error("push with invalid grouping succeeded")
|
||||
}
|
||||
|
||||
// Push registry, all good.
|
||||
if err := New(pgwOK.URL, "testjob").
|
||||
Gatherer(reg).
|
||||
Push(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if lastMethod != "PUT" {
|
||||
t.Error("want method PUT for Push, got", lastMethod)
|
||||
}
|
||||
if bytes.Compare(lastBody, wantBody) != 0 {
|
||||
t.Errorf("got body %v, want %v", lastBody, wantBody)
|
||||
}
|
||||
|
||||
// Add registry, all good.
|
||||
if err := New(pgwOK.URL, "testjob").
|
||||
Grouping("a", "x").
|
||||
Grouping("b", "y").
|
||||
Gatherer(reg).
|
||||
Add(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if lastMethod != "POST" {
|
||||
t.Error("want method POST for Add, got", lastMethod)
|
||||
}
|
||||
if bytes.Compare(lastBody, wantBody) != 0 {
|
||||
t.Errorf("got body %v, want %v", lastBody, wantBody)
|
||||
}
|
||||
if lastPath != "/metrics/job/testjob/a/x/b/y" && lastPath != "/metrics/job/testjob/b/y/a/x" {
|
||||
t.Error("unexpected path:", lastPath)
|
||||
}
|
||||
}
|
359
vendor/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
359
vendor/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
|
@ -15,17 +15,18 @@ package prometheus
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -38,12 +39,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
|
||||
|
@ -51,7 +53,7 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
MustRegister(NewProcessCollector(os.Getpid(), ""))
|
||||
MustRegister(NewProcessCollector(ProcessCollectorOpts{}))
|
||||
MustRegister(NewGoCollector())
|
||||
}
|
||||
|
||||
|
@ -67,7 +69,8 @@ func NewRegistry() *Registry {
|
|||
|
||||
// NewPedanticRegistry returns a registry that checks during collection if each
|
||||
// collected Metric is consistent with its reported Desc, and if the Desc has
|
||||
// actually been registered with the registry.
|
||||
// actually been registered with the registry. Unchecked Collectors (those whose
|
||||
// Describe methed does not yield any descriptors) are excluded from the check.
|
||||
//
|
||||
// Usually, a Registry will be happy as long as the union of all collected
|
||||
// Metrics is consistent and valid even if some metrics are not consistent with
|
||||
|
@ -97,6 +100,14 @@ type Registerer interface {
|
|||
// returned error is an instance of AlreadyRegisteredError, which
|
||||
// contains the previously registered Collector.
|
||||
//
|
||||
// A Collector whose Describe method does not yield any Desc is treated
|
||||
// as unchecked. Registration will always succeed. No check for
|
||||
// re-registering (see previous paragraph) is performed. Thus, the
|
||||
// caller is responsible for not double-registering the same unchecked
|
||||
// Collector, and for providing a Collector that will not cause
|
||||
// inconsistent metrics on collection. (This would lead to scrape
|
||||
// errors.)
|
||||
//
|
||||
// It is in general not safe to register the same Collector multiple
|
||||
// times concurrently.
|
||||
Register(Collector) error
|
||||
|
@ -107,7 +118,9 @@ type Registerer interface {
|
|||
// Unregister unregisters the Collector that equals the Collector passed
|
||||
// in as an argument. (Two Collectors are considered equal if their
|
||||
// Describe method yields the same set of descriptors.) The function
|
||||
// returns whether a Collector was unregistered.
|
||||
// returns whether a Collector was unregistered. Note that an unchecked
|
||||
// Collector cannot be unregistered (as its Describe method does not
|
||||
// yield any descriptor).
|
||||
//
|
||||
// Note that even after unregistering, it will not be possible to
|
||||
// register a new Collector that is inconsistent with the unregistered
|
||||
|
@ -125,15 +138,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)
|
||||
}
|
||||
|
||||
|
@ -234,6 +255,7 @@ type Registry struct {
|
|||
collectorsByID map[uint64]Collector // ID is a hash of the descIDs.
|
||||
descIDs map[uint64]struct{}
|
||||
dimHashesByName map[string]uint64
|
||||
uncheckedCollectors []Collector
|
||||
pedanticChecksEnabled bool
|
||||
}
|
||||
|
||||
|
@ -291,9 +313,10 @@ func (r *Registry) Register(c Collector) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Did anything happen at all?
|
||||
// A Collector yielding no Desc at all is considered unchecked.
|
||||
if len(newDescIDs) == 0 {
|
||||
return errors.New("collector has no descriptors")
|
||||
r.uncheckedCollectors = append(r.uncheckedCollectors, c)
|
||||
return nil
|
||||
}
|
||||
if existing, exists := r.collectorsByID[collectorID]; exists {
|
||||
return AlreadyRegisteredError{
|
||||
|
@ -367,20 +390,24 @@ func (r *Registry) MustRegister(cs ...Collector) {
|
|||
// Gather implements Gatherer.
|
||||
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
|
||||
checkedMetricChan = make(chan Metric, capMetricChan)
|
||||
uncheckedMetricChan = make(chan Metric, capMetricChan)
|
||||
metricHashes = map[uint64]struct{}{}
|
||||
wg sync.WaitGroup
|
||||
errs MultiError // The collected errors to return in the end.
|
||||
registeredDescIDs map[uint64]struct{} // Only used for pedantic checks
|
||||
)
|
||||
|
||||
r.mtx.RLock()
|
||||
goroutineBudget := len(r.collectorsByID)
|
||||
goroutineBudget := len(r.collectorsByID) + len(r.uncheckedCollectors)
|
||||
metricFamiliesByName := make(map[string]*dto.MetricFamily, len(r.dimHashesByName))
|
||||
collectors := make(chan Collector, len(r.collectorsByID))
|
||||
checkedCollectors := make(chan Collector, len(r.collectorsByID))
|
||||
uncheckedCollectors := make(chan Collector, len(r.uncheckedCollectors))
|
||||
for _, collector := range r.collectorsByID {
|
||||
collectors <- collector
|
||||
checkedCollectors <- collector
|
||||
}
|
||||
for _, collector := range r.uncheckedCollectors {
|
||||
uncheckedCollectors <- collector
|
||||
}
|
||||
// In case pedantic checks are enabled, we have to copy the map before
|
||||
// giving up the RLock.
|
||||
|
@ -397,12 +424,14 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
|||
collectWorker := func() {
|
||||
for {
|
||||
select {
|
||||
case collector := <-collectors:
|
||||
collector.Collect(metricChan)
|
||||
wg.Done()
|
||||
case collector := <-checkedCollectors:
|
||||
collector.Collect(checkedMetricChan)
|
||||
case collector := <-uncheckedCollectors:
|
||||
collector.Collect(uncheckedMetricChan)
|
||||
default:
|
||||
return
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,53 +439,96 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
|||
go collectWorker()
|
||||
goroutineBudget--
|
||||
|
||||
// Close the metricChan once all collectors are collected.
|
||||
// Close checkedMetricChan and uncheckedMetricChan once all collectors
|
||||
// are collected.
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(metricChan)
|
||||
close(checkedMetricChan)
|
||||
close(uncheckedMetricChan)
|
||||
}()
|
||||
|
||||
// Drain metricChan in case of premature return.
|
||||
// Drain checkedMetricChan and uncheckedMetricChan in case of premature return.
|
||||
defer func() {
|
||||
for range metricChan {
|
||||
if checkedMetricChan != nil {
|
||||
for range checkedMetricChan {
|
||||
}
|
||||
}
|
||||
if uncheckedMetricChan != nil {
|
||||
for range uncheckedMetricChan {
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
collectLoop:
|
||||
// Copy the channel references so we can nil them out later to remove
|
||||
// them from the select statements below.
|
||||
cmc := checkedMetricChan
|
||||
umc := uncheckedMetricChan
|
||||
|
||||
for {
|
||||
select {
|
||||
case metric, ok := <-metricChan:
|
||||
case metric, ok := <-cmc:
|
||||
if !ok {
|
||||
// metricChan is closed, we are done.
|
||||
break collectLoop
|
||||
cmc = nil
|
||||
break
|
||||
}
|
||||
errs.Append(processMetric(
|
||||
metric, metricFamiliesByName,
|
||||
metricHashes, dimHashes,
|
||||
metricHashes,
|
||||
registeredDescIDs,
|
||||
))
|
||||
case metric, ok := <-umc:
|
||||
if !ok {
|
||||
umc = nil
|
||||
break
|
||||
}
|
||||
errs.Append(processMetric(
|
||||
metric, metricFamiliesByName,
|
||||
metricHashes,
|
||||
nil,
|
||||
))
|
||||
default:
|
||||
if goroutineBudget <= 0 || len(collectors) == 0 {
|
||||
// All collectors are aleady being worked on or
|
||||
if goroutineBudget <= 0 || len(checkedCollectors)+len(uncheckedCollectors) == 0 {
|
||||
// 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 {
|
||||
// there are collectors. Do the same as above,
|
||||
// just without the default.
|
||||
select {
|
||||
case metric, ok := <-cmc:
|
||||
if !ok {
|
||||
cmc = nil
|
||||
break
|
||||
}
|
||||
errs.Append(processMetric(
|
||||
metric, metricFamiliesByName,
|
||||
metricHashes, dimHashes,
|
||||
metricHashes,
|
||||
registeredDescIDs,
|
||||
))
|
||||
case metric, ok := <-umc:
|
||||
if !ok {
|
||||
umc = nil
|
||||
break
|
||||
}
|
||||
errs.Append(processMetric(
|
||||
metric, metricFamiliesByName,
|
||||
metricHashes,
|
||||
nil,
|
||||
))
|
||||
}
|
||||
break collectLoop
|
||||
break
|
||||
}
|
||||
// Start more workers.
|
||||
go collectWorker()
|
||||
goroutineBudget--
|
||||
runtime.Gosched()
|
||||
}
|
||||
// Once both checkedMetricChan and uncheckdMetricChan are closed
|
||||
// and drained, the contraption above will nil out cmc and umc,
|
||||
// and then we can leave the collect loop here.
|
||||
if cmc == nil && umc == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return normalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap()
|
||||
return internal.NormalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap()
|
||||
}
|
||||
|
||||
// processMetric is an internal helper method only used by the Gather method.
|
||||
|
@ -464,16 +536,20 @@ 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()
|
||||
// Wrapped metrics collected by an unchecked Collector can have an
|
||||
// invalid Desc.
|
||||
if desc.err != nil {
|
||||
return desc.err
|
||||
}
|
||||
dtoMetric := &dto.Metric{}
|
||||
if err := metric.Write(dtoMetric); err != nil {
|
||||
return fmt.Errorf("error collecting metric %v: %s", desc, err)
|
||||
}
|
||||
metricFamily, ok := metricFamiliesByName[desc.fqName]
|
||||
if ok {
|
||||
if ok { // Existing name.
|
||||
if metricFamily.GetHelp() != desc.help {
|
||||
return fmt.Errorf(
|
||||
"collected metric %s %s has help %q but should have %q",
|
||||
|
@ -520,7 +596,7 @@ func processMetric(
|
|||
default:
|
||||
panic("encountered MetricFamily with invalid type")
|
||||
}
|
||||
} else {
|
||||
} else { // New name.
|
||||
metricFamily = &dto.MetricFamily{}
|
||||
metricFamily.Name = proto.String(desc.fqName)
|
||||
metricFamily.Help = proto.String(desc.help)
|
||||
|
@ -539,9 +615,12 @@ func processMetric(
|
|||
default:
|
||||
return fmt.Errorf("empty metric collected: %s", dtoMetric)
|
||||
}
|
||||
if err := checkSuffixCollisions(metricFamily, metricFamiliesByName); err != nil {
|
||||
return err
|
||||
}
|
||||
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 +662,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.
|
||||
)
|
||||
|
||||
|
@ -620,10 +698,14 @@ func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) {
|
|||
existingMF.Name = mf.Name
|
||||
existingMF.Help = mf.Help
|
||||
existingMF.Type = mf.Type
|
||||
if err := checkSuffixCollisions(existingMF, metricFamiliesByName); err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -631,87 +713,77 @@ func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return normalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap()
|
||||
return internal.NormalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap()
|
||||
}
|
||||
|
||||
// metricSorter is a sortable slice of *dto.Metric.
|
||||
type metricSorter []*dto.Metric
|
||||
|
||||
func (s metricSorter) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s metricSorter) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s metricSorter) Less(i, j int) bool {
|
||||
if len(s[i].Label) != len(s[j].Label) {
|
||||
// This should not happen. The metrics are
|
||||
// inconsistent. However, we have to deal with the fact, as
|
||||
// people might use custom collectors or metric family injection
|
||||
// to create inconsistent metrics. So let's simply compare the
|
||||
// number of labels in this case. That will still yield
|
||||
// reproducible sorting.
|
||||
return len(s[i].Label) < len(s[j].Label)
|
||||
// checkSuffixCollisions checks for collisions with the “magic” suffixes the
|
||||
// Prometheus text format and the internal metric representation of the
|
||||
// Prometheus server add while flattening Summaries and Histograms.
|
||||
func checkSuffixCollisions(mf *dto.MetricFamily, mfs map[string]*dto.MetricFamily) error {
|
||||
var (
|
||||
newName = mf.GetName()
|
||||
newType = mf.GetType()
|
||||
newNameWithoutSuffix = ""
|
||||
)
|
||||
switch {
|
||||
case strings.HasSuffix(newName, "_count"):
|
||||
newNameWithoutSuffix = newName[:len(newName)-6]
|
||||
case strings.HasSuffix(newName, "_sum"):
|
||||
newNameWithoutSuffix = newName[:len(newName)-4]
|
||||
case strings.HasSuffix(newName, "_bucket"):
|
||||
newNameWithoutSuffix = newName[:len(newName)-7]
|
||||
}
|
||||
for n, lp := range s[i].Label {
|
||||
vi := lp.GetValue()
|
||||
vj := s[j].Label[n].GetValue()
|
||||
if vi != vj {
|
||||
return vi < vj
|
||||
if newNameWithoutSuffix != "" {
|
||||
if existingMF, ok := mfs[newNameWithoutSuffix]; ok {
|
||||
switch existingMF.GetType() {
|
||||
case dto.MetricType_SUMMARY:
|
||||
if !strings.HasSuffix(newName, "_bucket") {
|
||||
return fmt.Errorf(
|
||||
"collected metric named %q collides with previously collected summary named %q",
|
||||
newName, newNameWithoutSuffix,
|
||||
)
|
||||
}
|
||||
case dto.MetricType_HISTOGRAM:
|
||||
return fmt.Errorf(
|
||||
"collected metric named %q collides with previously collected histogram named %q",
|
||||
newName, newNameWithoutSuffix,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We should never arrive here. Multiple metrics with the same
|
||||
// label set in the same scrape will lead to undefined ingestion
|
||||
// behavior. However, as above, we have to provide stable sorting
|
||||
// here, even for inconsistent metrics. So sort equal metrics
|
||||
// by their timestamp, with missing timestamps (implying "now")
|
||||
// coming last.
|
||||
if s[i].TimestampMs == nil {
|
||||
return false
|
||||
}
|
||||
if s[j].TimestampMs == nil {
|
||||
return true
|
||||
}
|
||||
return s[i].GetTimestampMs() < s[j].GetTimestampMs()
|
||||
}
|
||||
|
||||
// normalizeMetricFamilies returns a MetricFamily slice with empty
|
||||
// MetricFamilies pruned and the remaining MetricFamilies sorted by name within
|
||||
// the slice, with the contained Metrics sorted within each MetricFamily.
|
||||
func normalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily {
|
||||
for _, mf := range metricFamiliesByName {
|
||||
sort.Sort(metricSorter(mf.Metric))
|
||||
}
|
||||
names := make([]string, 0, len(metricFamiliesByName))
|
||||
for name, mf := range metricFamiliesByName {
|
||||
if len(mf.Metric) > 0 {
|
||||
names = append(names, name)
|
||||
if newType == dto.MetricType_SUMMARY || newType == dto.MetricType_HISTOGRAM {
|
||||
if _, ok := mfs[newName+"_count"]; ok {
|
||||
return fmt.Errorf(
|
||||
"collected histogram or summary named %q collides with previously collected metric named %q",
|
||||
newName, newName+"_count",
|
||||
)
|
||||
}
|
||||
if _, ok := mfs[newName+"_sum"]; ok {
|
||||
return fmt.Errorf(
|
||||
"collected histogram or summary named %q collides with previously collected metric named %q",
|
||||
newName, newName+"_sum",
|
||||
)
|
||||
}
|
||||
}
|
||||
sort.Strings(names)
|
||||
result := make([]*dto.MetricFamily, 0, len(names))
|
||||
for _, name := range names {
|
||||
result = append(result, metricFamiliesByName[name])
|
||||
if newType == dto.MetricType_HISTOGRAM {
|
||||
if _, ok := mfs[newName+"_bucket"]; ok {
|
||||
return fmt.Errorf(
|
||||
"collected histogram named %q collides with previously collected metric named %q",
|
||||
newName, newName+"_bucket",
|
||||
)
|
||||
}
|
||||
}
|
||||
return result
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 ||
|
||||
|
@ -720,47 +792,50 @@ func checkMetricConsistency(
|
|||
metricFamily.GetType() == dto.MetricType_HISTOGRAM && dtoMetric.Histogram == nil ||
|
||||
metricFamily.GetType() == dto.MetricType_UNTYPED && dtoMetric.Untyped == nil {
|
||||
return fmt.Errorf(
|
||||
"collected metric %s %s is not a %s",
|
||||
"collected metric %q { %s} is not a %s",
|
||||
metricFamily.GetName(), dtoMetric, metricFamily.GetType(),
|
||||
)
|
||||
}
|
||||
|
||||
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 !checkLabelName(labelPair.GetName()) {
|
||||
return fmt.Errorf(
|
||||
"collected metric %q { %s} has a label with an invalid name: %s",
|
||||
metricFamily.GetName(), dtoMetric, labelPair.GetName(),
|
||||
)
|
||||
}
|
||||
if dtoMetric.Summary != nil && labelPair.GetName() == quantileLabel {
|
||||
return fmt.Errorf(
|
||||
"collected metric %q { %s} must not have an explicit %q label",
|
||||
metricFamily.GetName(), dtoMetric, quantileLabel,
|
||||
)
|
||||
}
|
||||
if !utf8.ValidString(labelPair.GetValue()) {
|
||||
return fmt.Errorf(
|
||||
"collected metric %q { %s} has a label named %q whose value is not utf8: %#v",
|
||||
metricFamily.GetName(), dtoMetric, 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))
|
||||
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(
|
||||
"collected metric %s %s was collected before with the same name and label values",
|
||||
"collected metric %q { %s} was collected before with the same name and label values",
|
||||
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
|
||||
}
|
||||
|
@ -792,7 +867,7 @@ func checkDescConsistency(
|
|||
metricFamily.GetName(), dtoMetric, desc,
|
||||
)
|
||||
}
|
||||
sort.Sort(LabelPairSorter(lpsFromDesc))
|
||||
sort.Sort(labelPairSorter(lpsFromDesc))
|
||||
for i, lpFromDesc := range lpsFromDesc {
|
||||
lpFromMetric := dtoMetric.Label[i]
|
||||
if lpFromDesc.GetName() != lpFromMetric.GetName() ||
|
||||
|
|
156
vendor/github.com/prometheus/client_golang/prometheus/registry_test.go
generated
vendored
156
vendor/github.com/prometheus/client_golang/prometheus/registry_test.go
generated
vendored
|
@ -34,7 +34,22 @@ import (
|
|||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
// uncheckedCollector wraps a Collector but its Describe method yields no Desc.
|
||||
type uncheckedCollector struct {
|
||||
c prometheus.Collector
|
||||
}
|
||||
|
||||
func (u uncheckedCollector) Describe(_ chan<- *prometheus.Desc) {}
|
||||
func (u uncheckedCollector) Collect(c chan<- prometheus.Metric) {
|
||||
u.c.Collect(c)
|
||||
}
|
||||
|
||||
func testHandler(t testing.TB) {
|
||||
// TODO(beorn7): This test is a bit too "end-to-end". It tests quite a
|
||||
// few moving parts that are not strongly coupled. They could/should be
|
||||
// tested separately. However, the changes planned for v0.10 will
|
||||
// require a major rework of this test anyway, at which time I will
|
||||
// structure it in a better way.
|
||||
|
||||
metricVec := prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
|
@ -234,7 +249,64 @@ metric: <
|
|||
|
||||
expectedMetricFamilyInvalidLabelValueAsText := []byte(`An error has occurred during metrics gathering:
|
||||
|
||||
collected metric's label constname is not utf8: "\xff"
|
||||
collected metric "name" { label:<name:"constname" value:"\377" > label:<name:"labelname" value:"different_val" > counter:<value:42 > } has a label named "constname" whose value is not utf8: "\xff"
|
||||
`)
|
||||
|
||||
summary := prometheus.NewSummary(prometheus.SummaryOpts{
|
||||
Name: "complex",
|
||||
Help: "A metric to check collisions with _sum and _count.",
|
||||
})
|
||||
summaryAsText := []byte(`# HELP complex A metric to check collisions with _sum and _count.
|
||||
# TYPE complex summary
|
||||
complex{quantile="0.5"} NaN
|
||||
complex{quantile="0.9"} NaN
|
||||
complex{quantile="0.99"} NaN
|
||||
complex_sum 0
|
||||
complex_count 0
|
||||
`)
|
||||
histogram := prometheus.NewHistogram(prometheus.HistogramOpts{
|
||||
Name: "complex",
|
||||
Help: "A metric to check collisions with _sun, _count, and _bucket.",
|
||||
})
|
||||
externalMetricFamilyWithBucketSuffix := &dto.MetricFamily{
|
||||
Name: proto.String("complex_bucket"),
|
||||
Help: proto.String("externaldocstring"),
|
||||
Type: dto.MetricType_COUNTER.Enum(),
|
||||
Metric: []*dto.Metric{
|
||||
{
|
||||
Counter: &dto.Counter{
|
||||
Value: proto.Float64(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
externalMetricFamilyWithBucketSuffixAsText := []byte(`# HELP complex_bucket externaldocstring
|
||||
# TYPE complex_bucket counter
|
||||
complex_bucket 1
|
||||
`)
|
||||
externalMetricFamilyWithCountSuffix := &dto.MetricFamily{
|
||||
Name: proto.String("complex_count"),
|
||||
Help: proto.String("externaldocstring"),
|
||||
Type: dto.MetricType_COUNTER.Enum(),
|
||||
Metric: []*dto.Metric{
|
||||
{
|
||||
Counter: &dto.Counter{
|
||||
Value: proto.Float64(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
bucketCollisionMsg := []byte(`An error has occurred during metrics gathering:
|
||||
|
||||
collected metric named "complex_bucket" collides with previously collected histogram named "complex"
|
||||
`)
|
||||
summaryCountCollisionMsg := []byte(`An error has occurred during metrics gathering:
|
||||
|
||||
collected metric named "complex_count" collides with previously collected summary named "complex"
|
||||
`)
|
||||
histogramCountCollisionMsg := []byte(`An error has occurred during metrics gathering:
|
||||
|
||||
collected metric named "complex_count" collides with previously collected histogram named "complex"
|
||||
`)
|
||||
|
||||
type output struct {
|
||||
|
@ -496,6 +568,84 @@ collected metric's label constname is not utf8: "\xff"
|
|||
externalMetricFamilyWithInvalidLabelValue,
|
||||
},
|
||||
},
|
||||
{ // 17
|
||||
headers: map[string]string{
|
||||
"Accept": "text/plain",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; version=0.0.4; charset=utf-8`,
|
||||
},
|
||||
body: expectedMetricFamilyAsText,
|
||||
},
|
||||
collector: uncheckedCollector{metricVec},
|
||||
},
|
||||
{ // 18
|
||||
headers: map[string]string{
|
||||
"Accept": "text/plain",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; charset=utf-8`,
|
||||
},
|
||||
body: histogramCountCollisionMsg,
|
||||
},
|
||||
collector: histogram,
|
||||
externalMF: []*dto.MetricFamily{
|
||||
externalMetricFamilyWithCountSuffix,
|
||||
},
|
||||
},
|
||||
{ // 19
|
||||
headers: map[string]string{
|
||||
"Accept": "text/plain",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; charset=utf-8`,
|
||||
},
|
||||
body: bucketCollisionMsg,
|
||||
},
|
||||
collector: histogram,
|
||||
externalMF: []*dto.MetricFamily{
|
||||
externalMetricFamilyWithBucketSuffix,
|
||||
},
|
||||
},
|
||||
{ // 20
|
||||
headers: map[string]string{
|
||||
"Accept": "text/plain",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; charset=utf-8`,
|
||||
},
|
||||
body: summaryCountCollisionMsg,
|
||||
},
|
||||
collector: summary,
|
||||
externalMF: []*dto.MetricFamily{
|
||||
externalMetricFamilyWithCountSuffix,
|
||||
},
|
||||
},
|
||||
{ // 21
|
||||
headers: map[string]string{
|
||||
"Accept": "text/plain",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; version=0.0.4; charset=utf-8`,
|
||||
},
|
||||
body: bytes.Join(
|
||||
[][]byte{
|
||||
summaryAsText,
|
||||
externalMetricFamilyWithBucketSuffixAsText,
|
||||
},
|
||||
[]byte{},
|
||||
),
|
||||
},
|
||||
collector: summary,
|
||||
externalMF: []*dto.MetricFamily{
|
||||
externalMetricFamilyWithBucketSuffix,
|
||||
},
|
||||
},
|
||||
}
|
||||
for i, scenario := range scenarios {
|
||||
registry := prometheus.NewPedanticRegistry()
|
||||
|
@ -510,7 +660,7 @@ collected metric's label constname is not utf8: "\xff"
|
|||
}
|
||||
|
||||
if scenario.collector != nil {
|
||||
registry.Register(scenario.collector)
|
||||
registry.MustRegister(scenario.collector)
|
||||
}
|
||||
writer := httptest.NewRecorder()
|
||||
handler := prometheus.InstrumentHandler("prometheus", promhttp.HandlerFor(gatherer, promhttp.HandlerOpts{}))
|
||||
|
@ -521,7 +671,7 @@ collected metric's label constname is not utf8: "\xff"
|
|||
handler(writer, request)
|
||||
|
||||
for key, value := range scenario.out.headers {
|
||||
if writer.HeaderMap.Get(key) != value {
|
||||
if writer.Header().Get(key) != value {
|
||||
t.Errorf(
|
||||
"%d. expected %q for header %q, got %q",
|
||||
i, value, key, writer.Header().Get(key),
|
||||
|
|
31
vendor/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
31
vendor/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
|
@ -37,7 +37,7 @@ const quantileLabel = "quantile"
|
|||
// A typical use-case is the observation of request latencies. By default, a
|
||||
// Summary provides the median, the 90th and the 99th percentile of the latency
|
||||
// as rank estimations. However, the default behavior will change in the
|
||||
// upcoming v0.10 of the library. There will be no rank estiamtions at all by
|
||||
// upcoming v0.10 of the library. There will be no rank estimations at all by
|
||||
// default. For a sane transition, it is recommended to set the desired rank
|
||||
// estimations explicitly.
|
||||
//
|
||||
|
@ -81,10 +81,10 @@ const (
|
|||
)
|
||||
|
||||
// SummaryOpts bundles the options for creating a Summary metric. It is
|
||||
// mandatory to set Name and Help to a non-empty string. While all other fields
|
||||
// are optional and can safely be left at their zero value, it is recommended to
|
||||
// explicitly set the Objectives field to the desired value as the default value
|
||||
// will change in the upcoming v0.10 of the library.
|
||||
// mandatory to set Name to a non-empty string. While all other fields are
|
||||
// optional and can safely be left at their zero value, it is recommended to set
|
||||
// a help string and to explicitly set the Objectives field to the desired value
|
||||
// as the default value will change in the upcoming v0.10 of the library.
|
||||
type SummaryOpts struct {
|
||||
// Namespace, Subsystem, and Name are components of the fully-qualified
|
||||
// name of the Summary (created by joining these components with
|
||||
|
@ -95,7 +95,7 @@ type SummaryOpts struct {
|
|||
Subsystem string
|
||||
Name string
|
||||
|
||||
// Help provides information about this Summary. Mandatory!
|
||||
// Help provides information about this Summary.
|
||||
//
|
||||
// Metrics with the same fully-qualified name must have the same Help
|
||||
// string.
|
||||
|
@ -105,6 +105,11 @@ type SummaryOpts struct {
|
|||
// with the same fully-qualified name must have the same label names in
|
||||
// their ConstLabels.
|
||||
//
|
||||
// Due to the way a Summary is represented in the Prometheus text format
|
||||
// and how it is handled by the Prometheus server internally, “quantile”
|
||||
// is an illegal label name. Construction of a Summary or SummaryVec
|
||||
// will panic if this label name is used in ConstLabels.
|
||||
//
|
||||
// ConstLabels are only used rarely. In particular, do not use them to
|
||||
// attach the same labels to all your metrics. Those use cases are
|
||||
// better covered by target labels set by the scraping Prometheus
|
||||
|
@ -402,7 +407,16 @@ type SummaryVec struct {
|
|||
|
||||
// NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and
|
||||
// partitioned by the given label names.
|
||||
//
|
||||
// Due to the way a Summary is represented in the Prometheus text format and how
|
||||
// it is handled by the Prometheus server internally, “quantile” is an illegal
|
||||
// label name. NewSummaryVec will panic if this label name is used.
|
||||
func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
|
||||
for _, ln := range labelNames {
|
||||
if ln == quantileLabel {
|
||||
panic(errQuantileLabelNotAllowed)
|
||||
}
|
||||
}
|
||||
desc := NewDesc(
|
||||
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
opts.Help,
|
||||
|
@ -572,7 +586,7 @@ func (s *constSummary) Write(out *dto.Metric) error {
|
|||
// map[float64]float64{0.5: 0.23, 0.99: 0.56}
|
||||
//
|
||||
// NewConstSummary returns an error if the length of labelValues is not
|
||||
// consistent with the variable labels in Desc.
|
||||
// consistent with the variable labels in Desc or if Desc is invalid.
|
||||
func NewConstSummary(
|
||||
desc *Desc,
|
||||
count uint64,
|
||||
|
@ -580,6 +594,9 @@ func NewConstSummary(
|
|||
quantiles map[float64]float64,
|
||||
labelValues ...string,
|
||||
) (Metric, error) {
|
||||
if desc.err != nil {
|
||||
return nil, desc.err
|
||||
}
|
||||
if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
25
vendor/github.com/prometheus/client_golang/prometheus/summary_test.go
generated
vendored
25
vendor/github.com/prometheus/client_golang/prometheus/summary_test.go
generated
vendored
|
@ -64,6 +64,31 @@ func TestSummaryWithoutObjectives(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSummaryWithQuantileLabel(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("Attempt to create Summary with 'quantile' label did not panic.")
|
||||
}
|
||||
}()
|
||||
_ = NewSummary(SummaryOpts{
|
||||
Name: "test_summary",
|
||||
Help: "less",
|
||||
ConstLabels: Labels{"quantile": "test"},
|
||||
})
|
||||
}
|
||||
|
||||
func TestSummaryVecWithQuantileLabel(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("Attempt to create SummaryVec with 'quantile' label did not panic.")
|
||||
}
|
||||
}()
|
||||
_ = NewSummaryVec(SummaryOpts{
|
||||
Name: "test_summary",
|
||||
Help: "less",
|
||||
}, []string{"quantile"})
|
||||
}
|
||||
|
||||
func benchmarkSummaryObserve(w int, b *testing.B) {
|
||||
b.StopTimer()
|
||||
|
||||
|
|
184
vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go
generated
vendored
Normal file
184
vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go
generated
vendored
Normal file
|
@ -0,0 +1,184 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package testutil provides helpers to test code using the prometheus package
|
||||
// of client_golang.
|
||||
//
|
||||
// While writing unit tests to verify correct instrumentation of your code, it's
|
||||
// a common mistake to mostly test the instrumentation library instead of your
|
||||
// own code. Rather than verifying that a prometheus.Counter's value has changed
|
||||
// as expected or that it shows up in the exposition after registration, it is
|
||||
// in general more robust and more faithful to the concept of unit tests to use
|
||||
// mock implementations of the prometheus.Counter and prometheus.Registerer
|
||||
// interfaces that simply assert that the Add or Register methods have been
|
||||
// called with the expected arguments. However, this might be overkill in simple
|
||||
// scenarios. The ToFloat64 function is provided for simple inspection of a
|
||||
// single-value metric, but it has to be used with caution.
|
||||
//
|
||||
// End-to-end tests to verify all or larger parts of the metrics exposition can
|
||||
// be implemented with the CollectAndCompare or GatherAndCompare functions. The
|
||||
// most appropriate use is not so much testing instrumentation of your code, but
|
||||
// testing custom prometheus.Collector implementations and in particular whole
|
||||
// exporters, i.e. programs that retrieve telemetry data from a 3rd party source
|
||||
// and convert it into Prometheus metrics.
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"github.com/prometheus/common/expfmt"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/internal"
|
||||
)
|
||||
|
||||
// ToFloat64 collects all Metrics from the provided Collector. It expects that
|
||||
// this results in exactly one Metric being collected, which must be a Gauge,
|
||||
// Counter, or Untyped. In all other cases, ToFloat64 panics. ToFloat64 returns
|
||||
// the value of the collected Metric.
|
||||
//
|
||||
// The Collector provided is typically a simple instance of Gauge or Counter, or
|
||||
// – less commonly – a GaugeVec or CounterVec with exactly one element. But any
|
||||
// Collector fulfilling the prerequisites described above will do.
|
||||
//
|
||||
// Use this function with caution. It is computationally very expensive and thus
|
||||
// not suited at all to read values from Metrics in regular code. This is really
|
||||
// only for testing purposes, and even for testing, other approaches are often
|
||||
// more appropriate (see this package's documentation).
|
||||
//
|
||||
// A clear anti-pattern would be to use a metric type from the prometheus
|
||||
// package to track values that are also needed for something else than the
|
||||
// exposition of Prometheus metrics. For example, you would like to track the
|
||||
// number of items in a queue because your code should reject queuing further
|
||||
// items if a certain limit is reached. It is tempting to track the number of
|
||||
// items in a prometheus.Gauge, as it is then easily available as a metric for
|
||||
// exposition, too. However, then you would need to call ToFloat64 in your
|
||||
// regular code, potentially quite often. The recommended way is to track the
|
||||
// number of items conventionally (in the way you would have done it without
|
||||
// considering Prometheus metrics) and then expose the number with a
|
||||
// prometheus.GaugeFunc.
|
||||
func ToFloat64(c prometheus.Collector) float64 {
|
||||
var (
|
||||
m prometheus.Metric
|
||||
mCount int
|
||||
mChan = make(chan prometheus.Metric)
|
||||
done = make(chan struct{})
|
||||
)
|
||||
|
||||
go func() {
|
||||
for m = range mChan {
|
||||
mCount++
|
||||
}
|
||||
close(done)
|
||||
}()
|
||||
|
||||
c.Collect(mChan)
|
||||
close(mChan)
|
||||
<-done
|
||||
|
||||
if mCount != 1 {
|
||||
panic(fmt.Errorf("collected %d metrics instead of exactly 1", mCount))
|
||||
}
|
||||
|
||||
pb := &dto.Metric{}
|
||||
m.Write(pb)
|
||||
if pb.Gauge != nil {
|
||||
return pb.Gauge.GetValue()
|
||||
}
|
||||
if pb.Counter != nil {
|
||||
return pb.Counter.GetValue()
|
||||
}
|
||||
if pb.Untyped != nil {
|
||||
return pb.Untyped.GetValue()
|
||||
}
|
||||
panic(fmt.Errorf("collected a non-gauge/counter/untyped metric: %s", pb))
|
||||
}
|
||||
|
||||
// CollectAndCompare registers the provided Collector with a newly created
|
||||
// pedantic Registry. It then does the same as GatherAndCompare, gathering the
|
||||
// metrics from the pedantic Registry.
|
||||
func CollectAndCompare(c prometheus.Collector, expected io.Reader, metricNames ...string) error {
|
||||
reg := prometheus.NewPedanticRegistry()
|
||||
if err := reg.Register(c); err != nil {
|
||||
return fmt.Errorf("registering collector failed: %s", err)
|
||||
}
|
||||
return GatherAndCompare(reg, expected, metricNames...)
|
||||
}
|
||||
|
||||
// GatherAndCompare gathers all metrics from the provided Gatherer and compares
|
||||
// it to an expected output read from the provided Reader in the Prometheus text
|
||||
// exposition format. If any metricNames are provided, only metrics with those
|
||||
// names are compared.
|
||||
func GatherAndCompare(g prometheus.Gatherer, expected io.Reader, metricNames ...string) error {
|
||||
metrics, err := g.Gather()
|
||||
if err != nil {
|
||||
return fmt.Errorf("gathering metrics failed: %s", err)
|
||||
}
|
||||
if metricNames != nil {
|
||||
metrics = filterMetrics(metrics, metricNames)
|
||||
}
|
||||
var tp expfmt.TextParser
|
||||
expectedMetrics, err := tp.TextToMetricFamilies(expected)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing expected metrics failed: %s", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(metrics, internal.NormalizeMetricFamilies(expectedMetrics)) {
|
||||
// Encode the gathered output to the readable text format for comparison.
|
||||
var buf1 bytes.Buffer
|
||||
enc := expfmt.NewEncoder(&buf1, expfmt.FmtText)
|
||||
for _, mf := range metrics {
|
||||
if err := enc.Encode(mf); err != nil {
|
||||
return fmt.Errorf("encoding result failed: %s", err)
|
||||
}
|
||||
}
|
||||
// Encode normalized expected metrics again to generate them in the same ordering
|
||||
// the registry does to spot differences more easily.
|
||||
var buf2 bytes.Buffer
|
||||
enc = expfmt.NewEncoder(&buf2, expfmt.FmtText)
|
||||
for _, mf := range internal.NormalizeMetricFamilies(expectedMetrics) {
|
||||
if err := enc.Encode(mf); err != nil {
|
||||
return fmt.Errorf("encoding result failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf(`
|
||||
metric output does not match expectation; want:
|
||||
|
||||
%s
|
||||
|
||||
got:
|
||||
|
||||
%s
|
||||
`, buf2.String(), buf1.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func filterMetrics(metrics []*dto.MetricFamily, names []string) []*dto.MetricFamily {
|
||||
var filtered []*dto.MetricFamily
|
||||
for _, m := range metrics {
|
||||
for _, name := range names {
|
||||
if m.GetName() == name {
|
||||
filtered = append(filtered, m)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
213
vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil_test.go
generated
vendored
Normal file
213
vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil_test.go
generated
vendored
Normal file
|
@ -0,0 +1,213 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
type untypedCollector struct{}
|
||||
|
||||
func (u untypedCollector) Describe(c chan<- *prometheus.Desc) {
|
||||
c <- prometheus.NewDesc("name", "help", nil, nil)
|
||||
}
|
||||
|
||||
func (u untypedCollector) Collect(c chan<- prometheus.Metric) {
|
||||
c <- prometheus.MustNewConstMetric(
|
||||
prometheus.NewDesc("name", "help", nil, nil),
|
||||
prometheus.UntypedValue,
|
||||
2001,
|
||||
)
|
||||
}
|
||||
|
||||
func TestToFloat64(t *testing.T) {
|
||||
gaugeWithAValueSet := prometheus.NewGauge(prometheus.GaugeOpts{})
|
||||
gaugeWithAValueSet.Set(3.14)
|
||||
|
||||
counterVecWithOneElement := prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"foo"})
|
||||
counterVecWithOneElement.WithLabelValues("bar").Inc()
|
||||
|
||||
counterVecWithTwoElements := prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"foo"})
|
||||
counterVecWithTwoElements.WithLabelValues("bar").Add(42)
|
||||
counterVecWithTwoElements.WithLabelValues("baz").Inc()
|
||||
|
||||
histogramVecWithOneElement := prometheus.NewHistogramVec(prometheus.HistogramOpts{}, []string{"foo"})
|
||||
histogramVecWithOneElement.WithLabelValues("bar").Observe(2.7)
|
||||
|
||||
scenarios := map[string]struct {
|
||||
collector prometheus.Collector
|
||||
panics bool
|
||||
want float64
|
||||
}{
|
||||
"simple counter": {
|
||||
collector: prometheus.NewCounter(prometheus.CounterOpts{}),
|
||||
panics: false,
|
||||
want: 0,
|
||||
},
|
||||
"simple gauge": {
|
||||
collector: prometheus.NewGauge(prometheus.GaugeOpts{}),
|
||||
panics: false,
|
||||
want: 0,
|
||||
},
|
||||
"simple untyped": {
|
||||
collector: untypedCollector{},
|
||||
panics: false,
|
||||
want: 2001,
|
||||
},
|
||||
"simple histogram": {
|
||||
collector: prometheus.NewHistogram(prometheus.HistogramOpts{}),
|
||||
panics: true,
|
||||
},
|
||||
"simple summary": {
|
||||
collector: prometheus.NewSummary(prometheus.SummaryOpts{}),
|
||||
panics: true,
|
||||
},
|
||||
"simple gauge with an actual value set": {
|
||||
collector: gaugeWithAValueSet,
|
||||
panics: false,
|
||||
want: 3.14,
|
||||
},
|
||||
"counter vec with zero elements": {
|
||||
collector: prometheus.NewCounterVec(prometheus.CounterOpts{}, nil),
|
||||
panics: true,
|
||||
},
|
||||
"counter vec with one element": {
|
||||
collector: counterVecWithOneElement,
|
||||
panics: false,
|
||||
want: 1,
|
||||
},
|
||||
"counter vec with two elements": {
|
||||
collector: counterVecWithTwoElements,
|
||||
panics: true,
|
||||
},
|
||||
"histogram vec with one element": {
|
||||
collector: histogramVecWithOneElement,
|
||||
panics: true,
|
||||
},
|
||||
}
|
||||
|
||||
for n, s := range scenarios {
|
||||
t.Run(n, func(t *testing.T) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil && s.panics {
|
||||
t.Error("expected panic")
|
||||
} else if r != nil && !s.panics {
|
||||
t.Error("unexpected panic: ", r)
|
||||
}
|
||||
// Any other combination is the expected outcome.
|
||||
}()
|
||||
if got := ToFloat64(s.collector); got != s.want {
|
||||
t.Errorf("want %f, got %f", s.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollectAndCompare(t *testing.T) {
|
||||
const metadata = `
|
||||
# HELP some_total A value that represents a counter.
|
||||
# TYPE some_total counter
|
||||
`
|
||||
|
||||
c := prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "some_total",
|
||||
Help: "A value that represents a counter.",
|
||||
ConstLabels: prometheus.Labels{
|
||||
"label1": "value1",
|
||||
},
|
||||
})
|
||||
c.Inc()
|
||||
|
||||
expected := `
|
||||
|
||||
some_total{ label1 = "value1" } 1
|
||||
`
|
||||
|
||||
if err := CollectAndCompare(c, strings.NewReader(metadata+expected), "some_total"); err != nil {
|
||||
t.Errorf("unexpected collecting result:\n%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoMetricFilter(t *testing.T) {
|
||||
const metadata = `
|
||||
# HELP some_total A value that represents a counter.
|
||||
# TYPE some_total counter
|
||||
`
|
||||
|
||||
c := prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "some_total",
|
||||
Help: "A value that represents a counter.",
|
||||
ConstLabels: prometheus.Labels{
|
||||
"label1": "value1",
|
||||
},
|
||||
})
|
||||
c.Inc()
|
||||
|
||||
expected := `
|
||||
some_total{label1="value1"} 1
|
||||
`
|
||||
|
||||
if err := CollectAndCompare(c, strings.NewReader(metadata+expected)); err != nil {
|
||||
t.Errorf("unexpected collecting result:\n%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricNotFound(t *testing.T) {
|
||||
const metadata = `
|
||||
# HELP some_other_metric A value that represents a counter.
|
||||
# TYPE some_other_metric counter
|
||||
`
|
||||
|
||||
c := prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "some_total",
|
||||
Help: "A value that represents a counter.",
|
||||
ConstLabels: prometheus.Labels{
|
||||
"label1": "value1",
|
||||
},
|
||||
})
|
||||
c.Inc()
|
||||
|
||||
expected := `
|
||||
some_other_metric{label1="value1"} 1
|
||||
`
|
||||
|
||||
expectedError := `
|
||||
metric output does not match expectation; want:
|
||||
|
||||
# HELP some_other_metric A value that represents a counter.
|
||||
# TYPE some_other_metric counter
|
||||
some_other_metric{label1="value1"} 1
|
||||
|
||||
|
||||
got:
|
||||
|
||||
# HELP some_total A value that represents a counter.
|
||||
# TYPE some_total counter
|
||||
some_total{label1="value1"} 1
|
||||
|
||||
`
|
||||
|
||||
err := CollectAndCompare(c, strings.NewReader(metadata+expected))
|
||||
if err == nil {
|
||||
t.Error("Expected error, got no error.")
|
||||
}
|
||||
|
||||
if err.Error() != expectedError {
|
||||
t.Errorf("Expected\n%#+v\nGot:\n%#+v\n", expectedError, err.Error())
|
||||
}
|
||||
}
|
16
vendor/github.com/prometheus/client_golang/prometheus/value.go
generated
vendored
16
vendor/github.com/prometheus/client_golang/prometheus/value.go
generated
vendored
|
@ -17,9 +17,9 @@ import (
|
|||
"fmt"
|
||||
"sort"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
// ValueType is an enumeration of metric types that represent a simple value.
|
||||
|
@ -77,8 +77,12 @@ func (v *valueFunc) Write(out *dto.Metric) error {
|
|||
// operations. However, when implementing custom Collectors, it is useful as a
|
||||
// throw-away metric that is generated on the fly to send it to Prometheus in
|
||||
// the Collect method. NewConstMetric returns an error if the length of
|
||||
// labelValues is not consistent with the variable labels in Desc.
|
||||
// labelValues is not consistent with the variable labels in Desc or if Desc is
|
||||
// invalid.
|
||||
func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) (Metric, error) {
|
||||
if desc.err != nil {
|
||||
return nil, desc.err
|
||||
}
|
||||
if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -152,9 +156,7 @@ func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
|
|||
Value: proto.String(labelValues[i]),
|
||||
})
|
||||
}
|
||||
for _, lp := range desc.constLabelPairs {
|
||||
labelPairs = append(labelPairs, lp)
|
||||
}
|
||||
sort.Sort(LabelPairSorter(labelPairs))
|
||||
labelPairs = append(labelPairs, desc.constLabelPairs...)
|
||||
sort.Sort(labelPairSorter(labelPairs))
|
||||
return labelPairs
|
||||
}
|
||||
|
|
13
vendor/github.com/prometheus/client_golang/prometheus/value_test.go
generated
vendored
13
vendor/github.com/prometheus/client_golang/prometheus/value_test.go
generated
vendored
|
@ -1,3 +1,16 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
|
|
3
vendor/github.com/prometheus/client_golang/prometheus/vec.go
generated
vendored
3
vendor/github.com/prometheus/client_golang/prometheus/vec.go
generated
vendored
|
@ -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
|
||||
|
|
179
vendor/github.com/prometheus/client_golang/prometheus/wrap.go
generated
vendored
Normal file
179
vendor/github.com/prometheus/client_golang/prometheus/wrap.go
generated
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
// WrapRegistererWith returns a Registerer wrapping the provided
|
||||
// Registerer. Collectors registered with the returned Registerer will be
|
||||
// registered with the wrapped Registerer in a modified way. The modified
|
||||
// Collector adds the provided Labels to all Metrics it collects (as
|
||||
// ConstLabels). The Metrics collected by the unmodified Collector must not
|
||||
// duplicate any of those labels.
|
||||
//
|
||||
// WrapRegistererWith provides a way to add fixed labels to a subset of
|
||||
// Collectors. It should not be used to add fixed labels to all metrics exposed.
|
||||
//
|
||||
// The Collector example demonstrates a use of WrapRegistererWith.
|
||||
func WrapRegistererWith(labels Labels, reg Registerer) Registerer {
|
||||
return &wrappingRegisterer{
|
||||
wrappedRegisterer: reg,
|
||||
labels: labels,
|
||||
}
|
||||
}
|
||||
|
||||
// WrapRegistererWithPrefix returns a Registerer wrapping the provided
|
||||
// Registerer. Collectors registered with the returned Registerer will be
|
||||
// registered with the wrapped Registerer in a modified way. The modified
|
||||
// Collector adds the provided prefix to the name of all Metrics it collects.
|
||||
//
|
||||
// WrapRegistererWithPrefix is useful to have one place to prefix all metrics of
|
||||
// a sub-system. To make this work, register metrics of the sub-system with the
|
||||
// wrapping Registerer returned by WrapRegistererWithPrefix. It is rarely useful
|
||||
// to use the same prefix for all metrics exposed. In particular, do not prefix
|
||||
// metric names that are standardized across applications, as that would break
|
||||
// horizontal monitoring, for example the metrics provided by the Go collector
|
||||
// (see NewGoCollector) and the process collector (see NewProcessCollector). (In
|
||||
// fact, those metrics are already prefixed with “go_” or “process_”,
|
||||
// respectively.)
|
||||
func WrapRegistererWithPrefix(prefix string, reg Registerer) Registerer {
|
||||
return &wrappingRegisterer{
|
||||
wrappedRegisterer: reg,
|
||||
prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
type wrappingRegisterer struct {
|
||||
wrappedRegisterer Registerer
|
||||
prefix string
|
||||
labels Labels
|
||||
}
|
||||
|
||||
func (r *wrappingRegisterer) Register(c Collector) error {
|
||||
return r.wrappedRegisterer.Register(&wrappingCollector{
|
||||
wrappedCollector: c,
|
||||
prefix: r.prefix,
|
||||
labels: r.labels,
|
||||
})
|
||||
}
|
||||
|
||||
func (r *wrappingRegisterer) MustRegister(cs ...Collector) {
|
||||
for _, c := range cs {
|
||||
if err := r.Register(c); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *wrappingRegisterer) Unregister(c Collector) bool {
|
||||
return r.wrappedRegisterer.Unregister(&wrappingCollector{
|
||||
wrappedCollector: c,
|
||||
prefix: r.prefix,
|
||||
labels: r.labels,
|
||||
})
|
||||
}
|
||||
|
||||
type wrappingCollector struct {
|
||||
wrappedCollector Collector
|
||||
prefix string
|
||||
labels Labels
|
||||
}
|
||||
|
||||
func (c *wrappingCollector) Collect(ch chan<- Metric) {
|
||||
wrappedCh := make(chan Metric)
|
||||
go func() {
|
||||
c.wrappedCollector.Collect(wrappedCh)
|
||||
close(wrappedCh)
|
||||
}()
|
||||
for m := range wrappedCh {
|
||||
ch <- &wrappingMetric{
|
||||
wrappedMetric: m,
|
||||
prefix: c.prefix,
|
||||
labels: c.labels,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *wrappingCollector) Describe(ch chan<- *Desc) {
|
||||
wrappedCh := make(chan *Desc)
|
||||
go func() {
|
||||
c.wrappedCollector.Describe(wrappedCh)
|
||||
close(wrappedCh)
|
||||
}()
|
||||
for desc := range wrappedCh {
|
||||
ch <- wrapDesc(desc, c.prefix, c.labels)
|
||||
}
|
||||
}
|
||||
|
||||
type wrappingMetric struct {
|
||||
wrappedMetric Metric
|
||||
prefix string
|
||||
labels Labels
|
||||
}
|
||||
|
||||
func (m *wrappingMetric) Desc() *Desc {
|
||||
return wrapDesc(m.wrappedMetric.Desc(), m.prefix, m.labels)
|
||||
}
|
||||
|
||||
func (m *wrappingMetric) Write(out *dto.Metric) error {
|
||||
if err := m.wrappedMetric.Write(out); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(m.labels) == 0 {
|
||||
// No wrapping labels.
|
||||
return nil
|
||||
}
|
||||
for ln, lv := range m.labels {
|
||||
out.Label = append(out.Label, &dto.LabelPair{
|
||||
Name: proto.String(ln),
|
||||
Value: proto.String(lv),
|
||||
})
|
||||
}
|
||||
sort.Sort(labelPairSorter(out.Label))
|
||||
return nil
|
||||
}
|
||||
|
||||
func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc {
|
||||
constLabels := Labels{}
|
||||
for _, lp := range desc.constLabelPairs {
|
||||
constLabels[*lp.Name] = *lp.Value
|
||||
}
|
||||
for ln, lv := range labels {
|
||||
if _, alreadyUsed := constLabels[ln]; alreadyUsed {
|
||||
return &Desc{
|
||||
fqName: desc.fqName,
|
||||
help: desc.help,
|
||||
variableLabels: desc.variableLabels,
|
||||
constLabelPairs: desc.constLabelPairs,
|
||||
err: fmt.Errorf("attempted wrapping with already existing label name %q", ln),
|
||||
}
|
||||
}
|
||||
constLabels[ln] = lv
|
||||
}
|
||||
// NewDesc will do remaining validations.
|
||||
newDesc := NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels)
|
||||
// Propagate errors if there was any. This will override any errer
|
||||
// created by NewDesc above, i.e. earlier errors get precedence.
|
||||
if desc.err != nil {
|
||||
newDesc.err = desc.err
|
||||
}
|
||||
return newDesc
|
||||
}
|
322
vendor/github.com/prometheus/client_golang/prometheus/wrap_test.go
generated
vendored
Normal file
322
vendor/github.com/prometheus/client_golang/prometheus/wrap_test.go
generated
vendored
Normal file
|
@ -0,0 +1,322 @@
|
|||
// Copyright 2018 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
// uncheckedCollector wraps a Collector but its Describe method yields no Desc.
|
||||
type uncheckedCollector struct {
|
||||
c Collector
|
||||
}
|
||||
|
||||
func (u uncheckedCollector) Describe(_ chan<- *Desc) {}
|
||||
func (u uncheckedCollector) Collect(c chan<- Metric) {
|
||||
u.c.Collect(c)
|
||||
}
|
||||
|
||||
func toMetricFamilies(cs ...Collector) []*dto.MetricFamily {
|
||||
reg := NewRegistry()
|
||||
reg.MustRegister(cs...)
|
||||
out, err := reg.Gather()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func TestWrap(t *testing.T) {
|
||||
|
||||
simpleCnt := NewCounter(CounterOpts{
|
||||
Name: "simpleCnt",
|
||||
Help: "helpSimpleCnt",
|
||||
})
|
||||
simpleCnt.Inc()
|
||||
|
||||
simpleGge := NewGauge(GaugeOpts{
|
||||
Name: "simpleGge",
|
||||
Help: "helpSimpleGge",
|
||||
})
|
||||
simpleGge.Set(3.14)
|
||||
|
||||
preCnt := NewCounter(CounterOpts{
|
||||
Name: "pre_simpleCnt",
|
||||
Help: "helpSimpleCnt",
|
||||
})
|
||||
preCnt.Inc()
|
||||
|
||||
barLabeledCnt := NewCounter(CounterOpts{
|
||||
Name: "simpleCnt",
|
||||
Help: "helpSimpleCnt",
|
||||
ConstLabels: Labels{"foo": "bar"},
|
||||
})
|
||||
barLabeledCnt.Inc()
|
||||
|
||||
bazLabeledCnt := NewCounter(CounterOpts{
|
||||
Name: "simpleCnt",
|
||||
Help: "helpSimpleCnt",
|
||||
ConstLabels: Labels{"foo": "baz"},
|
||||
})
|
||||
bazLabeledCnt.Inc()
|
||||
|
||||
labeledPreCnt := NewCounter(CounterOpts{
|
||||
Name: "pre_simpleCnt",
|
||||
Help: "helpSimpleCnt",
|
||||
ConstLabels: Labels{"foo": "bar"},
|
||||
})
|
||||
labeledPreCnt.Inc()
|
||||
|
||||
twiceLabeledPreCnt := NewCounter(CounterOpts{
|
||||
Name: "pre_simpleCnt",
|
||||
Help: "helpSimpleCnt",
|
||||
ConstLabels: Labels{"foo": "bar", "dings": "bums"},
|
||||
})
|
||||
twiceLabeledPreCnt.Inc()
|
||||
|
||||
barLabeledUncheckedCollector := uncheckedCollector{barLabeledCnt}
|
||||
|
||||
scenarios := map[string]struct {
|
||||
prefix string // First wrap with this prefix.
|
||||
labels Labels // Then wrap the result with these labels.
|
||||
labels2 Labels // If any, wrap the prefix-wrapped one again.
|
||||
preRegister []Collector
|
||||
toRegister []struct { // If there are any labels2, register every other with that one.
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}
|
||||
gatherFails bool
|
||||
output []Collector
|
||||
}{
|
||||
"wrap nothing": {
|
||||
prefix: "pre_",
|
||||
labels: Labels{"foo": "bar"},
|
||||
},
|
||||
"wrap with nothing": {
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{simpleCnt, false}},
|
||||
output: []Collector{simpleGge, simpleCnt},
|
||||
},
|
||||
"wrap counter with prefix": {
|
||||
prefix: "pre_",
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{simpleCnt, false}},
|
||||
output: []Collector{simpleGge, preCnt},
|
||||
},
|
||||
"wrap counter with label pair": {
|
||||
labels: Labels{"foo": "bar"},
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{simpleCnt, false}},
|
||||
output: []Collector{simpleGge, barLabeledCnt},
|
||||
},
|
||||
"wrap counter with label pair and prefix": {
|
||||
prefix: "pre_",
|
||||
labels: Labels{"foo": "bar"},
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{simpleCnt, false}},
|
||||
output: []Collector{simpleGge, labeledPreCnt},
|
||||
},
|
||||
"wrap counter with invalid prefix": {
|
||||
prefix: "1+1",
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{simpleCnt, true}},
|
||||
output: []Collector{simpleGge},
|
||||
},
|
||||
"wrap counter with invalid label": {
|
||||
preRegister: []Collector{simpleGge},
|
||||
labels: Labels{"42": "bar"},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{simpleCnt, true}},
|
||||
output: []Collector{simpleGge},
|
||||
},
|
||||
"counter registered twice but wrapped with different label values": {
|
||||
labels: Labels{"foo": "bar"},
|
||||
labels2: Labels{"foo": "baz"},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{simpleCnt, false}, {simpleCnt, false}},
|
||||
output: []Collector{barLabeledCnt, bazLabeledCnt},
|
||||
},
|
||||
"counter registered twice but wrapped with different inconsistent label values": {
|
||||
labels: Labels{"foo": "bar"},
|
||||
labels2: Labels{"bar": "baz"},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{simpleCnt, false}, {simpleCnt, true}},
|
||||
output: []Collector{barLabeledCnt},
|
||||
},
|
||||
"wrap counter with prefix and two labels": {
|
||||
prefix: "pre_",
|
||||
labels: Labels{"foo": "bar", "dings": "bums"},
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{simpleCnt, false}},
|
||||
output: []Collector{simpleGge, twiceLabeledPreCnt},
|
||||
},
|
||||
"wrap labeled counter with prefix and another label": {
|
||||
prefix: "pre_",
|
||||
labels: Labels{"dings": "bums"},
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{barLabeledCnt, false}},
|
||||
output: []Collector{simpleGge, twiceLabeledPreCnt},
|
||||
},
|
||||
"wrap labeled counter with prefix and inconsistent label": {
|
||||
prefix: "pre_",
|
||||
labels: Labels{"foo": "bums"},
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{barLabeledCnt, true}},
|
||||
output: []Collector{simpleGge},
|
||||
},
|
||||
"wrap labeled counter with prefix and the same label again": {
|
||||
prefix: "pre_",
|
||||
labels: Labels{"foo": "bar"},
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{barLabeledCnt, true}},
|
||||
output: []Collector{simpleGge},
|
||||
},
|
||||
"wrap labeled unchecked collector with prefix and another label": {
|
||||
prefix: "pre_",
|
||||
labels: Labels{"dings": "bums"},
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{barLabeledUncheckedCollector, false}},
|
||||
output: []Collector{simpleGge, twiceLabeledPreCnt},
|
||||
},
|
||||
"wrap labeled unchecked collector with prefix and inconsistent label": {
|
||||
prefix: "pre_",
|
||||
labels: Labels{"foo": "bums"},
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{barLabeledUncheckedCollector, false}},
|
||||
gatherFails: true,
|
||||
output: []Collector{simpleGge},
|
||||
},
|
||||
"wrap labeled unchecked collector with prefix and the same label again": {
|
||||
prefix: "pre_",
|
||||
labels: Labels{"foo": "bar"},
|
||||
preRegister: []Collector{simpleGge},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{barLabeledUncheckedCollector, false}},
|
||||
gatherFails: true,
|
||||
output: []Collector{simpleGge},
|
||||
},
|
||||
"wrap labeled unchecked collector with prefix and another label resulting in collision with pre-registered counter": {
|
||||
prefix: "pre_",
|
||||
labels: Labels{"dings": "bums"},
|
||||
preRegister: []Collector{twiceLabeledPreCnt},
|
||||
toRegister: []struct {
|
||||
collector Collector
|
||||
registrationFails bool
|
||||
}{{barLabeledUncheckedCollector, false}},
|
||||
gatherFails: true,
|
||||
output: []Collector{twiceLabeledPreCnt},
|
||||
},
|
||||
}
|
||||
|
||||
for n, s := range scenarios {
|
||||
t.Run(n, func(t *testing.T) {
|
||||
reg := NewPedanticRegistry()
|
||||
for _, c := range s.preRegister {
|
||||
if err := reg.Register(c); err != nil {
|
||||
t.Fatal("error registering with unwrapped registry:", err)
|
||||
}
|
||||
}
|
||||
preReg := WrapRegistererWithPrefix(s.prefix, reg)
|
||||
lReg := WrapRegistererWith(s.labels, preReg)
|
||||
l2Reg := WrapRegistererWith(s.labels2, preReg)
|
||||
for i, tr := range s.toRegister {
|
||||
var err error
|
||||
if i%2 != 0 && len(s.labels2) != 0 {
|
||||
err = l2Reg.Register(tr.collector)
|
||||
} else {
|
||||
err = lReg.Register(tr.collector)
|
||||
}
|
||||
if tr.registrationFails && err == nil {
|
||||
t.Fatalf("registration with wrapping registry unexpectedly succeded for collector #%d", i)
|
||||
}
|
||||
if !tr.registrationFails && err != nil {
|
||||
t.Fatalf("registration with wrapping registry failed for collector #%d: %s", i, err)
|
||||
}
|
||||
}
|
||||
wantMF := toMetricFamilies(s.output...)
|
||||
gotMF, err := reg.Gather()
|
||||
if s.gatherFails && err == nil {
|
||||
t.Fatal("gathering unexpectedly succeded")
|
||||
}
|
||||
if !s.gatherFails && err != nil {
|
||||
t.Fatal("gathering failed:", err)
|
||||
}
|
||||
if !reflect.DeepEqual(gotMF, wantMF) {
|
||||
var want, got []string
|
||||
|
||||
for i, mf := range wantMF {
|
||||
want = append(want, fmt.Sprintf("%3d: %s", i, proto.MarshalTextString(mf)))
|
||||
}
|
||||
for i, mf := range gotMF {
|
||||
got = append(got, fmt.Sprintf("%3d: %s", i, proto.MarshalTextString(mf)))
|
||||
}
|
||||
|
||||
t.Fatalf(
|
||||
"unexpected output of gathering:\n\nWANT:\n%s\n\nGOT:\n%s\n",
|
||||
strings.Join(want, "\n"),
|
||||
strings.Join(got, "\n"),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
2
vendor/github.com/prometheus/client_model/Makefile
generated
vendored
2
vendor/github.com/prometheus/client_model/Makefile
generated
vendored
|
@ -28,7 +28,7 @@ cpp/metrics.pb.h: metrics.proto
|
|||
go: go/metrics.pb.go
|
||||
|
||||
go/metrics.pb.go: metrics.proto
|
||||
protoc $< --go_out=go/
|
||||
protoc $< --go_out=import_path=github.com/prometheus/client_model/,paths=source_relative:go/
|
||||
|
||||
java: src/main/java/io/prometheus/client/Metrics.java pom.xml
|
||||
mvn clean compile package
|
||||
|
|
3380
vendor/github.com/prometheus/client_model/cpp/metrics.pb.cc
generated
vendored
Normal file
3380
vendor/github.com/prometheus/client_model/cpp/metrics.pb.cc
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
2072
vendor/github.com/prometheus/client_model/cpp/metrics.pb.h
generated
vendored
Normal file
2072
vendor/github.com/prometheus/client_model/cpp/metrics.pb.h
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
379
vendor/github.com/prometheus/client_model/go/metrics.pb.go
generated
vendored
379
vendor/github.com/prometheus/client_model/go/metrics.pb.go
generated
vendored
|
@ -1,34 +1,23 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: metrics.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package io_prometheus_client is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
metrics.proto
|
||||
|
||||
It has these top-level messages:
|
||||
LabelPair
|
||||
Gauge
|
||||
Counter
|
||||
Quantile
|
||||
Summary
|
||||
Untyped
|
||||
Histogram
|
||||
Bucket
|
||||
Metric
|
||||
MetricFamily
|
||||
*/
|
||||
package io_prometheus_client
|
||||
package io_prometheus_client // import "github.com/prometheus/client_model/go"
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type MetricType int32
|
||||
|
||||
const (
|
||||
|
@ -70,16 +59,41 @@ func (x *MetricType) UnmarshalJSON(data []byte) error {
|
|||
*x = MetricType(value)
|
||||
return nil
|
||||
}
|
||||
func (MetricType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{0}
|
||||
}
|
||||
|
||||
type LabelPair struct {
|
||||
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *LabelPair) Reset() { *m = LabelPair{} }
|
||||
func (m *LabelPair) String() string { return proto.CompactTextString(m) }
|
||||
func (*LabelPair) ProtoMessage() {}
|
||||
func (*LabelPair) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{0}
|
||||
}
|
||||
func (m *LabelPair) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_LabelPair.Unmarshal(m, b)
|
||||
}
|
||||
func (m *LabelPair) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_LabelPair.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *LabelPair) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_LabelPair.Merge(dst, src)
|
||||
}
|
||||
func (m *LabelPair) XXX_Size() int {
|
||||
return xxx_messageInfo_LabelPair.Size(m)
|
||||
}
|
||||
func (m *LabelPair) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_LabelPair.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_LabelPair proto.InternalMessageInfo
|
||||
|
||||
func (m *LabelPair) GetName() string {
|
||||
if m != nil && m.Name != nil {
|
||||
|
@ -96,13 +110,35 @@ func (m *LabelPair) GetValue() string {
|
|||
}
|
||||
|
||||
type Gauge struct {
|
||||
Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Gauge) Reset() { *m = Gauge{} }
|
||||
func (m *Gauge) String() string { return proto.CompactTextString(m) }
|
||||
func (*Gauge) ProtoMessage() {}
|
||||
func (*Gauge) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{1}
|
||||
}
|
||||
func (m *Gauge) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Gauge.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Gauge) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Gauge.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Gauge) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Gauge.Merge(dst, src)
|
||||
}
|
||||
func (m *Gauge) XXX_Size() int {
|
||||
return xxx_messageInfo_Gauge.Size(m)
|
||||
}
|
||||
func (m *Gauge) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Gauge.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Gauge proto.InternalMessageInfo
|
||||
|
||||
func (m *Gauge) GetValue() float64 {
|
||||
if m != nil && m.Value != nil {
|
||||
|
@ -112,13 +148,35 @@ func (m *Gauge) GetValue() float64 {
|
|||
}
|
||||
|
||||
type Counter struct {
|
||||
Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Counter) Reset() { *m = Counter{} }
|
||||
func (m *Counter) String() string { return proto.CompactTextString(m) }
|
||||
func (*Counter) ProtoMessage() {}
|
||||
func (*Counter) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{2}
|
||||
}
|
||||
func (m *Counter) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Counter.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Counter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Counter.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Counter) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Counter.Merge(dst, src)
|
||||
}
|
||||
func (m *Counter) XXX_Size() int {
|
||||
return xxx_messageInfo_Counter.Size(m)
|
||||
}
|
||||
func (m *Counter) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Counter.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Counter proto.InternalMessageInfo
|
||||
|
||||
func (m *Counter) GetValue() float64 {
|
||||
if m != nil && m.Value != nil {
|
||||
|
@ -128,14 +186,36 @@ func (m *Counter) GetValue() float64 {
|
|||
}
|
||||
|
||||
type Quantile struct {
|
||||
Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"`
|
||||
Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"`
|
||||
Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Quantile) Reset() { *m = Quantile{} }
|
||||
func (m *Quantile) String() string { return proto.CompactTextString(m) }
|
||||
func (*Quantile) ProtoMessage() {}
|
||||
func (*Quantile) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{3}
|
||||
}
|
||||
func (m *Quantile) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Quantile.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Quantile) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Quantile.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Quantile) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Quantile.Merge(dst, src)
|
||||
}
|
||||
func (m *Quantile) XXX_Size() int {
|
||||
return xxx_messageInfo_Quantile.Size(m)
|
||||
}
|
||||
func (m *Quantile) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Quantile.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Quantile proto.InternalMessageInfo
|
||||
|
||||
func (m *Quantile) GetQuantile() float64 {
|
||||
if m != nil && m.Quantile != nil {
|
||||
|
@ -152,15 +232,37 @@ func (m *Quantile) GetValue() float64 {
|
|||
}
|
||||
|
||||
type Summary struct {
|
||||
SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count" json:"sample_count,omitempty"`
|
||||
SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum" json:"sample_sum,omitempty"`
|
||||
Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"`
|
||||
SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"`
|
||||
Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Summary) Reset() { *m = Summary{} }
|
||||
func (m *Summary) String() string { return proto.CompactTextString(m) }
|
||||
func (*Summary) ProtoMessage() {}
|
||||
func (*Summary) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{4}
|
||||
}
|
||||
func (m *Summary) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Summary.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Summary) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Summary.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Summary) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Summary.Merge(dst, src)
|
||||
}
|
||||
func (m *Summary) XXX_Size() int {
|
||||
return xxx_messageInfo_Summary.Size(m)
|
||||
}
|
||||
func (m *Summary) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Summary.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Summary proto.InternalMessageInfo
|
||||
|
||||
func (m *Summary) GetSampleCount() uint64 {
|
||||
if m != nil && m.SampleCount != nil {
|
||||
|
@ -184,13 +286,35 @@ func (m *Summary) GetQuantile() []*Quantile {
|
|||
}
|
||||
|
||||
type Untyped struct {
|
||||
Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Untyped) Reset() { *m = Untyped{} }
|
||||
func (m *Untyped) String() string { return proto.CompactTextString(m) }
|
||||
func (*Untyped) ProtoMessage() {}
|
||||
func (*Untyped) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{5}
|
||||
}
|
||||
func (m *Untyped) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Untyped.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Untyped) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Untyped.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Untyped) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Untyped.Merge(dst, src)
|
||||
}
|
||||
func (m *Untyped) XXX_Size() int {
|
||||
return xxx_messageInfo_Untyped.Size(m)
|
||||
}
|
||||
func (m *Untyped) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Untyped.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Untyped proto.InternalMessageInfo
|
||||
|
||||
func (m *Untyped) GetValue() float64 {
|
||||
if m != nil && m.Value != nil {
|
||||
|
@ -200,15 +324,37 @@ func (m *Untyped) GetValue() float64 {
|
|||
}
|
||||
|
||||
type Histogram struct {
|
||||
SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count" json:"sample_count,omitempty"`
|
||||
SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum" json:"sample_sum,omitempty"`
|
||||
Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"`
|
||||
SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"`
|
||||
Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Histogram) Reset() { *m = Histogram{} }
|
||||
func (m *Histogram) String() string { return proto.CompactTextString(m) }
|
||||
func (*Histogram) ProtoMessage() {}
|
||||
func (*Histogram) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{6}
|
||||
}
|
||||
func (m *Histogram) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Histogram.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Histogram) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Histogram.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Histogram) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Histogram.Merge(dst, src)
|
||||
}
|
||||
func (m *Histogram) XXX_Size() int {
|
||||
return xxx_messageInfo_Histogram.Size(m)
|
||||
}
|
||||
func (m *Histogram) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Histogram.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Histogram proto.InternalMessageInfo
|
||||
|
||||
func (m *Histogram) GetSampleCount() uint64 {
|
||||
if m != nil && m.SampleCount != nil {
|
||||
|
@ -232,14 +378,36 @@ func (m *Histogram) GetBucket() []*Bucket {
|
|||
}
|
||||
|
||||
type Bucket struct {
|
||||
CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count" json:"cumulative_count,omitempty"`
|
||||
UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound" json:"upper_bound,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count,json=cumulativeCount" json:"cumulative_count,omitempty"`
|
||||
UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound,json=upperBound" json:"upper_bound,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Bucket) Reset() { *m = Bucket{} }
|
||||
func (m *Bucket) String() string { return proto.CompactTextString(m) }
|
||||
func (*Bucket) ProtoMessage() {}
|
||||
func (*Bucket) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{7}
|
||||
}
|
||||
func (m *Bucket) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Bucket.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Bucket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Bucket.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Bucket) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Bucket.Merge(dst, src)
|
||||
}
|
||||
func (m *Bucket) XXX_Size() int {
|
||||
return xxx_messageInfo_Bucket.Size(m)
|
||||
}
|
||||
func (m *Bucket) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Bucket.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Bucket proto.InternalMessageInfo
|
||||
|
||||
func (m *Bucket) GetCumulativeCount() uint64 {
|
||||
if m != nil && m.CumulativeCount != nil {
|
||||
|
@ -256,19 +424,41 @@ func (m *Bucket) GetUpperBound() float64 {
|
|||
}
|
||||
|
||||
type Metric struct {
|
||||
Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"`
|
||||
Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"`
|
||||
Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"`
|
||||
Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"`
|
||||
Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"`
|
||||
Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"`
|
||||
TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms" json:"timestamp_ms,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"`
|
||||
Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"`
|
||||
Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"`
|
||||
Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"`
|
||||
Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"`
|
||||
Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"`
|
||||
TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms,json=timestampMs" json:"timestamp_ms,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Metric) Reset() { *m = Metric{} }
|
||||
func (m *Metric) String() string { return proto.CompactTextString(m) }
|
||||
func (*Metric) ProtoMessage() {}
|
||||
func (*Metric) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{8}
|
||||
}
|
||||
func (m *Metric) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Metric.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Metric) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Metric.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Metric) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Metric.Merge(dst, src)
|
||||
}
|
||||
func (m *Metric) XXX_Size() int {
|
||||
return xxx_messageInfo_Metric.Size(m)
|
||||
}
|
||||
func (m *Metric) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Metric.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Metric proto.InternalMessageInfo
|
||||
|
||||
func (m *Metric) GetLabel() []*LabelPair {
|
||||
if m != nil {
|
||||
|
@ -320,16 +510,38 @@ func (m *Metric) GetTimestampMs() int64 {
|
|||
}
|
||||
|
||||
type MetricFamily struct {
|
||||
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"`
|
||||
Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"`
|
||||
Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"`
|
||||
Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"`
|
||||
Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *MetricFamily) Reset() { *m = MetricFamily{} }
|
||||
func (m *MetricFamily) String() string { return proto.CompactTextString(m) }
|
||||
func (*MetricFamily) ProtoMessage() {}
|
||||
func (*MetricFamily) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{9}
|
||||
}
|
||||
func (m *MetricFamily) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_MetricFamily.Unmarshal(m, b)
|
||||
}
|
||||
func (m *MetricFamily) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_MetricFamily.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *MetricFamily) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_MetricFamily.Merge(dst, src)
|
||||
}
|
||||
func (m *MetricFamily) XXX_Size() int {
|
||||
return xxx_messageInfo_MetricFamily.Size(m)
|
||||
}
|
||||
func (m *MetricFamily) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_MetricFamily.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_MetricFamily proto.InternalMessageInfo
|
||||
|
||||
func (m *MetricFamily) GetName() string {
|
||||
if m != nil && m.Name != nil {
|
||||
|
@ -360,5 +572,58 @@ func (m *MetricFamily) GetMetric() []*Metric {
|
|||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*LabelPair)(nil), "io.prometheus.client.LabelPair")
|
||||
proto.RegisterType((*Gauge)(nil), "io.prometheus.client.Gauge")
|
||||
proto.RegisterType((*Counter)(nil), "io.prometheus.client.Counter")
|
||||
proto.RegisterType((*Quantile)(nil), "io.prometheus.client.Quantile")
|
||||
proto.RegisterType((*Summary)(nil), "io.prometheus.client.Summary")
|
||||
proto.RegisterType((*Untyped)(nil), "io.prometheus.client.Untyped")
|
||||
proto.RegisterType((*Histogram)(nil), "io.prometheus.client.Histogram")
|
||||
proto.RegisterType((*Bucket)(nil), "io.prometheus.client.Bucket")
|
||||
proto.RegisterType((*Metric)(nil), "io.prometheus.client.Metric")
|
||||
proto.RegisterType((*MetricFamily)(nil), "io.prometheus.client.MetricFamily")
|
||||
proto.RegisterEnum("io.prometheus.client.MetricType", MetricType_name, MetricType_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("metrics.proto", fileDescriptor_metrics_c97c9a2b9560cb8f) }
|
||||
|
||||
var fileDescriptor_metrics_c97c9a2b9560cb8f = []byte{
|
||||
// 591 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x4f, 0xdb, 0x4e,
|
||||
0x14, 0xfc, 0x99, 0xd8, 0x09, 0x7e, 0x86, 0x5f, 0xad, 0x15, 0x07, 0xab, 0x2d, 0x25, 0xcd, 0x89,
|
||||
0xf6, 0x10, 0x54, 0x04, 0xaa, 0x44, 0xdb, 0x03, 0x50, 0x1a, 0x2a, 0xd5, 0x40, 0x37, 0xc9, 0x81,
|
||||
0x5e, 0xac, 0x8d, 0x59, 0x25, 0x56, 0xbd, 0xb6, 0x6b, 0xef, 0x22, 0xe5, 0xdc, 0x43, 0xbf, 0x47,
|
||||
0xbf, 0x68, 0xab, 0xfd, 0xe3, 0x18, 0x24, 0xc3, 0xa9, 0xb7, 0xb7, 0xf3, 0x66, 0xde, 0x8e, 0x77,
|
||||
0xc7, 0x0b, 0x9b, 0x8c, 0xf2, 0x32, 0x89, 0xab, 0x61, 0x51, 0xe6, 0x3c, 0x47, 0x5b, 0x49, 0x2e,
|
||||
0x2b, 0x46, 0xf9, 0x82, 0x8a, 0x6a, 0x18, 0xa7, 0x09, 0xcd, 0xf8, 0xe0, 0x10, 0xdc, 0x2f, 0x64,
|
||||
0x46, 0xd3, 0x2b, 0x92, 0x94, 0x08, 0x81, 0x9d, 0x11, 0x46, 0x03, 0xab, 0x6f, 0xed, 0xba, 0x58,
|
||||
0xd5, 0x68, 0x0b, 0x9c, 0x5b, 0x92, 0x0a, 0x1a, 0xac, 0x29, 0x50, 0x2f, 0x06, 0xdb, 0xe0, 0x8c,
|
||||
0x88, 0x98, 0xdf, 0x69, 0x4b, 0x8d, 0x55, 0xb7, 0x77, 0xa0, 0x77, 0x9a, 0x8b, 0x8c, 0xd3, 0xf2,
|
||||
0x01, 0xc2, 0x7b, 0x58, 0xff, 0x2a, 0x48, 0xc6, 0x93, 0x94, 0xa2, 0xa7, 0xb0, 0xfe, 0xc3, 0xd4,
|
||||
0x86, 0xb4, 0x5a, 0xdf, 0xdf, 0x7d, 0xa5, 0xfe, 0x65, 0x41, 0x6f, 0x2c, 0x18, 0x23, 0xe5, 0x12,
|
||||
0xbd, 0x84, 0x8d, 0x8a, 0xb0, 0x22, 0xa5, 0x51, 0x2c, 0x77, 0x54, 0x13, 0x6c, 0xec, 0x69, 0x4c,
|
||||
0x99, 0x40, 0xdb, 0x00, 0x86, 0x52, 0x09, 0x66, 0x26, 0xb9, 0x1a, 0x19, 0x0b, 0x86, 0x8e, 0xee,
|
||||
0xec, 0xdf, 0xe9, 0x77, 0x76, 0xbd, 0xfd, 0x17, 0xc3, 0xb6, 0xb3, 0x1a, 0xd6, 0x8e, 0x1b, 0x7f,
|
||||
0xf2, 0x43, 0xa7, 0x19, 0x5f, 0x16, 0xf4, 0xe6, 0x81, 0x0f, 0xfd, 0x69, 0x81, 0x7b, 0x9e, 0x54,
|
||||
0x3c, 0x9f, 0x97, 0x84, 0xfd, 0x03, 0xb3, 0x07, 0xd0, 0x9d, 0x89, 0xf8, 0x3b, 0xe5, 0xc6, 0xea,
|
||||
0xf3, 0x76, 0xab, 0x27, 0x8a, 0x83, 0x0d, 0x77, 0x30, 0x81, 0xae, 0x46, 0xd0, 0x2b, 0xf0, 0x63,
|
||||
0xc1, 0x44, 0x4a, 0x78, 0x72, 0x7b, 0xdf, 0xc5, 0x93, 0x06, 0xd7, 0x4e, 0x76, 0xc0, 0x13, 0x45,
|
||||
0x41, 0xcb, 0x68, 0x96, 0x8b, 0xec, 0xc6, 0x58, 0x01, 0x05, 0x9d, 0x48, 0x64, 0xf0, 0x67, 0x0d,
|
||||
0xba, 0xa1, 0xca, 0x18, 0x3a, 0x04, 0x27, 0x95, 0x31, 0x0a, 0x2c, 0xe5, 0x6a, 0xa7, 0xdd, 0xd5,
|
||||
0x2a, 0x69, 0x58, 0xb3, 0xd1, 0x1b, 0x70, 0xe6, 0x32, 0x46, 0x6a, 0xb8, 0xb7, 0xff, 0xac, 0x5d,
|
||||
0xa6, 0x92, 0x86, 0x35, 0x13, 0xbd, 0x85, 0x5e, 0xac, 0xa3, 0x15, 0x74, 0x94, 0x68, 0xbb, 0x5d,
|
||||
0x64, 0xf2, 0x87, 0x6b, 0xb6, 0x14, 0x56, 0x3a, 0x33, 0x81, 0xfd, 0x98, 0xd0, 0x04, 0x0b, 0xd7,
|
||||
0x6c, 0x29, 0x14, 0xfa, 0x8e, 0x03, 0xe7, 0x31, 0xa1, 0x09, 0x02, 0xae, 0xd9, 0xe8, 0x03, 0xb8,
|
||||
0x8b, 0xfa, 0xea, 0x83, 0x9e, 0x92, 0x3e, 0x70, 0x30, 0xab, 0x84, 0xe0, 0x46, 0x21, 0xc3, 0xc2,
|
||||
0x13, 0x46, 0x2b, 0x4e, 0x58, 0x11, 0xb1, 0x2a, 0xe8, 0xf6, 0xad, 0xdd, 0x0e, 0xf6, 0x56, 0x58,
|
||||
0x58, 0x0d, 0x7e, 0x5b, 0xb0, 0xa1, 0x6f, 0xe0, 0x13, 0x61, 0x49, 0xba, 0x6c, 0xfd, 0x83, 0x11,
|
||||
0xd8, 0x0b, 0x9a, 0x16, 0xe6, 0x07, 0x56, 0x35, 0x3a, 0x00, 0x5b, 0x7a, 0x54, 0x47, 0xf8, 0xff,
|
||||
0x7e, 0xbf, 0xdd, 0x95, 0x9e, 0x3c, 0x59, 0x16, 0x14, 0x2b, 0xb6, 0x0c, 0x9f, 0x7e, 0x53, 0x02,
|
||||
0xfb, 0xb1, 0xf0, 0x69, 0x1d, 0x36, 0xdc, 0xd7, 0x21, 0x40, 0x33, 0x09, 0x79, 0xd0, 0x3b, 0xbd,
|
||||
0x9c, 0x5e, 0x4c, 0xce, 0xb0, 0xff, 0x1f, 0x72, 0xc1, 0x19, 0x1d, 0x4f, 0x47, 0x67, 0xbe, 0x25,
|
||||
0xf1, 0xf1, 0x34, 0x0c, 0x8f, 0xf1, 0xb5, 0xbf, 0x26, 0x17, 0xd3, 0x8b, 0xc9, 0xf5, 0xd5, 0xd9,
|
||||
0x47, 0xbf, 0x83, 0x36, 0xc1, 0x3d, 0xff, 0x3c, 0x9e, 0x5c, 0x8e, 0xf0, 0x71, 0xe8, 0xdb, 0x27,
|
||||
0x18, 0x5a, 0x5f, 0xb2, 0x6f, 0x47, 0xf3, 0x84, 0x2f, 0xc4, 0x6c, 0x18, 0xe7, 0x6c, 0xaf, 0xe9,
|
||||
0xee, 0xe9, 0x6e, 0xc4, 0xf2, 0x1b, 0x9a, 0xee, 0xcd, 0xf3, 0x77, 0x49, 0x1e, 0x35, 0xdd, 0x48,
|
||||
0x77, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x45, 0x21, 0x7f, 0x64, 0x2b, 0x05, 0x00, 0x00,
|
||||
}
|
||||
|
|
1
vendor/github.com/prometheus/client_model/metrics.proto
generated
vendored
1
vendor/github.com/prometheus/client_model/metrics.proto
generated
vendored
|
@ -15,6 +15,7 @@ syntax = "proto2";
|
|||
|
||||
package io.prometheus.client;
|
||||
option java_package = "io.prometheus.client";
|
||||
option go_package = "github.com/prometheus/client_model/go;io_prometheus_client";
|
||||
|
||||
message LabelPair {
|
||||
optional string name = 1;
|
||||
|
|
12
vendor/github.com/prometheus/client_model/python/prometheus/__init__.py
generated
vendored
Normal file
12
vendor/github.com/prometheus/client_model/python/prometheus/__init__.py
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Copyright 2013 Prometheus Team
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
12
vendor/github.com/prometheus/client_model/python/prometheus/client/__init__.py
generated
vendored
Normal file
12
vendor/github.com/prometheus/client_model/python/prometheus/client/__init__.py
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Copyright 2013 Prometheus Team
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
14
vendor/github.com/prometheus/client_model/python/prometheus/client/model/__init__.py
generated
vendored
Normal file
14
vendor/github.com/prometheus/client_model/python/prometheus/client/model/__init__.py
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Copyright 2013 Prometheus Team
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
__all__ = ['metrics_pb2']
|
575
vendor/github.com/prometheus/client_model/python/prometheus/client/model/metrics_pb2.py
generated
vendored
Normal file
575
vendor/github.com/prometheus/client_model/python/prometheus/client/model/metrics_pb2.py
generated
vendored
Normal file
|
@ -0,0 +1,575 @@
|
|||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: metrics.proto
|
||||
|
||||
import sys
|
||||
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
|
||||
from google.protobuf.internal import enum_type_wrapper
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf import descriptor_pb2
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='metrics.proto',
|
||||
package='io.prometheus.client',
|
||||
serialized_pb=_b('\n\rmetrics.proto\x12\x14io.prometheus.client\"(\n\tLabelPair\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"\x16\n\x05Gauge\x12\r\n\x05value\x18\x01 \x01(\x01\"\x18\n\x07\x43ounter\x12\r\n\x05value\x18\x01 \x01(\x01\"+\n\x08Quantile\x12\x10\n\x08quantile\x18\x01 \x01(\x01\x12\r\n\x05value\x18\x02 \x01(\x01\"e\n\x07Summary\x12\x14\n\x0csample_count\x18\x01 \x01(\x04\x12\x12\n\nsample_sum\x18\x02 \x01(\x01\x12\x30\n\x08quantile\x18\x03 \x03(\x0b\x32\x1e.io.prometheus.client.Quantile\"\x18\n\x07Untyped\x12\r\n\x05value\x18\x01 \x01(\x01\"c\n\tHistogram\x12\x14\n\x0csample_count\x18\x01 \x01(\x04\x12\x12\n\nsample_sum\x18\x02 \x01(\x01\x12,\n\x06\x62ucket\x18\x03 \x03(\x0b\x32\x1c.io.prometheus.client.Bucket\"7\n\x06\x42ucket\x12\x18\n\x10\x63umulative_count\x18\x01 \x01(\x04\x12\x13\n\x0bupper_bound\x18\x02 \x01(\x01\"\xbe\x02\n\x06Metric\x12.\n\x05label\x18\x01 \x03(\x0b\x32\x1f.io.prometheus.client.LabelPair\x12*\n\x05gauge\x18\x02 \x01(\x0b\x32\x1b.io.prometheus.client.Gauge\x12.\n\x07\x63ounter\x18\x03 \x01(\x0b\x32\x1d.io.prometheus.client.Counter\x12.\n\x07summary\x18\x04 \x01(\x0b\x32\x1d.io.prometheus.client.Summary\x12.\n\x07untyped\x18\x05 \x01(\x0b\x32\x1d.io.prometheus.client.Untyped\x12\x32\n\thistogram\x18\x07 \x01(\x0b\x32\x1f.io.prometheus.client.Histogram\x12\x14\n\x0ctimestamp_ms\x18\x06 \x01(\x03\"\x88\x01\n\x0cMetricFamily\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04help\x18\x02 \x01(\t\x12.\n\x04type\x18\x03 \x01(\x0e\x32 .io.prometheus.client.MetricType\x12,\n\x06metric\x18\x04 \x03(\x0b\x32\x1c.io.prometheus.client.Metric*M\n\nMetricType\x12\x0b\n\x07\x43OUNTER\x10\x00\x12\t\n\x05GAUGE\x10\x01\x12\x0b\n\x07SUMMARY\x10\x02\x12\x0b\n\x07UNTYPED\x10\x03\x12\r\n\tHISTOGRAM\x10\x04\x42\x16\n\x14io.prometheus.client')
|
||||
)
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
_METRICTYPE = _descriptor.EnumDescriptor(
|
||||
name='MetricType',
|
||||
full_name='io.prometheus.client.MetricType',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
values=[
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='COUNTER', index=0, number=0,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='GAUGE', index=1, number=1,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='SUMMARY', index=2, number=2,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='UNTYPED', index=3, number=3,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='HISTOGRAM', index=4, number=4,
|
||||
options=None,
|
||||
type=None),
|
||||
],
|
||||
containing_type=None,
|
||||
options=None,
|
||||
serialized_start=923,
|
||||
serialized_end=1000,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_METRICTYPE)
|
||||
|
||||
MetricType = enum_type_wrapper.EnumTypeWrapper(_METRICTYPE)
|
||||
COUNTER = 0
|
||||
GAUGE = 1
|
||||
SUMMARY = 2
|
||||
UNTYPED = 3
|
||||
HISTOGRAM = 4
|
||||
|
||||
|
||||
|
||||
_LABELPAIR = _descriptor.Descriptor(
|
||||
name='LabelPair',
|
||||
full_name='io.prometheus.client.LabelPair',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='name', full_name='io.prometheus.client.LabelPair.name', index=0,
|
||||
number=1, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='value', full_name='io.prometheus.client.LabelPair.value', index=1,
|
||||
number=2, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=39,
|
||||
serialized_end=79,
|
||||
)
|
||||
|
||||
|
||||
_GAUGE = _descriptor.Descriptor(
|
||||
name='Gauge',
|
||||
full_name='io.prometheus.client.Gauge',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='value', full_name='io.prometheus.client.Gauge.value', index=0,
|
||||
number=1, type=1, cpp_type=5, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=81,
|
||||
serialized_end=103,
|
||||
)
|
||||
|
||||
|
||||
_COUNTER = _descriptor.Descriptor(
|
||||
name='Counter',
|
||||
full_name='io.prometheus.client.Counter',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='value', full_name='io.prometheus.client.Counter.value', index=0,
|
||||
number=1, type=1, cpp_type=5, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=105,
|
||||
serialized_end=129,
|
||||
)
|
||||
|
||||
|
||||
_QUANTILE = _descriptor.Descriptor(
|
||||
name='Quantile',
|
||||
full_name='io.prometheus.client.Quantile',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='quantile', full_name='io.prometheus.client.Quantile.quantile', index=0,
|
||||
number=1, type=1, cpp_type=5, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='value', full_name='io.prometheus.client.Quantile.value', index=1,
|
||||
number=2, type=1, cpp_type=5, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=131,
|
||||
serialized_end=174,
|
||||
)
|
||||
|
||||
|
||||
_SUMMARY = _descriptor.Descriptor(
|
||||
name='Summary',
|
||||
full_name='io.prometheus.client.Summary',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='sample_count', full_name='io.prometheus.client.Summary.sample_count', index=0,
|
||||
number=1, type=4, cpp_type=4, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='sample_sum', full_name='io.prometheus.client.Summary.sample_sum', index=1,
|
||||
number=2, type=1, cpp_type=5, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='quantile', full_name='io.prometheus.client.Summary.quantile', index=2,
|
||||
number=3, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=176,
|
||||
serialized_end=277,
|
||||
)
|
||||
|
||||
|
||||
_UNTYPED = _descriptor.Descriptor(
|
||||
name='Untyped',
|
||||
full_name='io.prometheus.client.Untyped',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='value', full_name='io.prometheus.client.Untyped.value', index=0,
|
||||
number=1, type=1, cpp_type=5, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=279,
|
||||
serialized_end=303,
|
||||
)
|
||||
|
||||
|
||||
_HISTOGRAM = _descriptor.Descriptor(
|
||||
name='Histogram',
|
||||
full_name='io.prometheus.client.Histogram',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='sample_count', full_name='io.prometheus.client.Histogram.sample_count', index=0,
|
||||
number=1, type=4, cpp_type=4, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='sample_sum', full_name='io.prometheus.client.Histogram.sample_sum', index=1,
|
||||
number=2, type=1, cpp_type=5, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='bucket', full_name='io.prometheus.client.Histogram.bucket', index=2,
|
||||
number=3, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=305,
|
||||
serialized_end=404,
|
||||
)
|
||||
|
||||
|
||||
_BUCKET = _descriptor.Descriptor(
|
||||
name='Bucket',
|
||||
full_name='io.prometheus.client.Bucket',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='cumulative_count', full_name='io.prometheus.client.Bucket.cumulative_count', index=0,
|
||||
number=1, type=4, cpp_type=4, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='upper_bound', full_name='io.prometheus.client.Bucket.upper_bound', index=1,
|
||||
number=2, type=1, cpp_type=5, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=406,
|
||||
serialized_end=461,
|
||||
)
|
||||
|
||||
|
||||
_METRIC = _descriptor.Descriptor(
|
||||
name='Metric',
|
||||
full_name='io.prometheus.client.Metric',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='label', full_name='io.prometheus.client.Metric.label', index=0,
|
||||
number=1, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='gauge', full_name='io.prometheus.client.Metric.gauge', index=1,
|
||||
number=2, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='counter', full_name='io.prometheus.client.Metric.counter', index=2,
|
||||
number=3, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='summary', full_name='io.prometheus.client.Metric.summary', index=3,
|
||||
number=4, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='untyped', full_name='io.prometheus.client.Metric.untyped', index=4,
|
||||
number=5, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='histogram', full_name='io.prometheus.client.Metric.histogram', index=5,
|
||||
number=7, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='timestamp_ms', full_name='io.prometheus.client.Metric.timestamp_ms', index=6,
|
||||
number=6, type=3, cpp_type=2, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=464,
|
||||
serialized_end=782,
|
||||
)
|
||||
|
||||
|
||||
_METRICFAMILY = _descriptor.Descriptor(
|
||||
name='MetricFamily',
|
||||
full_name='io.prometheus.client.MetricFamily',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='name', full_name='io.prometheus.client.MetricFamily.name', index=0,
|
||||
number=1, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='help', full_name='io.prometheus.client.MetricFamily.help', index=1,
|
||||
number=2, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='type', full_name='io.prometheus.client.MetricFamily.type', index=2,
|
||||
number=3, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='metric', full_name='io.prometheus.client.MetricFamily.metric', index=3,
|
||||
number=4, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=785,
|
||||
serialized_end=921,
|
||||
)
|
||||
|
||||
_SUMMARY.fields_by_name['quantile'].message_type = _QUANTILE
|
||||
_HISTOGRAM.fields_by_name['bucket'].message_type = _BUCKET
|
||||
_METRIC.fields_by_name['label'].message_type = _LABELPAIR
|
||||
_METRIC.fields_by_name['gauge'].message_type = _GAUGE
|
||||
_METRIC.fields_by_name['counter'].message_type = _COUNTER
|
||||
_METRIC.fields_by_name['summary'].message_type = _SUMMARY
|
||||
_METRIC.fields_by_name['untyped'].message_type = _UNTYPED
|
||||
_METRIC.fields_by_name['histogram'].message_type = _HISTOGRAM
|
||||
_METRICFAMILY.fields_by_name['type'].enum_type = _METRICTYPE
|
||||
_METRICFAMILY.fields_by_name['metric'].message_type = _METRIC
|
||||
DESCRIPTOR.message_types_by_name['LabelPair'] = _LABELPAIR
|
||||
DESCRIPTOR.message_types_by_name['Gauge'] = _GAUGE
|
||||
DESCRIPTOR.message_types_by_name['Counter'] = _COUNTER
|
||||
DESCRIPTOR.message_types_by_name['Quantile'] = _QUANTILE
|
||||
DESCRIPTOR.message_types_by_name['Summary'] = _SUMMARY
|
||||
DESCRIPTOR.message_types_by_name['Untyped'] = _UNTYPED
|
||||
DESCRIPTOR.message_types_by_name['Histogram'] = _HISTOGRAM
|
||||
DESCRIPTOR.message_types_by_name['Bucket'] = _BUCKET
|
||||
DESCRIPTOR.message_types_by_name['Metric'] = _METRIC
|
||||
DESCRIPTOR.message_types_by_name['MetricFamily'] = _METRICFAMILY
|
||||
DESCRIPTOR.enum_types_by_name['MetricType'] = _METRICTYPE
|
||||
|
||||
LabelPair = _reflection.GeneratedProtocolMessageType('LabelPair', (_message.Message,), dict(
|
||||
DESCRIPTOR = _LABELPAIR,
|
||||
__module__ = 'metrics_pb2'
|
||||
# @@protoc_insertion_point(class_scope:io.prometheus.client.LabelPair)
|
||||
))
|
||||
_sym_db.RegisterMessage(LabelPair)
|
||||
|
||||
Gauge = _reflection.GeneratedProtocolMessageType('Gauge', (_message.Message,), dict(
|
||||
DESCRIPTOR = _GAUGE,
|
||||
__module__ = 'metrics_pb2'
|
||||
# @@protoc_insertion_point(class_scope:io.prometheus.client.Gauge)
|
||||
))
|
||||
_sym_db.RegisterMessage(Gauge)
|
||||
|
||||
Counter = _reflection.GeneratedProtocolMessageType('Counter', (_message.Message,), dict(
|
||||
DESCRIPTOR = _COUNTER,
|
||||
__module__ = 'metrics_pb2'
|
||||
# @@protoc_insertion_point(class_scope:io.prometheus.client.Counter)
|
||||
))
|
||||
_sym_db.RegisterMessage(Counter)
|
||||
|
||||
Quantile = _reflection.GeneratedProtocolMessageType('Quantile', (_message.Message,), dict(
|
||||
DESCRIPTOR = _QUANTILE,
|
||||
__module__ = 'metrics_pb2'
|
||||
# @@protoc_insertion_point(class_scope:io.prometheus.client.Quantile)
|
||||
))
|
||||
_sym_db.RegisterMessage(Quantile)
|
||||
|
||||
Summary = _reflection.GeneratedProtocolMessageType('Summary', (_message.Message,), dict(
|
||||
DESCRIPTOR = _SUMMARY,
|
||||
__module__ = 'metrics_pb2'
|
||||
# @@protoc_insertion_point(class_scope:io.prometheus.client.Summary)
|
||||
))
|
||||
_sym_db.RegisterMessage(Summary)
|
||||
|
||||
Untyped = _reflection.GeneratedProtocolMessageType('Untyped', (_message.Message,), dict(
|
||||
DESCRIPTOR = _UNTYPED,
|
||||
__module__ = 'metrics_pb2'
|
||||
# @@protoc_insertion_point(class_scope:io.prometheus.client.Untyped)
|
||||
))
|
||||
_sym_db.RegisterMessage(Untyped)
|
||||
|
||||
Histogram = _reflection.GeneratedProtocolMessageType('Histogram', (_message.Message,), dict(
|
||||
DESCRIPTOR = _HISTOGRAM,
|
||||
__module__ = 'metrics_pb2'
|
||||
# @@protoc_insertion_point(class_scope:io.prometheus.client.Histogram)
|
||||
))
|
||||
_sym_db.RegisterMessage(Histogram)
|
||||
|
||||
Bucket = _reflection.GeneratedProtocolMessageType('Bucket', (_message.Message,), dict(
|
||||
DESCRIPTOR = _BUCKET,
|
||||
__module__ = 'metrics_pb2'
|
||||
# @@protoc_insertion_point(class_scope:io.prometheus.client.Bucket)
|
||||
))
|
||||
_sym_db.RegisterMessage(Bucket)
|
||||
|
||||
Metric = _reflection.GeneratedProtocolMessageType('Metric', (_message.Message,), dict(
|
||||
DESCRIPTOR = _METRIC,
|
||||
__module__ = 'metrics_pb2'
|
||||
# @@protoc_insertion_point(class_scope:io.prometheus.client.Metric)
|
||||
))
|
||||
_sym_db.RegisterMessage(Metric)
|
||||
|
||||
MetricFamily = _reflection.GeneratedProtocolMessageType('MetricFamily', (_message.Message,), dict(
|
||||
DESCRIPTOR = _METRICFAMILY,
|
||||
__module__ = 'metrics_pb2'
|
||||
# @@protoc_insertion_point(class_scope:io.prometheus.client.MetricFamily)
|
||||
))
|
||||
_sym_db.RegisterMessage(MetricFamily)
|
||||
|
||||
|
||||
DESCRIPTOR.has_options = True
|
||||
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\024io.prometheus.client'))
|
||||
# @@protoc_insertion_point(module_scope)
|
5
vendor/github.com/prometheus/client_model/ruby/.gitignore
generated
vendored
Normal file
5
vendor/github.com/prometheus/client_model/ruby/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
*.gem
|
||||
.bundle
|
||||
Gemfile.lock
|
||||
pkg
|
||||
vendor/bundle
|
4
vendor/github.com/prometheus/client_model/ruby/Gemfile
generated
vendored
Normal file
4
vendor/github.com/prometheus/client_model/ruby/Gemfile
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
# Specify your gem's dependencies in prometheus-client-model.gemspec
|
||||
gemspec
|
201
vendor/github.com/prometheus/client_model/ruby/LICENSE
generated
vendored
Normal file
201
vendor/github.com/prometheus/client_model/ruby/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
17
vendor/github.com/prometheus/client_model/ruby/Makefile
generated
vendored
Normal file
17
vendor/github.com/prometheus/client_model/ruby/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
VENDOR_BUNDLE = vendor/bundle
|
||||
|
||||
build: $(VENDOR_BUNDLE)/.bundled
|
||||
BEEFCAKE_NAMESPACE=Prometheus::Client protoc --beefcake_out lib/prometheus/client/model -I .. ../metrics.proto
|
||||
|
||||
$(VENDOR_BUNDLE):
|
||||
mkdir -p $@
|
||||
|
||||
$(VENDOR_BUNDLE)/.bundled: $(VENDOR_BUNDLE) Gemfile
|
||||
bundle install --quiet --path $<
|
||||
@touch $@
|
||||
|
||||
clean:
|
||||
-rm -f lib/prometheus/client/model/metrics.pb.rb
|
||||
-rm -rf $(VENDOR_BUNDLE)
|
||||
|
||||
.PHONY: build clean
|
31
vendor/github.com/prometheus/client_model/ruby/README.md
generated
vendored
Normal file
31
vendor/github.com/prometheus/client_model/ruby/README.md
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Prometheus Ruby client model
|
||||
|
||||
Data model artifacts for the [Prometheus Ruby client][1].
|
||||
|
||||
## Installation
|
||||
|
||||
gem install prometheus-client-model
|
||||
|
||||
## Usage
|
||||
|
||||
Build the artifacts from the protobuf specification:
|
||||
|
||||
make build
|
||||
|
||||
While this Gem's main purpose is to define the Prometheus data types for the
|
||||
[client][1], it's possible to use it without the client to decode a stream of
|
||||
delimited protobuf messages:
|
||||
|
||||
```ruby
|
||||
require 'open-uri'
|
||||
require 'prometheus/client/model'
|
||||
|
||||
CONTENT_TYPE = 'application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited'
|
||||
|
||||
stream = open('http://localhost:9090/metrics', 'Accept' => CONTENT_TYPE).read
|
||||
while family = Prometheus::Client::MetricFamily.read_delimited(stream)
|
||||
puts family
|
||||
end
|
||||
```
|
||||
|
||||
[1]: https://github.com/prometheus/client_ruby
|
1
vendor/github.com/prometheus/client_model/ruby/Rakefile
generated
vendored
Normal file
1
vendor/github.com/prometheus/client_model/ruby/Rakefile
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
require "bundler/gem_tasks"
|
2
vendor/github.com/prometheus/client_model/ruby/lib/prometheus/client/model.rb
generated
vendored
Normal file
2
vendor/github.com/prometheus/client_model/ruby/lib/prometheus/client/model.rb
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
require 'prometheus/client/model/metrics.pb'
|
||||
require 'prometheus/client/model/version'
|
111
vendor/github.com/prometheus/client_model/ruby/lib/prometheus/client/model/metrics.pb.rb
generated
vendored
Normal file
111
vendor/github.com/prometheus/client_model/ruby/lib/prometheus/client/model/metrics.pb.rb
generated
vendored
Normal file
|
@ -0,0 +1,111 @@
|
|||
## Generated from metrics.proto for io.prometheus.client
|
||||
require "beefcake"
|
||||
|
||||
module Prometheus
|
||||
module Client
|
||||
|
||||
module MetricType
|
||||
COUNTER = 0
|
||||
GAUGE = 1
|
||||
SUMMARY = 2
|
||||
UNTYPED = 3
|
||||
HISTOGRAM = 4
|
||||
end
|
||||
|
||||
class LabelPair
|
||||
include Beefcake::Message
|
||||
end
|
||||
|
||||
class Gauge
|
||||
include Beefcake::Message
|
||||
end
|
||||
|
||||
class Counter
|
||||
include Beefcake::Message
|
||||
end
|
||||
|
||||
class Quantile
|
||||
include Beefcake::Message
|
||||
end
|
||||
|
||||
class Summary
|
||||
include Beefcake::Message
|
||||
end
|
||||
|
||||
class Untyped
|
||||
include Beefcake::Message
|
||||
end
|
||||
|
||||
class Histogram
|
||||
include Beefcake::Message
|
||||
end
|
||||
|
||||
class Bucket
|
||||
include Beefcake::Message
|
||||
end
|
||||
|
||||
class Metric
|
||||
include Beefcake::Message
|
||||
end
|
||||
|
||||
class MetricFamily
|
||||
include Beefcake::Message
|
||||
end
|
||||
|
||||
class LabelPair
|
||||
optional :name, :string, 1
|
||||
optional :value, :string, 2
|
||||
end
|
||||
|
||||
class Gauge
|
||||
optional :value, :double, 1
|
||||
end
|
||||
|
||||
class Counter
|
||||
optional :value, :double, 1
|
||||
end
|
||||
|
||||
class Quantile
|
||||
optional :quantile, :double, 1
|
||||
optional :value, :double, 2
|
||||
end
|
||||
|
||||
class Summary
|
||||
optional :sample_count, :uint64, 1
|
||||
optional :sample_sum, :double, 2
|
||||
repeated :quantile, Quantile, 3
|
||||
end
|
||||
|
||||
class Untyped
|
||||
optional :value, :double, 1
|
||||
end
|
||||
|
||||
class Histogram
|
||||
optional :sample_count, :uint64, 1
|
||||
optional :sample_sum, :double, 2
|
||||
repeated :bucket, Bucket, 3
|
||||
end
|
||||
|
||||
class Bucket
|
||||
optional :cumulative_count, :uint64, 1
|
||||
optional :upper_bound, :double, 2
|
||||
end
|
||||
|
||||
class Metric
|
||||
repeated :label, LabelPair, 1
|
||||
optional :gauge, Gauge, 2
|
||||
optional :counter, Counter, 3
|
||||
optional :summary, Summary, 4
|
||||
optional :untyped, Untyped, 5
|
||||
optional :histogram, Histogram, 7
|
||||
optional :timestamp_ms, :int64, 6
|
||||
end
|
||||
|
||||
class MetricFamily
|
||||
optional :name, :string, 1
|
||||
optional :help, :string, 2
|
||||
optional :type, MetricType, 3
|
||||
repeated :metric, Metric, 4
|
||||
end
|
||||
end
|
||||
end
|
7
vendor/github.com/prometheus/client_model/ruby/lib/prometheus/client/model/version.rb
generated
vendored
Normal file
7
vendor/github.com/prometheus/client_model/ruby/lib/prometheus/client/model/version.rb
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
module Prometheus
|
||||
module Client
|
||||
module Model
|
||||
VERSION = '0.1.0'
|
||||
end
|
||||
end
|
||||
end
|
22
vendor/github.com/prometheus/client_model/ruby/prometheus-client-model.gemspec
generated
vendored
Normal file
22
vendor/github.com/prometheus/client_model/ruby/prometheus-client-model.gemspec
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
# coding: utf-8
|
||||
lib = File.expand_path('../lib', __FILE__)
|
||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||
require 'prometheus/client/model/version'
|
||||
|
||||
Gem::Specification.new do |spec|
|
||||
spec.name = 'prometheus-client-model'
|
||||
spec.version = Prometheus::Client::Model::VERSION
|
||||
spec.authors = ['Tobias Schmidt']
|
||||
spec.email = ['tobidt@gmail.com']
|
||||
spec.summary = 'Data model artifacts for the Prometheus Ruby client'
|
||||
spec.homepage = 'https://github.com/prometheus/client_model/tree/master/ruby'
|
||||
spec.license = 'Apache 2.0'
|
||||
|
||||
spec.files = %w[README.md LICENSE] + Dir.glob('{lib/**/*}')
|
||||
spec.require_paths = ['lib']
|
||||
|
||||
spec.add_dependency 'beefcake', '>= 0.4.0'
|
||||
|
||||
spec.add_development_dependency 'bundler', '~> 1.3'
|
||||
spec.add_development_dependency 'rake'
|
||||
end
|
7683
vendor/github.com/prometheus/client_model/src/main/java/io/prometheus/client/Metrics.java
generated
vendored
Normal file
7683
vendor/github.com/prometheus/client_model/src/main/java/io/prometheus/client/Metrics.java
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
2
vendor/github.com/prometheus/common/README.md
generated
vendored
2
vendor/github.com/prometheus/common/README.md
generated
vendored
|
@ -9,4 +9,4 @@ components and libraries.
|
|||
* **log**: A logging wrapper around [logrus](https://github.com/sirupsen/logrus)
|
||||
* **model**: Shared data structures
|
||||
* **route**: A routing wrapper around [httprouter](https://github.com/julienschmidt/httprouter) using `context.Context`
|
||||
* **version**: Version informations and metric
|
||||
* **version**: Version information and metrics
|
||||
|
|
34
vendor/github.com/prometheus/common/config/config.go
generated
vendored
Normal file
34
vendor/github.com/prometheus/common/config/config.go
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2016 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This package no longer handles safe yaml parsing. In order to
|
||||
// ensure correct yaml unmarshalling, use "yaml.UnmarshalStrict()".
|
||||
|
||||
package config
|
||||
|
||||
// Secret special type for storing secrets.
|
||||
type Secret string
|
||||
|
||||
// MarshalYAML implements the yaml.Marshaler interface for Secrets.
|
||||
func (s Secret) MarshalYAML() (interface{}, error) {
|
||||
if s != "" {
|
||||
return "<secret>", nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
//UnmarshalYAML implements the yaml.Unmarshaler interface for Secrets.
|
||||
func (s *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
type plain Secret
|
||||
return unmarshal((*plain)(s))
|
||||
}
|
317
vendor/github.com/prometheus/common/config/http_config.go
generated
vendored
Normal file
317
vendor/github.com/prometheus/common/config/http_config.go
generated
vendored
Normal file
|
@ -0,0 +1,317 @@
|
|||
// Copyright 2016 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mwitkow/go-conntrack"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// BasicAuth contains basic HTTP authentication credentials.
|
||||
type BasicAuth struct {
|
||||
Username string `yaml:"username"`
|
||||
Password Secret `yaml:"password,omitempty"`
|
||||
PasswordFile string `yaml:"password_file,omitempty"`
|
||||
}
|
||||
|
||||
// URL is a custom URL type that allows validation at configuration load time.
|
||||
type URL struct {
|
||||
*url.URL
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface for URLs.
|
||||
func (u *URL) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var s string
|
||||
if err := unmarshal(&s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
urlp, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.URL = urlp
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalYAML implements the yaml.Marshaler interface for URLs.
|
||||
func (u URL) MarshalYAML() (interface{}, error) {
|
||||
if u.URL != nil {
|
||||
return u.String(), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// HTTPClientConfig configures an HTTP client.
|
||||
type HTTPClientConfig struct {
|
||||
// The HTTP basic authentication credentials for the targets.
|
||||
BasicAuth *BasicAuth `yaml:"basic_auth,omitempty"`
|
||||
// The bearer token for the targets.
|
||||
BearerToken Secret `yaml:"bearer_token,omitempty"`
|
||||
// The bearer token file for the targets.
|
||||
BearerTokenFile string `yaml:"bearer_token_file,omitempty"`
|
||||
// HTTP proxy server to use to connect to the targets.
|
||||
ProxyURL URL `yaml:"proxy_url,omitempty"`
|
||||
// TLSConfig to use to connect to the targets.
|
||||
TLSConfig TLSConfig `yaml:"tls_config,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates the HTTPClientConfig to check only one of BearerToken,
|
||||
// BasicAuth and BearerTokenFile is configured.
|
||||
func (c *HTTPClientConfig) Validate() error {
|
||||
if len(c.BearerToken) > 0 && len(c.BearerTokenFile) > 0 {
|
||||
return fmt.Errorf("at most one of bearer_token & bearer_token_file must be configured")
|
||||
}
|
||||
if c.BasicAuth != nil && (len(c.BearerToken) > 0 || len(c.BearerTokenFile) > 0) {
|
||||
return fmt.Errorf("at most one of basic_auth, bearer_token & bearer_token_file must be configured")
|
||||
}
|
||||
if c.BasicAuth != nil && (string(c.BasicAuth.Password) != "" && c.BasicAuth.PasswordFile != "") {
|
||||
return fmt.Errorf("at most one of basic_auth password & password_file must be configured")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface
|
||||
func (c *HTTPClientConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
type plain HTTPClientConfig
|
||||
if err := unmarshal((*plain)(c)); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Validate()
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||
func (a *BasicAuth) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
type plain BasicAuth
|
||||
return unmarshal((*plain)(a))
|
||||
}
|
||||
|
||||
// NewClient returns a http.Client using the specified http.RoundTripper.
|
||||
func newClient(rt http.RoundTripper) *http.Client {
|
||||
return &http.Client{Transport: rt}
|
||||
}
|
||||
|
||||
// NewClientFromConfig returns a new HTTP client configured for the
|
||||
// given config.HTTPClientConfig. The name is used as go-conntrack metric label.
|
||||
func NewClientFromConfig(cfg HTTPClientConfig, name string) (*http.Client, error) {
|
||||
rt, err := NewRoundTripperFromConfig(cfg, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newClient(rt), nil
|
||||
}
|
||||
|
||||
// NewRoundTripperFromConfig returns a new HTTP RoundTripper configured for the
|
||||
// given config.HTTPClientConfig. The name is used as go-conntrack metric label.
|
||||
func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string) (http.RoundTripper, error) {
|
||||
tlsConfig, err := NewTLSConfig(&cfg.TLSConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// The only timeout we care about is the configured scrape timeout.
|
||||
// It is applied on request. So we leave out any timings here.
|
||||
var rt http.RoundTripper = &http.Transport{
|
||||
Proxy: http.ProxyURL(cfg.ProxyURL.URL),
|
||||
MaxIdleConns: 20000,
|
||||
MaxIdleConnsPerHost: 1000, // see https://github.com/golang/go/issues/13801
|
||||
DisableKeepAlives: false,
|
||||
TLSClientConfig: tlsConfig,
|
||||
DisableCompression: true,
|
||||
// 5 minutes is typically above the maximum sane scrape interval. So we can
|
||||
// use keepalive for all configurations.
|
||||
IdleConnTimeout: 5 * time.Minute,
|
||||
DialContext: conntrack.NewDialContextFunc(
|
||||
conntrack.DialWithTracing(),
|
||||
conntrack.DialWithName(name),
|
||||
),
|
||||
}
|
||||
|
||||
// If a bearer token is provided, create a round tripper that will set the
|
||||
// Authorization header correctly on each request.
|
||||
if len(cfg.BearerToken) > 0 {
|
||||
rt = NewBearerAuthRoundTripper(cfg.BearerToken, rt)
|
||||
} else if len(cfg.BearerTokenFile) > 0 {
|
||||
rt = NewBearerAuthFileRoundTripper(cfg.BearerTokenFile, rt)
|
||||
}
|
||||
|
||||
if cfg.BasicAuth != nil {
|
||||
rt = NewBasicAuthRoundTripper(cfg.BasicAuth.Username, cfg.BasicAuth.Password, cfg.BasicAuth.PasswordFile, rt)
|
||||
}
|
||||
|
||||
// Return a new configured RoundTripper.
|
||||
return rt, nil
|
||||
}
|
||||
|
||||
type bearerAuthRoundTripper struct {
|
||||
bearerToken Secret
|
||||
rt http.RoundTripper
|
||||
}
|
||||
|
||||
// NewBearerAuthRoundTripper adds the provided bearer token to a request unless the authorization
|
||||
// header has already been set.
|
||||
func NewBearerAuthRoundTripper(token Secret, rt http.RoundTripper) http.RoundTripper {
|
||||
return &bearerAuthRoundTripper{token, rt}
|
||||
}
|
||||
|
||||
func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if len(req.Header.Get("Authorization")) == 0 {
|
||||
req = cloneRequest(req)
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(rt.bearerToken)))
|
||||
}
|
||||
return rt.rt.RoundTrip(req)
|
||||
}
|
||||
|
||||
type bearerAuthFileRoundTripper struct {
|
||||
bearerFile string
|
||||
rt http.RoundTripper
|
||||
}
|
||||
|
||||
// NewBearerAuthFileRoundTripper adds the bearer token read from the provided file to a request unless
|
||||
// the authorization header has already been set. This file is read for every request.
|
||||
func NewBearerAuthFileRoundTripper(bearerFile string, rt http.RoundTripper) http.RoundTripper {
|
||||
return &bearerAuthFileRoundTripper{bearerFile, rt}
|
||||
}
|
||||
|
||||
func (rt *bearerAuthFileRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if len(req.Header.Get("Authorization")) == 0 {
|
||||
b, err := ioutil.ReadFile(rt.bearerFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read bearer token file %s: %s", rt.bearerFile, err)
|
||||
}
|
||||
bearerToken := strings.TrimSpace(string(b))
|
||||
|
||||
req = cloneRequest(req)
|
||||
req.Header.Set("Authorization", "Bearer "+bearerToken)
|
||||
}
|
||||
|
||||
return rt.rt.RoundTrip(req)
|
||||
}
|
||||
|
||||
type basicAuthRoundTripper struct {
|
||||
username string
|
||||
password Secret
|
||||
passwordFile string
|
||||
rt http.RoundTripper
|
||||
}
|
||||
|
||||
// NewBasicAuthRoundTripper will apply a BASIC auth authorization header to a request unless it has
|
||||
// already been set.
|
||||
func NewBasicAuthRoundTripper(username string, password Secret, passwordFile string, rt http.RoundTripper) http.RoundTripper {
|
||||
return &basicAuthRoundTripper{username, password, passwordFile, rt}
|
||||
}
|
||||
|
||||
func (rt *basicAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if len(req.Header.Get("Authorization")) != 0 {
|
||||
return rt.rt.RoundTrip(req)
|
||||
}
|
||||
req = cloneRequest(req)
|
||||
if rt.passwordFile != "" {
|
||||
bs, err := ioutil.ReadFile(rt.passwordFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read basic auth password file %s: %s", rt.passwordFile, err)
|
||||
}
|
||||
req.SetBasicAuth(rt.username, strings.TrimSpace(string(bs)))
|
||||
} else {
|
||||
req.SetBasicAuth(rt.username, strings.TrimSpace(string(rt.password)))
|
||||
}
|
||||
return rt.rt.RoundTrip(req)
|
||||
}
|
||||
|
||||
// cloneRequest returns a clone of the provided *http.Request.
|
||||
// The clone is a shallow copy of the struct and its Header map.
|
||||
func cloneRequest(r *http.Request) *http.Request {
|
||||
// Shallow copy of the struct.
|
||||
r2 := new(http.Request)
|
||||
*r2 = *r
|
||||
// Deep copy of the Header.
|
||||
r2.Header = make(http.Header)
|
||||
for k, s := range r.Header {
|
||||
r2.Header[k] = s
|
||||
}
|
||||
return r2
|
||||
}
|
||||
|
||||
// NewTLSConfig creates a new tls.Config from the given TLSConfig.
|
||||
func NewTLSConfig(cfg *TLSConfig) (*tls.Config, error) {
|
||||
tlsConfig := &tls.Config{InsecureSkipVerify: cfg.InsecureSkipVerify}
|
||||
|
||||
// If a CA cert is provided then let's read it in so we can validate the
|
||||
// scrape target's certificate properly.
|
||||
if len(cfg.CAFile) > 0 {
|
||||
caCertPool := x509.NewCertPool()
|
||||
// Load CA cert.
|
||||
caCert, err := ioutil.ReadFile(cfg.CAFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to use specified CA cert %s: %s", cfg.CAFile, err)
|
||||
}
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
tlsConfig.RootCAs = caCertPool
|
||||
}
|
||||
|
||||
if len(cfg.ServerName) > 0 {
|
||||
tlsConfig.ServerName = cfg.ServerName
|
||||
}
|
||||
// If a client cert & key is provided then configure TLS config accordingly.
|
||||
if len(cfg.CertFile) > 0 && len(cfg.KeyFile) == 0 {
|
||||
return nil, fmt.Errorf("client cert file %q specified without client key file", cfg.CertFile)
|
||||
} else if len(cfg.KeyFile) > 0 && len(cfg.CertFile) == 0 {
|
||||
return nil, fmt.Errorf("client key file %q specified without client cert file", cfg.KeyFile)
|
||||
} else if len(cfg.CertFile) > 0 && len(cfg.KeyFile) > 0 {
|
||||
cert, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to use specified client cert (%s) & key (%s): %s", cfg.CertFile, cfg.KeyFile, err)
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||
}
|
||||
tlsConfig.BuildNameToCertificate()
|
||||
|
||||
return tlsConfig, nil
|
||||
}
|
||||
|
||||
// TLSConfig configures the options for TLS connections.
|
||||
type TLSConfig struct {
|
||||
// The CA cert to use for the targets.
|
||||
CAFile string `yaml:"ca_file,omitempty"`
|
||||
// The client cert file for the targets.
|
||||
CertFile string `yaml:"cert_file,omitempty"`
|
||||
// The client key file for the targets.
|
||||
KeyFile string `yaml:"key_file,omitempty"`
|
||||
// Used to verify the hostname for the targets.
|
||||
ServerName string `yaml:"server_name,omitempty"`
|
||||
// Disable target certificate validation.
|
||||
InsecureSkipVerify bool `yaml:"insecure_skip_verify"`
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||
func (c *TLSConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
type plain TLSConfig
|
||||
return unmarshal((*plain)(c))
|
||||
}
|
||||
|
||||
func (c HTTPClientConfig) String() string {
|
||||
b, err := yaml.Marshal(c)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("<error creating http client config string: %s>", err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
618
vendor/github.com/prometheus/common/config/http_config_test.go
generated
vendored
Normal file
618
vendor/github.com/prometheus/common/config/http_config_test.go
generated
vendored
Normal file
|
@ -0,0 +1,618 @@
|
|||
// Copyright 2015 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
TLSCAChainPath = "testdata/tls-ca-chain.pem"
|
||||
ServerCertificatePath = "testdata/server.crt"
|
||||
ServerKeyPath = "testdata/server.key"
|
||||
BarneyCertificatePath = "testdata/barney.crt"
|
||||
BarneyKeyNoPassPath = "testdata/barney-no-pass.key"
|
||||
MissingCA = "missing/ca.crt"
|
||||
MissingCert = "missing/cert.crt"
|
||||
MissingKey = "missing/secret.key"
|
||||
|
||||
ExpectedMessage = "I'm here to serve you!!!"
|
||||
BearerToken = "theanswertothegreatquestionoflifetheuniverseandeverythingisfortytwo"
|
||||
BearerTokenFile = "testdata/bearer.token"
|
||||
MissingBearerTokenFile = "missing/bearer.token"
|
||||
ExpectedBearer = "Bearer " + BearerToken
|
||||
ExpectedUsername = "arthurdent"
|
||||
ExpectedPassword = "42"
|
||||
)
|
||||
|
||||
var invalidHTTPClientConfigs = []struct {
|
||||
httpClientConfigFile string
|
||||
errMsg string
|
||||
}{
|
||||
{
|
||||
httpClientConfigFile: "testdata/http.conf.bearer-token-and-file-set.bad.yml",
|
||||
errMsg: "at most one of bearer_token & bearer_token_file must be configured",
|
||||
},
|
||||
{
|
||||
httpClientConfigFile: "testdata/http.conf.empty.bad.yml",
|
||||
errMsg: "at most one of basic_auth, bearer_token & bearer_token_file must be configured",
|
||||
},
|
||||
{
|
||||
httpClientConfigFile: "testdata/http.conf.basic-auth.too-much.bad.yaml",
|
||||
errMsg: "at most one of basic_auth password & password_file must be configured",
|
||||
},
|
||||
}
|
||||
|
||||
func newTestServer(handler func(w http.ResponseWriter, r *http.Request)) (*httptest.Server, error) {
|
||||
testServer := httptest.NewUnstartedServer(http.HandlerFunc(handler))
|
||||
|
||||
tlsCAChain, err := ioutil.ReadFile(TLSCAChainPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Can't read %s", TLSCAChainPath)
|
||||
}
|
||||
serverCertificate, err := tls.LoadX509KeyPair(ServerCertificatePath, ServerKeyPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Can't load X509 key pair %s - %s", ServerCertificatePath, ServerKeyPath)
|
||||
}
|
||||
|
||||
rootCAs := x509.NewCertPool()
|
||||
rootCAs.AppendCertsFromPEM(tlsCAChain)
|
||||
|
||||
testServer.TLS = &tls.Config{
|
||||
Certificates: make([]tls.Certificate, 1),
|
||||
RootCAs: rootCAs,
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
ClientCAs: rootCAs}
|
||||
testServer.TLS.Certificates[0] = serverCertificate
|
||||
testServer.TLS.BuildNameToCertificate()
|
||||
|
||||
testServer.StartTLS()
|
||||
|
||||
return testServer, nil
|
||||
}
|
||||
|
||||
func TestNewClientFromConfig(t *testing.T) {
|
||||
var newClientValidConfig = []struct {
|
||||
clientConfig HTTPClientConfig
|
||||
handler func(w http.ResponseWriter, r *http.Request)
|
||||
}{
|
||||
{
|
||||
clientConfig: HTTPClientConfig{
|
||||
TLSConfig: TLSConfig{
|
||||
CAFile: "",
|
||||
CertFile: BarneyCertificatePath,
|
||||
KeyFile: BarneyKeyNoPassPath,
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: true},
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, ExpectedMessage)
|
||||
},
|
||||
}, {
|
||||
clientConfig: HTTPClientConfig{
|
||||
TLSConfig: TLSConfig{
|
||||
CAFile: TLSCAChainPath,
|
||||
CertFile: BarneyCertificatePath,
|
||||
KeyFile: BarneyKeyNoPassPath,
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: false},
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, ExpectedMessage)
|
||||
},
|
||||
}, {
|
||||
clientConfig: HTTPClientConfig{
|
||||
BearerToken: BearerToken,
|
||||
TLSConfig: TLSConfig{
|
||||
CAFile: TLSCAChainPath,
|
||||
CertFile: BarneyCertificatePath,
|
||||
KeyFile: BarneyKeyNoPassPath,
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: false},
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
bearer := r.Header.Get("Authorization")
|
||||
if bearer != ExpectedBearer {
|
||||
fmt.Fprintf(w, "The expected Bearer Authorization (%s) differs from the obtained Bearer Authorization (%s)",
|
||||
ExpectedBearer, bearer)
|
||||
} else {
|
||||
fmt.Fprint(w, ExpectedMessage)
|
||||
}
|
||||
},
|
||||
}, {
|
||||
clientConfig: HTTPClientConfig{
|
||||
BearerTokenFile: BearerTokenFile,
|
||||
TLSConfig: TLSConfig{
|
||||
CAFile: TLSCAChainPath,
|
||||
CertFile: BarneyCertificatePath,
|
||||
KeyFile: BarneyKeyNoPassPath,
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: false},
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
bearer := r.Header.Get("Authorization")
|
||||
if bearer != ExpectedBearer {
|
||||
fmt.Fprintf(w, "The expected Bearer Authorization (%s) differs from the obtained Bearer Authorization (%s)",
|
||||
ExpectedBearer, bearer)
|
||||
} else {
|
||||
fmt.Fprint(w, ExpectedMessage)
|
||||
}
|
||||
},
|
||||
}, {
|
||||
clientConfig: HTTPClientConfig{
|
||||
BasicAuth: &BasicAuth{
|
||||
Username: ExpectedUsername,
|
||||
Password: ExpectedPassword,
|
||||
},
|
||||
TLSConfig: TLSConfig{
|
||||
CAFile: TLSCAChainPath,
|
||||
CertFile: BarneyCertificatePath,
|
||||
KeyFile: BarneyKeyNoPassPath,
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: false},
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
username, password, ok := r.BasicAuth()
|
||||
if !ok {
|
||||
fmt.Fprintf(w, "The Authorization header wasn't set")
|
||||
} else if ExpectedUsername != username {
|
||||
fmt.Fprintf(w, "The expected username (%s) differs from the obtained username (%s).", ExpectedUsername, username)
|
||||
} else if ExpectedPassword != password {
|
||||
fmt.Fprintf(w, "The expected password (%s) differs from the obtained password (%s).", ExpectedPassword, password)
|
||||
} else {
|
||||
fmt.Fprint(w, ExpectedMessage)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, validConfig := range newClientValidConfig {
|
||||
testServer, err := newTestServer(validConfig.handler)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
defer testServer.Close()
|
||||
|
||||
client, err := NewClientFromConfig(validConfig.clientConfig, "test")
|
||||
if err != nil {
|
||||
t.Errorf("Can't create a client from this config: %+v", validConfig.clientConfig)
|
||||
continue
|
||||
}
|
||||
response, err := client.Get(testServer.URL)
|
||||
if err != nil {
|
||||
t.Errorf("Can't connect to the test server using this config: %+v", validConfig.clientConfig)
|
||||
continue
|
||||
}
|
||||
|
||||
message, err := ioutil.ReadAll(response.Body)
|
||||
response.Body.Close()
|
||||
if err != nil {
|
||||
t.Errorf("Can't read the server response body using this config: %+v", validConfig.clientConfig)
|
||||
continue
|
||||
}
|
||||
|
||||
trimMessage := strings.TrimSpace(string(message))
|
||||
if ExpectedMessage != trimMessage {
|
||||
t.Errorf("The expected message (%s) differs from the obtained message (%s) using this config: %+v",
|
||||
ExpectedMessage, trimMessage, validConfig.clientConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewClientFromInvalidConfig(t *testing.T) {
|
||||
var newClientInvalidConfig = []struct {
|
||||
clientConfig HTTPClientConfig
|
||||
errorMsg string
|
||||
}{
|
||||
{
|
||||
clientConfig: HTTPClientConfig{
|
||||
TLSConfig: TLSConfig{
|
||||
CAFile: MissingCA,
|
||||
CertFile: "",
|
||||
KeyFile: "",
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: true},
|
||||
},
|
||||
errorMsg: fmt.Sprintf("unable to use specified CA cert %s:", MissingCA),
|
||||
},
|
||||
}
|
||||
|
||||
for _, invalidConfig := range newClientInvalidConfig {
|
||||
client, err := NewClientFromConfig(invalidConfig.clientConfig, "test")
|
||||
if client != nil {
|
||||
t.Errorf("A client instance was returned instead of nil using this config: %+v", invalidConfig.clientConfig)
|
||||
}
|
||||
if err == nil {
|
||||
t.Errorf("No error was returned using this config: %+v", invalidConfig.clientConfig)
|
||||
}
|
||||
if !strings.Contains(err.Error(), invalidConfig.errorMsg) {
|
||||
t.Errorf("Expected error %s does not contain %s", err.Error(), invalidConfig.errorMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissingBearerAuthFile(t *testing.T) {
|
||||
cfg := HTTPClientConfig{
|
||||
BearerTokenFile: MissingBearerTokenFile,
|
||||
TLSConfig: TLSConfig{
|
||||
CAFile: TLSCAChainPath,
|
||||
CertFile: BarneyCertificatePath,
|
||||
KeyFile: BarneyKeyNoPassPath,
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: false},
|
||||
}
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
bearer := r.Header.Get("Authorization")
|
||||
if bearer != ExpectedBearer {
|
||||
fmt.Fprintf(w, "The expected Bearer Authorization (%s) differs from the obtained Bearer Authorization (%s)",
|
||||
ExpectedBearer, bearer)
|
||||
} else {
|
||||
fmt.Fprint(w, ExpectedMessage)
|
||||
}
|
||||
}
|
||||
|
||||
testServer, err := newTestServer(handler)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
defer testServer.Close()
|
||||
|
||||
client, err := NewClientFromConfig(cfg, "test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = client.Get(testServer.URL)
|
||||
if err == nil {
|
||||
t.Fatal("No error is returned here")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), "unable to read bearer token file missing/bearer.token: open missing/bearer.token: no such file or directory") {
|
||||
t.Fatal("wrong error message being returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBearerAuthRoundTripper(t *testing.T) {
|
||||
const (
|
||||
newBearerToken = "goodbyeandthankyouforthefish"
|
||||
)
|
||||
|
||||
fakeRoundTripper := NewRoundTripCheckRequest(func(req *http.Request) {
|
||||
bearer := req.Header.Get("Authorization")
|
||||
if bearer != ExpectedBearer {
|
||||
t.Errorf("The expected Bearer Authorization (%s) differs from the obtained Bearer Authorization (%s)",
|
||||
ExpectedBearer, bearer)
|
||||
}
|
||||
}, nil, nil)
|
||||
|
||||
// Normal flow.
|
||||
bearerAuthRoundTripper := NewBearerAuthRoundTripper(BearerToken, fakeRoundTripper)
|
||||
request, _ := http.NewRequest("GET", "/hitchhiker", nil)
|
||||
request.Header.Set("User-Agent", "Douglas Adams mind")
|
||||
bearerAuthRoundTripper.RoundTrip(request)
|
||||
|
||||
// Should honor already Authorization header set.
|
||||
bearerAuthRoundTripperShouldNotModifyExistingAuthorization := NewBearerAuthRoundTripper(newBearerToken, fakeRoundTripper)
|
||||
request, _ = http.NewRequest("GET", "/hitchhiker", nil)
|
||||
request.Header.Set("Authorization", ExpectedBearer)
|
||||
bearerAuthRoundTripperShouldNotModifyExistingAuthorization.RoundTrip(request)
|
||||
}
|
||||
|
||||
func TestBearerAuthFileRoundTripper(t *testing.T) {
|
||||
const (
|
||||
newBearerToken = "goodbyeandthankyouforthefish"
|
||||
)
|
||||
|
||||
fakeRoundTripper := NewRoundTripCheckRequest(func(req *http.Request) {
|
||||
bearer := req.Header.Get("Authorization")
|
||||
if bearer != ExpectedBearer {
|
||||
t.Errorf("The expected Bearer Authorization (%s) differs from the obtained Bearer Authorization (%s)",
|
||||
ExpectedBearer, bearer)
|
||||
}
|
||||
}, nil, nil)
|
||||
|
||||
// Normal flow.
|
||||
bearerAuthRoundTripper := NewBearerAuthFileRoundTripper(BearerTokenFile, fakeRoundTripper)
|
||||
request, _ := http.NewRequest("GET", "/hitchhiker", nil)
|
||||
request.Header.Set("User-Agent", "Douglas Adams mind")
|
||||
bearerAuthRoundTripper.RoundTrip(request)
|
||||
|
||||
// Should honor already Authorization header set.
|
||||
bearerAuthRoundTripperShouldNotModifyExistingAuthorization := NewBearerAuthFileRoundTripper(MissingBearerTokenFile, fakeRoundTripper)
|
||||
request, _ = http.NewRequest("GET", "/hitchhiker", nil)
|
||||
request.Header.Set("Authorization", ExpectedBearer)
|
||||
bearerAuthRoundTripperShouldNotModifyExistingAuthorization.RoundTrip(request)
|
||||
}
|
||||
|
||||
func TestTLSConfig(t *testing.T) {
|
||||
configTLSConfig := TLSConfig{
|
||||
CAFile: TLSCAChainPath,
|
||||
CertFile: BarneyCertificatePath,
|
||||
KeyFile: BarneyKeyNoPassPath,
|
||||
ServerName: "localhost",
|
||||
InsecureSkipVerify: false}
|
||||
|
||||
tlsCAChain, err := ioutil.ReadFile(TLSCAChainPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't read the CA certificate chain (%s)",
|
||||
TLSCAChainPath)
|
||||
}
|
||||
rootCAs := x509.NewCertPool()
|
||||
rootCAs.AppendCertsFromPEM(tlsCAChain)
|
||||
|
||||
barneyCertificate, err := tls.LoadX509KeyPair(BarneyCertificatePath, BarneyKeyNoPassPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't load the client key pair ('%s' and '%s'). Reason: %s",
|
||||
BarneyCertificatePath, BarneyKeyNoPassPath, err)
|
||||
}
|
||||
|
||||
expectedTLSConfig := &tls.Config{
|
||||
RootCAs: rootCAs,
|
||||
Certificates: []tls.Certificate{barneyCertificate},
|
||||
ServerName: configTLSConfig.ServerName,
|
||||
InsecureSkipVerify: configTLSConfig.InsecureSkipVerify}
|
||||
expectedTLSConfig.BuildNameToCertificate()
|
||||
|
||||
tlsConfig, err := NewTLSConfig(&configTLSConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't create a new TLS Config from a configuration (%s).", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tlsConfig, expectedTLSConfig) {
|
||||
t.Fatalf("Unexpected TLS Config result: \n\n%+v\n expected\n\n%+v", tlsConfig, expectedTLSConfig)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSConfigEmpty(t *testing.T) {
|
||||
configTLSConfig := TLSConfig{
|
||||
CAFile: "",
|
||||
CertFile: "",
|
||||
KeyFile: "",
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: true}
|
||||
|
||||
expectedTLSConfig := &tls.Config{
|
||||
InsecureSkipVerify: configTLSConfig.InsecureSkipVerify}
|
||||
expectedTLSConfig.BuildNameToCertificate()
|
||||
|
||||
tlsConfig, err := NewTLSConfig(&configTLSConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't create a new TLS Config from a configuration (%s).", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tlsConfig, expectedTLSConfig) {
|
||||
t.Fatalf("Unexpected TLS Config result: \n\n%+v\n expected\n\n%+v", tlsConfig, expectedTLSConfig)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSConfigInvalidCA(t *testing.T) {
|
||||
var invalidTLSConfig = []struct {
|
||||
configTLSConfig TLSConfig
|
||||
errorMessage string
|
||||
}{
|
||||
{
|
||||
configTLSConfig: TLSConfig{
|
||||
CAFile: MissingCA,
|
||||
CertFile: "",
|
||||
KeyFile: "",
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: false},
|
||||
errorMessage: fmt.Sprintf("unable to use specified CA cert %s:", MissingCA),
|
||||
}, {
|
||||
configTLSConfig: TLSConfig{
|
||||
CAFile: "",
|
||||
CertFile: MissingCert,
|
||||
KeyFile: BarneyKeyNoPassPath,
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: false},
|
||||
errorMessage: fmt.Sprintf("unable to use specified client cert (%s) & key (%s):", MissingCert, BarneyKeyNoPassPath),
|
||||
}, {
|
||||
configTLSConfig: TLSConfig{
|
||||
CAFile: "",
|
||||
CertFile: BarneyCertificatePath,
|
||||
KeyFile: MissingKey,
|
||||
ServerName: "",
|
||||
InsecureSkipVerify: false},
|
||||
errorMessage: fmt.Sprintf("unable to use specified client cert (%s) & key (%s):", BarneyCertificatePath, MissingKey),
|
||||
},
|
||||
}
|
||||
|
||||
for _, anInvalididTLSConfig := range invalidTLSConfig {
|
||||
tlsConfig, err := NewTLSConfig(&anInvalididTLSConfig.configTLSConfig)
|
||||
if tlsConfig != nil && err == nil {
|
||||
t.Errorf("The TLS Config could be created even with this %+v", anInvalididTLSConfig.configTLSConfig)
|
||||
continue
|
||||
}
|
||||
if !strings.Contains(err.Error(), anInvalididTLSConfig.errorMessage) {
|
||||
t.Errorf("The expected error should contain %s, but got %s", anInvalididTLSConfig.errorMessage, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasicAuthNoPassword(t *testing.T) {
|
||||
cfg, _, err := LoadHTTPConfigFile("testdata/http.conf.basic-auth.no-password.yaml")
|
||||
if err != nil {
|
||||
t.Errorf("Error loading HTTP client config: %v", err)
|
||||
}
|
||||
client, err := NewClientFromConfig(*cfg, "test")
|
||||
if err != nil {
|
||||
t.Errorf("Error creating HTTP Client: %v", err)
|
||||
}
|
||||
|
||||
rt, ok := client.Transport.(*basicAuthRoundTripper)
|
||||
if !ok {
|
||||
t.Fatalf("Error casting to basic auth transport, %v", client.Transport)
|
||||
}
|
||||
|
||||
if rt.username != "user" {
|
||||
t.Errorf("Bad HTTP client username: %s", rt.username)
|
||||
}
|
||||
if string(rt.password) != "" {
|
||||
t.Errorf("Expected empty HTTP client password: %s", rt.password)
|
||||
}
|
||||
if string(rt.passwordFile) != "" {
|
||||
t.Errorf("Expected empty HTTP client passwordFile: %s", rt.passwordFile)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasicAuthNoUsername(t *testing.T) {
|
||||
cfg, _, err := LoadHTTPConfigFile("testdata/http.conf.basic-auth.no-username.yaml")
|
||||
if err != nil {
|
||||
t.Errorf("Error loading HTTP client config: %v", err)
|
||||
}
|
||||
client, err := NewClientFromConfig(*cfg, "test")
|
||||
if err != nil {
|
||||
t.Errorf("Error creating HTTP Client: %v", err)
|
||||
}
|
||||
|
||||
rt, ok := client.Transport.(*basicAuthRoundTripper)
|
||||
if !ok {
|
||||
t.Fatalf("Error casting to basic auth transport, %v", client.Transport)
|
||||
}
|
||||
|
||||
if rt.username != "" {
|
||||
t.Errorf("Got unexpected username: %s", rt.username)
|
||||
}
|
||||
if string(rt.password) != "secret" {
|
||||
t.Errorf("Unexpected HTTP client password: %s", string(rt.password))
|
||||
}
|
||||
if string(rt.passwordFile) != "" {
|
||||
t.Errorf("Expected empty HTTP client passwordFile: %s", rt.passwordFile)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasicAuthPasswordFile(t *testing.T) {
|
||||
cfg, _, err := LoadHTTPConfigFile("testdata/http.conf.basic-auth.good.yaml")
|
||||
if err != nil {
|
||||
t.Errorf("Error loading HTTP client config: %v", err)
|
||||
}
|
||||
client, err := NewClientFromConfig(*cfg, "test")
|
||||
if err != nil {
|
||||
t.Errorf("Error creating HTTP Client: %v", err)
|
||||
}
|
||||
|
||||
rt, ok := client.Transport.(*basicAuthRoundTripper)
|
||||
if !ok {
|
||||
t.Errorf("Error casting to basic auth transport, %v", client.Transport)
|
||||
}
|
||||
|
||||
if rt.username != "user" {
|
||||
t.Errorf("Bad HTTP client username: %s", rt.username)
|
||||
}
|
||||
if string(rt.password) != "" {
|
||||
t.Errorf("Bad HTTP client password: %s", rt.password)
|
||||
}
|
||||
if string(rt.passwordFile) != "testdata/basic-auth-password" {
|
||||
t.Errorf("Bad HTTP client passwordFile: %s", rt.passwordFile)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHideHTTPClientConfigSecrets(t *testing.T) {
|
||||
c, _, err := LoadHTTPConfigFile("testdata/http.conf.good.yml")
|
||||
if err != nil {
|
||||
t.Errorf("Error parsing %s: %s", "testdata/http.conf.good.yml", err)
|
||||
}
|
||||
|
||||
// String method must not reveal authentication credentials.
|
||||
s := c.String()
|
||||
if strings.Contains(s, "mysecret") {
|
||||
t.Fatal("http client config's String method reveals authentication credentials.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateHTTPConfig(t *testing.T) {
|
||||
cfg, _, err := LoadHTTPConfigFile("testdata/http.conf.good.yml")
|
||||
if err != nil {
|
||||
t.Errorf("Error loading HTTP client config: %v", err)
|
||||
}
|
||||
err = cfg.Validate()
|
||||
if err != nil {
|
||||
t.Fatalf("Error validating %s: %s", "testdata/http.conf.good.yml", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidHTTPConfigs(t *testing.T) {
|
||||
for _, ee := range invalidHTTPClientConfigs {
|
||||
_, _, err := LoadHTTPConfigFile(ee.httpClientConfigFile)
|
||||
if err == nil {
|
||||
t.Error("Expected error with config but got none")
|
||||
continue
|
||||
}
|
||||
if !strings.Contains(err.Error(), ee.errMsg) {
|
||||
t.Errorf("Expected error for invalid HTTP client configuration to contain %q but got: %s", ee.errMsg, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LoadHTTPConfig parses the YAML input s into a HTTPClientConfig.
|
||||
func LoadHTTPConfig(s string) (*HTTPClientConfig, error) {
|
||||
cfg := &HTTPClientConfig{}
|
||||
err := yaml.UnmarshalStrict([]byte(s), cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// LoadHTTPConfigFile parses the given YAML file into a HTTPClientConfig.
|
||||
func LoadHTTPConfigFile(filename string) (*HTTPClientConfig, []byte, error) {
|
||||
content, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
cfg, err := LoadHTTPConfig(string(content))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return cfg, content, nil
|
||||
}
|
||||
|
||||
type roundTrip struct {
|
||||
theResponse *http.Response
|
||||
theError error
|
||||
}
|
||||
|
||||
func (rt *roundTrip) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
return rt.theResponse, rt.theError
|
||||
}
|
||||
|
||||
type roundTripCheckRequest struct {
|
||||
checkRequest func(*http.Request)
|
||||
roundTrip
|
||||
}
|
||||
|
||||
func (rt *roundTripCheckRequest) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
rt.checkRequest(r)
|
||||
return rt.theResponse, rt.theError
|
||||
}
|
||||
|
||||
// NewRoundTripCheckRequest creates a new instance of a type that implements http.RoundTripper,
|
||||
// which before returning theResponse and theError, executes checkRequest against a http.Request.
|
||||
func NewRoundTripCheckRequest(checkRequest func(*http.Request), theResponse *http.Response, theError error) http.RoundTripper {
|
||||
return &roundTripCheckRequest{
|
||||
checkRequest: checkRequest,
|
||||
roundTrip: roundTrip{
|
||||
theResponse: theResponse,
|
||||
theError: theError}}
|
||||
}
|
27
vendor/github.com/prometheus/common/config/testdata/barney-no-pass.key
generated
vendored
Normal file
27
vendor/github.com/prometheus/common/config/testdata/barney-no-pass.key
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAxmYjfBZhZbAup9uSULehoqPCv/U+77ETxUNyS2nviWEHDAb/
|
||||
pFS8Btx4oCQ1ECVSyxcUmXSlrvDjMY4sisOHvndNRlGi274M5a8Q5yD1BUqvxq3u
|
||||
XB/+SYNVShBzaswrSjpzMe89AlOPxPjnE14OXh00j2hHunOG4jhlWgJnY0YyvUQQ
|
||||
YWO6KrmKMiZ4MgmY0SWh/ZhlkDJPtkp3aUVM2sheCru/70E9viLGfdlhc2pIMshy
|
||||
wNp4/5IkHBZwbqXFFGX4sRtSXI/auZNvcHOBse+3e3BonWvBWS2lIYbzpX3vLB7B
|
||||
E9BGIxWn1fgNQr14yFPaccSszBvgtmEUONolnwIDAQABAoIBAQC7nBhQHgXKGBl2
|
||||
Z97rb0pstrjRtsLl/Cg68LWi9LEr0tHMIM4bgnkvb8qtfK+k7fZl0BSNrE2EqYvd
|
||||
75jVO2MgzEYJieccLpKZm7u7JGIut9qSYSU2fpaCw6uiVv4dbqY9EhqejKG/km8w
|
||||
j0JMATRK8Qkj1zOE7/wL7dKBlCZaK3u+OT17spuA/21PG/cLiPaSGSA3CU/eqbkU
|
||||
BD6JeBxp33XNTytwWoOvarsigpL0dGqQ7+qhGq6t69qFfWoe9rimV7Ya+tB9zF/U
|
||||
HzOIEspOYvzxe+C7VJjlVFr4haMYmsrO9qRUJ2ofp49OLVdfEANsdVISSvS63BEp
|
||||
gBZN8Ko5AoGBAO1z8y8YCsI+2vBG6nxZ1eMba0KHi3bS8db1TaenJBV22w6WQATh
|
||||
hEaU6VLMFcMvrOUjXN/7HJfnEMyvFT6gb9obPDVEMZw88s9lVN6njgGLZR/jodyN
|
||||
7N7utLopN043Ra0WfEILAXPSz8esT1yn05OZV6AFHxJEWMrX3/4+spCLAoGBANXl
|
||||
RomieVY4u3FF/uzhbzKNNb9ETxrQuexfbangKp5eLniwnr2SQWIbyPzeurwp15J8
|
||||
HvxB2vpNvs1khSwNx9dQfMdiUVPGLWj7MimAHTHsnQ9LVV9W28ghuSWbjQDGTUt1
|
||||
WCCu1MkKIOzupbi+zgsNlI33yilRQKAb9SRxdy29AoGBAOKpvyZiPcrkMxwPpb/k
|
||||
BU7QGpgcSR25CQ+Xg3QZEVHH7h1DgYLnPtwdQ4g8tj1mohTsp7hKvSWndRrdulrY
|
||||
zUyWmOeD3BN2/pTI9rW/nceNp49EPHsLo2O+2xelRlzMWB98ikqEtPM59gt1SSB6
|
||||
N3X6d3GR0fIe+d9PKEtK0Cs3AoGAZ9r8ReXSvm+ra5ON9Nx8znHMEAON2TpRnBi1
|
||||
uY7zgpO+QrGXUfqKrqVJEKbgym4SkribnuYm+fP32eid1McYKk6VV4ZAcMm/0MJv
|
||||
F8Fx64S0ufFdEX6uFl1xdXYyn5apfyMJ2EyrWrYFSKWTZ8GVb753S/tteGRQWa1Z
|
||||
eQly0Y0CgYEAnI6G9KFvXI+MLu5y2LPYAwsesDFzaWwyDl96ioQTA9hNSrjR33Vw
|
||||
xwpiEe0T/WKF8NQ0QWnrQDbTvuCvZUK37TVxscYWuItL6vnBrYqr4Ck0j1BcGwV5
|
||||
jT581A/Vw8JJiR/vfcxgmrFYqoUmkMKDmCN1oImfz09GtQ4jQ1rlxz8=
|
||||
-----END RSA PRIVATE KEY-----
|
96
vendor/github.com/prometheus/common/config/testdata/barney.crt
generated
vendored
Normal file
96
vendor/github.com/prometheus/common/config/testdata/barney.crt
generated
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 2 (0x2)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green TLS CA
|
||||
Validity
|
||||
Not Before: Jul 13 04:02:47 2017 GMT
|
||||
Not After : Jul 13 04:02:47 2019 GMT
|
||||
Subject: C=NO, O=Telenor AS, OU=Support, CN=Barney Rubble
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:c6:66:23:7c:16:61:65:b0:2e:a7:db:92:50:b7:
|
||||
a1:a2:a3:c2:bf:f5:3e:ef:b1:13:c5:43:72:4b:69:
|
||||
ef:89:61:07:0c:06:ff:a4:54:bc:06:dc:78:a0:24:
|
||||
35:10:25:52:cb:17:14:99:74:a5:ae:f0:e3:31:8e:
|
||||
2c:8a:c3:87:be:77:4d:46:51:a2:db:be:0c:e5:af:
|
||||
10:e7:20:f5:05:4a:af:c6:ad:ee:5c:1f:fe:49:83:
|
||||
55:4a:10:73:6a:cc:2b:4a:3a:73:31:ef:3d:02:53:
|
||||
8f:c4:f8:e7:13:5e:0e:5e:1d:34:8f:68:47:ba:73:
|
||||
86:e2:38:65:5a:02:67:63:46:32:bd:44:10:61:63:
|
||||
ba:2a:b9:8a:32:26:78:32:09:98:d1:25:a1:fd:98:
|
||||
65:90:32:4f:b6:4a:77:69:45:4c:da:c8:5e:0a:bb:
|
||||
bf:ef:41:3d:be:22:c6:7d:d9:61:73:6a:48:32:c8:
|
||||
72:c0:da:78:ff:92:24:1c:16:70:6e:a5:c5:14:65:
|
||||
f8:b1:1b:52:5c:8f:da:b9:93:6f:70:73:81:b1:ef:
|
||||
b7:7b:70:68:9d:6b:c1:59:2d:a5:21:86:f3:a5:7d:
|
||||
ef:2c:1e:c1:13:d0:46:23:15:a7:d5:f8:0d:42:bd:
|
||||
78:c8:53:da:71:c4:ac:cc:1b:e0:b6:61:14:38:da:
|
||||
25:9f
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Key Usage: critical
|
||||
Digital Signature
|
||||
X509v3 Basic Constraints:
|
||||
CA:FALSE
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Client Authentication
|
||||
X509v3 Subject Key Identifier:
|
||||
F4:17:02:DD:1B:01:AB:C5:BC:17:A4:5C:4B:75:8E:EC:B1:E0:C8:F1
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:AE:42:88:75:DD:05:A6:8E:48:7F:50:69:F9:B7:34:23:49:B8:B4:71
|
||||
|
||||
Authority Information Access:
|
||||
CA Issuers - URI:http://green.no/ca/tls-ca.cer
|
||||
|
||||
X509v3 CRL Distribution Points:
|
||||
|
||||
Full Name:
|
||||
URI:http://green.no/ca/tls-ca.crl
|
||||
|
||||
X509v3 Subject Alternative Name:
|
||||
email:barney@telenor.no
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
96:9a:c5:41:8a:2f:4a:c4:80:d9:2b:1a:cf:07:85:e9:b6:18:
|
||||
01:20:41:b9:c3:d4:ca:d3:2d:66:c3:1d:52:7f:25:d7:92:0c:
|
||||
e9:a9:ae:e6:2e:fa:9d:0a:cf:84:b9:03:f2:63:e3:d3:c9:70:
|
||||
6a:ac:04:5e:a9:2d:a2:43:7a:34:60:f7:a9:32:e1:48:ec:c6:
|
||||
03:ac:b3:06:2e:48:6e:d0:35:11:31:3d:0c:04:66:41:e6:b2:
|
||||
ec:8c:68:f8:e4:bc:47:85:39:60:69:a9:8a:ee:2f:56:88:8a:
|
||||
19:45:d0:84:8e:c2:27:2c:82:9c:07:6c:34:ae:41:61:63:f9:
|
||||
32:cb:8b:33:ea:2c:15:5f:f9:35:b0:3c:51:4d:5f:30:de:0b:
|
||||
88:28:94:79:f3:bd:69:37:ad:12:20:e1:6b:1d:b6:77:d9:83:
|
||||
db:81:a4:53:6c:0f:6a:17:5e:2b:c1:94:c6:42:e3:73:cd:9e:
|
||||
79:1b:8c:89:cd:da:ce:b0:f4:21:c5:32:25:04:6e:68:9f:a7:
|
||||
ca:f4:c5:86:e5:4e:d9:fd:69:73:e6:15:50:6e:76:0f:73:5e:
|
||||
7a:a3:f4:dc:15:4a:ab:bb:3c:9a:fa:9f:01:7a:5c:47:a9:a3:
|
||||
68:1c:49:e0:37:37:77:af:87:07:16:e4:e1:d7:98:39:15:a6:
|
||||
51:5d:4c:db
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEITCCAwmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBdMQswCQYDVQQGEwJOTzER
|
||||
MA8GA1UECgwIR3JlZW4gQVMxJDAiBgNVBAsMG0dyZWVuIENlcnRpZmljYXRlIEF1
|
||||
dGhvcml0eTEVMBMGA1UEAwwMR3JlZW4gVExTIENBMB4XDTE3MDcxMzA0MDI0N1oX
|
||||
DTE5MDcxMzA0MDI0N1owTDELMAkGA1UEBhMCTk8xEzARBgNVBAoMClRlbGVub3Ig
|
||||
QVMxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDUJhcm5leSBSdWJibGUwggEi
|
||||
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGZiN8FmFlsC6n25JQt6Gio8K/
|
||||
9T7vsRPFQ3JLae+JYQcMBv+kVLwG3HigJDUQJVLLFxSZdKWu8OMxjiyKw4e+d01G
|
||||
UaLbvgzlrxDnIPUFSq/Gre5cH/5Jg1VKEHNqzCtKOnMx7z0CU4/E+OcTXg5eHTSP
|
||||
aEe6c4biOGVaAmdjRjK9RBBhY7oquYoyJngyCZjRJaH9mGWQMk+2SndpRUzayF4K
|
||||
u7/vQT2+IsZ92WFzakgyyHLA2nj/kiQcFnBupcUUZfixG1Jcj9q5k29wc4Gx77d7
|
||||
cGida8FZLaUhhvOlfe8sHsET0EYjFafV+A1CvXjIU9pxxKzMG+C2YRQ42iWfAgMB
|
||||
AAGjgfwwgfkwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQCMAAwEwYDVR0lBAwwCgYI
|
||||
KwYBBQUHAwIwHQYDVR0OBBYEFPQXAt0bAavFvBekXEt1juyx4MjxMB8GA1UdIwQY
|
||||
MBaAFK5CiHXdBaaOSH9Qafm3NCNJuLRxMDkGCCsGAQUFBwEBBC0wKzApBggrBgEF
|
||||
BQcwAoYdaHR0cDovL2dyZWVuLm5vL2NhL3Rscy1jYS5jZXIwLgYDVR0fBCcwJTAj
|
||||
oCGgH4YdaHR0cDovL2dyZWVuLm5vL2NhL3Rscy1jYS5jcmwwHAYDVR0RBBUwE4ER
|
||||
YmFybmV5QHRlbGVub3Iubm8wDQYJKoZIhvcNAQEFBQADggEBAJaaxUGKL0rEgNkr
|
||||
Gs8Hhem2GAEgQbnD1MrTLWbDHVJ/JdeSDOmpruYu+p0Kz4S5A/Jj49PJcGqsBF6p
|
||||
LaJDejRg96ky4UjsxgOsswYuSG7QNRExPQwEZkHmsuyMaPjkvEeFOWBpqYruL1aI
|
||||
ihlF0ISOwicsgpwHbDSuQWFj+TLLizPqLBVf+TWwPFFNXzDeC4golHnzvWk3rRIg
|
||||
4WsdtnfZg9uBpFNsD2oXXivBlMZC43PNnnkbjInN2s6w9CHFMiUEbmifp8r0xYbl
|
||||
Ttn9aXPmFVBudg9zXnqj9NwVSqu7PJr6nwF6XEepo2gcSeA3N3evhwcW5OHXmDkV
|
||||
plFdTNs=
|
||||
-----END CERTIFICATE-----
|
1
vendor/github.com/prometheus/common/config/testdata/basic-auth-password
generated
vendored
Normal file
1
vendor/github.com/prometheus/common/config/testdata/basic-auth-password
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
foobar
|
1
vendor/github.com/prometheus/common/config/testdata/bearer.token
generated
vendored
Normal file
1
vendor/github.com/prometheus/common/config/testdata/bearer.token
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
theanswertothegreatquestionoflifetheuniverseandeverythingisfortytwo
|
3
vendor/github.com/prometheus/common/config/testdata/http.conf.basic-auth.good.yaml
generated
vendored
Normal file
3
vendor/github.com/prometheus/common/config/testdata/http.conf.basic-auth.good.yaml
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
basic_auth:
|
||||
username: user
|
||||
password_file: testdata/basic-auth-password
|
2
vendor/github.com/prometheus/common/config/testdata/http.conf.basic-auth.no-password.yaml
generated
vendored
Normal file
2
vendor/github.com/prometheus/common/config/testdata/http.conf.basic-auth.no-password.yaml
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
basic_auth:
|
||||
username: user
|
2
vendor/github.com/prometheus/common/config/testdata/http.conf.basic-auth.no-username.yaml
generated
vendored
Normal file
2
vendor/github.com/prometheus/common/config/testdata/http.conf.basic-auth.no-username.yaml
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
basic_auth:
|
||||
password: secret
|
4
vendor/github.com/prometheus/common/config/testdata/http.conf.basic-auth.too-much.bad.yaml
generated
vendored
Normal file
4
vendor/github.com/prometheus/common/config/testdata/http.conf.basic-auth.too-much.bad.yaml
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
basic_auth:
|
||||
username: user
|
||||
password: foo
|
||||
password_file: testdata/basic-auth-password
|
5
vendor/github.com/prometheus/common/config/testdata/http.conf.bearer-token-and-file-set.bad.yml
generated
vendored
Normal file
5
vendor/github.com/prometheus/common/config/testdata/http.conf.bearer-token-and-file-set.bad.yml
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
basic_auth:
|
||||
username: username
|
||||
password: "mysecret"
|
||||
bearer_token: mysecret
|
||||
bearer_token_file: file
|
4
vendor/github.com/prometheus/common/config/testdata/http.conf.empty.bad.yml
generated
vendored
Normal file
4
vendor/github.com/prometheus/common/config/testdata/http.conf.empty.bad.yml
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
basic_auth:
|
||||
username: username
|
||||
password: mysecret
|
||||
bearer_token_file: file
|
4
vendor/github.com/prometheus/common/config/testdata/http.conf.good.yml
generated
vendored
Normal file
4
vendor/github.com/prometheus/common/config/testdata/http.conf.good.yml
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
basic_auth:
|
||||
username: username
|
||||
password: "mysecret"
|
||||
proxy_url: "http://remote.host"
|
1
vendor/github.com/prometheus/common/config/testdata/http.conf.invalid-bearer-token-file.bad.yml
generated
vendored
Normal file
1
vendor/github.com/prometheus/common/config/testdata/http.conf.invalid-bearer-token-file.bad.yml
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
bearer_token_file: file
|
96
vendor/github.com/prometheus/common/config/testdata/server.crt
generated
vendored
Normal file
96
vendor/github.com/prometheus/common/config/testdata/server.crt
generated
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 4 (0x4)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green TLS CA
|
||||
Validity
|
||||
Not Before: Jul 26 12:47:08 2017 GMT
|
||||
Not After : Jul 26 12:47:08 2019 GMT
|
||||
Subject: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green TLS CA
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:97:43:c5:f6:24:b8:ce:30:12:70:ea:17:9c:c0:
|
||||
ce:f2:ef:58:8b:12:7d:46:5e:01:f1:1a:93:b2:3e:
|
||||
d8:cf:99:bc:10:32:f1:12:b0:ef:00:6c:d6:c4:45:
|
||||
85:a8:33:7b:cd:ec:8f:4a:92:d0:5a:4a:41:69:7f:
|
||||
e3:dd:7e:71:d2:21:9c:df:43:b5:6c:60:bb:2a:12:
|
||||
a8:08:cf:c5:ee:08:7d:48:ea:4b:54:e4:82:d9:88:
|
||||
b0:b8:5e:02:12:cb:0e:09:99:b7:5f:42:b6:d7:26:
|
||||
34:0f:4a:e7:fc:ac:9c:59:cd:a1:50:4c:88:5f:f1:
|
||||
d2:7e:5b:21:41:f0:37:50:80:48:71:50:26:61:26:
|
||||
79:64:4b:7e:91:8d:0e:f4:27:fe:19:80:bf:39:55:
|
||||
b7:f3:d0:cd:61:6c:d8:c1:c7:d3:26:77:92:1a:14:
|
||||
42:56:cb:bc:fd:1a:4a:eb:17:d8:8d:af:d1:c0:46:
|
||||
9f:f0:40:5e:0e:34:2f:e7:db:be:66:fd:89:0b:6b:
|
||||
8c:71:c1:0b:0a:c5:c4:c4:eb:7f:44:c1:75:36:23:
|
||||
fd:ed:b6:ee:87:d9:88:47:e1:4b:7c:60:53:e7:85:
|
||||
1c:2f:82:4b:2b:5e:63:1a:49:17:36:2c:fc:39:23:
|
||||
49:22:4d:43:b5:51:22:12:24:9e:31:44:d8:16:4e:
|
||||
a8:eb
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Key Usage: critical
|
||||
Digital Signature, Key Encipherment
|
||||
X509v3 Basic Constraints:
|
||||
CA:FALSE
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication, TLS Web Client Authentication
|
||||
X509v3 Subject Key Identifier:
|
||||
70:A9:FB:44:66:3C:63:96:E6:05:B2:74:47:C8:18:7E:43:6D:EE:8B
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:AE:42:88:75:DD:05:A6:8E:48:7F:50:69:F9:B7:34:23:49:B8:B4:71
|
||||
|
||||
Authority Information Access:
|
||||
CA Issuers - URI:http://green.no/ca/tls-ca.cer
|
||||
|
||||
X509v3 CRL Distribution Points:
|
||||
|
||||
Full Name:
|
||||
URI:http://green.no/ca/tls-ca.crl
|
||||
|
||||
X509v3 Subject Alternative Name:
|
||||
IP Address:127.0.0.1, IP Address:127.0.0.0, DNS:localhost
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
56:1e:b8:52:ba:f5:72:42:ad:15:71:c1:5e:00:63:c9:4d:56:
|
||||
f2:8d:a3:a9:91:db:d0:b5:1b:88:80:93:80:28:48:b2:d0:a9:
|
||||
d0:ea:de:40:78:cc:57:8c:00:b8:65:99:68:95:98:9b:fb:a2:
|
||||
43:21:ea:00:37:01:77:c7:3b:1a:ec:58:2d:25:9c:ad:23:41:
|
||||
5e:ae:fd:ac:2f:26:81:b8:a7:49:9b:5a:10:fe:ad:c3:86:ab:
|
||||
59:67:b0:c7:81:72:95:60:b5:cb:fc:9f:ad:27:16:50:85:76:
|
||||
33:16:20:2c:1f:c6:14:09:0c:48:9f:c0:19:16:c9:fa:b0:d8:
|
||||
bf:b7:8d:a7:aa:eb:fe:f8:6f:dd:2b:83:ee:c7:8a:df:c8:59:
|
||||
e6:2e:13:1f:57:cc:6f:31:db:f7:b7:5c:3f:78:ad:22:2c:48:
|
||||
bb:6d:c4:ab:dc:c1:76:34:29:d9:1e:67:e0:ac:37:2b:90:f9:
|
||||
71:bd:cf:a1:01:b9:eb:0b:0b:79:2e:8b:52:3d:8e:13:97:c8:
|
||||
05:a3:ef:68:82:49:12:2a:25:1a:48:49:b8:7c:3c:66:0d:74:
|
||||
f9:00:8c:5b:57:d7:76:b1:26:95:86:b2:2e:a3:b2:9c:e0:eb:
|
||||
2d:fc:77:03:8f:cd:56:46:3a:c9:6a:fa:72:e3:19:d8:ef:de:
|
||||
4b:36:95:79
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEQjCCAyqgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBdMQswCQYDVQQGEwJOTzER
|
||||
MA8GA1UECgwIR3JlZW4gQVMxJDAiBgNVBAsMG0dyZWVuIENlcnRpZmljYXRlIEF1
|
||||
dGhvcml0eTEVMBMGA1UEAwwMR3JlZW4gVExTIENBMB4XDTE3MDcyNjEyNDcwOFoX
|
||||
DTE5MDcyNjEyNDcwOFowXTELMAkGA1UEBhMCTk8xETAPBgNVBAoMCEdyZWVuIEFT
|
||||
MSQwIgYDVQQLDBtHcmVlbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFTATBgNVBAMM
|
||||
DEdyZWVuIFRMUyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJdD
|
||||
xfYkuM4wEnDqF5zAzvLvWIsSfUZeAfEak7I+2M+ZvBAy8RKw7wBs1sRFhagze83s
|
||||
j0qS0FpKQWl/491+cdIhnN9DtWxguyoSqAjPxe4IfUjqS1TkgtmIsLheAhLLDgmZ
|
||||
t19CttcmNA9K5/ysnFnNoVBMiF/x0n5bIUHwN1CASHFQJmEmeWRLfpGNDvQn/hmA
|
||||
vzlVt/PQzWFs2MHH0yZ3khoUQlbLvP0aSusX2I2v0cBGn/BAXg40L+fbvmb9iQtr
|
||||
jHHBCwrFxMTrf0TBdTYj/e227ofZiEfhS3xgU+eFHC+CSyteYxpJFzYs/DkjSSJN
|
||||
Q7VRIhIknjFE2BZOqOsCAwEAAaOCAQswggEHMA4GA1UdDwEB/wQEAwIFoDAJBgNV
|
||||
HRMEAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQU
|
||||
cKn7RGY8Y5bmBbJ0R8gYfkNt7oswHwYDVR0jBBgwFoAUrkKIdd0Fpo5If1Bp+bc0
|
||||
I0m4tHEwOQYIKwYBBQUHAQEELTArMCkGCCsGAQUFBzAChh1odHRwOi8vZ3JlZW4u
|
||||
bm8vY2EvdGxzLWNhLmNlcjAuBgNVHR8EJzAlMCOgIaAfhh1odHRwOi8vZ3JlZW4u
|
||||
bm8vY2EvdGxzLWNhLmNybDAgBgNVHREEGTAXhwR/AAABhwR/AAAAgglsb2NhbGhv
|
||||
c3QwDQYJKoZIhvcNAQEFBQADggEBAFYeuFK69XJCrRVxwV4AY8lNVvKNo6mR29C1
|
||||
G4iAk4AoSLLQqdDq3kB4zFeMALhlmWiVmJv7okMh6gA3AXfHOxrsWC0lnK0jQV6u
|
||||
/awvJoG4p0mbWhD+rcOGq1lnsMeBcpVgtcv8n60nFlCFdjMWICwfxhQJDEifwBkW
|
||||
yfqw2L+3jaeq6/74b90rg+7Hit/IWeYuEx9XzG8x2/e3XD94rSIsSLttxKvcwXY0
|
||||
KdkeZ+CsNyuQ+XG9z6EBuesLC3kui1I9jhOXyAWj72iCSRIqJRpISbh8PGYNdPkA
|
||||
jFtX13axJpWGsi6jspzg6y38dwOPzVZGOslq+nLjGdjv3ks2lXk=
|
||||
-----END CERTIFICATE-----
|
28
vendor/github.com/prometheus/common/config/testdata/server.key
generated
vendored
Normal file
28
vendor/github.com/prometheus/common/config/testdata/server.key
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXQ8X2JLjOMBJw
|
||||
6hecwM7y71iLEn1GXgHxGpOyPtjPmbwQMvESsO8AbNbERYWoM3vN7I9KktBaSkFp
|
||||
f+PdfnHSIZzfQ7VsYLsqEqgIz8XuCH1I6ktU5ILZiLC4XgISyw4JmbdfQrbXJjQP
|
||||
Suf8rJxZzaFQTIhf8dJ+WyFB8DdQgEhxUCZhJnlkS36RjQ70J/4ZgL85Vbfz0M1h
|
||||
bNjBx9Mmd5IaFEJWy7z9GkrrF9iNr9HARp/wQF4ONC/n275m/YkLa4xxwQsKxcTE
|
||||
639EwXU2I/3ttu6H2YhH4Ut8YFPnhRwvgksrXmMaSRc2LPw5I0kiTUO1USISJJ4x
|
||||
RNgWTqjrAgMBAAECggEAVurwo4FyV7gzwIIi00XPJLT3ceJL7dUy1HHrEG8gchnq
|
||||
gHxlHdJhYyMnPVydcosyxp75r2YxJtCoSZDdRHbVvGLoGzpy0zW6FnDl8TpCh4aF
|
||||
RxKp+rvbnFf5A9ew5U+cX1PelHRnT7V6EJeAOiaNKOUJnnR7oHX59/UxZQw9HJnX
|
||||
3H4xUdRDmSS3BGKXEswbd7beQjqJtEIkbConfaw32yEod0w2MC0LI4miZ87/6Hsk
|
||||
pyvfpeYxXp4z3BTvFBbf/GEBFuozu63VWHayB9PDmEN/TlphoQpJQihdR2r1lz/H
|
||||
I5QwVlFTDvUSFitNLu+FoaHOfgLprQndbojBXb+tcQKBgQDHCPyM4V7k97RvJgmB
|
||||
ELgZiDYufDrjRLXvFzrrZ7ySU3N+nx3Gz/EhtgbHicDjnRVagHBIwi/QAfBJksCd
|
||||
xcioY5k2OW+8PSTsfFZTAA6XwJp/LGfJik/JjvAVv5CnxBu9lYG4WiSBJFp59ojC
|
||||
zTmfEuB4GPwrjQvzjlqaSpij9QKBgQDCjriwAB2UJIdlgK+DkryLqgim5I4cteB3
|
||||
+juVKz+S8ufFmVvmIXkyDcpyy/26VLC6esy8dV0JoWc4EeitoJvQD1JVZ5+CBTY+
|
||||
r9umx18oe2A/ZgcEf/A3Zd94jM1MwriF6YC+eIOhwhpi7T1xTLf3hc9B0OJ5B1mA
|
||||
vob9rGDtXwKBgD4rkW+UCictNIAvenKFPWxEPuBgT6ij0sx/DhlwCtgOFxprK0rp
|
||||
syFbkVyMq+KtM3lUez5O4c5wfJUOsPnXSOlISxhD8qHy23C/GdvNPcGrGNc2kKjE
|
||||
ek20R0wTzWSJ/jxG0gE6rwJjz5sfJfLrVd9ZbyI0c7hK03vdcHGXcXxtAoGAeGHl
|
||||
BwnbQ3niyTx53VijD2wTVGjhQgSLstEDowYSnTNtk8eTpG6b1gvQc32jLnMOsyQe
|
||||
oJGiEr5q5re2GBDjuDZyxGOMv9/Hs7wOlkCQsbS9Vh0kRHWBRlXjk2zT7yYhFMLp
|
||||
pXFeSW2X9BRFS2CkCCUkm93K9AZHLDE3x6ishNMCgYEAsDsUCzGhI49Aqe+CMP2l
|
||||
WPZl7SEMYS5AtdC5sLtbLYBl8+rMXVGL2opKXqVFYBYkqMJiHGdX3Ub6XSVKLYkN
|
||||
vm4PWmlQS24ZT+jlUl4jk6JU6SAlM/o6ixZl5KNR7yQm6zN2O/RHDeYm0urUQ9tF
|
||||
9dux7LbIFeOoJmoDTWG2+fI=
|
||||
-----END PRIVATE KEY-----
|
172
vendor/github.com/prometheus/common/config/testdata/tls-ca-chain.pem
generated
vendored
Normal file
172
vendor/github.com/prometheus/common/config/testdata/tls-ca-chain.pem
generated
vendored
Normal file
|
@ -0,0 +1,172 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 2 (0x2)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green Root CA
|
||||
Validity
|
||||
Not Before: Jul 13 03:47:20 2017 GMT
|
||||
Not After : Jul 13 03:47:20 2027 GMT
|
||||
Subject: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green TLS CA
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:b5:5a:b3:7a:7f:6a:5b:e9:ee:62:ee:4f:61:42:
|
||||
79:93:06:bf:81:fc:9a:1f:b5:80:83:7c:b3:a6:94:
|
||||
54:58:8a:b1:74:cb:c3:b8:3c:23:a8:69:1f:ca:2b:
|
||||
af:be:97:ba:31:73:b5:b8:ce:d9:bf:bf:9a:7a:cf:
|
||||
3a:64:51:83:c9:36:d2:f7:3b:3a:0e:4c:c7:66:2e:
|
||||
bf:1a:df:ce:10:aa:3d:0f:19:74:03:7e:b5:10:bb:
|
||||
e8:37:bd:62:f0:42:2d:df:3d:ca:70:50:10:17:ce:
|
||||
a9:ec:55:8e:87:6f:ce:9a:04:36:14:96:cb:d1:a5:
|
||||
48:d5:d2:87:02:62:93:4e:21:4a:ff:be:44:f1:d2:
|
||||
7e:ed:74:da:c2:51:26:8e:03:a0:c2:bd:bd:5f:b0:
|
||||
50:11:78:fd:ab:1d:04:86:6c:c1:8d:20:bd:05:5f:
|
||||
51:67:c6:d3:07:95:92:2d:92:90:00:c6:9f:2d:dd:
|
||||
36:5c:dc:78:10:7c:f6:68:39:1d:2c:e0:e1:26:64:
|
||||
4f:36:34:66:a7:84:6a:90:15:3a:94:b7:79:b1:47:
|
||||
f5:d2:51:95:54:bf:92:76:9a:b9:88:ee:63:f9:6c:
|
||||
0d:38:c6:b6:1c:06:43:ed:24:1d:bb:6c:72:48:cc:
|
||||
8c:f4:35:bc:43:fe:a6:96:4c:31:5f:82:0d:0d:20:
|
||||
2a:3d
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Key Usage: critical
|
||||
Certificate Sign, CRL Sign
|
||||
X509v3 Basic Constraints: critical
|
||||
CA:TRUE, pathlen:0
|
||||
X509v3 Subject Key Identifier:
|
||||
AE:42:88:75:DD:05:A6:8E:48:7F:50:69:F9:B7:34:23:49:B8:B4:71
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:60:93:53:2F:C7:CF:2A:D7:F3:09:28:F6:3C:AE:9C:50:EC:93:63:E5
|
||||
|
||||
Authority Information Access:
|
||||
CA Issuers - URI:http://green.no/ca/root-ca.cer
|
||||
|
||||
X509v3 CRL Distribution Points:
|
||||
|
||||
Full Name:
|
||||
URI:http://green.no/ca/root-ca.crl
|
||||
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
15:a7:ac:d7:25:9e:2a:d4:d1:14:b4:99:38:3d:2f:73:61:2a:
|
||||
d9:b6:8b:13:ea:fe:db:78:d9:0a:6c:df:26:6e:c1:d5:4a:97:
|
||||
42:19:dd:97:05:03:e4:2b:fc:1e:1f:38:3c:4e:b0:3b:8c:38:
|
||||
ad:2b:65:fa:35:2d:81:8e:e0:f6:0a:89:4c:38:97:01:4b:9c:
|
||||
ac:4e:e1:55:17:ef:0a:ad:a7:eb:1e:4b:86:23:12:f1:52:69:
|
||||
cb:a3:8a:ce:fb:14:8b:86:d7:bb:81:5e:bd:2a:c7:a7:79:58:
|
||||
00:10:c0:db:ff:d4:a5:b9:19:74:b3:23:19:4a:1f:78:4b:a8:
|
||||
b6:f6:20:26:c1:69:f9:89:7f:b8:1c:3b:a2:f9:37:31:80:2c:
|
||||
b0:b6:2b:d2:84:44:d7:42:e4:e6:44:51:04:35:d9:1c:a4:48:
|
||||
c6:b7:35:de:f2:ae:da:4b:ba:c8:09:42:8d:ed:7a:81:dc:ed:
|
||||
9d:f0:de:6e:21:b9:01:1c:ad:64:3d:25:4c:91:94:f1:13:18:
|
||||
bb:89:e9:48:ac:05:73:07:c8:db:bd:69:8e:6f:02:9d:b0:18:
|
||||
c0:b9:e1:a8:b1:17:50:3d:ac:05:6e:6f:63:4f:b1:73:33:60:
|
||||
9a:77:d2:81:8a:01:38:43:e9:4c:3c:90:63:a4:99:4b:d2:1b:
|
||||
f9:1b:ec:ee
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIECzCCAvOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJOTzER
|
||||
MA8GA1UECgwIR3JlZW4gQVMxJDAiBgNVBAsMG0dyZWVuIENlcnRpZmljYXRlIEF1
|
||||
dGhvcml0eTEWMBQGA1UEAwwNR3JlZW4gUm9vdCBDQTAeFw0xNzA3MTMwMzQ3MjBa
|
||||
Fw0yNzA3MTMwMzQ3MjBaMF0xCzAJBgNVBAYTAk5PMREwDwYDVQQKDAhHcmVlbiBB
|
||||
UzEkMCIGA1UECwwbR3JlZW4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRUwEwYDVQQD
|
||||
DAxHcmVlbiBUTFMgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1
|
||||
WrN6f2pb6e5i7k9hQnmTBr+B/JoftYCDfLOmlFRYirF0y8O4PCOoaR/KK6++l7ox
|
||||
c7W4ztm/v5p6zzpkUYPJNtL3OzoOTMdmLr8a384Qqj0PGXQDfrUQu+g3vWLwQi3f
|
||||
PcpwUBAXzqnsVY6Hb86aBDYUlsvRpUjV0ocCYpNOIUr/vkTx0n7tdNrCUSaOA6DC
|
||||
vb1fsFAReP2rHQSGbMGNIL0FX1FnxtMHlZItkpAAxp8t3TZc3HgQfPZoOR0s4OEm
|
||||
ZE82NGanhGqQFTqUt3mxR/XSUZVUv5J2mrmI7mP5bA04xrYcBkPtJB27bHJIzIz0
|
||||
NbxD/qaWTDFfgg0NICo9AgMBAAGjgdQwgdEwDgYDVR0PAQH/BAQDAgEGMBIGA1Ud
|
||||
EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFK5CiHXdBaaOSH9Qafm3NCNJuLRxMB8G
|
||||
A1UdIwQYMBaAFGCTUy/HzyrX8wko9jyunFDsk2PlMDoGCCsGAQUFBwEBBC4wLDAq
|
||||
BggrBgEFBQcwAoYeaHR0cDovL2dyZWVuLm5vL2NhL3Jvb3QtY2EuY2VyMC8GA1Ud
|
||||
HwQoMCYwJKAioCCGHmh0dHA6Ly9ncmVlbi5uby9jYS9yb290LWNhLmNybDANBgkq
|
||||
hkiG9w0BAQUFAAOCAQEAFaes1yWeKtTRFLSZOD0vc2Eq2baLE+r+23jZCmzfJm7B
|
||||
1UqXQhndlwUD5Cv8Hh84PE6wO4w4rStl+jUtgY7g9gqJTDiXAUucrE7hVRfvCq2n
|
||||
6x5LhiMS8VJpy6OKzvsUi4bXu4FevSrHp3lYABDA2//UpbkZdLMjGUofeEuotvYg
|
||||
JsFp+Yl/uBw7ovk3MYAssLYr0oRE10Lk5kRRBDXZHKRIxrc13vKu2ku6yAlCje16
|
||||
gdztnfDebiG5ARytZD0lTJGU8RMYu4npSKwFcwfI271pjm8CnbAYwLnhqLEXUD2s
|
||||
BW5vY0+xczNgmnfSgYoBOEPpTDyQY6SZS9Ib+Rvs7g==
|
||||
-----END CERTIFICATE-----
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 1 (0x1)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green Root CA
|
||||
Validity
|
||||
Not Before: Jul 13 03:44:39 2017 GMT
|
||||
Not After : Dec 31 23:59:59 2030 GMT
|
||||
Subject: C=NO, O=Green AS, OU=Green Certificate Authority, CN=Green Root CA
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:a7:e8:ed:de:d4:54:08:41:07:40:d5:c0:43:d6:
|
||||
ab:d3:9e:21:87:c6:13:bf:a7:cf:3d:08:4f:c1:fe:
|
||||
8f:e5:6c:c5:89:97:e5:27:75:26:c3:2a:73:2d:34:
|
||||
7c:6f:35:8d:40:66:61:05:c0:eb:e9:b3:38:47:f8:
|
||||
8b:26:35:2c:df:dc:24:31:fe:72:e3:87:10:d1:f7:
|
||||
a0:57:b7:f3:b1:1a:fe:c7:4b:f8:7b:14:6d:73:08:
|
||||
54:eb:63:3c:0c:ce:22:95:5f:3f:f2:6f:89:ae:63:
|
||||
da:80:74:36:21:13:e8:91:01:58:77:cc:c2:f2:42:
|
||||
bf:eb:b3:60:a7:21:ed:88:24:7f:eb:ff:07:41:9b:
|
||||
93:c8:5f:6a:8e:a6:1a:15:3c:bc:e7:0d:fd:05:fd:
|
||||
3c:c1:1c:1d:1f:57:2b:40:27:62:a1:7c:48:63:c1:
|
||||
45:e7:2f:20:ed:92:1c:42:94:e4:58:70:7a:b6:d2:
|
||||
85:c5:61:d8:cd:c6:37:6b:72:3b:7f:af:55:81:d6:
|
||||
9d:dc:10:c9:d8:0e:81:e4:5e:40:13:2f:20:e8:6b:
|
||||
46:81:ce:88:47:dd:38:71:3d:ef:21:cc:c0:67:cf:
|
||||
0a:f4:e9:3f:a8:9d:26:25:2e:23:1e:a3:11:18:cb:
|
||||
d1:70:1c:9e:7d:09:b1:a4:20:dc:95:15:1d:49:cf:
|
||||
1b:ad
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Key Usage: critical
|
||||
Certificate Sign, CRL Sign
|
||||
X509v3 Basic Constraints: critical
|
||||
CA:TRUE
|
||||
X509v3 Subject Key Identifier:
|
||||
60:93:53:2F:C7:CF:2A:D7:F3:09:28:F6:3C:AE:9C:50:EC:93:63:E5
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:60:93:53:2F:C7:CF:2A:D7:F3:09:28:F6:3C:AE:9C:50:EC:93:63:E5
|
||||
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
a7:77:71:8b:1a:e5:5a:5b:87:54:08:bf:07:3e:cb:99:2f:dc:
|
||||
0e:8d:63:94:95:83:19:c9:92:82:d5:cb:5b:8f:1f:86:55:bc:
|
||||
70:01:1d:33:46:ec:99:de:6b:1f:c3:c2:7a:dd:ef:69:ab:96:
|
||||
58:ec:6c:6f:6c:70:82:71:8a:7f:f0:3b:80:90:d5:64:fa:80:
|
||||
27:b8:7b:50:69:98:4b:37:99:ad:bf:a2:5b:93:22:5e:96:44:
|
||||
3c:5a:cf:0c:f4:62:63:4a:6f:72:a7:f6:89:1d:09:26:3d:8f:
|
||||
a8:86:d4:b4:bc:dd:b3:38:ca:c0:59:16:8c:20:1f:89:35:12:
|
||||
b4:2d:c0:e9:de:93:e0:39:76:32:fc:80:db:da:44:26:fd:01:
|
||||
32:74:97:f8:44:ae:fe:05:b1:34:96:13:34:56:73:b4:93:a5:
|
||||
55:56:d1:01:51:9d:9c:55:e7:38:53:28:12:4e:38:72:0c:8f:
|
||||
bd:91:4c:45:48:3b:e1:0d:03:5f:58:40:c9:d3:a0:ac:b3:89:
|
||||
ce:af:27:8a:0f:ab:ec:72:4d:40:77:30:6b:36:fd:32:46:9f:
|
||||
ee:f9:c4:f5:17:06:0f:4b:d3:88:f5:a4:2f:3d:87:9e:f5:26:
|
||||
74:f0:c9:dc:cb:ad:d9:a7:8a:d3:71:15:00:d3:5d:9f:4c:59:
|
||||
3e:24:63:f5
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDnDCCAoSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJOTzER
|
||||
MA8GA1UECgwIR3JlZW4gQVMxJDAiBgNVBAsMG0dyZWVuIENlcnRpZmljYXRlIEF1
|
||||
dGhvcml0eTEWMBQGA1UEAwwNR3JlZW4gUm9vdCBDQTAgFw0xNzA3MTMwMzQ0Mzla
|
||||
GA8yMDMwMTIzMTIzNTk1OVowXjELMAkGA1UEBhMCTk8xETAPBgNVBAoMCEdyZWVu
|
||||
IEFTMSQwIgYDVQQLDBtHcmVlbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFjAUBgNV
|
||||
BAMMDUdyZWVuIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||
AQCn6O3e1FQIQQdA1cBD1qvTniGHxhO/p889CE/B/o/lbMWJl+UndSbDKnMtNHxv
|
||||
NY1AZmEFwOvpszhH+IsmNSzf3CQx/nLjhxDR96BXt/OxGv7HS/h7FG1zCFTrYzwM
|
||||
ziKVXz/yb4muY9qAdDYhE+iRAVh3zMLyQr/rs2CnIe2IJH/r/wdBm5PIX2qOphoV
|
||||
PLznDf0F/TzBHB0fVytAJ2KhfEhjwUXnLyDtkhxClORYcHq20oXFYdjNxjdrcjt/
|
||||
r1WB1p3cEMnYDoHkXkATLyDoa0aBzohH3ThxPe8hzMBnzwr06T+onSYlLiMeoxEY
|
||||
y9FwHJ59CbGkINyVFR1JzxutAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNV
|
||||
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRgk1Mvx88q1/MJKPY8rpxQ7JNj5TAfBgNV
|
||||
HSMEGDAWgBRgk1Mvx88q1/MJKPY8rpxQ7JNj5TANBgkqhkiG9w0BAQUFAAOCAQEA
|
||||
p3dxixrlWluHVAi/Bz7LmS/cDo1jlJWDGcmSgtXLW48fhlW8cAEdM0bsmd5rH8PC
|
||||
et3vaauWWOxsb2xwgnGKf/A7gJDVZPqAJ7h7UGmYSzeZrb+iW5MiXpZEPFrPDPRi
|
||||
Y0pvcqf2iR0JJj2PqIbUtLzdszjKwFkWjCAfiTUStC3A6d6T4Dl2MvyA29pEJv0B
|
||||
MnSX+ESu/gWxNJYTNFZztJOlVVbRAVGdnFXnOFMoEk44cgyPvZFMRUg74Q0DX1hA
|
||||
ydOgrLOJzq8nig+r7HJNQHcwazb9Mkaf7vnE9RcGD0vTiPWkLz2HnvUmdPDJ3Mut
|
||||
2aeK03EVANNdn0xZPiRj9Q==
|
||||
-----END CERTIFICATE-----
|
1
vendor/github.com/prometheus/common/config/testdata/tls_config.cert_no_key.bad.yml
generated
vendored
Normal file
1
vendor/github.com/prometheus/common/config/testdata/tls_config.cert_no_key.bad.yml
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
cert_file: somefile
|
0
vendor/github.com/prometheus/common/config/testdata/tls_config.empty.good.yml
generated
vendored
Normal file
0
vendor/github.com/prometheus/common/config/testdata/tls_config.empty.good.yml
generated
vendored
Normal file
1
vendor/github.com/prometheus/common/config/testdata/tls_config.insecure.good.yml
generated
vendored
Normal file
1
vendor/github.com/prometheus/common/config/testdata/tls_config.insecure.good.yml
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
insecure_skip_verify: true
|
1
vendor/github.com/prometheus/common/config/testdata/tls_config.invalid_field.bad.yml
generated
vendored
Normal file
1
vendor/github.com/prometheus/common/config/testdata/tls_config.invalid_field.bad.yml
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
something_invalid: true
|
1
vendor/github.com/prometheus/common/config/testdata/tls_config.key_no_cert.bad.yml
generated
vendored
Normal file
1
vendor/github.com/prometheus/common/config/testdata/tls_config.key_no_cert.bad.yml
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
key_file: somefile
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue