mirror of https://github.com/prometheus/prometheus
Julien
6 months ago
committed by
GitHub
483 changed files with 26856 additions and 31109 deletions
@ -0,0 +1,52 @@
|
||||
--- |
||||
name: Push README to Docker Hub |
||||
on: |
||||
push: |
||||
paths: |
||||
- "README.md" |
||||
- ".github/workflows/container_description.yml" |
||||
branches: [ main, master ] |
||||
|
||||
permissions: |
||||
contents: read |
||||
|
||||
jobs: |
||||
PushDockerHubReadme: |
||||
runs-on: ubuntu-latest |
||||
name: Push README to Docker Hub |
||||
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks. |
||||
steps: |
||||
- name: git checkout |
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 |
||||
- name: Set docker hub repo name |
||||
run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV |
||||
- name: Push README to Dockerhub |
||||
uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8 # v1 |
||||
env: |
||||
DOCKER_USER: ${{ secrets.DOCKER_HUB_LOGIN }} |
||||
DOCKER_PASS: ${{ secrets.DOCKER_HUB_PASSWORD }} |
||||
with: |
||||
destination_container_repo: ${{ env.DOCKER_REPO_NAME }} |
||||
provider: dockerhub |
||||
short_description: ${{ env.DOCKER_REPO_NAME }} |
||||
readme_file: 'README.md' |
||||
|
||||
PushQuayIoReadme: |
||||
runs-on: ubuntu-latest |
||||
name: Push README to quay.io |
||||
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks. |
||||
steps: |
||||
- name: git checkout |
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 |
||||
- name: Set quay.io org name |
||||
run: echo "DOCKER_REPO=$(echo quay.io/${GITHUB_REPOSITORY_OWNER} | tr -d '-')" >> $GITHUB_ENV |
||||
- name: Set quay.io repo name |
||||
run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV |
||||
- name: Push README to quay.io |
||||
uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8 # v1 |
||||
env: |
||||
DOCKER_APIKEY: ${{ secrets.QUAY_IO_API_TOKEN }} |
||||
with: |
||||
destination_container_repo: ${{ env.DOCKER_REPO_NAME }} |
||||
provider: quay |
||||
readme_file: 'README.md' |
@ -0,0 +1,370 @@
|
||||
// Copyright 2023 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 main |
||||
|
||||
import ( |
||||
"context" |
||||
"errors" |
||||
"fmt" |
||||
"io" |
||||
"math" |
||||
"net/http" |
||||
"net/url" |
||||
"os" |
||||
"sort" |
||||
"strconv" |
||||
"strings" |
||||
"time" |
||||
|
||||
v1 "github.com/prometheus/client_golang/api/prometheus/v1" |
||||
"github.com/prometheus/common/model" |
||||
|
||||
"github.com/prometheus/prometheus/model/labels" |
||||
) |
||||
|
||||
var ( |
||||
errNotNativeHistogram = fmt.Errorf("not a native histogram") |
||||
errNotEnoughData = fmt.Errorf("not enough data") |
||||
|
||||
outputHeader = `Bucket stats for each histogram series over time |
||||
------------------------------------------------ |
||||
First the min, avg, and max number of populated buckets, followed by the total |
||||
number of buckets (only if different from the max number of populated buckets |
||||
which is typical for classic but not native histograms).` |
||||
outputFooter = `Aggregated bucket stats |
||||
----------------------- |
||||
Each line shows min/avg/max over the series above.` |
||||
) |
||||
|
||||
type QueryAnalyzeConfig struct { |
||||
metricType string |
||||
duration time.Duration |
||||
time string |
||||
matchers []string |
||||
} |
||||
|
||||
// run retrieves metrics that look like conventional histograms (i.e. have _bucket
|
||||
// suffixes) or native histograms, depending on metricType flag.
|
||||
func (c *QueryAnalyzeConfig) run(url *url.URL, roundtripper http.RoundTripper) error { |
||||
if c.metricType != "histogram" { |
||||
return fmt.Errorf("analyze type is %s, must be 'histogram'", c.metricType) |
||||
} |
||||
|
||||
ctx := context.Background() |
||||
|
||||
api, err := newAPI(url, roundtripper, nil) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
var endTime time.Time |
||||
if c.time != "" { |
||||
endTime, err = parseTime(c.time) |
||||
if err != nil { |
||||
return fmt.Errorf("error parsing time '%s': %w", c.time, err) |
||||
} |
||||
} else { |
||||
endTime = time.Now() |
||||
} |
||||
|
||||
return c.getStatsFromMetrics(ctx, api, endTime, os.Stdout, c.matchers) |
||||
} |
||||
|
||||
func (c *QueryAnalyzeConfig) getStatsFromMetrics(ctx context.Context, api v1.API, endTime time.Time, out io.Writer, matchers []string) error { |
||||
fmt.Fprintf(out, "%s\n\n", outputHeader) |
||||
metastatsNative := newMetaStatistics() |
||||
metastatsClassic := newMetaStatistics() |
||||
for _, matcher := range matchers { |
||||
seriesSel := seriesSelector(matcher, c.duration) |
||||
matrix, err := querySamples(ctx, api, seriesSel, endTime) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
matrices := make(map[string]model.Matrix) |
||||
for _, series := range matrix { |
||||
// We do not handle mixed types. If there are float values, we assume it is a
|
||||
// classic histogram, otherwise we assume it is a native histogram, and we
|
||||
// ignore series with errors if they do not match the expected type.
|
||||
if len(series.Values) == 0 { |
||||
stats, err := calcNativeBucketStatistics(series) |
||||
if err != nil { |
||||
if errors.Is(err, errNotNativeHistogram) || errors.Is(err, errNotEnoughData) { |
||||
continue |
||||
} |
||||
return err |
||||
} |
||||
fmt.Fprintf(out, "- %s (native): %v\n", series.Metric, *stats) |
||||
metastatsNative.update(stats) |
||||
} else { |
||||
lbs := model.LabelSet(series.Metric).Clone() |
||||
if _, ok := lbs["le"]; !ok { |
||||
continue |
||||
} |
||||
metricName := string(lbs[labels.MetricName]) |
||||
if !strings.HasSuffix(metricName, "_bucket") { |
||||
continue |
||||
} |
||||
delete(lbs, labels.MetricName) |
||||
delete(lbs, "le") |
||||
key := formatSeriesName(metricName, lbs) |
||||
matrices[key] = append(matrices[key], series) |
||||
} |
||||
} |
||||
|
||||
for key, matrix := range matrices { |
||||
stats, err := calcClassicBucketStatistics(matrix) |
||||
if err != nil { |
||||
if errors.Is(err, errNotEnoughData) { |
||||
continue |
||||
} |
||||
return err |
||||
} |
||||
fmt.Fprintf(out, "- %s (classic): %v\n", key, *stats) |
||||
metastatsClassic.update(stats) |
||||
} |
||||
} |
||||
fmt.Fprintf(out, "\n%s\n", outputFooter) |
||||
if metastatsNative.Count() > 0 { |
||||
fmt.Fprintf(out, "\nNative %s\n", metastatsNative) |
||||
} |
||||
if metastatsClassic.Count() > 0 { |
||||
fmt.Fprintf(out, "\nClassic %s\n", metastatsClassic) |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func seriesSelector(metricName string, duration time.Duration) string { |
||||
builder := strings.Builder{} |
||||
builder.WriteString(metricName) |
||||
builder.WriteRune('[') |
||||
builder.WriteString(duration.String()) |
||||
builder.WriteRune(']') |
||||
return builder.String() |
||||
} |
||||
|
||||
func formatSeriesName(metricName string, lbs model.LabelSet) string { |
||||
builder := strings.Builder{} |
||||
builder.WriteString(metricName) |
||||
builder.WriteString(lbs.String()) |
||||
return builder.String() |
||||
} |
||||
|
||||
func querySamples(ctx context.Context, api v1.API, query string, end time.Time) (model.Matrix, error) { |
||||
values, _, err := api.Query(ctx, query, end) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
matrix, ok := values.(model.Matrix) |
||||
if !ok { |
||||
return nil, fmt.Errorf("query of buckets resulted in non-Matrix") |
||||
} |
||||
|
||||
return matrix, nil |
||||
} |
||||
|
||||
// minPop/avgPop/maxPop is for the number of populated (non-zero) buckets.
|
||||
// total is the total number of buckets across all samples in the series,
|
||||
// populated or not.
|
||||
type statistics struct { |
||||
minPop, maxPop, total int |
||||
avgPop float64 |
||||
} |
||||
|
||||
func (s statistics) String() string { |
||||
if s.maxPop == s.total { |
||||
return fmt.Sprintf("%d/%.3f/%d", s.minPop, s.avgPop, s.maxPop) |
||||
} |
||||
return fmt.Sprintf("%d/%.3f/%d/%d", s.minPop, s.avgPop, s.maxPop, s.total) |
||||
} |
||||
|
||||
func calcClassicBucketStatistics(matrix model.Matrix) (*statistics, error) { |
||||
numBuckets := len(matrix) |
||||
|
||||
stats := &statistics{ |
||||
minPop: math.MaxInt, |
||||
total: numBuckets, |
||||
} |
||||
|
||||
if numBuckets == 0 || len(matrix[0].Values) < 2 { |
||||
return stats, errNotEnoughData |
||||
} |
||||
|
||||
numSamples := len(matrix[0].Values) |
||||
|
||||
sortMatrix(matrix) |
||||
|
||||
totalPop := 0 |
||||
for timeIdx := 0; timeIdx < numSamples; timeIdx++ { |
||||
curr, err := getBucketCountsAtTime(matrix, numBuckets, timeIdx) |
||||
if err != nil { |
||||
return stats, err |
||||
} |
||||
countPop := 0 |
||||
for _, b := range curr { |
||||
if b != 0 { |
||||
countPop++ |
||||
} |
||||
} |
||||
|
||||
totalPop += countPop |
||||
if stats.minPop > countPop { |
||||
stats.minPop = countPop |
||||
} |
||||
if stats.maxPop < countPop { |
||||
stats.maxPop = countPop |
||||
} |
||||
} |
||||
stats.avgPop = float64(totalPop) / float64(numSamples) |
||||
return stats, nil |
||||
} |
||||
|
||||
func sortMatrix(matrix model.Matrix) { |
||||
sort.SliceStable(matrix, func(i, j int) bool { |
||||
return getLe(matrix[i]) < getLe(matrix[j]) |
||||
}) |
||||
} |
||||
|
||||
func getLe(series *model.SampleStream) float64 { |
||||
lbs := model.LabelSet(series.Metric) |
||||
le, _ := strconv.ParseFloat(string(lbs["le"]), 64) |
||||
return le |
||||
} |
||||
|
||||
func getBucketCountsAtTime(matrix model.Matrix, numBuckets, timeIdx int) ([]int, error) { |
||||
counts := make([]int, numBuckets) |
||||
if timeIdx >= len(matrix[0].Values) { |
||||
// Just return zeroes instead of erroring out so we can get partial results.
|
||||
return counts, nil |
||||
} |
||||
counts[0] = int(matrix[0].Values[timeIdx].Value) |
||||
for i, bucket := range matrix[1:] { |
||||
if timeIdx >= len(bucket.Values) { |
||||
// Just return zeroes instead of erroring out so we can get partial results.
|
||||
return counts, nil |
||||
} |
||||
curr := bucket.Values[timeIdx] |
||||
prev := matrix[i].Values[timeIdx] |
||||
// Assume the results are nicely aligned.
|
||||
if curr.Timestamp != prev.Timestamp { |
||||
return counts, fmt.Errorf("matrix result is not time aligned") |
||||
} |
||||
counts[i+1] = int(curr.Value - prev.Value) |
||||
} |
||||
return counts, nil |
||||
} |
||||
|
||||
type bucketBounds struct { |
||||
boundaries int32 |
||||
upper, lower float64 |
||||
} |
||||
|
||||
func makeBucketBounds(b *model.HistogramBucket) bucketBounds { |
||||
return bucketBounds{ |
||||
boundaries: b.Boundaries, |
||||
upper: float64(b.Upper), |
||||
lower: float64(b.Lower), |
||||
} |
||||
} |
||||
|
||||
func calcNativeBucketStatistics(series *model.SampleStream) (*statistics, error) { |
||||
stats := &statistics{ |
||||
minPop: math.MaxInt, |
||||
} |
||||
|
||||
overall := make(map[bucketBounds]struct{}) |
||||
totalPop := 0 |
||||
if len(series.Histograms) == 0 { |
||||
return nil, errNotNativeHistogram |
||||
} |
||||
if len(series.Histograms) == 1 { |
||||
return nil, errNotEnoughData |
||||
} |
||||
for _, histogram := range series.Histograms { |
||||
for _, bucket := range histogram.Histogram.Buckets { |
||||
bb := makeBucketBounds(bucket) |
||||
overall[bb] = struct{}{} |
||||
} |
||||
countPop := len(histogram.Histogram.Buckets) |
||||
|
||||
totalPop += countPop |
||||
if stats.minPop > countPop { |
||||
stats.minPop = countPop |
||||
} |
||||
if stats.maxPop < countPop { |
||||
stats.maxPop = countPop |
||||
} |
||||
} |
||||
stats.avgPop = float64(totalPop) / float64(len(series.Histograms)) |
||||
stats.total = len(overall) |
||||
return stats, nil |
||||
} |
||||
|
||||
type distribution struct { |
||||
min, max, count int |
||||
avg float64 |
||||
} |
||||
|
||||
func newDistribution() distribution { |
||||
return distribution{ |
||||
min: math.MaxInt, |
||||
} |
||||
} |
||||
|
||||
func (d *distribution) update(num int) { |
||||
if d.min > num { |
||||
d.min = num |
||||
} |
||||
if d.max < num { |
||||
d.max = num |
||||
} |
||||
d.count++ |
||||
d.avg += float64(num)/float64(d.count) - d.avg/float64(d.count) |
||||
} |
||||
|
||||
func (d distribution) String() string { |
||||
return fmt.Sprintf("%d/%.3f/%d", d.min, d.avg, d.max) |
||||
} |
||||
|
||||
type metaStatistics struct { |
||||
minPop, avgPop, maxPop, total distribution |
||||
} |
||||
|
||||
func newMetaStatistics() *metaStatistics { |
||||
return &metaStatistics{ |
||||
minPop: newDistribution(), |
||||
avgPop: newDistribution(), |
||||
maxPop: newDistribution(), |
||||
total: newDistribution(), |
||||
} |
||||
} |
||||
|
||||
func (ms metaStatistics) Count() int { |
||||
return ms.minPop.count |
||||
} |
||||
|
||||
func (ms metaStatistics) String() string { |
||||
if ms.maxPop == ms.total { |
||||
return fmt.Sprintf("histogram series (%d in total):\n- min populated: %v\n- avg populated: %v\n- max populated: %v", ms.Count(), ms.minPop, ms.avgPop, ms.maxPop) |
||||
} |
||||
return fmt.Sprintf("histogram series (%d in total):\n- min populated: %v\n- avg populated: %v\n- max populated: %v\n- total: %v", ms.Count(), ms.minPop, ms.avgPop, ms.maxPop, ms.total) |
||||
} |
||||
|
||||
func (ms *metaStatistics) update(s *statistics) { |
||||
ms.minPop.update(s.minPop) |
||||
ms.avgPop.update(int(s.avgPop)) |
||||
ms.maxPop.update(s.maxPop) |
||||
ms.total.update(s.total) |
||||
} |
@ -0,0 +1,170 @@
|
||||
// Copyright 2023 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 main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"testing" |
||||
|
||||
"github.com/stretchr/testify/require" |
||||
|
||||
"github.com/prometheus/common/model" |
||||
) |
||||
|
||||
var ( |
||||
exampleMatrix = model.Matrix{ |
||||
&model.SampleStream{ |
||||
Metric: model.Metric{ |
||||
"le": "+Inf", |
||||
}, |
||||
Values: []model.SamplePair{ |
||||
{ |
||||
Value: 31, |
||||
Timestamp: 100, |
||||
}, |
||||
{ |
||||
Value: 32, |
||||
Timestamp: 200, |
||||
}, |
||||
{ |
||||
Value: 40, |
||||
Timestamp: 300, |
||||
}, |
||||
}, |
||||
}, |
||||
&model.SampleStream{ |
||||
Metric: model.Metric{ |
||||
"le": "0.5", |
||||
}, |
||||
Values: []model.SamplePair{ |
||||
{ |
||||
Value: 10, |
||||
Timestamp: 100, |
||||
}, |
||||
{ |
||||
Value: 11, |
||||
Timestamp: 200, |
||||
}, |
||||
{ |
||||
Value: 11, |
||||
Timestamp: 300, |
||||
}, |
||||
}, |
||||
}, |
||||
&model.SampleStream{ |
||||
Metric: model.Metric{ |
||||
"le": "10", |
||||
}, |
||||
Values: []model.SamplePair{ |
||||
{ |
||||
Value: 30, |
||||
Timestamp: 100, |
||||
}, |
||||
{ |
||||
Value: 31, |
||||
Timestamp: 200, |
||||
}, |
||||
{ |
||||
Value: 37, |
||||
Timestamp: 300, |
||||
}, |
||||
}, |
||||
}, |
||||
&model.SampleStream{ |
||||
Metric: model.Metric{ |
||||
"le": "2", |
||||
}, |
||||
Values: []model.SamplePair{ |
||||
{ |
||||
Value: 25, |
||||
Timestamp: 100, |
||||
}, |
||||
{ |
||||
Value: 26, |
||||
Timestamp: 200, |
||||
}, |
||||
{ |
||||
Value: 27, |
||||
Timestamp: 300, |
||||
}, |
||||
}, |
||||
}, |
||||
} |
||||
exampleMatrixLength = len(exampleMatrix) |
||||
) |
||||
|
||||
func init() { |
||||
sortMatrix(exampleMatrix) |
||||
} |
||||
|
||||
func TestGetBucketCountsAtTime(t *testing.T) { |
||||
cases := []struct { |
||||
matrix model.Matrix |
||||
length int |
||||
timeIdx int |
||||
expected []int |
||||
}{ |
||||
{ |
||||
exampleMatrix, |
||||
exampleMatrixLength, |
||||
0, |
||||
[]int{10, 15, 5, 1}, |
||||
}, |
||||
{ |
||||
exampleMatrix, |
||||
exampleMatrixLength, |
||||
1, |
||||
[]int{11, 15, 5, 1}, |
||||
}, |
||||
{ |
||||
exampleMatrix, |
||||
exampleMatrixLength, |
||||
2, |
||||
[]int{11, 16, 10, 3}, |
||||
}, |
||||
} |
||||
|
||||
for _, c := range cases { |
||||
t.Run(fmt.Sprintf("exampleMatrix@%d", c.timeIdx), func(t *testing.T) { |
||||
res, err := getBucketCountsAtTime(c.matrix, c.length, c.timeIdx) |
||||
require.NoError(t, err) |
||||
require.Equal(t, c.expected, res) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
func TestCalcClassicBucketStatistics(t *testing.T) { |
||||
cases := []struct { |
||||
matrix model.Matrix |
||||
expected *statistics |
||||
}{ |
||||
{ |
||||
exampleMatrix, |
||||
&statistics{ |
||||
minPop: 4, |
||||
avgPop: 4, |
||||
maxPop: 4, |
||||
total: 4, |
||||
}, |
||||
}, |
||||
} |
||||
|
||||
for i, c := range cases { |
||||
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { |
||||
res, err := calcClassicBucketStatistics(c.matrix) |
||||
require.NoError(t, err) |
||||
require.Equal(t, c.expected, res) |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,251 @@
|
||||
// Copyright 2023 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 main |
||||
|
||||
import ( |
||||
"context" |
||||
"errors" |
||||
"fmt" |
||||
"math" |
||||
"net/http" |
||||
"net/url" |
||||
"os" |
||||
"strconv" |
||||
"strings" |
||||
"time" |
||||
|
||||
"github.com/prometheus/client_golang/api" |
||||
v1 "github.com/prometheus/client_golang/api/prometheus/v1" |
||||
"github.com/prometheus/client_golang/prometheus/promhttp" |
||||
|
||||
_ "github.com/prometheus/prometheus/plugins" // Register plugins.
|
||||
) |
||||
|
||||
func newAPI(url *url.URL, roundTripper http.RoundTripper, headers map[string]string) (v1.API, error) { |
||||
if url.Scheme == "" { |
||||
url.Scheme = "http" |
||||
} |
||||
config := api.Config{ |
||||
Address: url.String(), |
||||
RoundTripper: roundTripper, |
||||
} |
||||
|
||||
if len(headers) > 0 { |
||||
config.RoundTripper = promhttp.RoundTripperFunc(func(req *http.Request) (*http.Response, error) { |
||||
for key, value := range headers { |
||||
req.Header.Add(key, value) |
||||
} |
||||
return roundTripper.RoundTrip(req) |
||||
}) |
||||
} |
||||
|
||||
// Create new client.
|
||||
client, err := api.NewClient(config) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
api := v1.NewAPI(client) |
||||
return api, nil |
||||
} |
||||
|
||||
// QueryInstant performs an instant query against a Prometheus server.
|
||||
func QueryInstant(url *url.URL, roundTripper http.RoundTripper, query, evalTime string, p printer) int { |
||||
api, err := newAPI(url, roundTripper, nil) |
||||
if err != nil { |
||||
fmt.Fprintln(os.Stderr, "error creating API client:", err) |
||||
return failureExitCode |
||||
} |
||||
|
||||
eTime := time.Now() |
||||
if evalTime != "" { |
||||
eTime, err = parseTime(evalTime) |
||||
if err != nil { |
||||
fmt.Fprintln(os.Stderr, "error parsing evaluation time:", err) |
||||
return failureExitCode |
||||
} |
||||
} |
||||
|
||||
// Run query against client.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) |
||||
val, _, err := api.Query(ctx, query, eTime) // Ignoring warnings for now.
|
||||
cancel() |
||||
if err != nil { |
||||
return handleAPIError(err) |
||||
} |
||||
|
||||
p.printValue(val) |
||||
|
||||
return successExitCode |
||||
} |
||||
|
||||
// QueryRange performs a range query against a Prometheus server.
|
||||
func QueryRange(url *url.URL, roundTripper http.RoundTripper, headers map[string]string, query, start, end string, step time.Duration, p printer) int { |
||||
api, err := newAPI(url, roundTripper, headers) |
||||
if err != nil { |
||||
fmt.Fprintln(os.Stderr, "error creating API client:", err) |
||||
return failureExitCode |
||||
} |
||||
|
||||
var stime, etime time.Time |
||||
|
||||
if end == "" { |
||||
etime = time.Now() |
||||
} else { |
||||
etime, err = parseTime(end) |
||||
if err != nil { |
||||
fmt.Fprintln(os.Stderr, "error parsing end time:", err) |
||||
return failureExitCode |
||||
} |
||||
} |
||||
|
||||
if start == "" { |
||||
stime = etime.Add(-5 * time.Minute) |
||||
} else { |
||||
stime, err = parseTime(start) |
||||
if err != nil { |
||||
fmt.Fprintln(os.Stderr, "error parsing start time:", err) |
||||
return failureExitCode |
||||
} |
||||
} |
||||
|
||||
if !stime.Before(etime) { |
||||
fmt.Fprintln(os.Stderr, "start time is not before end time") |
||||
return failureExitCode |
||||
} |
||||
|
||||
if step == 0 { |
||||
resolution := math.Max(math.Floor(etime.Sub(stime).Seconds()/250), 1) |
||||
// Convert seconds to nanoseconds such that time.Duration parses correctly.
|
||||
step = time.Duration(resolution) * time.Second |
||||
} |
||||
|
||||
// Run query against client.
|
||||
r := v1.Range{Start: stime, End: etime, Step: step} |
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) |
||||
val, _, err := api.QueryRange(ctx, query, r) // Ignoring warnings for now.
|
||||
cancel() |
||||
|
||||
if err != nil { |
||||
return handleAPIError(err) |
||||
} |
||||
|
||||
p.printValue(val) |
||||
return successExitCode |
||||
} |
||||
|
||||
// QuerySeries queries for a series against a Prometheus server.
|
||||
func QuerySeries(url *url.URL, roundTripper http.RoundTripper, matchers []string, start, end string, p printer) int { |
||||
api, err := newAPI(url, roundTripper, nil) |
||||
if err != nil { |
||||
fmt.Fprintln(os.Stderr, "error creating API client:", err) |
||||
return failureExitCode |
||||
} |
||||
|
||||
stime, etime, err := parseStartTimeAndEndTime(start, end) |
||||
if err != nil { |
||||
fmt.Fprintln(os.Stderr, err) |
||||
return failureExitCode |
||||
} |
||||
|
||||
// Run query against client.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) |
||||
val, _, err := api.Series(ctx, matchers, stime, etime) // Ignoring warnings for now.
|
||||
cancel() |
||||
|
||||
if err != nil { |
||||
return handleAPIError(err) |
||||
} |
||||
|
||||
p.printSeries(val) |
||||
return successExitCode |
||||
} |
||||
|
||||
// QueryLabels queries for label values against a Prometheus server.
|
||||
func QueryLabels(url *url.URL, roundTripper http.RoundTripper, matchers []string, name, start, end string, p printer) int { |
||||
api, err := newAPI(url, roundTripper, nil) |
||||
if err != nil { |
||||
fmt.Fprintln(os.Stderr, "error creating API client:", err) |
||||
return failureExitCode |
||||
} |
||||
|
||||
stime, etime, err := parseStartTimeAndEndTime(start, end) |
||||
if err != nil { |
||||
fmt.Fprintln(os.Stderr, err) |
||||
return failureExitCode |
||||
} |
||||
|
||||
// Run query against client.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) |
||||
val, warn, err := api.LabelValues(ctx, name, matchers, stime, etime) |
||||
cancel() |
||||
|
||||
for _, v := range warn { |
||||
fmt.Fprintln(os.Stderr, "query warning:", v) |
||||
} |
||||
if err != nil { |
||||
return handleAPIError(err) |
||||
} |
||||
|
||||
p.printLabelValues(val) |
||||
return successExitCode |
||||
} |
||||
|
||||
func handleAPIError(err error) int { |
||||
var apiErr *v1.Error |
||||
if errors.As(err, &apiErr) && apiErr.Detail != "" { |
||||
fmt.Fprintf(os.Stderr, "query error: %v (detail: %s)\n", apiErr, strings.TrimSpace(apiErr.Detail)) |
||||
} else { |
||||
fmt.Fprintln(os.Stderr, "query error:", err) |
||||
} |
||||
|
||||
return failureExitCode |
||||
} |
||||
|
||||
func parseStartTimeAndEndTime(start, end string) (time.Time, time.Time, error) { |
||||
var ( |
||||
minTime = time.Now().Add(-9999 * time.Hour) |
||||
maxTime = time.Now().Add(9999 * time.Hour) |
||||
err error |
||||
) |
||||
|
||||
stime := minTime |
||||
etime := maxTime |
||||
|
||||
if start != "" { |
||||
stime, err = parseTime(start) |
||||
if err != nil { |
||||
return stime, etime, fmt.Errorf("error parsing start time: %w", err) |
||||
} |
||||
} |
||||
|
||||
if end != "" { |
||||
etime, err = parseTime(end) |
||||
if err != nil { |
||||
return stime, etime, fmt.Errorf("error parsing end time: %w", err) |
||||
} |
||||
} |
||||
return stime, etime, nil |
||||
} |
||||
|
||||
func parseTime(s string) (time.Time, error) { |
||||
if t, err := strconv.ParseFloat(s, 64); err == nil { |
||||
s, ns := math.Modf(t) |
||||
return time.Unix(int64(s), int64(ns*float64(time.Second))).UTC(), nil |
||||
} |
||||
if t, err := time.Parse(time.RFC3339Nano, s); err == nil { |
||||
return t, nil |
||||
} |
||||
return time.Time{}, fmt.Errorf("cannot parse %q to a valid timestamp", s) |
||||
} |
@ -0,0 +1,15 @@
|
||||
my_histogram_bucket{instance="localhost:8000",job="example2",le="+Inf"} 1.0267820369e+10 1700215884.373 |
||||
my_histogram_bucket{instance="localhost:8000",job="example2",le="+Inf"} 1.026872507e+10 1700215889.373 |
||||
my_histogram_bucket{instance="localhost:8000",job="example2",le="0.01"} 0 1700215884.373 |
||||
my_histogram_bucket{instance="localhost:8000",job="example2",le="0.01"} 0 1700215889.373 |
||||
my_histogram_count{instance="localhost:8000",job="example2"} 1.0267820369e+10 1700215884.373 |
||||
my_histogram_count{instance="localhost:8000",job="example2"} 1.026872507e+10 1700215889.373 |
||||
my_summary_count{instance="localhost:8000",job="example5"} 9.518161497e+09 1700211684.981 |
||||
my_summary_count{instance="localhost:8000",job="example5"} 9.519048034e+09 1700211689.984 |
||||
my_summary_sum{instance="localhost:8000",job="example5"} 5.2349889185e+10 1700211684.981 |
||||
my_summary_sum{instance="localhost:8000",job="example5"} 5.2354761848e+10 1700211689.984 |
||||
up{instance="localhost:8000",job="example2"} 1 1700226034.330 |
||||
up{instance="localhost:8000",job="example2"} 1 1700226094.329 |
||||
up{instance="localhost:8000",job="example3"} 1 1700210681.366 |
||||
up{instance="localhost:8000",job="example3"} 1 1700210686.366 |
||||
# EOF |
@ -0,0 +1,11 @@
|
||||
my_counter{baz="abc",foo="bar"} 1 0.000 |
||||
my_counter{baz="abc",foo="bar"} 2 60.000 |
||||
my_counter{baz="abc",foo="bar"} 3 120.000 |
||||
my_counter{baz="abc",foo="bar"} 4 180.000 |
||||
my_counter{baz="abc",foo="bar"} 5 240.000 |
||||
my_gauge{abc="baz",bar="foo"} 9 0.000 |
||||
my_gauge{abc="baz",bar="foo"} 8 60.000 |
||||
my_gauge{abc="baz",bar="foo"} 0 120.000 |
||||
my_gauge{abc="baz",bar="foo"} 4 180.000 |
||||
my_gauge{abc="baz",bar="foo"} 7 240.000 |
||||
# EOF |
@ -0,0 +1,15 @@
|
||||
{__name__="heavy_metric", foo="bar"} 5 0 |
||||
{__name__="heavy_metric", foo="bar"} 4 60000 |
||||
{__name__="heavy_metric", foo="bar"} 3 120000 |
||||
{__name__="heavy_metric", foo="bar"} 2 180000 |
||||
{__name__="heavy_metric", foo="bar"} 1 240000 |
||||
{__name__="heavy_metric", foo="foo"} 5 0 |
||||
{__name__="heavy_metric", foo="foo"} 4 60000 |
||||
{__name__="heavy_metric", foo="foo"} 3 120000 |
||||
{__name__="heavy_metric", foo="foo"} 2 180000 |
||||
{__name__="heavy_metric", foo="foo"} 1 240000 |
||||
{__name__="metric", baz="abc", foo="bar"} 1 0 |
||||
{__name__="metric", baz="abc", foo="bar"} 2 60000 |
||||
{__name__="metric", baz="abc", foo="bar"} 3 120000 |
||||
{__name__="metric", baz="abc", foo="bar"} 4 180000 |
||||
{__name__="metric", baz="abc", foo="bar"} 5 240000 |
@ -0,0 +1,10 @@
|
||||
{__name__="heavy_metric", foo="foo"} 5 0 |
||||
{__name__="heavy_metric", foo="foo"} 4 60000 |
||||
{__name__="heavy_metric", foo="foo"} 3 120000 |
||||
{__name__="heavy_metric", foo="foo"} 2 180000 |
||||
{__name__="heavy_metric", foo="foo"} 1 240000 |
||||
{__name__="metric", baz="abc", foo="bar"} 1 0 |
||||
{__name__="metric", baz="abc", foo="bar"} 2 60000 |
||||
{__name__="metric", baz="abc", foo="bar"} 3 120000 |
||||
{__name__="metric", baz="abc", foo="bar"} 4 180000 |
||||
{__name__="metric", baz="abc", foo="bar"} 5 240000 |
@ -0,0 +1,2 @@
|
||||
{__name__="metric", baz="abc", foo="bar"} 2 60000 |
||||
{__name__="metric", baz="abc", foo="bar"} 3 120000 |
@ -0,0 +1,32 @@
|
||||
// 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 aws |
||||
|
||||
import ( |
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
type ec2Metrics struct { |
||||
refreshMetrics discovery.RefreshMetricsInstantiator |
||||
} |
||||
|
||||
var _ discovery.DiscovererMetrics = (*ec2Metrics)(nil) |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *ec2Metrics) Register() error { |
||||
return nil |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *ec2Metrics) Unregister() {} |
@ -0,0 +1,32 @@
|
||||
// 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 aws |
||||
|
||||
import ( |
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
type lightsailMetrics struct { |
||||
refreshMetrics discovery.RefreshMetricsInstantiator |
||||
} |
||||
|
||||
var _ discovery.DiscovererMetrics = (*lightsailMetrics)(nil) |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *lightsailMetrics) Register() error { |
||||
return nil |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *lightsailMetrics) Unregister() {} |
@ -0,0 +1,64 @@
|
||||
// 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 azure |
||||
|
||||
import ( |
||||
"github.com/prometheus/client_golang/prometheus" |
||||
|
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*azureMetrics)(nil) |
||||
|
||||
type azureMetrics struct { |
||||
refreshMetrics discovery.RefreshMetricsInstantiator |
||||
|
||||
failuresCount prometheus.Counter |
||||
cacheHitCount prometheus.Counter |
||||
|
||||
metricRegisterer discovery.MetricRegisterer |
||||
} |
||||
|
||||
func newDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { |
||||
m := &azureMetrics{ |
||||
refreshMetrics: rmi, |
||||
failuresCount: prometheus.NewCounter( |
||||
prometheus.CounterOpts{ |
||||
Name: "prometheus_sd_azure_failures_total", |
||||
Help: "Number of Azure service discovery refresh failures.", |
||||
}), |
||||
cacheHitCount: prometheus.NewCounter( |
||||
prometheus.CounterOpts{ |
||||
Name: "prometheus_sd_azure_cache_hit_total", |
||||
Help: "Number of cache hit during refresh.", |
||||
}), |
||||
} |
||||
|
||||
m.metricRegisterer = discovery.NewMetricRegisterer(reg, []prometheus.Collector{ |
||||
m.failuresCount, |
||||
m.cacheHitCount, |
||||
}) |
||||
|
||||
return m |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *azureMetrics) Register() error { |
||||
return m.metricRegisterer.RegisterMetrics() |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *azureMetrics) Unregister() { |
||||
m.metricRegisterer.UnregisterMetrics() |
||||
} |
@ -0,0 +1,73 @@
|
||||
// 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 consul |
||||
|
||||
import ( |
||||
"github.com/prometheus/client_golang/prometheus" |
||||
|
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*consulMetrics)(nil) |
||||
|
||||
type consulMetrics struct { |
||||
rpcFailuresCount prometheus.Counter |
||||
rpcDuration *prometheus.SummaryVec |
||||
|
||||
servicesRPCDuration prometheus.Observer |
||||
serviceRPCDuration prometheus.Observer |
||||
|
||||
metricRegisterer discovery.MetricRegisterer |
||||
} |
||||
|
||||
func newDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { |
||||
m := &consulMetrics{ |
||||
rpcFailuresCount: prometheus.NewCounter( |
||||
prometheus.CounterOpts{ |
||||
Namespace: namespace, |
||||
Name: "sd_consul_rpc_failures_total", |
||||
Help: "The number of Consul RPC call failures.", |
||||
}), |
||||
rpcDuration: prometheus.NewSummaryVec( |
||||
prometheus.SummaryOpts{ |
||||
Namespace: namespace, |
||||
Name: "sd_consul_rpc_duration_seconds", |
||||
Help: "The duration of a Consul RPC call in seconds.", |
||||
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, |
||||
}, |
||||
[]string{"endpoint", "call"}, |
||||
), |
||||
} |
||||
|
||||
m.metricRegisterer = discovery.NewMetricRegisterer(reg, []prometheus.Collector{ |
||||
m.rpcFailuresCount, |
||||
m.rpcDuration, |
||||
}) |
||||
|
||||
// Initialize metric vectors.
|
||||
m.servicesRPCDuration = m.rpcDuration.WithLabelValues("catalog", "services") |
||||
m.serviceRPCDuration = m.rpcDuration.WithLabelValues("catalog", "service") |
||||
|
||||
return m |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *consulMetrics) Register() error { |
||||
return m.metricRegisterer.RegisterMetrics() |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *consulMetrics) Unregister() { |
||||
m.metricRegisterer.UnregisterMetrics() |
||||
} |
@ -0,0 +1,32 @@
|
||||
// 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 digitalocean |
||||
|
||||
import ( |
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*digitaloceanMetrics)(nil) |
||||
|
||||
type digitaloceanMetrics struct { |
||||
refreshMetrics discovery.RefreshMetricsInstantiator |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *digitaloceanMetrics) Register() error { |
||||
return nil |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *digitaloceanMetrics) Unregister() {} |
@ -0,0 +1,28 @@
|
||||
// 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 discovery |
||||
|
||||
// Create a dummy metrics struct, because this SD doesn't have any metrics.
|
||||
type NoopDiscovererMetrics struct{} |
||||
|
||||
var _ DiscovererMetrics = (*NoopDiscovererMetrics)(nil) |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (*NoopDiscovererMetrics) Register() error { |
||||
return nil |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (*NoopDiscovererMetrics) Unregister() { |
||||
} |
@ -0,0 +1,66 @@
|
||||
// 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 dns |
||||
|
||||
import ( |
||||
"github.com/prometheus/client_golang/prometheus" |
||||
|
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*dnsMetrics)(nil) |
||||
|
||||
type dnsMetrics struct { |
||||
refreshMetrics discovery.RefreshMetricsInstantiator |
||||
|
||||
dnsSDLookupsCount prometheus.Counter |
||||
dnsSDLookupFailuresCount prometheus.Counter |
||||
|
||||
metricRegisterer discovery.MetricRegisterer |
||||
} |
||||
|
||||
func newDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { |
||||
m := &dnsMetrics{ |
||||
refreshMetrics: rmi, |
||||
dnsSDLookupsCount: prometheus.NewCounter( |
||||
prometheus.CounterOpts{ |
||||
Namespace: namespace, |
||||
Name: "sd_dns_lookups_total", |
||||
Help: "The number of DNS-SD lookups.", |
||||
}), |
||||
dnsSDLookupFailuresCount: prometheus.NewCounter( |
||||
prometheus.CounterOpts{ |
||||
Namespace: namespace, |
||||
Name: "sd_dns_lookup_failures_total", |
||||
Help: "The number of DNS-SD lookup failures.", |
||||
}), |
||||
} |
||||
|
||||
m.metricRegisterer = discovery.NewMetricRegisterer(reg, []prometheus.Collector{ |
||||
m.dnsSDLookupsCount, |
||||
m.dnsSDLookupFailuresCount, |
||||
}) |
||||
|
||||
return m |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *dnsMetrics) Register() error { |
||||
return m.metricRegisterer.RegisterMetrics() |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *dnsMetrics) Unregister() { |
||||
m.metricRegisterer.UnregisterMetrics() |
||||
} |
@ -0,0 +1,32 @@
|
||||
// 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 eureka |
||||
|
||||
import ( |
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*eurekaMetrics)(nil) |
||||
|
||||
type eurekaMetrics struct { |
||||
refreshMetrics discovery.RefreshMetricsInstantiator |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *eurekaMetrics) Register() error { |
||||
return nil |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *eurekaMetrics) Unregister() {} |
@ -0,0 +1,76 @@
|
||||
// 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 file |
||||
|
||||
import ( |
||||
"github.com/prometheus/client_golang/prometheus" |
||||
|
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*fileMetrics)(nil) |
||||
|
||||
type fileMetrics struct { |
||||
fileSDReadErrorsCount prometheus.Counter |
||||
fileSDScanDuration prometheus.Summary |
||||
fileWatcherErrorsCount prometheus.Counter |
||||
fileSDTimeStamp *TimestampCollector |
||||
|
||||
metricRegisterer discovery.MetricRegisterer |
||||
} |
||||
|
||||
func newDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { |
||||
fm := &fileMetrics{ |
||||
fileSDReadErrorsCount: prometheus.NewCounter( |
||||
prometheus.CounterOpts{ |
||||
Name: "prometheus_sd_file_read_errors_total", |
||||
Help: "The number of File-SD read errors.", |
||||
}), |
||||
fileSDScanDuration: prometheus.NewSummary( |
||||
prometheus.SummaryOpts{ |
||||
Name: "prometheus_sd_file_scan_duration_seconds", |
||||
Help: "The duration of the File-SD scan in seconds.", |
||||
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, |
||||
}), |
||||
fileWatcherErrorsCount: prometheus.NewCounter( |
||||
prometheus.CounterOpts{ |
||||
Name: "prometheus_sd_file_watcher_errors_total", |
||||
Help: "The number of File-SD errors caused by filesystem watch failures.", |
||||
}), |
||||
fileSDTimeStamp: NewTimestampCollector(), |
||||
} |
||||
|
||||
fm.metricRegisterer = discovery.NewMetricRegisterer(reg, []prometheus.Collector{ |
||||
fm.fileSDReadErrorsCount, |
||||
fm.fileSDScanDuration, |
||||
fm.fileWatcherErrorsCount, |
||||
fm.fileSDTimeStamp, |
||||
}) |
||||
|
||||
return fm |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (fm *fileMetrics) Register() error { |
||||
return fm.metricRegisterer.RegisterMetrics() |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (fm *fileMetrics) Unregister() { |
||||
fm.metricRegisterer.UnregisterMetrics() |
||||
} |
||||
|
||||
func (fm *fileMetrics) init(disc *Discovery) { |
||||
fm.fileSDTimeStamp.addDiscoverer(disc) |
||||
} |
@ -0,0 +1,32 @@
|
||||
// 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 gce |
||||
|
||||
import ( |
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*gceMetrics)(nil) |
||||
|
||||
type gceMetrics struct { |
||||
refreshMetrics discovery.RefreshMetricsInstantiator |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *gceMetrics) Register() error { |
||||
return nil |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *gceMetrics) Unregister() {} |
@ -0,0 +1,32 @@
|
||||
// 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 hetzner |
||||
|
||||
import ( |
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*hetznerMetrics)(nil) |
||||
|
||||
type hetznerMetrics struct { |
||||
refreshMetrics discovery.RefreshMetricsInstantiator |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *hetznerMetrics) Register() error { |
||||
return nil |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *hetznerMetrics) Unregister() {} |
@ -0,0 +1,57 @@
|
||||
// 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 http |
||||
|
||||
import ( |
||||
"github.com/prometheus/client_golang/prometheus" |
||||
|
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*httpMetrics)(nil) |
||||
|
||||
type httpMetrics struct { |
||||
refreshMetrics discovery.RefreshMetricsInstantiator |
||||
|
||||
failuresCount prometheus.Counter |
||||
|
||||
metricRegisterer discovery.MetricRegisterer |
||||
} |
||||
|
||||
func newDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { |
||||
m := &httpMetrics{ |
||||
refreshMetrics: rmi, |
||||
failuresCount: prometheus.NewCounter( |
||||
prometheus.CounterOpts{ |
||||
Name: "prometheus_sd_http_failures_total", |
||||
Help: "Number of HTTP service discovery refresh failures.", |
||||
}), |
||||
} |
||||
|
||||
m.metricRegisterer = discovery.NewMetricRegisterer(reg, []prometheus.Collector{ |
||||
m.failuresCount, |
||||
}) |
||||
|
||||
return m |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *httpMetrics) Register() error { |
||||
return m.metricRegisterer.RegisterMetrics() |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *httpMetrics) Unregister() { |
||||
m.metricRegisterer.UnregisterMetrics() |
||||
} |
@ -0,0 +1,32 @@
|
||||
// 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 ionos |
||||
|
||||
import ( |
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*ionosMetrics)(nil) |
||||
|
||||
type ionosMetrics struct { |
||||
refreshMetrics discovery.RefreshMetricsInstantiator |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *ionosMetrics) Register() error { |
||||
return nil |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *ionosMetrics) Unregister() {} |
@ -0,0 +1,86 @@
|
||||
// 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 kubernetes |
||||
|
||||
import ( |
||||
"github.com/prometheus/client_golang/prometheus" |
||||
|
||||
"github.com/prometheus/prometheus/discovery" |
||||
) |
||||
|
||||
var _ discovery.DiscovererMetrics = (*kubernetesMetrics)(nil) |
||||
|
||||
type kubernetesMetrics struct { |
||||
eventCount *prometheus.CounterVec |
||||
failuresCount prometheus.Counter |
||||
|
||||
metricRegisterer discovery.MetricRegisterer |
||||
} |
||||
|
||||
func newDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { |
||||
m := &kubernetesMetrics{ |
||||
eventCount: prometheus.NewCounterVec( |
||||
prometheus.CounterOpts{ |
||||
Namespace: discovery.KubernetesMetricsNamespace, |
||||
Name: "events_total", |
||||
Help: "The number of Kubernetes events handled.", |
||||
}, |
||||
[]string{"role", "event"}, |
||||
), |
||||
failuresCount: prometheus.NewCounter( |
||||
prometheus.CounterOpts{ |
||||
Namespace: discovery.KubernetesMetricsNamespace, |
||||
Name: "failures_total", |
||||
Help: "The number of failed WATCH/LIST requests.", |
||||
}, |
||||
), |
||||
} |
||||
|
||||
m.metricRegisterer = discovery.NewMetricRegisterer(reg, []prometheus.Collector{ |
||||
m.eventCount, |
||||
m.failuresCount, |
||||
}) |
||||
|
||||
// Initialize metric vectors.
|
||||
for _, role := range []string{ |
||||
RoleEndpointSlice.String(), |
||||
RoleEndpoint.String(), |
||||
RoleNode.String(), |
||||
RolePod.String(), |
||||
RoleService.String(), |
||||
RoleIngress.String(), |
||||
} { |
||||
for _, evt := range []string{ |
||||
MetricLabelRoleAdd, |
||||
MetricLabelRoleDelete, |
||||
MetricLabelRoleUpdate, |
||||
} { |
||||
m.eventCount.WithLabelValues(role, evt) |
||||
} |
||||
} |
||||
|
||||
m.failuresCount.Add(0) |
||||
|
||||
return m |
||||
} |
||||
|
||||
// Register implements discovery.DiscovererMetrics.
|
||||
func (m *kubernetesMetrics) Register() error { |
||||
return m.metricRegisterer.RegisterMetrics() |
||||
} |
||||
|
||||
// Unregister implements discovery.DiscovererMetrics.
|
||||
func (m *kubernetesMetrics) Unregister() { |
||||
m.metricRegisterer.UnregisterMetrics() |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue