Merge pull request #95 from grafana/update-prometheus-2022-01-03

Update prometheus to `a961062c37f1675d5925d8b74ddda0a6322ed82d`
This commit is contained in:
Peter Štibraný 2022-01-03 12:47:14 +01:00 committed by GitHub
commit 5205ff1a81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 1252 additions and 435 deletions

View file

@ -2,7 +2,7 @@
version: 2.1 version: 2.1
orbs: orbs:
prometheus: prometheus/prometheus@0.14.0 prometheus: prometheus/prometheus@0.15.0
go: circleci/go@1.7.0 go: circleci/go@1.7.0
win: circleci/windows@2.3.0 win: circleci/windows@2.3.0
@ -12,9 +12,9 @@ executors:
golang: golang:
docker: docker:
- image: quay.io/prometheus/golang-builder:1.17-base - image: quay.io/prometheus/golang-builder:1.17-base
golang_115: golang_oldest:
docker: docker:
- image: quay.io/prometheus/golang-builder:1.15-base - image: quay.io/prometheus/golang-builder:1.16-base
jobs: jobs:
test_go: test_go:
@ -89,10 +89,11 @@ jobs:
GOGC: "20" GOGC: "20"
GOOPTS: "-p 2" GOOPTS: "-p 2"
test_tsdb_go115: test_golang_oldest:
executor: golang_115 executor: golang_oldest
steps: steps:
- checkout - checkout
- run: make build
- run: go test ./tsdb/... - run: go test ./tsdb/...
- run: go test ./tsdb/ -test.tsdb-isolation=false - run: go test ./tsdb/ -test.tsdb-isolation=false
@ -128,7 +129,7 @@ workflows:
filters: filters:
tags: tags:
only: /.*/ only: /.*/
- test_tsdb_go115: - test_golang_oldest:
filters: filters:
tags: tags:
only: /.*/ only: /.*/

View file

@ -6,6 +6,7 @@ updates:
interval: "weekly" interval: "weekly"
- package-ecosystem: "npm" - package-ecosystem: "npm"
directory: "/web/ui" directory: "/web/ui"
open-pull-requests-limit: 0
schedule: schedule:
interval: "weekly" interval: "weekly"
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"

View file

@ -1,18 +1,12 @@
## 2.32.0-rc.0 / 2021-12-01 ## 2.32.1 / 2021-12-17
This list of changes is relative to [v2.32.0-beta.0](https://github.com/prometheus/prometheus/releases/tag/v2.32.0-beta.0), which was a special 2.32 beta release to pre-publish the Prometheus Agent features. * [BUGFIX] Scrape: Fix reporting metrics when sample limit is reached during the report. #9996
* [BUGFIX] Scrape: Ensure that scrape interval and scrape timeout are always set. #10023
* [BUGFIX] TSDB: Expose and fix bug in iterators' `Seek()` method. #10030
* [FEATURE] TSDB: Add support for forwarding exemplars in Agent mode. #9664 ## 2.32.0 / 2021-12-09
* [FEATURE] UI: Adapt web UI for Prometheus Agent mode. #9851
* [ENHANCEMENT] Linode SD: Tune API request page sizes. #9779
* [BUGFIX] TSDB: Fix panic when checkpoint directory is empty. #9687
* [BUGFIX] TSDB: Fix panic, out of order chunks, and race warning during WAL replay. #9856
* [BUGFIX] UI: Correctly render links for targets with IPv6 addresses that contain a Zone ID. #9853
* [BUGFIX] Promtool: Fix checking of `authorization.credentials_file` and `bearer_token_file` fields. #9883
## 2.32.0-beta.0 / 2021-11-16 This release introduces the Prometheus Agent, a new mode of operation for
This beta release introduces the Prometheus Agent, a new mode of operation for
Prometheus optimized for remote-write only scenarios. In this mode, Prometheus Prometheus optimized for remote-write only scenarios. In this mode, Prometheus
does not generate blocks on the local filesystem and is not queryable locally. does not generate blocks on the local filesystem and is not queryable locally.
Enable with `--enable-feature=agent`. Enable with `--enable-feature=agent`.
@ -20,7 +14,7 @@ Enable with `--enable-feature=agent`.
Learn more about the Prometheus Agent in our [blog post](https://prometheus.io/blog/2021/11/16/agent/). Learn more about the Prometheus Agent in our [blog post](https://prometheus.io/blog/2021/11/16/agent/).
* [CHANGE] remote-write: Change default max retry time from 100ms to 5 seconds. #9634 * [CHANGE] remote-write: Change default max retry time from 100ms to 5 seconds. #9634
* [FEATURE] Agent: New mode of operation optimized for remote-write only scenarios, without local storage. Enable with `--enable-feature=agent`. #8785 * [FEATURE] Agent: New mode of operation optimized for remote-write only scenarios, without local storage. Enable with `--enable-feature=agent`. #8785 #9851 #9664 #9939 #9941 #9943
* [FEATURE] Promtool: Add `promtool check service-discovery` command. #8970 * [FEATURE] Promtool: Add `promtool check service-discovery` command. #8970
* [FEATURE] UI: Add search in metrics dropdown. #9629 * [FEATURE] UI: Add search in metrics dropdown. #9629
* [FEATURE] Templates: Add parseDuration to template functions. #8817 * [FEATURE] Templates: Add parseDuration to template functions. #8817
@ -32,8 +26,19 @@ Learn more about the Prometheus Agent in our [blog post](https://prometheus.io/b
* [ENHANCEMENT] TSDB: Optimize query by skipping unneeded sorting in TSDB. #9673 * [ENHANCEMENT] TSDB: Optimize query by skipping unneeded sorting in TSDB. #9673
* [ENHANCEMENT] Templates: Support int and uint as datatypes for template formatting. #9680 * [ENHANCEMENT] Templates: Support int and uint as datatypes for template formatting. #9680
* [ENHANCEMENT] UI: Prefer `rate` over `rad`, `delta` over `deg`, and `count` over `cos` in autocomplete. #9688 * [ENHANCEMENT] UI: Prefer `rate` over `rad`, `delta` over `deg`, and `count` over `cos` in autocomplete. #9688
* [ENHANCEMENT] Linode SD: Tune API request page sizes. #9779
* [BUGFIX] TSDB: Add more size checks when writing individual sections in the index. #9710 * [BUGFIX] TSDB: Add more size checks when writing individual sections in the index. #9710
* [BUGFIX] PromQL: Make `deriv()` return zero values for constant series. #9728 * [BUGFIX] PromQL: Make `deriv()` return zero values for constant series. #9728
* [BUGFIX] TSDB: Fix panic when checkpoint directory is empty. #9687
* [BUGFIX] TSDB: Fix panic, out of order chunks, and race warning during WAL replay. #9856
* [BUGFIX] UI: Correctly render links for targets with IPv6 addresses that contain a Zone ID. #9853
* [BUGFIX] Promtool: Fix checking of `authorization.credentials_file` and `bearer_token_file` fields. #9883
* [BUGFIX] Uyuni SD: Fix null pointer exception during initialization. #9924 #9950
* [BUGFIX] TSDB: Fix queries after a failed snapshot replay. #9980
## 2.31.2 / 2021-12-09
* [BUGFIX] TSDB: Fix queries after a failed snapshot replay. #9980
## 2.31.1 / 2021-11-05 ## 2.31.1 / 2021-11-05
@ -65,6 +70,10 @@ Learn more about the Prometheus Agent in our [blog post](https://prometheus.io/b
* [BUGFIX] TSDB: Fix memory leak in samples deletion. #9151 * [BUGFIX] TSDB: Fix memory leak in samples deletion. #9151
* [BUGFIX] UI: Use consistent margin-bottom for all alert kinds. #9318 * [BUGFIX] UI: Use consistent margin-bottom for all alert kinds. #9318
## 2.30.4 / 2021-12-09
* [BUGFIX] TSDB: Fix queries after a failed snapshot replay. #9980
## 2.30.3 / 2021-10-05 ## 2.30.3 / 2021-10-05
* [BUGFIX] TSDB: Fix panic on failed snapshot replay. #9438 * [BUGFIX] TSDB: Fix panic on failed snapshot replay. #9438

View file

@ -56,7 +56,7 @@ Prometheus will now be reachable at http://localhost:9090/.
### Building from source ### Building from source
To build Prometheus from source code, You need: To build Prometheus from source code, You need:
* Go [version 1.14 or greater](https://golang.org/doc/install). * Go [version 1.16 or greater](https://golang.org/doc/install).
* NodeJS [version 16 or greater](https://nodejs.org/). * NodeJS [version 16 or greater](https://nodejs.org/).
* npm [version 7 or greater](https://www.npmjs.com/). * npm [version 7 or greater](https://www.npmjs.com/).

View file

@ -1 +1 @@
2.32.0-rc.0 2.32.1

View file

@ -381,7 +381,7 @@ func main() {
serverOnlyFlag(a, "query.max-samples", "Maximum number of samples a single query can load into memory. Note that queries will fail if they try to load more samples than this into memory, so this also limits the number of samples a query can return."). serverOnlyFlag(a, "query.max-samples", "Maximum number of samples a single query can load into memory. Note that queries will fail if they try to load more samples than this into memory, so this also limits the number of samples a query can return.").
Default("50000000").IntVar(&cfg.queryMaxSamples) Default("50000000").IntVar(&cfg.queryMaxSamples)
a.Flag("enable-feature", "Comma separated feature names to enable. Valid options: exemplar-storage, expand-external-labels, memory-snapshot-on-shutdown, promql-at-modifier, promql-negative-offset, remote-write-receiver, extra-scrape-metrics, new-service-discovery-manager. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details."). a.Flag("enable-feature", "Comma separated feature names to enable. Valid options: agent, exemplar-storage, expand-external-labels, memory-snapshot-on-shutdown, promql-at-modifier, promql-negative-offset, remote-write-receiver, extra-scrape-metrics, new-service-discovery-manager. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details.").
Default("").StringsVar(&cfg.featureList) Default("").StringsVar(&cfg.featureList)
promlogflag.AddFlags(a, &cfg.promlogConfig) promlogflag.AddFlags(a, &cfg.promlogConfig)

View file

@ -56,6 +56,13 @@ import (
"github.com/prometheus/prometheus/scrape" "github.com/prometheus/prometheus/scrape"
) )
const (
successExitCode = 0
failureExitCode = 1
// Exit code 3 is used for "one or more lint issues detected".
lintErrExitCode = 3
)
func main() { func main() {
app := kingpin.New(filepath.Base(os.Args[0]), "Tooling for the Prometheus monitoring system.").UsageWriter(os.Stdout) app := kingpin.New(filepath.Base(os.Args[0]), "Tooling for the Prometheus monitoring system.").UsageWriter(os.Stdout)
app.Version(version.Print("promtool")) app.Version(version.Print("promtool"))
@ -298,9 +305,9 @@ func CheckConfig(agentMode, checkSyntaxOnly bool, files ...string) int {
} }
} }
if failed { if failed {
return 1 return failureExitCode
} }
return 0 return successExitCode
} }
// CheckWebConfig validates web configuration files. // CheckWebConfig validates web configuration files.
@ -316,9 +323,9 @@ func CheckWebConfig(files ...string) int {
fmt.Fprintln(os.Stderr, f, "SUCCESS") fmt.Fprintln(os.Stderr, f, "SUCCESS")
} }
if failed { if failed {
return 1 return failureExitCode
} }
return 0 return successExitCode
} }
func checkFileExists(fn string) error { func checkFileExists(fn string) error {
@ -521,9 +528,9 @@ func CheckRules(files ...string) int {
fmt.Println() fmt.Println()
} }
if failed { if failed {
return 1 return failureExitCode
} }
return 0 return successExitCode
} }
func checkRules(filename string) (int, []error) { func checkRules(filename string) (int, []error) {
@ -531,7 +538,7 @@ func checkRules(filename string) (int, []error) {
rgs, errs := rulefmt.ParseFile(filename) rgs, errs := rulefmt.ParseFile(filename)
if errs != nil { if errs != nil {
return 0, errs return successExitCode, errs
} }
numRules := 0 numRules := 0
@ -627,7 +634,7 @@ func CheckMetrics() int {
problems, err := l.Lint() problems, err := l.Lint()
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error while linting:", err) fmt.Fprintln(os.Stderr, "error while linting:", err)
return 1 return failureExitCode
} }
for _, p := range problems { for _, p := range problems {
@ -635,10 +642,10 @@ func CheckMetrics() int {
} }
if len(problems) > 0 { if len(problems) > 0 {
return 3 return lintErrExitCode
} }
return 0 return successExitCode
} }
// QueryInstant performs an instant query against a Prometheus server. // QueryInstant performs an instant query against a Prometheus server.
@ -654,7 +661,7 @@ func QueryInstant(url *url.URL, query, evalTime string, p printer) int {
c, err := api.NewClient(config) c, err := api.NewClient(config)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error creating API client:", err) fmt.Fprintln(os.Stderr, "error creating API client:", err)
return 1 return failureExitCode
} }
eTime := time.Now() eTime := time.Now()
@ -662,7 +669,7 @@ func QueryInstant(url *url.URL, query, evalTime string, p printer) int {
eTime, err = parseTime(evalTime) eTime, err = parseTime(evalTime)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error parsing evaluation time:", err) fmt.Fprintln(os.Stderr, "error parsing evaluation time:", err)
return 1 return failureExitCode
} }
} }
@ -678,7 +685,7 @@ func QueryInstant(url *url.URL, query, evalTime string, p printer) int {
p.printValue(val) p.printValue(val)
return 0 return successExitCode
} }
// QueryRange performs a range query against a Prometheus server. // QueryRange performs a range query against a Prometheus server.
@ -703,7 +710,7 @@ func QueryRange(url *url.URL, headers map[string]string, query, start, end strin
c, err := api.NewClient(config) c, err := api.NewClient(config)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error creating API client:", err) fmt.Fprintln(os.Stderr, "error creating API client:", err)
return 1 return failureExitCode
} }
var stime, etime time.Time var stime, etime time.Time
@ -714,7 +721,7 @@ func QueryRange(url *url.URL, headers map[string]string, query, start, end strin
etime, err = parseTime(end) etime, err = parseTime(end)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error parsing end time:", err) fmt.Fprintln(os.Stderr, "error parsing end time:", err)
return 1 return failureExitCode
} }
} }
@ -724,13 +731,13 @@ func QueryRange(url *url.URL, headers map[string]string, query, start, end strin
stime, err = parseTime(start) stime, err = parseTime(start)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error parsing start time:", err) fmt.Fprintln(os.Stderr, "error parsing start time:", err)
return 1 return failureExitCode
} }
} }
if !stime.Before(etime) { if !stime.Before(etime) {
fmt.Fprintln(os.Stderr, "start time is not before end time") fmt.Fprintln(os.Stderr, "start time is not before end time")
return 1 return failureExitCode
} }
if step == 0 { if step == 0 {
@ -751,7 +758,7 @@ func QueryRange(url *url.URL, headers map[string]string, query, start, end strin
} }
p.printValue(val) p.printValue(val)
return 0 return successExitCode
} }
// QuerySeries queries for a series against a Prometheus server. // QuerySeries queries for a series against a Prometheus server.
@ -767,13 +774,13 @@ func QuerySeries(url *url.URL, matchers []string, start, end string, p printer)
c, err := api.NewClient(config) c, err := api.NewClient(config)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error creating API client:", err) fmt.Fprintln(os.Stderr, "error creating API client:", err)
return 1 return failureExitCode
} }
stime, etime, err := parseStartTimeAndEndTime(start, end) stime, etime, err := parseStartTimeAndEndTime(start, end)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
return 1 return failureExitCode
} }
// Run query against client. // Run query against client.
@ -787,7 +794,7 @@ func QuerySeries(url *url.URL, matchers []string, start, end string, p printer)
} }
p.printSeries(val) p.printSeries(val)
return 0 return successExitCode
} }
// QueryLabels queries for label values against a Prometheus server. // QueryLabels queries for label values against a Prometheus server.
@ -803,13 +810,13 @@ func QueryLabels(url *url.URL, name, start, end string, p printer) int {
c, err := api.NewClient(config) c, err := api.NewClient(config)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error creating API client:", err) fmt.Fprintln(os.Stderr, "error creating API client:", err)
return 1 return failureExitCode
} }
stime, etime, err := parseStartTimeAndEndTime(start, end) stime, etime, err := parseStartTimeAndEndTime(start, end)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
return 1 return failureExitCode
} }
// Run query against client. // Run query against client.
@ -826,7 +833,7 @@ func QueryLabels(url *url.URL, name, start, end string, p printer) int {
} }
p.printLabelValues(val) p.printLabelValues(val)
return 0 return successExitCode
} }
func handleAPIError(err error) int { func handleAPIError(err error) int {
@ -837,7 +844,7 @@ func handleAPIError(err error) int {
fmt.Fprintln(os.Stderr, "query error:", err) fmt.Fprintln(os.Stderr, "query error:", err)
} }
return 1 return failureExitCode
} }
func parseStartTimeAndEndTime(start, end string) (time.Time, time.Time, error) { func parseStartTimeAndEndTime(start, end string) (time.Time, time.Time, error) {
@ -929,9 +936,9 @@ func debugPprof(url string) int {
endPointGroups: pprofEndpoints, endPointGroups: pprofEndpoints,
}); err != nil { }); err != nil {
fmt.Fprintln(os.Stderr, "error completing debug command:", err) fmt.Fprintln(os.Stderr, "error completing debug command:", err)
return 1 return failureExitCode
} }
return 0 return successExitCode
} }
func debugMetrics(url string) int { func debugMetrics(url string) int {
@ -941,9 +948,9 @@ func debugMetrics(url string) int {
endPointGroups: metricsEndpoints, endPointGroups: metricsEndpoints,
}); err != nil { }); err != nil {
fmt.Fprintln(os.Stderr, "error completing debug command:", err) fmt.Fprintln(os.Stderr, "error completing debug command:", err)
return 1 return failureExitCode
} }
return 0 return successExitCode
} }
func debugAll(url string) int { func debugAll(url string) int {
@ -953,9 +960,9 @@ func debugAll(url string) int {
endPointGroups: allEndpoints, endPointGroups: allEndpoints,
}); err != nil { }); err != nil {
fmt.Fprintln(os.Stderr, "error completing debug command:", err) fmt.Fprintln(os.Stderr, "error completing debug command:", err)
return 1 return failureExitCode
} }
return 0 return successExitCode
} }
type printer interface { type printer interface {

View file

@ -43,7 +43,7 @@ func CheckSD(sdConfigFiles, sdJobName string, sdTimeout time.Duration) int {
cfg, err := config.LoadFile(sdConfigFiles, false, false, logger) cfg, err := config.LoadFile(sdConfigFiles, false, false, logger)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "Cannot load config", err) fmt.Fprintln(os.Stderr, "Cannot load config", err)
return 2 return failureExitCode
} }
var scrapeConfig *config.ScrapeConfig var scrapeConfig *config.ScrapeConfig
@ -63,7 +63,7 @@ func CheckSD(sdConfigFiles, sdJobName string, sdTimeout time.Duration) int {
for _, job := range jobs { for _, job := range jobs {
fmt.Fprintf(os.Stderr, "\t%s\n", job) fmt.Fprintf(os.Stderr, "\t%s\n", job)
} }
return 1 return failureExitCode
} }
targetGroupChan := make(chan []*targetgroup.Group) targetGroupChan := make(chan []*targetgroup.Group)
@ -74,7 +74,7 @@ func CheckSD(sdConfigFiles, sdJobName string, sdTimeout time.Duration) int {
d, err := cfg.NewDiscoverer(discovery.DiscovererOptions{Logger: logger}) d, err := cfg.NewDiscoverer(discovery.DiscovererOptions{Logger: logger})
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "Could not create new discoverer", err) fmt.Fprintln(os.Stderr, "Could not create new discoverer", err)
return 2 return failureExitCode
} }
go d.Run(ctx, targetGroupChan) go d.Run(ctx, targetGroupChan)
} }
@ -100,11 +100,11 @@ outerLoop:
res, err := json.MarshalIndent(results, "", " ") res, err := json.MarshalIndent(results, "", " ")
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Could not marshal result json: %s", err) fmt.Fprintf(os.Stderr, "Could not marshal result json: %s", err)
return 2 return failureExitCode
} }
fmt.Printf("%s", res) fmt.Printf("%s", res)
return 0 return successExitCode
} }
func getSDCheckResult(targetGroups []*targetgroup.Group, scrapeConfig *config.ScrapeConfig) []sdCheckResult { func getSDCheckResult(targetGroups []*targetgroup.Group, scrapeConfig *config.ScrapeConfig) []sdCheckResult {

View file

@ -15,6 +15,7 @@ package main
import ( import (
"testing" "testing"
"time"
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
@ -37,6 +38,8 @@ func TestSDCheckResult(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
scrapeConfig := &config.ScrapeConfig{ scrapeConfig := &config.ScrapeConfig{
ScrapeInterval: model.Duration(1 * time.Minute),
ScrapeTimeout: model.Duration(10 * time.Second),
RelabelConfigs: []*relabel.Config{{ RelabelConfigs: []*relabel.Config{{
SourceLabels: model.LabelNames{"foo"}, SourceLabels: model.LabelNames{"foo"},
Action: relabel.Replace, Action: relabel.Replace,
@ -50,14 +53,14 @@ func TestSDCheckResult(t *testing.T) {
{ {
DiscoveredLabels: labels.Labels{ DiscoveredLabels: labels.Labels{
labels.Label{Name: "__address__", Value: "localhost:8080"}, labels.Label{Name: "__address__", Value: "localhost:8080"},
labels.Label{Name: "__scrape_interval__", Value: "0s"}, labels.Label{Name: "__scrape_interval__", Value: "1m"},
labels.Label{Name: "__scrape_timeout__", Value: "0s"}, labels.Label{Name: "__scrape_timeout__", Value: "10s"},
labels.Label{Name: "foo", Value: "bar"}, labels.Label{Name: "foo", Value: "bar"},
}, },
Labels: labels.Labels{ Labels: labels.Labels{
labels.Label{Name: "__address__", Value: "localhost:8080"}, labels.Label{Name: "__address__", Value: "localhost:8080"},
labels.Label{Name: "__scrape_interval__", Value: "0s"}, labels.Label{Name: "__scrape_interval__", Value: "1m"},
labels.Label{Name: "__scrape_timeout__", Value: "0s"}, labels.Label{Name: "__scrape_timeout__", Value: "10s"},
labels.Label{Name: "foo", Value: "bar"}, labels.Label{Name: "foo", Value: "bar"},
labels.Label{Name: "instance", Value: "localhost:8080"}, labels.Label{Name: "instance", Value: "localhost:8080"},
labels.Label{Name: "newfoo", Value: "bar"}, labels.Label{Name: "newfoo", Value: "bar"},

34
cmd/promtool/testdata/long-period.yml vendored Normal file
View file

@ -0,0 +1,34 @@
# Evaluate once every 100d to avoid this taking too long.
evaluation_interval: 100d
rule_files:
- rules.yml
tests:
- interval: 100d
input_series:
- series: test
# Max time in time.Duration is 106751d from 1970 (2^63/10^9), i.e. 2262.
# We use the nearest 100 days to that to ensure the unit tests can fully
# cover the expected range.
values: '0+1x1067'
promql_expr_test:
- expr: timestamp(test)
eval_time: 0m
exp_samples:
- value: 0
- expr: test
eval_time: 100d # one evaluation_interval.
exp_samples:
- labels: test
value: 1
- expr: timestamp(test)
eval_time: 106700d
exp_samples:
- value: 9218880000 # 106700d -> seconds.
- expr: fixed_data
eval_time: 106700d
exp_samples:
- labels: fixed_data
value: 1

View file

@ -56,9 +56,9 @@ func RulesUnitTest(queryOpts promql.LazyLoaderOpts, files ...string) int {
fmt.Println() fmt.Println()
} }
if failed { if failed {
return 1 return failureExitCode
} }
return 0 return successExitCode
} }
func ruleUnitTest(filename string, queryOpts promql.LazyLoaderOpts) []error { func ruleUnitTest(filename string, queryOpts promql.LazyLoaderOpts) []error {

View file

@ -36,6 +36,13 @@ func TestRulesUnitTest(t *testing.T) {
}, },
want: 0, want: 0,
}, },
{
name: "Long evaluation interval",
args: args{
files: []string{"./testdata/long-period.yml"},
},
want: 0,
},
{ {
name: "Bad input series", name: "Bad input series",
args: args{ args: args{

View file

@ -615,3 +615,86 @@ func TestEndpointsDiscoveryNamespaces(t *testing.T) {
}, },
}.Run(t) }.Run(t)
} }
func TestEndpointsDiscoveryOwnNamespace(t *testing.T) {
epOne := makeEndpoints()
epOne.Namespace = "own-ns"
epTwo := makeEndpoints()
epTwo.Namespace = "non-own-ns"
podOne := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "testpod",
Namespace: "own-ns",
UID: types.UID("deadbeef"),
},
Spec: v1.PodSpec{
NodeName: "testnode",
Containers: []v1.Container{
{
Name: "p1",
Ports: []v1.ContainerPort{
{
Name: "mainport",
ContainerPort: 9000,
Protocol: v1.ProtocolTCP,
},
},
},
},
},
Status: v1.PodStatus{
HostIP: "2.3.4.5",
PodIP: "4.3.2.1",
},
}
podTwo := podOne.DeepCopy()
podTwo.Namespace = "non-own-ns"
objs := []runtime.Object{
epOne,
epTwo,
podOne,
podTwo,
}
n, _ := makeDiscovery(RoleEndpoint, NamespaceDiscovery{IncludeOwnNamespace: true}, objs...)
k8sDiscoveryTest{
discovery: n,
expectedMaxItems: 1,
expectedRes: map[string]*targetgroup.Group{
"endpoints/own-ns/testendpoints": {
Targets: []model.LabelSet{
{
"__address__": "1.2.3.4:9000",
"__meta_kubernetes_endpoint_hostname": "testendpoint1",
"__meta_kubernetes_endpoint_node_name": "foobar",
"__meta_kubernetes_endpoint_port_name": "testport",
"__meta_kubernetes_endpoint_port_protocol": "TCP",
"__meta_kubernetes_endpoint_ready": "true",
},
{
"__address__": "2.3.4.5:9001",
"__meta_kubernetes_endpoint_port_name": "testport",
"__meta_kubernetes_endpoint_port_protocol": "TCP",
"__meta_kubernetes_endpoint_ready": "true",
},
{
"__address__": "2.3.4.5:9001",
"__meta_kubernetes_endpoint_port_name": "testport",
"__meta_kubernetes_endpoint_port_protocol": "TCP",
"__meta_kubernetes_endpoint_ready": "false",
},
},
Labels: model.LabelSet{
"__meta_kubernetes_namespace": "own-ns",
"__meta_kubernetes_endpoints_name": "testendpoints",
},
Source: "endpoints/own-ns/testendpoints",
},
},
}.Run(t)
}

View file

@ -630,3 +630,87 @@ func TestEndpointSliceDiscoveryNamespaces(t *testing.T) {
}, },
}.Run(t) }.Run(t)
} }
func TestEndpointSliceDiscoveryOwnNamespace(t *testing.T) {
epOne := makeEndpointSlice()
epOne.Namespace = "own-ns"
epTwo := makeEndpointSlice()
epTwo.Namespace = "non-own-ns"
podOne := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "testpod",
Namespace: "own-ns",
UID: types.UID("deadbeef"),
},
Spec: v1.PodSpec{
NodeName: "testnode",
Containers: []v1.Container{
{
Name: "p1",
Ports: []v1.ContainerPort{
{
Name: "mainport",
ContainerPort: 9000,
Protocol: v1.ProtocolTCP,
},
},
},
},
},
Status: v1.PodStatus{
HostIP: "2.3.4.5",
PodIP: "4.3.2.1",
},
}
podTwo := podOne.DeepCopy()
podTwo.Namespace = "non-own-ns"
objs := []runtime.Object{
epOne,
epTwo,
podOne,
podTwo,
}
n, _ := makeDiscovery(RoleEndpointSlice, NamespaceDiscovery{IncludeOwnNamespace: true}, objs...)
k8sDiscoveryTest{
discovery: n,
expectedMaxItems: 1,
expectedRes: map[string]*targetgroup.Group{
"endpointslice/own-ns/testendpoints": {
Targets: []model.LabelSet{
{
"__address__": "1.2.3.4:9000",
"__meta_kubernetes_endpointslice_endpoint_hostname": "testendpoint1",
"__meta_kubernetes_endpointslice_port": "9000",
"__meta_kubernetes_endpointslice_port_name": "testport",
"__meta_kubernetes_endpointslice_port_protocol": "TCP",
},
{
"__address__": "2.3.4.5:9000",
"__meta_kubernetes_endpointslice_endpoint_conditions_ready": "true",
"__meta_kubernetes_endpointslice_port": "9000",
"__meta_kubernetes_endpointslice_port_name": "testport",
"__meta_kubernetes_endpointslice_port_protocol": "TCP",
},
{
"__address__": "3.4.5.6:9000",
"__meta_kubernetes_endpointslice_endpoint_conditions_ready": "false",
"__meta_kubernetes_endpointslice_port": "9000",
"__meta_kubernetes_endpointslice_port_name": "testport",
"__meta_kubernetes_endpointslice_port_protocol": "TCP",
},
},
Labels: model.LabelSet{
"__meta_kubernetes_endpointslice_address_type": "IPv4",
"__meta_kubernetes_endpointslice_name": "testendpoints",
"__meta_kubernetes_namespace": "own-ns",
},
Source: "endpointslice/own-ns/testendpoints",
},
},
}.Run(t)
}

View file

@ -323,3 +323,21 @@ func TestIngressDiscoveryNamespacesV1beta1(t *testing.T) {
expectedRes: expected, expectedRes: expected,
}.Run(t) }.Run(t)
} }
func TestIngressDiscoveryOwnNamespace(t *testing.T) {
n, c := makeDiscovery(RoleIngress, NamespaceDiscovery{IncludeOwnNamespace: true})
expected := expectedTargetGroups("own-ns", TLSNo)
k8sDiscoveryTest{
discovery: n,
afterStart: func() {
for _, ns := range []string{"own-ns", "non-own-ns"} {
obj := makeIngress(TLSNo)
obj.Namespace = ns
c.NetworkingV1().Ingresses(obj.Namespace).Create(context.Background(), obj, metav1.CreateOptions{})
}
},
expectedMaxItems: 1,
expectedRes: expected,
}.Run(t)
}

View file

@ -16,6 +16,7 @@ package kubernetes
import ( import (
"context" "context"
"fmt" "fmt"
"io/ioutil"
"reflect" "reflect"
"strings" "strings"
"sync" "sync"
@ -48,7 +49,7 @@ import (
) )
const ( const (
// kubernetesMetaLabelPrefix is the meta prefix used for all meta labels. // metaLabelPrefix is the meta prefix used for all meta labels.
// in this discovery. // in this discovery.
metaLabelPrefix = model.MetaLabelPrefix + "kubernetes_" metaLabelPrefix = model.MetaLabelPrefix + "kubernetes_"
namespaceLabel = metaLabelPrefix + "namespace" namespaceLabel = metaLabelPrefix + "namespace"
@ -230,7 +231,8 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
// NamespaceDiscovery is the configuration for discovering // NamespaceDiscovery is the configuration for discovering
// Kubernetes namespaces. // Kubernetes namespaces.
type NamespaceDiscovery struct { type NamespaceDiscovery struct {
Names []string `yaml:"names"` IncludeOwnNamespace bool `yaml:"own_namespace"`
Names []string `yaml:"names"`
} }
// UnmarshalYAML implements the yaml.Unmarshaler interface. // UnmarshalYAML implements the yaml.Unmarshaler interface.
@ -250,13 +252,21 @@ type Discovery struct {
namespaceDiscovery *NamespaceDiscovery namespaceDiscovery *NamespaceDiscovery
discoverers []discovery.Discoverer discoverers []discovery.Discoverer
selectors roleSelector selectors roleSelector
ownNamespace string
} }
func (d *Discovery) getNamespaces() []string { func (d *Discovery) getNamespaces() []string {
namespaces := d.namespaceDiscovery.Names namespaces := d.namespaceDiscovery.Names
if len(namespaces) == 0 { includeOwnNamespace := d.namespaceDiscovery.IncludeOwnNamespace
namespaces = []string{apiv1.NamespaceAll}
if len(namespaces) == 0 && !includeOwnNamespace {
return []string{apiv1.NamespaceAll}
} }
if includeOwnNamespace {
return append(namespaces, d.ownNamespace)
}
return namespaces return namespaces
} }
@ -299,6 +309,12 @@ func New(l log.Logger, conf *SDConfig) (*Discovery, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
ownNamespace, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
if err != nil {
return nil, fmt.Errorf("could not determine the pod's namespace: %w", err)
}
return &Discovery{ return &Discovery{
client: c, client: c,
logger: l, logger: l,
@ -306,6 +322,7 @@ func New(l log.Logger, conf *SDConfig) (*Discovery, error) {
namespaceDiscovery: &conf.NamespaceDiscovery, namespaceDiscovery: &conf.NamespaceDiscovery,
discoverers: make([]discovery.Discoverer, 0), discoverers: make([]discovery.Discoverer, 0),
selectors: mapSelector(conf.Selectors), selectors: mapSelector(conf.Selectors),
ownNamespace: string(ownNamespace),
}, nil }, nil
} }

View file

@ -54,6 +54,7 @@ func makeDiscoveryWithVersion(role Role, nsDiscovery NamespaceDiscovery, k8sVer
logger: log.NewNopLogger(), logger: log.NewNopLogger(),
role: role, role: role,
namespaceDiscovery: &nsDiscovery, namespaceDiscovery: &nsDiscovery,
ownNamespace: "own-ns",
}, clientset }, clientset
} }

View file

@ -389,3 +389,21 @@ func TestPodDiscoveryNamespaces(t *testing.T) {
expectedRes: expected, expectedRes: expected,
}.Run(t) }.Run(t)
} }
func TestPodDiscoveryOwnNamespace(t *testing.T) {
n, c := makeDiscovery(RolePod, NamespaceDiscovery{IncludeOwnNamespace: true})
expected := expectedPodTargetGroups("own-ns")
k8sDiscoveryTest{
discovery: n,
beforeRun: func() {
for _, ns := range []string{"own-ns", "non-own-ns"} {
pod := makePods()
pod.Namespace = ns
c.CoreV1().Pods(pod.Namespace).Create(context.Background(), pod, metav1.CreateOptions{})
}
},
expectedMaxItems: 1,
expectedRes: expected,
}.Run(t)
}

View file

@ -254,3 +254,87 @@ func TestServiceDiscoveryNamespaces(t *testing.T) {
}, },
}.Run(t) }.Run(t)
} }
func TestServiceDiscoveryOwnNamespace(t *testing.T) {
n, c := makeDiscovery(RoleService, NamespaceDiscovery{IncludeOwnNamespace: true})
k8sDiscoveryTest{
discovery: n,
afterStart: func() {
for _, ns := range []string{"own-ns", "non-own-ns"} {
obj := makeService()
obj.Namespace = ns
c.CoreV1().Services(obj.Namespace).Create(context.Background(), obj, metav1.CreateOptions{})
}
},
expectedMaxItems: 1,
expectedRes: map[string]*targetgroup.Group{
"svc/own-ns/testservice": {
Targets: []model.LabelSet{
{
"__meta_kubernetes_service_port_protocol": "TCP",
"__address__": "testservice.own-ns.svc:30900",
"__meta_kubernetes_service_type": "ClusterIP",
"__meta_kubernetes_service_cluster_ip": "10.0.0.1",
"__meta_kubernetes_service_port_name": "testport",
},
},
Labels: model.LabelSet{
"__meta_kubernetes_service_name": "testservice",
"__meta_kubernetes_namespace": "own-ns",
},
Source: "svc/own-ns/testservice",
},
},
}.Run(t)
}
func TestServiceDiscoveryAllNamespaces(t *testing.T) {
n, c := makeDiscovery(RoleService, NamespaceDiscovery{})
k8sDiscoveryTest{
discovery: n,
afterStart: func() {
for _, ns := range []string{"own-ns", "non-own-ns"} {
obj := makeService()
obj.Namespace = ns
c.CoreV1().Services(obj.Namespace).Create(context.Background(), obj, metav1.CreateOptions{})
}
},
expectedMaxItems: 2,
expectedRes: map[string]*targetgroup.Group{
"svc/own-ns/testservice": {
Targets: []model.LabelSet{
{
"__meta_kubernetes_service_port_protocol": "TCP",
"__address__": "testservice.own-ns.svc:30900",
"__meta_kubernetes_service_type": "ClusterIP",
"__meta_kubernetes_service_cluster_ip": "10.0.0.1",
"__meta_kubernetes_service_port_name": "testport",
},
},
Labels: model.LabelSet{
"__meta_kubernetes_service_name": "testservice",
"__meta_kubernetes_namespace": "own-ns",
},
Source: "svc/own-ns/testservice",
},
"svc/non-own-ns/testservice": {
Targets: []model.LabelSet{
{
"__meta_kubernetes_service_port_protocol": "TCP",
"__address__": "testservice.non-own-ns.svc:30900",
"__meta_kubernetes_service_type": "ClusterIP",
"__meta_kubernetes_service_cluster_ip": "10.0.0.1",
"__meta_kubernetes_service_port_name": "testport",
},
},
Labels: model.LabelSet{
"__meta_kubernetes_service_name": "testservice",
"__meta_kubernetes_namespace": "non-own-ns",
},
Source: "svc/non-own-ns/testservice",
},
},
}.Run(t)
}

View file

@ -1607,15 +1607,15 @@ Available meta labels:
* `__meta_kubernetes_endpointslice_name`: The name of endpointslice object. * `__meta_kubernetes_endpointslice_name`: The name of endpointslice object.
* For all targets discovered directly from the endpointslice list (those not additionally inferred * For all targets discovered directly from the endpointslice list (those not additionally inferred
from underlying pods), the following labels are attached: from underlying pods), the following labels are attached:
* `__meta_kubernetes_endpointslice_address_target_kind`: Kind of the referenced object. * `__meta_kubernetes_endpointslice_address_target_kind`: Kind of the referenced object.
* `__meta_kubernetes_endpointslice_address_target_name`: Name of referenced object. * `__meta_kubernetes_endpointslice_address_target_name`: Name of referenced object.
* `__meta_kubernetes_endpointslice_address_type`: The ip protocol family of the address of the target. * `__meta_kubernetes_endpointslice_address_type`: The ip protocol family of the address of the target.
* `__meta_kubernetes_endpointslice_endpoint_conditions_ready`: Set to `true` or `false` for the referenced endpoint's ready state. * `__meta_kubernetes_endpointslice_endpoint_conditions_ready`: Set to `true` or `false` for the referenced endpoint's ready state.
* `__meta_kubernetes_endpointslice_endpoint_topology_kubernetes_io_hostname`: Name of the node hosting the referenced endpoint. * `__meta_kubernetes_endpointslice_endpoint_topology_kubernetes_io_hostname`: Name of the node hosting the referenced endpoint.
* `__meta_kubernetes_endpointslice_endpoint_topology_present_kubernetes_io_hostname`: Flag that shows if the referenced object has a kubernetes.io/hostname annotation. * `__meta_kubernetes_endpointslice_endpoint_topology_present_kubernetes_io_hostname`: Flag that shows if the referenced object has a kubernetes.io/hostname annotation.
* `__meta_kubernetes_endpointslice_port`: Port of the referenced endpoint. * `__meta_kubernetes_endpointslice_port`: Port of the referenced endpoint.
* `__meta_kubernetes_endpointslice_port_name`: Named port of the referenced endpoint. * `__meta_kubernetes_endpointslice_port_name`: Named port of the referenced endpoint.
* `__meta_kubernetes_endpointslice_port_protocol`: Protocol of the referenced endpoint. * `__meta_kubernetes_endpointslice_port_protocol`: Protocol of the referenced endpoint.
* If the endpoints belong to a service, all labels of the `role: service` discovery are attached. * If the endpoints belong to a service, all labels of the `role: service` discovery are attached.
* For all targets backed by a pod, all labels of the `role: pod` discovery are attached. * For all targets backed by a pod, all labels of the `role: pod` discovery are attached.
@ -1694,6 +1694,7 @@ tls_config:
# Optional namespace discovery. If omitted, all namespaces are used. # Optional namespace discovery. If omitted, all namespaces are used.
namespaces: namespaces:
own_namespace: <bool>
names: names:
[ - <string> ] [ - <string> ]

View file

@ -70,6 +70,7 @@ versions.
| title | string | string | [strings.Title](https://golang.org/pkg/strings/#Title), capitalises first character of each word.| | title | string | string | [strings.Title](https://golang.org/pkg/strings/#Title), capitalises first character of each word.|
| toUpper | string | string | [strings.ToUpper](https://golang.org/pkg/strings/#ToUpper), converts all characters to upper case.| | toUpper | string | string | [strings.ToUpper](https://golang.org/pkg/strings/#ToUpper), converts all characters to upper case.|
| toLower | string | string | [strings.ToLower](https://golang.org/pkg/strings/#ToLower), converts all characters to lower case.| | toLower | string | string | [strings.ToLower](https://golang.org/pkg/strings/#ToLower), converts all characters to lower case.|
| stripPort | string | string | [net.SplitHostPort](https://pkg.go.dev/net#SplitHostPort), splits string into host and port, then returns only host.|
| match | pattern, text | boolean | [regexp.MatchString](https://golang.org/pkg/regexp/#MatchString) Tests for a unanchored regexp match. | | match | pattern, text | boolean | [regexp.MatchString](https://golang.org/pkg/regexp/#MatchString) Tests for a unanchored regexp match. |
| reReplaceAll | pattern, replacement, text | string | [Regexp.ReplaceAllString](https://golang.org/pkg/regexp/#Regexp.ReplaceAllString) Regexp substitution, unanchored. | | reReplaceAll | pattern, replacement, text | string | [Regexp.ReplaceAllString](https://golang.org/pkg/regexp/#Regexp.ReplaceAllString) Regexp substitution, unanchored. |
| graphLink | expr | string | Returns path to graph view in the [expression browser](https://prometheus.io/docs/visualization/browser/) for the expression. | | graphLink | expr | string | Returns path to graph view in the [expression browser](https://prometheus.io/docs/visualization/browser/) for the expression. |

34
go.mod
View file

@ -1,23 +1,23 @@
module github.com/prometheus/prometheus module github.com/prometheus/prometheus
go 1.14 go 1.16
require ( require (
github.com/Azure/azure-sdk-for-go v59.4.0+incompatible github.com/Azure/azure-sdk-for-go v60.3.0+incompatible
github.com/Azure/go-autorest/autorest v0.11.22 github.com/Azure/go-autorest/autorest v0.11.23
github.com/Azure/go-autorest/autorest/adal v0.9.17 github.com/Azure/go-autorest/autorest/adal v0.9.18
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a
github.com/aws/aws-sdk-go v1.42.20 github.com/aws/aws-sdk-go v1.42.25
github.com/cespare/xxhash/v2 v2.1.2 github.com/cespare/xxhash/v2 v2.1.2
github.com/containerd/containerd v1.5.7 // indirect github.com/containerd/containerd v1.5.7 // indirect
github.com/dennwc/varint v1.0.0 github.com/dennwc/varint v1.0.0
github.com/dgryski/go-sip13 v0.0.0-20200911182023-62edffca9245 github.com/dgryski/go-sip13 v0.0.0-20200911182023-62edffca9245
github.com/digitalocean/godo v1.73.0 github.com/digitalocean/godo v1.73.0
github.com/docker/docker v20.10.11+incompatible github.com/docker/docker v20.10.12+incompatible
github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-connections v0.4.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 github.com/edsrzf/mmap-go v1.1.0
github.com/envoyproxy/go-control-plane v0.10.1 github.com/envoyproxy/go-control-plane v0.10.1
github.com/envoyproxy/protoc-gen-validate v0.6.2 github.com/envoyproxy/protoc-gen-validate v0.6.2
github.com/fsnotify/fsnotify v1.5.1 github.com/fsnotify/fsnotify v1.5.1
@ -28,15 +28,15 @@ require (
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
github.com/golang/snappy v0.0.4 github.com/golang/snappy v0.0.4
github.com/google/pprof v0.0.0-20211122183932-1daafda22083 github.com/google/pprof v0.0.0-20211122183932-1daafda22083
github.com/gophercloud/gophercloud v0.23.0 github.com/gophercloud/gophercloud v0.24.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/hashicorp/consul/api v1.11.0 github.com/hashicorp/consul/api v1.12.0
github.com/hetznercloud/hcloud-go v1.33.1 github.com/hetznercloud/hcloud-go v1.33.1
github.com/influxdata/influxdb v1.9.5 github.com/influxdata/influxdb v1.9.5
github.com/json-iterator/go v1.1.12 github.com/json-iterator/go v1.1.12
github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b
github.com/linode/linodego v1.2.1 github.com/linode/linodego v1.2.1
github.com/miekg/dns v1.1.43 github.com/miekg/dns v1.1.45
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/morikuni/aec v1.0.0 // indirect github.com/morikuni/aec v1.0.0 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
@ -50,23 +50,23 @@ require (
github.com/prometheus/client_model v0.2.0 github.com/prometheus/client_model v0.2.0
github.com/prometheus/common v0.32.1 github.com/prometheus/common v0.32.1
github.com/prometheus/common/sigv4 v0.1.0 github.com/prometheus/common/sigv4 v0.1.0
github.com/prometheus/exporter-toolkit v0.7.0 github.com/prometheus/exporter-toolkit v0.7.1
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210223165440-c65ae3540d44 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210223165440-c65ae3540d44
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/uber/jaeger-client-go v2.29.1+incompatible github.com/uber/jaeger-client-go v2.30.0+incompatible
github.com/uber/jaeger-lib v2.4.1+incompatible github.com/uber/jaeger-lib v2.4.1+incompatible
go.uber.org/atomic v1.9.0 go.uber.org/atomic v1.9.0
go.uber.org/goleak v1.1.12 go.uber.org/goleak v1.1.12
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 golang.org/x/net v0.0.0-20211209124913-491a49abca63
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
golang.org/x/tools v0.1.8 golang.org/x/tools v0.1.8
google.golang.org/api v0.61.0 google.golang.org/api v0.63.0
google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa
google.golang.org/protobuf v1.27.1 google.golang.org/protobuf v1.27.1
gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
@ -75,7 +75,7 @@ require (
k8s.io/apimachinery v0.22.4 k8s.io/apimachinery v0.22.4
k8s.io/client-go v0.22.4 k8s.io/client-go v0.22.4
k8s.io/klog v1.0.0 k8s.io/klog v1.0.0
k8s.io/klog/v2 v2.20.0 k8s.io/klog/v2 v2.30.0
) )
replace ( replace (

85
go.sum
View file

@ -26,8 +26,9 @@ cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWc
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.99.0 h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -51,8 +52,8 @@ collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v41.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v41.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v59.4.0+incompatible h1:gDA8odnngdNd3KYHL2NoK1j9vpWBgEnFSjKKLpkC8Aw= github.com/Azure/azure-sdk-for-go v60.3.0+incompatible h1:u6EXgnASaUOh38GXCwEpRs+u2bbfJpJpXeB42kU2cjg=
github.com/Azure/azure-sdk-for-go v59.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v60.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
@ -64,8 +65,8 @@ github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUd
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
github.com/Azure/go-autorest/autorest v0.11.9/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest v0.11.9/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest v0.11.22 h1:bXiQwDjrRmBQOE67bwlvUKAC1EU1yZTPQ38c+bstZws= github.com/Azure/go-autorest/autorest v0.11.23 h1:bRQWsW25/YkoxnIqXMPF94JW33qWDcrPMZ3bINaAruU=
github.com/Azure/go-autorest/autorest v0.11.22/go.mod h1:BAWYUWGPEtKPzjVkp0Q6an0MJcJDsoh5Z1BFAEFs4Xs= github.com/Azure/go-autorest/autorest v0.11.23/go.mod h1:BAWYUWGPEtKPzjVkp0Q6an0MJcJDsoh5Z1BFAEFs4Xs=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
@ -73,8 +74,8 @@ github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQW
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.17 h1:esOPl2dhcz9P3jqBSJ8tPGEj2EqzPPT6zfyuloiogKY= github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ=
github.com/Azure/go-autorest/autorest/adal v0.9.17/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.3/go.mod h1:4bJZhUhcq8LB20TruwHbAQsmUs2Xh+QR7utuJpLXX3A= github.com/Azure/go-autorest/autorest/azure/auth v0.5.3/go.mod h1:4bJZhUhcq8LB20TruwHbAQsmUs2Xh+QR7utuJpLXX3A=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM= github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
@ -187,8 +188,8 @@ github.com/aws/aws-sdk-go v1.30.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.40.11/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.40.11/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.42.20 h1:nQkkmTWK5N2Ao1iVzoOx1HTIxwbSWErxyZ1eiwLJWc4= github.com/aws/aws-sdk-go v1.42.25 h1:BbdvHAi+t9LRiaYUyd53noq9jcaAcfzOhSVbKfr6Avs=
github.com/aws/aws-sdk-go v1.42.20/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.42.25/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/benbjohnson/immutable v0.2.1/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI= github.com/benbjohnson/immutable v0.2.1/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI=
github.com/benbjohnson/tmpl v1.0.0/go.mod h1:igT620JFIi44B6awvU9IsDhR77IXWtFigTLil/RPdps= github.com/benbjohnson/tmpl v1.0.0/go.mod h1:igT620JFIi44B6awvU9IsDhR77IXWtFigTLil/RPdps=
@ -348,7 +349,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
@ -381,8 +381,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v20.10.11+incompatible h1:OqzI/g/W54LczvhnccGqniFoQghHx3pklbLuhfXpqGo= github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U=
github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
@ -401,8 +401,9 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
@ -739,8 +740,8 @@ github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.10.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss= github.com/gophercloud/gophercloud v0.10.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss=
github.com/gophercloud/gophercloud v0.23.0 h1:I3P10oKlGu3DHP9PrEWMr1ya+/+3Rc9uRHNkRZ9wO7g= github.com/gophercloud/gophercloud v0.24.0 h1:jDsIMGJ1KZpAjYfQgGI2coNQj5Q83oPzuiGJRFWgMzw=
github.com/gophercloud/gophercloud v0.23.0/go.mod h1:MRw6uyLj8uCGbIvBlqL7QW67t0QtNZnzydUzewo1Ioc= github.com/gophercloud/gophercloud v0.24.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
@ -763,8 +764,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/api v1.4.0/go.mod h1:xc8u05kyMa3Wjr9eEAsIAo3dg8+LywT5E/Cl7cNS5nU= github.com/hashicorp/consul/api v1.4.0/go.mod h1:xc8u05kyMa3Wjr9eEAsIAo3dg8+LywT5E/Cl7cNS5nU=
github.com/hashicorp/consul/api v1.11.0 h1:Hw/G8TtRvOElqxVIhBzXciiSTbapq8hZ2XKZsXk5ZCE= github.com/hashicorp/consul/api v1.12.0 h1:k3y1FYv6nuKyNTqj6w9gXOx5r5CfLj/k/euUeBXj1OY=
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/consul/sdk v0.4.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= github.com/hashicorp/consul/sdk v0.4.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM=
github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU= github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU=
@ -808,16 +809,17 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/memberlist v0.2.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.2.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.2.4 h1:OOhYzSvFnkFQXm1ysE8RjXTHsqSRDyP4emusC9K7DYg=
github.com/hashicorp/memberlist v0.2.4/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.2.4/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA=
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/serf v0.9.0/go.mod h1:YL0HO+FifKOW2u1ke99DGVu1zhcpZzNwrLIqBC7vbYU= github.com/hashicorp/serf v0.9.0/go.mod h1:YL0HO+FifKOW2u1ke99DGVu1zhcpZzNwrLIqBC7vbYU=
github.com/hashicorp/serf v0.9.5 h1:EBWvyu9tcRszt3Bxp3KNssBMP1KuHWyO51lz9+786iM= github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/hetznercloud/hcloud-go v1.33.1 h1:W1HdO2bRLTKU4WsyqAasDSpt54fYO4WNckWYfH5AuCQ= github.com/hetznercloud/hcloud-go v1.33.1 h1:W1HdO2bRLTKU4WsyqAasDSpt54fYO4WNckWYfH5AuCQ=
github.com/hetznercloud/hcloud-go v1.33.1/go.mod h1:XX/TQub3ge0yWR2yHWmnDVIrB+MQbda1pHxkUmDlUME= github.com/hetznercloud/hcloud-go v1.33.1/go.mod h1:XX/TQub3ge0yWR2yHWmnDVIrB+MQbda1pHxkUmDlUME=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@ -970,8 +972,9 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N
github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.45 h1:g5fRIhm9nx7g8osrAvgb16QJfmyMsyOCb+J7LSv+Qzk=
github.com/miekg/dns v1.1.45/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mileusna/useragent v0.0.0-20190129205925-3e331f0949a5/go.mod h1:JWhYAp2EXqUtsxTKdeGlY8Wp44M7VxThC9FEoNGi2IE= github.com/mileusna/useragent v0.0.0-20190129205925-3e331f0949a5/go.mod h1:JWhYAp2EXqUtsxTKdeGlY8Wp44M7VxThC9FEoNGi2IE=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
@ -1168,8 +1171,8 @@ github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+
github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4=
github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI=
github.com/prometheus/exporter-toolkit v0.6.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= github.com/prometheus/exporter-toolkit v0.6.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g=
github.com/prometheus/exporter-toolkit v0.7.0 h1:XtYeVeeC5daG4txbc9+mieKq+/AK4gtIBLl9Mulrjnk= github.com/prometheus/exporter-toolkit v0.7.1 h1:c6RXaK8xBVercEeUQ4tRNL8UGWzDHfvj9dseo1FcK1Y=
github.com/prometheus/exporter-toolkit v0.7.0/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= github.com/prometheus/exporter-toolkit v0.7.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@ -1288,8 +1291,8 @@ github.com/uber-go/tally v3.3.15+incompatible/go.mod h1:YDTIBxdXyOU/sCWilKB4bgyu
github.com/uber/athenadriver v1.1.4/go.mod h1:tQjho4NzXw55LGfSZEcETuYydpY1vtmixUabHkC1K/E= github.com/uber/athenadriver v1.1.4/go.mod h1:tQjho4NzXw55LGfSZEcETuYydpY1vtmixUabHkC1K/E=
github.com/uber/jaeger-client-go v2.23.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-client-go v2.28.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.28.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
@ -1417,8 +1420,9 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8=
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -1431,7 +1435,6 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
@ -1522,6 +1525,7 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@ -1529,8 +1533,9 @@ golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1672,8 +1677,10 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
@ -1777,6 +1784,7 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1787,10 +1795,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM=
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
@ -1822,8 +1828,9 @@ google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.61.0 h1:TXXKS1slM3b2bZNJwD5DV/Tp6/M2cLzLOLh9PjDhrw8=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.63.0 h1:n2bqqK895ygnBpdPDYetfy23K7fJ22wsrZKCyfuRkkA=
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -1898,8 +1905,9 @@ google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEc
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12 h1:DN5b3HU13J4sMd/QjDx34U6afpaexKTDdop+26pdjdk= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@ -1932,8 +1940,9 @@ google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1 h1:pnP7OclFFFgFi4VHQDQDaoXUVauOFyktqTsqqgzFKbc=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=

View file

@ -305,7 +305,7 @@ func newScrapePool(cfg *config.ScrapeConfig, app storage.Appendable, jitterSeed
return mutateSampleLabels(l, opts.target, opts.honorLabels, opts.mrc) return mutateSampleLabels(l, opts.target, opts.honorLabels, opts.mrc)
}, },
func(l labels.Labels) labels.Labels { return mutateReportSampleLabels(l, opts.target) }, func(l labels.Labels) labels.Labels { return mutateReportSampleLabels(l, opts.target) },
func(ctx context.Context) storage.Appender { return appender(app.Appender(ctx), opts.sampleLimit) }, func(ctx context.Context) storage.Appender { return app.Appender(ctx) },
cache, cache,
jitterSeed, jitterSeed,
opts.honorTimestamps, opts.honorTimestamps,
@ -1426,6 +1426,9 @@ func (sl *scrapeLoop) append(app storage.Appender, b []byte, contentType string,
e exemplar.Exemplar // escapes to heap so hoisted out of loop e exemplar.Exemplar // escapes to heap so hoisted out of loop
) )
// Take an appender with limits.
app = appender(app, sl.sampleLimit)
defer func() { defer func() {
if err != nil { if err != nil {
return return

View file

@ -463,7 +463,7 @@ func TestScrapePoolAppender(t *testing.T) {
appl, ok := loop.(*scrapeLoop) appl, ok := loop.(*scrapeLoop)
require.True(t, ok, "Expected scrapeLoop but got %T", loop) require.True(t, ok, "Expected scrapeLoop but got %T", loop)
wrapped := appl.appender(context.Background()) wrapped := appender(appl.appender(context.Background()), 0)
tl, ok := wrapped.(*timeLimitAppender) tl, ok := wrapped.(*timeLimitAppender)
require.True(t, ok, "Expected timeLimitAppender but got %T", wrapped) require.True(t, ok, "Expected timeLimitAppender but got %T", wrapped)
@ -471,20 +471,21 @@ func TestScrapePoolAppender(t *testing.T) {
_, ok = tl.Appender.(nopAppender) _, ok = tl.Appender.(nopAppender)
require.True(t, ok, "Expected base appender but got %T", tl.Appender) require.True(t, ok, "Expected base appender but got %T", tl.Appender)
sampleLimit := 100
loop = sp.newLoop(scrapeLoopOptions{ loop = sp.newLoop(scrapeLoopOptions{
target: &Target{}, target: &Target{},
sampleLimit: 100, sampleLimit: sampleLimit,
}) })
appl, ok = loop.(*scrapeLoop) appl, ok = loop.(*scrapeLoop)
require.True(t, ok, "Expected scrapeLoop but got %T", loop) require.True(t, ok, "Expected scrapeLoop but got %T", loop)
wrapped = appl.appender(context.Background()) wrapped = appender(appl.appender(context.Background()), sampleLimit)
sl, ok := wrapped.(*limitAppender) sl, ok := wrapped.(*limitAppender)
require.True(t, ok, "Expected limitAppender but got %T", wrapped) require.True(t, ok, "Expected limitAppender but got %T", wrapped)
tl, ok = sl.Appender.(*timeLimitAppender) tl, ok = sl.Appender.(*timeLimitAppender)
require.True(t, ok, "Expected limitAppender but got %T", sl.Appender) require.True(t, ok, "Expected timeLimitAppender but got %T", sl.Appender)
_, ok = tl.Appender.(nopAppender) _, ok = tl.Appender.(nopAppender)
require.True(t, ok, "Expected base appender but got %T", tl.Appender) require.True(t, ok, "Expected base appender but got %T", tl.Appender)
@ -2772,6 +2773,72 @@ func TestScrapeReportSingleAppender(t *testing.T) {
} }
} }
func TestScrapeReportLimit(t *testing.T) {
s := teststorage.New(t)
defer s.Close()
cfg := &config.ScrapeConfig{
JobName: "test",
SampleLimit: 5,
Scheme: "http",
ScrapeInterval: model.Duration(100 * time.Millisecond),
ScrapeTimeout: model.Duration(100 * time.Millisecond),
}
var (
scrapes int
scrapedTwice = make(chan bool)
)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "metric_a 44\nmetric_b 44\nmetric_c 44\nmetric_d 44\n")
scrapes++
if scrapes == 2 {
close(scrapedTwice)
}
}))
defer ts.Close()
sp, err := newScrapePool(cfg, s, 0, nil, false)
require.NoError(t, err)
defer sp.stop()
testURL, err := url.Parse(ts.URL)
require.NoError(t, err)
sp.Sync([]*targetgroup.Group{
{
Targets: []model.LabelSet{{model.AddressLabel: model.LabelValue(testURL.Host)}},
},
})
select {
case <-time.After(5 * time.Second):
t.Fatalf("target was not scraped twice")
case <-scrapedTwice:
// If the target has been scraped twice, report samples from the first
// scrape have been inserted in the database.
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
q, err := s.Querier(ctx, time.Time{}.UnixNano(), time.Now().UnixNano())
require.NoError(t, err)
defer q.Close()
series := q.Select(false, nil, labels.MustNewMatcher(labels.MatchRegexp, "__name__", "up"))
var found bool
for series.Next() {
i := series.At().Iterator()
for i.Next() {
_, v := i.At()
require.Equal(t, 1.0, v)
found = true
}
}
require.True(t, found)
}
func TestScrapeLoopLabelLimit(t *testing.T) { func TestScrapeLoopLabelLimit(t *testing.T) {
tests := []struct { tests := []struct {
title string title string

View file

@ -418,28 +418,22 @@ func PopulateLabels(lset labels.Labels, cfg *config.ScrapeConfig) (res, orig lab
return nil, nil, err return nil, nil, err
} }
var interval string interval := lset.Get(model.ScrapeIntervalLabel)
var intervalDuration model.Duration intervalDuration, err := model.ParseDuration(interval)
if interval = lset.Get(model.ScrapeIntervalLabel); interval != cfg.ScrapeInterval.String() { if err != nil {
intervalDuration, err = model.ParseDuration(interval) return nil, nil, errors.Errorf("error parsing scrape interval: %v", err)
if err != nil { }
return nil, nil, errors.Errorf("error parsing scrape interval: %v", err) if time.Duration(intervalDuration) == 0 {
} return nil, nil, errors.New("scrape interval cannot be 0")
if time.Duration(intervalDuration) == 0 {
return nil, nil, errors.New("scrape interval cannot be 0")
}
} }
var timeout string timeout := lset.Get(model.ScrapeTimeoutLabel)
var timeoutDuration model.Duration timeoutDuration, err := model.ParseDuration(timeout)
if timeout = lset.Get(model.ScrapeTimeoutLabel); timeout != cfg.ScrapeTimeout.String() { if err != nil {
timeoutDuration, err = model.ParseDuration(timeout) return nil, nil, errors.Errorf("error parsing scrape timeout: %v", err)
if err != nil { }
return nil, nil, errors.Errorf("error parsing scrape timeout: %v", err) if time.Duration(timeoutDuration) == 0 {
} return nil, nil, errors.New("scrape timeout cannot be 0")
if time.Duration(timeoutDuration) == 0 {
return nil, nil, errors.New("scrape timeout cannot be 0")
}
} }
if timeoutDuration > intervalDuration { if timeoutDuration > intervalDuration {

View file

@ -371,7 +371,11 @@ func TestNewClientWithBadTLSConfig(t *testing.T) {
func TestTargetsFromGroup(t *testing.T) { func TestTargetsFromGroup(t *testing.T) {
expectedError := "instance 0 in group : no address" expectedError := "instance 0 in group : no address"
targets, failures := TargetsFromGroup(&targetgroup.Group{Targets: []model.LabelSet{{}, {model.AddressLabel: "localhost:9090"}}}, &config.ScrapeConfig{}) cfg := config.ScrapeConfig{
ScrapeTimeout: model.Duration(10 * time.Second),
ScrapeInterval: model.Duration(1 * time.Minute),
}
targets, failures := TargetsFromGroup(&targetgroup.Group{Targets: []model.LabelSet{{}, {model.AddressLabel: "localhost:9090"}}}, &cfg)
if len(targets) != 1 { if len(targets) != 1 {
t.Fatalf("Expected 1 target, got %v", len(targets)) t.Fatalf("Expected 1 target, got %v", len(targets))
} }

View file

@ -360,6 +360,9 @@ func (c *concreteSeriesIterator) Seek(t int64) bool {
if c.cur == -1 { if c.cur == -1 {
c.cur = 0 c.cur = 0
} }
if c.cur >= len(c.series.samples) {
return false
}
// No-op check. // No-op check.
if s := c.series.samples[c.cur]; s.Timestamp >= t { if s := c.series.samples[c.cur]; s.Timestamp >= t {
return true return true

View file

@ -233,6 +233,11 @@ func TestConcreteSeriesIterator(t *testing.T) {
ts, v = it.At() ts, v = it.At()
require.Equal(t, int64(3), ts) require.Equal(t, int64(3), ts)
require.Equal(t, 3., v) require.Equal(t, 3., v)
// Seek beyond the end.
require.False(t, it.Seek(5))
// And we don't go back. (This exposes issue #10027.)
require.False(t, it.Seek(2))
} }
func TestFromQueryResultWithDuplicates(t *testing.T) { func TestFromQueryResultWithDuplicates(t *testing.T) {

View file

@ -507,7 +507,6 @@ func (t *QueueManager) sendMetadataWithBackoff(ctx context.Context, metadata []p
// Append queues a sample to be sent to the remote storage. Blocks until all samples are // Append queues a sample to be sent to the remote storage. Blocks until all samples are
// enqueued on their shards or a shutdown signal is received. // enqueued on their shards or a shutdown signal is received.
func (t *QueueManager) Append(samples []record.RefSample) bool { func (t *QueueManager) Append(samples []record.RefSample) bool {
var appendSample prompb.Sample
outer: outer:
for _, s := range samples { for _, s := range samples {
t.seriesMtx.Lock() t.seriesMtx.Lock()
@ -530,9 +529,12 @@ outer:
return false return false
default: default:
} }
appendSample.Value = s.V if t.shards.enqueue(s.Ref, sampleOrExemplar{
appendSample.Timestamp = s.T seriesLabels: lbls,
if t.shards.enqueue(s.Ref, writeSample{lbls, appendSample}) { timestamp: s.T,
value: s.V,
isSample: true,
}) {
continue outer continue outer
} }
@ -552,7 +554,6 @@ func (t *QueueManager) AppendExemplars(exemplars []record.RefExemplar) bool {
return true return true
} }
var appendExemplar prompb.Exemplar
outer: outer:
for _, e := range exemplars { for _, e := range exemplars {
t.seriesMtx.Lock() t.seriesMtx.Lock()
@ -576,10 +577,12 @@ outer:
return false return false
default: default:
} }
appendExemplar.Labels = labelsToLabelsProto(e.Labels, nil) if t.shards.enqueue(e.Ref, sampleOrExemplar{
appendExemplar.Timestamp = e.T seriesLabels: lbls,
appendExemplar.Value = e.V timestamp: e.T,
if t.shards.enqueue(e.Ref, writeExemplar{lbls, appendExemplar}) { value: e.V,
exemplarLabels: e.Labels,
}) {
continue outer continue outer
} }
@ -901,16 +904,6 @@ func (t *QueueManager) newShards() *shards {
return s return s
} }
type writeSample struct {
seriesLabels labels.Labels
sample prompb.Sample
}
type writeExemplar struct {
seriesLabels labels.Labels
exemplar prompb.Exemplar
}
type shards struct { type shards struct {
mtx sync.RWMutex // With the WAL, this is never actually contended. mtx sync.RWMutex // With the WAL, this is never actually contended.
@ -999,7 +992,7 @@ func (s *shards) stop() {
// enqueue data (sample or exemplar). If we are currently in the process of shutting down or resharding, // enqueue data (sample or exemplar). If we are currently in the process of shutting down or resharding,
// will return false; in this case, you should back off and retry. // will return false; in this case, you should back off and retry.
func (s *shards) enqueue(ref chunks.HeadSeriesRef, data interface{}) bool { func (s *shards) enqueue(ref chunks.HeadSeriesRef, data sampleOrExemplar) bool {
s.mtx.RLock() s.mtx.RLock()
defer s.mtx.RUnlock() defer s.mtx.RUnlock()
@ -1018,43 +1011,48 @@ func (s *shards) enqueue(ref chunks.HeadSeriesRef, data interface{}) bool {
if !appended { if !appended {
return false return false
} }
switch data.(type) { if data.isSample {
case writeSample:
s.qm.metrics.pendingSamples.Inc() s.qm.metrics.pendingSamples.Inc()
s.enqueuedSamples.Inc() s.enqueuedSamples.Inc()
case writeExemplar: } else {
s.qm.metrics.pendingExemplars.Inc() s.qm.metrics.pendingExemplars.Inc()
s.enqueuedExemplars.Inc() s.enqueuedExemplars.Inc()
default:
level.Warn(s.qm.logger).Log("msg", "Invalid object type in shards enqueue")
} }
return true return true
} }
} }
type queue struct { type queue struct {
batch []interface{} batch []sampleOrExemplar
batchQueue chan []interface{} batchQueue chan []sampleOrExemplar
// Since we know there are a limited number of batches out, using a stack // Since we know there are a limited number of batches out, using a stack
// is easy and safe so a sync.Pool is not necessary. // is easy and safe so a sync.Pool is not necessary.
batchPool [][]interface{} batchPool [][]sampleOrExemplar
// This mutex covers adding and removing batches from the batchPool. // This mutex covers adding and removing batches from the batchPool.
poolMux sync.Mutex poolMux sync.Mutex
} }
type sampleOrExemplar struct {
seriesLabels labels.Labels
value float64
timestamp int64
exemplarLabels labels.Labels
isSample bool
}
func newQueue(batchSize, capacity int) *queue { func newQueue(batchSize, capacity int) *queue {
batches := capacity / batchSize batches := capacity / batchSize
return &queue{ return &queue{
batch: make([]interface{}, 0, batchSize), batch: make([]sampleOrExemplar, 0, batchSize),
batchQueue: make(chan []interface{}, batches), batchQueue: make(chan []sampleOrExemplar, batches),
// batchPool should have capacity for everything in the channel + 1 for // batchPool should have capacity for everything in the channel + 1 for
// the batch being processed. // the batch being processed.
batchPool: make([][]interface{}, 0, batches+1), batchPool: make([][]sampleOrExemplar, 0, batches+1),
} }
} }
func (q *queue) Append(datum interface{}, stop <-chan struct{}) bool { func (q *queue) Append(datum sampleOrExemplar, stop <-chan struct{}) bool {
q.batch = append(q.batch, datum) q.batch = append(q.batch, datum)
if len(q.batch) == cap(q.batch) { if len(q.batch) == cap(q.batch) {
select { select {
@ -1070,20 +1068,20 @@ func (q *queue) Append(datum interface{}, stop <-chan struct{}) bool {
return true return true
} }
func (q *queue) Chan() <-chan []interface{} { func (q *queue) Chan() <-chan []sampleOrExemplar {
return q.batchQueue return q.batchQueue
} }
// Batch returns the current batch and allocates a new batch. Must not be // Batch returns the current batch and allocates a new batch. Must not be
// called concurrently with Append. // called concurrently with Append.
func (q *queue) Batch() []interface{} { func (q *queue) Batch() []sampleOrExemplar {
batch := q.batch batch := q.batch
q.batch = q.newBatch(cap(batch)) q.batch = q.newBatch(cap(batch))
return batch return batch
} }
// ReturnForReuse adds the batch buffer back to the internal pool. // ReturnForReuse adds the batch buffer back to the internal pool.
func (q *queue) ReturnForReuse(batch []interface{}) { func (q *queue) ReturnForReuse(batch []sampleOrExemplar) {
q.poolMux.Lock() q.poolMux.Lock()
defer q.poolMux.Unlock() defer q.poolMux.Unlock()
if len(q.batchPool) < cap(q.batchPool) { if len(q.batchPool) < cap(q.batchPool) {
@ -1106,7 +1104,7 @@ func (q *queue) FlushAndShutdown(done <-chan struct{}) {
close(q.batchQueue) close(q.batchQueue)
} }
func (q *queue) newBatch(capacity int) []interface{} { func (q *queue) newBatch(capacity int) []sampleOrExemplar {
q.poolMux.Lock() q.poolMux.Lock()
defer q.poolMux.Unlock() defer q.poolMux.Unlock()
batches := len(q.batchPool) batches := len(q.batchPool)
@ -1115,7 +1113,7 @@ func (q *queue) newBatch(capacity int) []interface{} {
q.batchPool = q.batchPool[:batches-1] q.batchPool = q.batchPool[:batches-1]
return batch return batch
} }
return make([]interface{}, 0, capacity) return make([]sampleOrExemplar, 0, capacity)
} }
func (s *shards) runShard(ctx context.Context, shardID int, queue *queue) { func (s *shards) runShard(ctx context.Context, shardID int, queue *queue) {
@ -1192,7 +1190,7 @@ func (s *shards) runShard(ctx context.Context, shardID int, queue *queue) {
// traffic instances. // traffic instances.
s.mtx.Lock() s.mtx.Lock()
// First, we need to see if we can happen to get a batch from the queue if it filled while acquiring the lock. // First, we need to see if we can happen to get a batch from the queue if it filled while acquiring the lock.
var batch []interface{} var batch []sampleOrExemplar
select { select {
case batch = <-batchQueue: case batch = <-batchQueue:
default: default:
@ -1211,9 +1209,9 @@ func (s *shards) runShard(ctx context.Context, shardID int, queue *queue) {
} }
} }
func (s *shards) populateTimeSeries(batch []interface{}, pendingData []prompb.TimeSeries) (int, int) { func (s *shards) populateTimeSeries(batch []sampleOrExemplar, pendingData []prompb.TimeSeries) (int, int) {
var nPendingSamples, nPendingExemplars int var nPendingSamples, nPendingExemplars int
for nPending, sample := range batch { for nPending, d := range batch {
pendingData[nPending].Samples = pendingData[nPending].Samples[:0] pendingData[nPending].Samples = pendingData[nPending].Samples[:0]
if s.qm.sendExemplars { if s.qm.sendExemplars {
pendingData[nPending].Exemplars = pendingData[nPending].Exemplars[:0] pendingData[nPending].Exemplars = pendingData[nPending].Exemplars[:0]
@ -1221,14 +1219,20 @@ func (s *shards) populateTimeSeries(batch []interface{}, pendingData []prompb.Ti
// Number of pending samples is limited by the fact that sendSamples (via sendSamplesWithBackoff) // Number of pending samples is limited by the fact that sendSamples (via sendSamplesWithBackoff)
// retries endlessly, so once we reach max samples, if we can never send to the endpoint we'll // retries endlessly, so once we reach max samples, if we can never send to the endpoint we'll
// stop reading from the queue. This makes it safe to reference pendingSamples by index. // stop reading from the queue. This makes it safe to reference pendingSamples by index.
switch d := sample.(type) { if d.isSample {
case writeSample:
pendingData[nPending].Labels = labelsToLabelsProto(d.seriesLabels, pendingData[nPending].Labels) pendingData[nPending].Labels = labelsToLabelsProto(d.seriesLabels, pendingData[nPending].Labels)
pendingData[nPending].Samples = append(pendingData[nPending].Samples, d.sample) pendingData[nPending].Samples = append(pendingData[nPending].Samples, prompb.Sample{
Value: d.value,
Timestamp: d.timestamp,
})
nPendingSamples++ nPendingSamples++
case writeExemplar: } else {
pendingData[nPending].Labels = labelsToLabelsProto(d.seriesLabels, pendingData[nPending].Labels) pendingData[nPending].Labels = labelsToLabelsProto(d.seriesLabels, pendingData[nPending].Labels)
pendingData[nPending].Exemplars = append(pendingData[nPending].Exemplars, d.exemplar) pendingData[nPending].Exemplars = append(pendingData[nPending].Exemplars, prompb.Exemplar{
Labels: labelsToLabelsProto(d.exemplarLabels, nil),
Value: d.value,
Timestamp: d.timestamp,
})
nPendingExemplars++ nPendingExemplars++
} }
} }

View file

@ -578,22 +578,6 @@ func (c *TestWriteClient) waitForExpectedData(tb testing.TB) {
} }
} }
func (c *TestWriteClient) expectDataCount(numSamples int) {
if !c.withWaitGroup {
return
}
c.mtx.Lock()
defer c.mtx.Unlock()
c.wg.Add(numSamples)
}
func (c *TestWriteClient) waitForExpectedDataCount() {
if !c.withWaitGroup {
return
}
c.wg.Wait()
}
func (c *TestWriteClient) Store(_ context.Context, req []byte) error { func (c *TestWriteClient) Store(_ context.Context, req []byte) error {
c.mtx.Lock() c.mtx.Lock()
defer c.mtx.Unlock() defer c.mtx.Unlock()
@ -682,7 +666,15 @@ func (c *TestBlockingWriteClient) Endpoint() string {
return "http://test-remote-blocking.com/1234" return "http://test-remote-blocking.com/1234"
} }
func BenchmarkSampleDelivery(b *testing.B) { // For benchmarking the send and not the receive side.
type NopWriteClient struct{}
func NewNopWriteClient() *NopWriteClient { return &NopWriteClient{} }
func (c *NopWriteClient) Store(_ context.Context, req []byte) error { return nil }
func (c *NopWriteClient) Name() string { return "nopwriteclient" }
func (c *NopWriteClient) Endpoint() string { return "http://test-remote.com/1234" }
func BenchmarkSampleSend(b *testing.B) {
// Send one sample per series, which is the typical remote_write case // Send one sample per series, which is the typical remote_write case
const numSamples = 1 const numSamples = 1
const numSeries = 10000 const numSeries = 10000
@ -707,12 +699,13 @@ func BenchmarkSampleDelivery(b *testing.B) {
} }
samples, series := createTimeseries(numSamples, numSeries, extraLabels...) samples, series := createTimeseries(numSamples, numSeries, extraLabels...)
c := NewTestWriteClient() c := NewNopWriteClient()
cfg := config.DefaultQueueConfig cfg := config.DefaultQueueConfig
mcfg := config.DefaultMetadataConfig mcfg := config.DefaultMetadataConfig
cfg.BatchSendDeadline = model.Duration(100 * time.Millisecond) cfg.BatchSendDeadline = model.Duration(100 * time.Millisecond)
cfg.MaxShards = 1 cfg.MinShards = 20
cfg.MaxShards = 20
dir := b.TempDir() dir := b.TempDir()
@ -726,11 +719,9 @@ func BenchmarkSampleDelivery(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
c.expectDataCount(len(samples)) m.Append(samples)
go m.Append(samples)
m.UpdateSeriesSegment(series, i+1) // simulate what wal.Watcher.garbageCollectSeries does m.UpdateSeriesSegment(series, i+1) // simulate what wal.Watcher.garbageCollectSeries does
m.SeriesReset(i + 1) m.SeriesReset(i + 1)
c.waitForExpectedDataCount()
} }
// Do not include shutdown // Do not include shutdown
b.StopTimer() b.StopTimer()

View file

@ -99,6 +99,9 @@ func (it *listSeriesIterator) Seek(t int64) bool {
if it.idx == -1 { if it.idx == -1 {
it.idx = 0 it.idx = 0
} }
if it.idx >= it.samples.Len() {
return false
}
// No-op check. // No-op check.
if s := it.samples.Get(it.idx); s.T() >= t { if s := it.samples.Get(it.idx); s.T() >= t {
return true return true

View file

@ -51,4 +51,9 @@ func TestListSeriesIterator(t *testing.T) {
ts, v = it.At() ts, v = it.At()
require.Equal(t, int64(3), ts) require.Equal(t, int64(3), ts)
require.Equal(t, 3., v) require.Equal(t, 3., v)
// Seek beyond the end.
require.False(t, it.Seek(5))
// And we don't go back. (This exposes issue #10027.)
require.False(t, it.Seek(2))
} }

View file

@ -19,6 +19,7 @@ import (
"fmt" "fmt"
html_template "html/template" html_template "html/template"
"math" "math"
"net"
"net/url" "net/url"
"regexp" "regexp"
"sort" "sort"
@ -184,6 +185,13 @@ func NewTemplateExpander(
sort.Stable(sorter) sort.Stable(sorter)
return v return v
}, },
"stripPort": func(hostPort string) string {
host, _, err := net.SplitHostPort(hostPort)
if err != nil {
return hostPort
}
return host
},
"humanize": func(i interface{}) (string, error) { "humanize": func(i interface{}) (string, error) {
v, err := convertToFloat(i) v, err := convertToFloat(i)
if err != nil { if err != nil {

View file

@ -161,6 +161,41 @@ func TestTemplateExpansion(t *testing.T) {
}, },
output: "a:11: b:21: ", output: "a:11: b:21: ",
}, },
{
// Simple hostname.
text: "{{ \"foo.example.com\" | stripPort }}",
output: "foo.example.com",
},
{
// Hostname with port.
text: "{{ \"foo.example.com:12345\" | stripPort }}",
output: "foo.example.com",
},
{
// Simple IPv4 address.
text: "{{ \"192.0.2.1\" | stripPort }}",
output: "192.0.2.1",
},
{
// IPv4 address with port.
text: "{{ \"192.0.2.1:12345\" | stripPort }}",
output: "192.0.2.1",
},
{
// Simple IPv6 address.
text: "{{ \"2001:0DB8::1\" | stripPort }}",
output: "2001:0DB8::1",
},
{
// IPv6 address with port.
text: "{{ \"[2001:0DB8::1]:12345\" | stripPort }}",
output: "2001:0DB8::1",
},
{
// Value can't be split into host and port.
text: "{{ \"[2001:0DB8::1]::12345\" | stripPort }}",
output: "[2001:0DB8::1]::12345",
},
{ {
// Missing value is no value for nil options. // Missing value is no value for nil options.
text: "{{ .Foo }}", text: "{{ .Foo }}",

View file

@ -103,11 +103,18 @@ func (h *headIndexReader) LabelNames(matchers ...*labels.Matcher) ([]string, err
// Postings returns the postings list iterator for the label pairs. // Postings returns the postings list iterator for the label pairs.
func (h *headIndexReader) Postings(name string, values ...string) (index.Postings, error) { func (h *headIndexReader) Postings(name string, values ...string) (index.Postings, error) {
res := make([]index.Postings, 0, len(values)) switch len(values) {
for _, value := range values { case 0:
res = append(res, h.head.postings.Get(name, value)) return index.EmptyPostings(), nil
case 1:
return h.head.postings.Get(name, values[0]), nil
default:
res := make([]index.Postings, 0, len(values))
for _, value := range values {
res = append(res, h.head.postings.Get(name, value))
}
return index.Merge(res...), nil
} }
return index.Merge(res...), nil
} }
func (h *headIndexReader) PostingsForMatchers(concurrent bool, ms ...*labels.Matcher) (index.Postings, error) { func (h *headIndexReader) PostingsForMatchers(concurrent bool, ms ...*labels.Matcher) (index.Postings, error) {

View file

@ -20,6 +20,8 @@ import (
"sort" "sort"
"sync" "sync"
"github.com/pkg/errors"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/storage"
) )
@ -853,3 +855,78 @@ type seriesRefSlice []storage.SeriesRef
func (x seriesRefSlice) Len() int { return len(x) } func (x seriesRefSlice) Len() int { return len(x) }
func (x seriesRefSlice) Less(i, j int) bool { return x[i] < x[j] } func (x seriesRefSlice) Less(i, j int) bool { return x[i] < x[j] }
func (x seriesRefSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] } func (x seriesRefSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
// FindIntersectingPostings checks the intersection of p and candidates[i] for each i in candidates,
// if intersection is non empty, then i is added to the indexes returned.
// Returned indexes are not sorted.
func FindIntersectingPostings(p Postings, candidates []Postings) (indexes []int, err error) {
h := make(postingsWithIndexHeap, 0, len(candidates))
for idx, it := range candidates {
if it.Next() {
h = append(h, postingsWithIndex{index: idx, p: it})
} else if it.Err() != nil {
return nil, it.Err()
}
}
if len(h) == 0 {
return nil, nil
}
h.Init()
for len(h) > 0 {
if !p.Seek(h.At()) {
return indexes, p.Err()
}
if p.At() == h.At() {
found := heap.Pop(&h).(postingsWithIndex)
indexes = append(indexes, found.index)
} else if err := h.Next(); err != nil {
return nil, err
}
}
return indexes, nil
}
type postingsWithIndex struct {
index int
p Postings
}
type postingsWithIndexHeap []postingsWithIndex
func (h *postingsWithIndexHeap) Init() { heap.Init(h) }
func (h postingsWithIndexHeap) At() storage.SeriesRef { return h[0].p.At() }
func (h *postingsWithIndexHeap) Next() error {
pi := (*h)[0]
next := pi.p.Next()
if next {
heap.Fix(h, 0)
return nil
}
if err := pi.p.Err(); err != nil {
return errors.Wrapf(err, "postings %d", pi.index)
}
heap.Pop(h)
return nil
}
func (h postingsWithIndexHeap) Len() int { return len(h) }
func (h postingsWithIndexHeap) Less(i, j int) bool { return h[i].p.At() < h[j].p.At() }
func (h *postingsWithIndexHeap) Swap(i, j int) { (*h)[i], (*h)[j] = (*h)[j], (*h)[i] }
func (h *postingsWithIndexHeap) Push(x interface{}) {
*h = append(*h, x.(postingsWithIndex))
}
// Pop implements heap.Interface and pops the last element, which is NOT the min element,
// so this doesn't return the same heap.Pop()
func (h *postingsWithIndexHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}

View file

@ -14,6 +14,8 @@
package index package index
import ( import (
"container/heap"
"context"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math/rand" "math/rand"
@ -21,6 +23,7 @@ import (
"strconv" "strconv"
"testing" "testing"
"github.com/pkg/errors"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
@ -1052,3 +1055,142 @@ func TestPostingsCloner(t *testing.T) {
require.Equal(t, expectedErr, p.Err()) require.Equal(t, expectedErr, p.Err())
}) })
} }
func TestFindIntersectingPostings(t *testing.T) {
t.Run("multiple intersections", func(t *testing.T) {
p := NewListPostings([]storage.SeriesRef{10, 15, 20, 25, 30, 35, 40, 45, 50})
candidates := []Postings{
0: NewListPostings([]storage.SeriesRef{7, 13, 14, 27}), // Does not intersect.
1: NewListPostings([]storage.SeriesRef{10, 20}), // Does intersect.
2: NewListPostings([]storage.SeriesRef{29, 30, 31}), // Does intersect.
3: NewListPostings([]storage.SeriesRef{29, 30, 31}), // Does intersect (same again).
4: NewListPostings([]storage.SeriesRef{60}), // Does not intersect.
5: NewListPostings([]storage.SeriesRef{45}), // Does intersect.
6: EmptyPostings(), // Does not intersect.
}
indexes, err := FindIntersectingPostings(p, candidates)
require.NoError(t, err)
sort.Ints(indexes)
require.Equal(t, []int{1, 2, 3, 5}, indexes)
})
t.Run("no intersections", func(t *testing.T) {
p := NewListPostings([]storage.SeriesRef{10, 15, 20, 25, 30, 35, 40, 45, 50})
candidates := []Postings{
0: NewListPostings([]storage.SeriesRef{7, 13, 14, 27}), // Does not intersect.
1: NewListPostings([]storage.SeriesRef{60}), // Does not intersect.
2: EmptyPostings(), // Does not intersect.
}
indexes, err := FindIntersectingPostings(p, candidates)
require.NoError(t, err)
require.Empty(t, indexes)
})
t.Run("p is ErrPostings", func(t *testing.T) {
p := ErrPostings(context.Canceled)
candidates := []Postings{NewListPostings([]storage.SeriesRef{1})}
_, err := FindIntersectingPostings(p, candidates)
require.Error(t, err)
})
t.Run("one of the candidates is ErrPostings", func(t *testing.T) {
p := NewListPostings([]storage.SeriesRef{1})
candidates := []Postings{
NewListPostings([]storage.SeriesRef{1}),
ErrPostings(context.Canceled),
}
_, err := FindIntersectingPostings(p, candidates)
require.Error(t, err)
})
t.Run("one of the candidates fails on nth call", func(t *testing.T) {
p := NewListPostings([]storage.SeriesRef{10, 20, 30, 40, 50, 60, 70})
candidates := []Postings{
NewListPostings([]storage.SeriesRef{7, 13, 14, 27}),
&postingsFailingAfterNthCall{2, NewListPostings([]storage.SeriesRef{29, 30, 31, 40})},
}
_, err := FindIntersectingPostings(p, candidates)
require.Error(t, err)
})
t.Run("p fails on the nth call", func(t *testing.T) {
p := &postingsFailingAfterNthCall{2, NewListPostings([]storage.SeriesRef{10, 20, 30, 40, 50, 60, 70})}
candidates := []Postings{
NewListPostings([]storage.SeriesRef{7, 13, 14, 27}),
NewListPostings([]storage.SeriesRef{29, 30, 31, 40}),
}
_, err := FindIntersectingPostings(p, candidates)
require.Error(t, err)
})
}
type postingsFailingAfterNthCall struct {
ttl int
Postings
}
func (p *postingsFailingAfterNthCall) Seek(v storage.SeriesRef) bool {
p.ttl--
if p.ttl <= 0 {
return false
}
return p.Postings.Seek(v)
}
func (p *postingsFailingAfterNthCall) Next() bool {
p.ttl--
if p.ttl <= 0 {
return false
}
return p.Postings.Next()
}
func (p *postingsFailingAfterNthCall) Err() error {
if p.ttl <= 0 {
return errors.New("ttl exceeded")
}
return p.Postings.Err()
}
func TestPostingsWithIndexHeap(t *testing.T) {
t.Run("iterate", func(t *testing.T) {
h := postingsWithIndexHeap{
{index: 0, p: NewListPostings([]storage.SeriesRef{10, 20, 30})},
{index: 1, p: NewListPostings([]storage.SeriesRef{1, 5})},
{index: 2, p: NewListPostings([]storage.SeriesRef{25, 50})},
}
for _, node := range h {
node.p.Next()
}
h.Init()
for _, expected := range []storage.SeriesRef{1, 5, 10, 20, 25, 30, 50} {
require.Equal(t, expected, h.At())
require.NoError(t, h.Next())
}
require.Empty(t, h)
})
t.Run("pop", func(t *testing.T) {
h := postingsWithIndexHeap{
{index: 0, p: NewListPostings([]storage.SeriesRef{10, 20, 30})},
{index: 1, p: NewListPostings([]storage.SeriesRef{1, 5})},
{index: 2, p: NewListPostings([]storage.SeriesRef{25, 50})},
}
for _, node := range h {
node.p.Next()
}
h.Init()
for _, expected := range []storage.SeriesRef{1, 5, 10, 20} {
require.Equal(t, expected, h.At())
require.NoError(t, h.Next())
}
require.Equal(t, storage.SeriesRef(25), h.At())
node := heap.Pop(&h).(postingsWithIndex)
require.Equal(t, 2, node.index)
require.Equal(t, storage.SeriesRef(25), node.p.At())
})
}

View file

@ -324,38 +324,30 @@ func inversePostingsForMatcher(ix IndexPostingsReader, m *labels.Matcher) (index
} }
func labelValuesWithMatchers(r IndexReader, name string, matchers ...*labels.Matcher) ([]string, error) { func labelValuesWithMatchers(r IndexReader, name string, matchers ...*labels.Matcher) ([]string, error) {
// We're only interested in metrics which have the label <name>. p, err := PostingsForMatchers(r, matchers...)
requireLabel, err := labels.NewMatcher(labels.MatchNotEqual, name, "")
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "Failed to instantiate label matcher") return nil, errors.Wrap(err, "fetching postings for matchers")
} }
var p index.Postings allValues, err := r.LabelValues(name)
p, err = r.PostingsForMatchers(false, append(matchers, requireLabel)...)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrapf(err, "fetching values of label %s", name)
} }
valuesPostings := make([]index.Postings, len(allValues))
dedupe := map[string]interface{}{} for i, value := range allValues {
for p.Next() { valuesPostings[i], err = r.Postings(name, value)
v, err := r.LabelValueFor(p.At(), name)
if err != nil { if err != nil {
if err == storage.ErrNotFound { return nil, errors.Wrapf(err, "fetching postings for %s=%q", name, value)
continue
}
return nil, err
} }
dedupe[v] = nil }
indexes, err := index.FindIntersectingPostings(p, valuesPostings)
if err != nil {
return nil, errors.Wrap(err, "intersecting postings")
} }
if err = p.Err(); err != nil { values := make([]string, 0, len(indexes))
return nil, err for _, idx := range indexes {
} values = append(values, allValues[idx])
values := make([]string, 0, len(dedupe))
for value := range dedupe {
values = append(values, value)
} }
return values, nil return values, nil

View file

@ -33,7 +33,7 @@ const (
postingsBenchSuffix = "aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd" postingsBenchSuffix = "aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd"
) )
func BenchmarkPostingsForMatchers(b *testing.B) { func BenchmarkQuerier(b *testing.B) {
chunkDir, err := ioutil.TempDir("", "chunk_dir") chunkDir, err := ioutil.TempDir("", "chunk_dir")
require.NoError(b, err) require.NoError(b, err)
defer func() { defer func() {
@ -68,7 +68,12 @@ func BenchmarkPostingsForMatchers(b *testing.B) {
ir, err := h.Index() ir, err := h.Index()
require.NoError(b, err) require.NoError(b, err)
b.Run("Head", func(b *testing.B) { b.Run("Head", func(b *testing.B) {
benchmarkPostingsForMatchers(b, ir) b.Run("PostingsForMatchers", func(b *testing.B) {
benchmarkPostingsForMatchers(b, ir)
})
b.Run("labelValuesWithMatchers", func(b *testing.B) {
benchmarkLabelValuesWithMatchers(b, ir)
})
}) })
tmpdir, err := ioutil.TempDir("", "test_benchpostingsformatchers") tmpdir, err := ioutil.TempDir("", "test_benchpostingsformatchers")
@ -87,7 +92,12 @@ func BenchmarkPostingsForMatchers(b *testing.B) {
require.NoError(b, err) require.NoError(b, err)
defer ir.Close() defer ir.Close()
b.Run("Block", func(b *testing.B) { b.Run("Block", func(b *testing.B) {
benchmarkPostingsForMatchers(b, ir) b.Run("PostingsForMatchers", func(b *testing.B) {
benchmarkPostingsForMatchers(b, ir)
})
b.Run("labelValuesWithMatchers", func(b *testing.B) {
benchmarkLabelValuesWithMatchers(b, ir)
})
}) })
} }
@ -105,7 +115,7 @@ func benchmarkPostingsForMatchers(b *testing.B, ir IndexReader) {
i1Plus := labels.MustNewMatcher(labels.MatchRegexp, "i", "^1.+$") i1Plus := labels.MustNewMatcher(labels.MatchRegexp, "i", "^1.+$")
iEmptyRe := labels.MustNewMatcher(labels.MatchRegexp, "i", "^$") iEmptyRe := labels.MustNewMatcher(labels.MatchRegexp, "i", "^$")
iNotEmpty := labels.MustNewMatcher(labels.MatchNotEqual, "i", "") iNotEmpty := labels.MustNewMatcher(labels.MatchNotEqual, "i", "")
iNot2 := labels.MustNewMatcher(labels.MatchNotEqual, "n", "2"+postingsBenchSuffix) iNot2 := labels.MustNewMatcher(labels.MatchNotEqual, "i", "2"+postingsBenchSuffix)
iNot2Star := labels.MustNewMatcher(labels.MatchNotRegexp, "i", "^2.*$") iNot2Star := labels.MustNewMatcher(labels.MatchNotRegexp, "i", "^2.*$")
iNotStar2Star := labels.MustNewMatcher(labels.MatchNotRegexp, "i", "^.*2.*$") iNotStar2Star := labels.MustNewMatcher(labels.MatchNotRegexp, "i", "^.*2.*$")
jFooBar := labels.MustNewMatcher(labels.MatchRegexp, "j", "foo|bar") jFooBar := labels.MustNewMatcher(labels.MatchRegexp, "j", "foo|bar")
@ -150,6 +160,38 @@ func benchmarkPostingsForMatchers(b *testing.B, ir IndexReader) {
} }
} }
func benchmarkLabelValuesWithMatchers(b *testing.B, ir IndexReader) {
i1 := labels.MustNewMatcher(labels.MatchEqual, "i", "1")
iStar := labels.MustNewMatcher(labels.MatchRegexp, "i", "^.*$")
jNotFoo := labels.MustNewMatcher(labels.MatchNotEqual, "j", "foo")
n1 := labels.MustNewMatcher(labels.MatchEqual, "n", "1"+postingsBenchSuffix)
nPlus := labels.MustNewMatcher(labels.MatchRegexp, "i", "^.+$")
cases := []struct {
name string
labelName string
matchers []*labels.Matcher
}{
// i has 100k values.
{`i with n="1"`, "i", []*labels.Matcher{n1}},
{`i with n="^.+$"`, "i", []*labels.Matcher{nPlus}},
{`i with n="1",j!="foo"`, "i", []*labels.Matcher{n1, jNotFoo}},
{`i with n="1",i=~"^.*$",j!="foo"`, "i", []*labels.Matcher{n1, iStar, jNotFoo}},
// n has 10 values.
{`n with j!="foo"`, "n", []*labels.Matcher{jNotFoo}},
{`n with i="1"`, "n", []*labels.Matcher{i1}},
}
for _, c := range cases {
b.Run(c.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := labelValuesWithMatchers(ir, c.labelName, c.matchers...)
require.NoError(b, err)
}
})
}
}
func BenchmarkQuerierSelect(b *testing.B) { func BenchmarkQuerierSelect(b *testing.B) {
chunkDir, err := ioutil.TempDir("", "chunk_dir") chunkDir, err := ioutil.TempDir("", "chunk_dir")
require.NoError(b, err) require.NoError(b, err)

View file

@ -159,6 +159,9 @@ func (it *listSeriesIterator) Seek(t int64) bool {
if it.idx == -1 { if it.idx == -1 {
it.idx = 0 it.idx = 0
} }
if it.idx >= len(it.list) {
return false
}
// No-op check. // No-op check.
if s := it.list[it.idx]; s.T() >= t { if s := it.list[it.idx]; s.T() >= t {
return true return true

View file

@ -190,7 +190,7 @@ func OpenSegmentWAL(dir string, logger log.Logger, flushInterval time.Duration,
flushInterval: flushInterval, flushInterval: flushInterval,
donec: make(chan struct{}), donec: make(chan struct{}),
stopc: make(chan struct{}), stopc: make(chan struct{}),
actorc: make(chan func() error, 1), actorc: make(chan func() error, 2),
segmentSize: walSegmentSizeBytes, segmentSize: walSegmentSizeBytes,
crc32: newCRC32(), crc32: newCRC32(),
} }

View file

@ -39,6 +39,7 @@ func New(t testutil.T) *TestStorage {
opts := tsdb.DefaultOptions() opts := tsdb.DefaultOptions()
opts.MinBlockDuration = int64(24 * time.Hour / time.Millisecond) opts.MinBlockDuration = int64(24 * time.Hour / time.Millisecond)
opts.MaxBlockDuration = int64(24 * time.Hour / time.Millisecond) opts.MaxBlockDuration = int64(24 * time.Hour / time.Millisecond)
opts.RetentionDuration = 0
db, err := tsdb.Open(dir, nil, nil, opts, tsdb.NewDBStats()) db, err := tsdb.Open(dir, nil, nil, opts, tsdb.NewDBStats())
require.NoError(t, err, "unexpected error while opening test storage") require.NoError(t, err, "unexpected error while opening test storage")
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()

View file

@ -155,11 +155,18 @@ type TSDBAdminStats interface {
WALReplayStatus() (tsdb.WALReplayStatus, error) WALReplayStatus() (tsdb.WALReplayStatus, error)
} }
// QueryEngine defines the interface for the *promql.Engine, so it can be replaced, wrapped or mocked.
type QueryEngine interface {
SetQueryLogger(l promql.QueryLogger)
NewInstantQuery(q storage.Queryable, qs string, ts time.Time) (promql.Query, error)
NewRangeQuery(q storage.Queryable, qs string, start, end time.Time, interval time.Duration) (promql.Query, error)
}
// API can register a set of endpoints in a router and handle // API can register a set of endpoints in a router and handle
// them using the provided storage and query engine. // them using the provided storage and query engine.
type API struct { type API struct {
Queryable storage.SampleAndChunkQueryable Queryable storage.SampleAndChunkQueryable
QueryEngine *promql.Engine QueryEngine QueryEngine
ExemplarQueryable storage.ExemplarQueryable ExemplarQueryable storage.ExemplarQueryable
targetRetriever func(context.Context) TargetRetriever targetRetriever func(context.Context) TargetRetriever
@ -192,7 +199,7 @@ func init() {
// NewAPI returns an initialized API type. // NewAPI returns an initialized API type.
func NewAPI( func NewAPI(
qe *promql.Engine, qe QueryEngine,
q storage.SampleAndChunkQueryable, q storage.SampleAndChunkQueryable,
ap storage.Appendable, ap storage.Appendable,
eq storage.ExemplarQueryable, eq storage.ExemplarQueryable,

View file

@ -1,9 +1,15 @@
0.19.0 / 2021-12-20
===================
* **[Enhancement]**: Add a negative autocompletion boost to some trigonometric functions that can overlap with other more popular PromQL functions.
* **[BugFix]**: Improve checking of whether a `PrometheusConfig` object was passed to `newCompleteStrategy()`.
0.18.0 / 2021-10-20 0.18.0 / 2021-10-20
=================== ===================
* **[Feature]**: Allow overriding the API prefix used to contact a remote Prometheus. * **[Feature]**: Allow overriding the API prefix used to contact a remote Prometheus.
* **[Feature]**: Add linter and autocompletion support for trigonometric functions (like `sin`, `cos`) * **[Feature]**: Add linter and autocompletion support for trigonometric functions (like `sin`, `cos`)
* **[BreakingChange]**: The lib is now exposed under the `dist` folder. When importing `codemirror-promql`, it means you * **[BreakingChange]**: The lib is now exposed under the `dist` folder. When importing `codemirror-promql`, it means you
will need to add `dist` in the import. For example `import { newCompleteStrategy } from 'codemirror-promql/cjs/complete';` will need to add `dist` in the import. For example `import { newCompleteStrategy } from 'codemirror-promql/cjs/complete';`
becomes `import { newCompleteStrategy } from 'codemirror-promql/dist/cjs/complete';` becomes `import { newCompleteStrategy } from 'codemirror-promql/dist/cjs/complete';`
* **[BreakingChange]**: lezer-promql has been migrated into codemirror-promql in the `grammar` folder * **[BreakingChange]**: lezer-promql has been migrated into codemirror-promql in the `grammar` folder
@ -22,8 +28,8 @@ becomes `import { newCompleteStrategy } from 'codemirror-promql/dist/cjs/complet
name. (#142) name. (#142)
* **[Feature]**: Autocomplete `NaN` and `Inf` (#141) * **[Feature]**: Autocomplete `NaN` and `Inf` (#141)
* **[Enhancement]**: Fetch series using the HTTP `POST` method (#139) * **[Enhancement]**: Fetch series using the HTTP `POST` method (#139)
* **[Enhancement]**: Upgrade lezer-promql that fixed the parsing of metric names starting with `Inf`/`NaN` like infra (#142) * **[Enhancement]**: Upgrade lezer-promql that fixed the parsing of metric names starting with `Inf`/`NaN` like infra (#142)
* **[BreakingChange]**: The constant `promQLLanguage` has been changed to be a function. It takes a `LanguageType` as a * **[BreakingChange]**: The constant `promQLLanguage` has been changed to be a function. It takes a `LanguageType` as a
parameter (#142) parameter (#142)
0.15.0 / 2021-04-13 0.15.0 / 2021-04-13

View file

@ -1,12 +1,12 @@
{ {
"name": "codemirror-promql", "name": "codemirror-promql",
"version": "0.18.0", "version": "0.19.0",
"description": "a CodeMirror mode for the PromQL language", "description": "a CodeMirror mode for the PromQL language",
"main": "dist/cjs/index.js", "main": "dist/cjs/index.js",
"module": "dist/esm/index.js", "module": "dist/esm/index.js",
"scripts": { "scripts": {
"build": "npm run build:grammar && npm run build:lib", "build": "npm run build:grammar && npm run build:lib",
"build:grammar": "lezer-generator src/grammar/promql.grammar -o src/grammar/parser", "build:grammar": "npx lezer-generator src/grammar/promql.grammar -o src/grammar/parser",
"build:lib": "bash ./build.sh", "build:lib": "bash ./build.sh",
"test": "npm run build:grammar && ts-mocha -p tsconfig.json ./**/*.test.ts", "test": "npm run build:grammar && ts-mocha -p tsconfig.json ./**/*.test.ts",
"test:coverage": "npm run build:grammar && nyc ts-mocha -p ./tsconfig.json ./**/*.test.ts", "test:coverage": "npm run build:grammar && nyc ts-mocha -p ./tsconfig.json ./**/*.test.ts",
@ -41,17 +41,18 @@
"@codemirror/lint": "^0.19.3", "@codemirror/lint": "^0.19.3",
"@codemirror/state": "^0.19.6", "@codemirror/state": "^0.19.6",
"@codemirror/view": "^0.19.27", "@codemirror/view": "^0.19.27",
"@lezer/common": "^0.15.10", "@lezer/common": "^0.15.11",
"@lezer/lr": "^0.15.5",
"@lezer/generator": "^0.15.2", "@lezer/generator": "^0.15.2",
"@types/chai": "^4.2.22", "@types/chai": "^4.2.22",
"@types/lru-cache": "^5.1.1", "@types/lru-cache": "^5.1.1",
"@types/mocha": "^9.0.0", "@types/mocha": "^9.0.0",
"@types/node": "^16.11.12", "@types/node": "^16.11.12",
"@typescript-eslint/eslint-plugin": "^5.5.0", "@typescript-eslint/eslint-plugin": "^5.8.0",
"@typescript-eslint/parser": "^5.5.0", "@typescript-eslint/parser": "^5.8.0",
"chai": "^4.2.0", "chai": "^4.2.0",
"codecov": "^3.8.3", "codecov": "^3.8.3",
"eslint": "^8.4.0", "eslint": "^8.4.1",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.25.3", "eslint-plugin-import": "^2.25.3",
@ -73,7 +74,7 @@
"@codemirror/lint": "^0.19.3", "@codemirror/lint": "^0.19.3",
"@codemirror/state": "^0.19.6", "@codemirror/state": "^0.19.6",
"@codemirror/view": "^0.19.27", "@codemirror/view": "^0.19.27",
"@lezer/common": "^0.15.10" "@lezer/common": "^0.15.11"
}, },
"prettier": { "prettier": {
"singleQuote": true, "singleQuote": true,

View file

@ -342,7 +342,7 @@ export function analyzeCompletion(state: EditorState, node: SyntaxNode): Context
} }
break; break;
case PromQL: case PromQL:
if (!node.firstChild) { if (node.firstChild !== null && node.firstChild.type.id === 0) {
// this situation can happen when there is nothing in the text area and the user is explicitly triggering the autocompletion (with ctrl + space) // this situation can happen when there is nothing in the text area and the user is explicitly triggering the autocompletion (with ctrl + space)
result.push( result.push(
{ kind: ContextKind.MetricName, metricName: '' }, { kind: ContextKind.MetricName, metricName: '' },

221
web/ui/package-lock.json generated
View file

@ -14,7 +14,7 @@
} }
}, },
"module/codemirror-promql": { "module/codemirror-promql": {
"version": "0.18.0", "version": "0.19.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"lru-cache": "^6.0.0" "lru-cache": "^6.0.0"
@ -27,17 +27,18 @@
"@codemirror/lint": "^0.19.3", "@codemirror/lint": "^0.19.3",
"@codemirror/state": "^0.19.6", "@codemirror/state": "^0.19.6",
"@codemirror/view": "^0.19.27", "@codemirror/view": "^0.19.27",
"@lezer/common": "^0.15.10", "@lezer/common": "^0.15.11",
"@lezer/generator": "^0.15.2", "@lezer/generator": "^0.15.2",
"@lezer/lr": "^0.15.5",
"@types/chai": "^4.2.22", "@types/chai": "^4.2.22",
"@types/lru-cache": "^5.1.1", "@types/lru-cache": "^5.1.1",
"@types/mocha": "^9.0.0", "@types/mocha": "^9.0.0",
"@types/node": "^16.11.12", "@types/node": "^16.11.12",
"@typescript-eslint/eslint-plugin": "^5.5.0", "@typescript-eslint/eslint-plugin": "^5.8.0",
"@typescript-eslint/parser": "^5.5.0", "@typescript-eslint/parser": "^5.8.0",
"chai": "^4.2.0", "chai": "^4.2.0",
"codecov": "^3.8.3", "codecov": "^3.8.3",
"eslint": "^8.4.0", "eslint": "^8.4.1",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.25.3", "eslint-plugin-import": "^2.25.3",
@ -62,7 +63,7 @@
"@codemirror/lint": "^0.19.3", "@codemirror/lint": "^0.19.3",
"@codemirror/state": "^0.19.6", "@codemirror/state": "^0.19.6",
"@codemirror/view": "^0.19.27", "@codemirror/view": "^0.19.27",
"@lezer/common": "^0.15.10" "@lezer/common": "^0.15.11"
} }
}, },
"module/codemirror-promql/node_modules/@eslint/eslintrc": { "module/codemirror-promql/node_modules/@eslint/eslintrc": {
@ -100,13 +101,13 @@
} }
}, },
"module/codemirror-promql/node_modules/@typescript-eslint/eslint-plugin": { "module/codemirror-promql/node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.8.0.tgz",
"integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==", "integrity": "sha512-spu1UW7QuBn0nJ6+psnfCc3iVoQAifjKORgBngKOmC8U/1tbe2YJMzYQqDGYB4JCss7L8+RM2kKLb1B1Aw9BNA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/experimental-utils": "5.5.0", "@typescript-eslint/experimental-utils": "5.8.0",
"@typescript-eslint/scope-manager": "5.5.0", "@typescript-eslint/scope-manager": "5.8.0",
"debug": "^4.3.2", "debug": "^4.3.2",
"functional-red-black-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1",
"ignore": "^5.1.8", "ignore": "^5.1.8",
@ -140,15 +141,15 @@
} }
}, },
"module/codemirror-promql/node_modules/@typescript-eslint/experimental-utils": { "module/codemirror-promql/node_modules/@typescript-eslint/experimental-utils": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.8.0.tgz",
"integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==", "integrity": "sha512-KN5FvNH71bhZ8fKtL+lhW7bjm7cxs1nt+hrDZWIqb6ViCffQcWyLunGrgvISgkRojIDcXIsH+xlFfI4RCDA0xA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/json-schema": "^7.0.9", "@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.5.0", "@typescript-eslint/scope-manager": "5.8.0",
"@typescript-eslint/types": "5.5.0", "@typescript-eslint/types": "5.8.0",
"@typescript-eslint/typescript-estree": "5.5.0", "@typescript-eslint/typescript-estree": "5.8.0",
"eslint-scope": "^5.1.1", "eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0" "eslint-utils": "^3.0.0"
}, },
@ -160,18 +161,18 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "*" "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
} }
}, },
"module/codemirror-promql/node_modules/@typescript-eslint/parser": { "module/codemirror-promql/node_modules/@typescript-eslint/parser": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.8.0.tgz",
"integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==", "integrity": "sha512-Gleacp/ZhRtJRYs5/T8KQR3pAQjQI89Dn/k+OzyCKOsLiZH2/Vh60cFBTnFsHNI6WAD+lNUo/xGZ4NeA5u0Ipw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "5.5.0", "@typescript-eslint/scope-manager": "5.8.0",
"@typescript-eslint/types": "5.5.0", "@typescript-eslint/types": "5.8.0",
"@typescript-eslint/typescript-estree": "5.5.0", "@typescript-eslint/typescript-estree": "5.8.0",
"debug": "^4.3.2" "debug": "^4.3.2"
}, },
"engines": { "engines": {
@ -191,13 +192,13 @@
} }
}, },
"module/codemirror-promql/node_modules/@typescript-eslint/scope-manager": { "module/codemirror-promql/node_modules/@typescript-eslint/scope-manager": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.8.0.tgz",
"integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==", "integrity": "sha512-x82CYJsLOjPCDuFFEbS6e7K1QEWj7u5Wk1alw8A+gnJiYwNnDJk0ib6PCegbaPMjrfBvFKa7SxE3EOnnIQz2Gg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.5.0", "@typescript-eslint/types": "5.8.0",
"@typescript-eslint/visitor-keys": "5.5.0" "@typescript-eslint/visitor-keys": "5.8.0"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -208,9 +209,9 @@
} }
}, },
"module/codemirror-promql/node_modules/@typescript-eslint/types": { "module/codemirror-promql/node_modules/@typescript-eslint/types": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.8.0.tgz",
"integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==", "integrity": "sha512-LdCYOqeqZWqCMOmwFnum6YfW9F3nKuxJiR84CdIRN5nfHJ7gyvGpXWqL/AaW0k3Po0+wm93ARAsOdzlZDPCcXg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -221,13 +222,13 @@
} }
}, },
"module/codemirror-promql/node_modules/@typescript-eslint/typescript-estree": { "module/codemirror-promql/node_modules/@typescript-eslint/typescript-estree": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.8.0.tgz",
"integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==", "integrity": "sha512-srfeZ3URdEcUsSLbkOFqS7WoxOqn8JNil2NSLO9O+I2/Uyc85+UlfpEvQHIpj5dVts7KKOZnftoJD/Fdv0L7nQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.5.0", "@typescript-eslint/types": "5.8.0",
"@typescript-eslint/visitor-keys": "5.5.0", "@typescript-eslint/visitor-keys": "5.8.0",
"debug": "^4.3.2", "debug": "^4.3.2",
"globby": "^11.0.4", "globby": "^11.0.4",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -248,12 +249,12 @@
} }
}, },
"module/codemirror-promql/node_modules/@typescript-eslint/visitor-keys": { "module/codemirror-promql/node_modules/@typescript-eslint/visitor-keys": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.8.0.tgz",
"integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==", "integrity": "sha512-+HDIGOEMnqbxdAHegxvnOqESUH6RWFRR2b8qxP1W9CZnnYh4Usz6MBL+2KMAgPk/P0o9c1HqnYtwzVH6GTIqug==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.5.0", "@typescript-eslint/types": "5.8.0",
"eslint-visitor-keys": "^3.0.0" "eslint-visitor-keys": "^3.0.0"
}, },
"engines": { "engines": {
@ -313,9 +314,9 @@
} }
}, },
"module/codemirror-promql/node_modules/eslint": { "module/codemirror-promql/node_modules/eslint": {
"version": "8.4.0", "version": "8.4.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.4.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.4.1.tgz",
"integrity": "sha512-kv0XQcAQJL/VD9THQKhTQZVqkJKA+tIj/v2ZKNaIHRAADcJWFb+B/BAewUYuF6UVg1s2xC5qXVoDk0G8sKGeTA==", "integrity": "sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint/eslintrc": "^1.0.5", "@eslint/eslintrc": "^1.0.5",
@ -1567,9 +1568,9 @@
} }
}, },
"node_modules/@lezer/common": { "node_modules/@lezer/common": {
"version": "0.15.10", "version": "0.15.11",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.10.tgz", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.11.tgz",
"integrity": "sha512-vlr+be73zTDoQBIknBVOh/633tmbQcjxUu9PIeVeYESeBK3V6TuBW96RRFg93Y2cyK9lglz241gOgSn452HFvA==" "integrity": "sha512-vv0nSdIaVCRcJ8rPuDdsrNVfBOYe/4Szr/LhF929XyDmBndLDuWiCCHooGlGlJfzELyO608AyDhVsuX/ZG36NA=="
}, },
"node_modules/@lezer/generator": { "node_modules/@lezer/generator": {
"version": "0.15.2", "version": "0.15.2",
@ -1584,8 +1585,9 @@
} }
}, },
"node_modules/@lezer/lr": { "node_modules/@lezer/lr": {
"version": "0.15.2", "version": "0.15.5",
"license": "MIT", "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.5.tgz",
"integrity": "sha512-DEcLyhdmBxD1foQe7RegLrSlfS/XaTMGLkO5evkzHWAQKh/JnFWp7j7iNB7s2EpxzRrBCh0U+W7JDCeFhv2mng==",
"dependencies": { "dependencies": {
"@lezer/common": "^0.15.0" "@lezer/common": "^0.15.0"
} }
@ -1855,9 +1857,10 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/sanitize-html": { "node_modules/@types/sanitize-html": {
"version": "2.5.0", "version": "2.6.1",
"resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.6.1.tgz",
"integrity": "sha512-+JLlZdJkIHdgvlFnMorJeLv5WIORNcI+jHsAoPBWMnhGx5Rbz/D1QN5D4qvmoA7fooDlEVy6zlioWSgqbU0KeQ==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"htmlparser2": "^6.0.0" "htmlparser2": "^6.0.0"
} }
@ -4130,12 +4133,6 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/i": {
"version": "0.3.7",
"engines": {
"node": ">=0.4"
}
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "4.0.6", "version": "4.0.6",
"dev": true, "dev": true,
@ -7244,10 +7241,9 @@
"@fortawesome/react-fontawesome": "^0.1.16", "@fortawesome/react-fontawesome": "^0.1.16",
"@nexucis/fuzzy": "^0.3.0", "@nexucis/fuzzy": "^0.3.0",
"bootstrap": "^4.6.1", "bootstrap": "^4.6.1",
"codemirror-promql": "0.18.0", "codemirror-promql": "0.19.0",
"css.escape": "^1.5.1", "css.escape": "^1.5.1",
"downshift": "^6.1.7", "downshift": "^6.1.7",
"i": "^0.3.7",
"jquery": "^3.5.1", "jquery": "^3.5.1",
"jquery.flot.tooltip": "^0.9.0", "jquery.flot.tooltip": "^0.9.0",
"moment": "^2.24.0", "moment": "^2.24.0",
@ -7277,7 +7273,7 @@
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",
"@types/react-resize-detector": "^6.1.0", "@types/react-resize-detector": "^6.1.0",
"@types/react-router-dom": "^5.3.2", "@types/react-router-dom": "^5.3.2",
"@types/sanitize-html": "^2.5.0", "@types/sanitize-html": "^2.6.1",
"@types/sinon": "^10.0.6", "@types/sinon": "^10.0.6",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.5", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.5",
"enzyme": "^3.11.0", "enzyme": "^3.11.0",
@ -27644,9 +27640,9 @@
} }
}, },
"@lezer/common": { "@lezer/common": {
"version": "0.15.10", "version": "0.15.11",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.10.tgz", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.11.tgz",
"integrity": "sha512-vlr+be73zTDoQBIknBVOh/633tmbQcjxUu9PIeVeYESeBK3V6TuBW96RRFg93Y2cyK9lglz241gOgSn452HFvA==" "integrity": "sha512-vv0nSdIaVCRcJ8rPuDdsrNVfBOYe/4Szr/LhF929XyDmBndLDuWiCCHooGlGlJfzELyO608AyDhVsuX/ZG36NA=="
}, },
"@lezer/generator": { "@lezer/generator": {
"version": "0.15.2", "version": "0.15.2",
@ -27657,7 +27653,9 @@
} }
}, },
"@lezer/lr": { "@lezer/lr": {
"version": "0.15.2", "version": "0.15.5",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.5.tgz",
"integrity": "sha512-DEcLyhdmBxD1foQe7RegLrSlfS/XaTMGLkO5evkzHWAQKh/JnFWp7j7iNB7s2EpxzRrBCh0U+W7JDCeFhv2mng==",
"requires": { "requires": {
"@lezer/common": "^0.15.0" "@lezer/common": "^0.15.0"
} }
@ -27893,7 +27891,9 @@
"version": "0.1.6" "version": "0.1.6"
}, },
"@types/sanitize-html": { "@types/sanitize-html": {
"version": "2.5.0", "version": "2.6.1",
"resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.6.1.tgz",
"integrity": "sha512-+JLlZdJkIHdgvlFnMorJeLv5WIORNcI+jHsAoPBWMnhGx5Rbz/D1QN5D4qvmoA7fooDlEVy6zlioWSgqbU0KeQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"htmlparser2": "^6.0.0" "htmlparser2": "^6.0.0"
@ -28431,17 +28431,18 @@
"@codemirror/lint": "^0.19.3", "@codemirror/lint": "^0.19.3",
"@codemirror/state": "^0.19.6", "@codemirror/state": "^0.19.6",
"@codemirror/view": "^0.19.27", "@codemirror/view": "^0.19.27",
"@lezer/common": "^0.15.10", "@lezer/common": "^0.15.11",
"@lezer/generator": "^0.15.2", "@lezer/generator": "^0.15.2",
"@lezer/lr": "^0.15.5",
"@types/chai": "^4.2.22", "@types/chai": "^4.2.22",
"@types/lru-cache": "^5.1.1", "@types/lru-cache": "^5.1.1",
"@types/mocha": "^9.0.0", "@types/mocha": "^9.0.0",
"@types/node": "^16.11.12", "@types/node": "^16.11.12",
"@typescript-eslint/eslint-plugin": "^5.5.0", "@typescript-eslint/eslint-plugin": "^5.8.0",
"@typescript-eslint/parser": "^5.5.0", "@typescript-eslint/parser": "^5.8.0",
"chai": "^4.2.0", "chai": "^4.2.0",
"codecov": "^3.8.3", "codecov": "^3.8.3",
"eslint": "^8.4.0", "eslint": "^8.4.1",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.25.3", "eslint-plugin-import": "^2.25.3",
@ -28487,13 +28488,13 @@
} }
}, },
"@typescript-eslint/eslint-plugin": { "@typescript-eslint/eslint-plugin": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.8.0.tgz",
"integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==", "integrity": "sha512-spu1UW7QuBn0nJ6+psnfCc3iVoQAifjKORgBngKOmC8U/1tbe2YJMzYQqDGYB4JCss7L8+RM2kKLb1B1Aw9BNA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/experimental-utils": "5.5.0", "@typescript-eslint/experimental-utils": "5.8.0",
"@typescript-eslint/scope-manager": "5.5.0", "@typescript-eslint/scope-manager": "5.8.0",
"debug": "^4.3.2", "debug": "^4.3.2",
"functional-red-black-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1",
"ignore": "^5.1.8", "ignore": "^5.1.8",
@ -28509,55 +28510,55 @@
} }
}, },
"@typescript-eslint/experimental-utils": { "@typescript-eslint/experimental-utils": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.8.0.tgz",
"integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==", "integrity": "sha512-KN5FvNH71bhZ8fKtL+lhW7bjm7cxs1nt+hrDZWIqb6ViCffQcWyLunGrgvISgkRojIDcXIsH+xlFfI4RCDA0xA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/json-schema": "^7.0.9", "@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.5.0", "@typescript-eslint/scope-manager": "5.8.0",
"@typescript-eslint/types": "5.5.0", "@typescript-eslint/types": "5.8.0",
"@typescript-eslint/typescript-estree": "5.5.0", "@typescript-eslint/typescript-estree": "5.8.0",
"eslint-scope": "^5.1.1", "eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0" "eslint-utils": "^3.0.0"
} }
}, },
"@typescript-eslint/parser": { "@typescript-eslint/parser": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.8.0.tgz",
"integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==", "integrity": "sha512-Gleacp/ZhRtJRYs5/T8KQR3pAQjQI89Dn/k+OzyCKOsLiZH2/Vh60cFBTnFsHNI6WAD+lNUo/xGZ4NeA5u0Ipw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/scope-manager": "5.5.0", "@typescript-eslint/scope-manager": "5.8.0",
"@typescript-eslint/types": "5.5.0", "@typescript-eslint/types": "5.8.0",
"@typescript-eslint/typescript-estree": "5.5.0", "@typescript-eslint/typescript-estree": "5.8.0",
"debug": "^4.3.2" "debug": "^4.3.2"
} }
}, },
"@typescript-eslint/scope-manager": { "@typescript-eslint/scope-manager": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.8.0.tgz",
"integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==", "integrity": "sha512-x82CYJsLOjPCDuFFEbS6e7K1QEWj7u5Wk1alw8A+gnJiYwNnDJk0ib6PCegbaPMjrfBvFKa7SxE3EOnnIQz2Gg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.5.0", "@typescript-eslint/types": "5.8.0",
"@typescript-eslint/visitor-keys": "5.5.0" "@typescript-eslint/visitor-keys": "5.8.0"
} }
}, },
"@typescript-eslint/types": { "@typescript-eslint/types": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.8.0.tgz",
"integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==", "integrity": "sha512-LdCYOqeqZWqCMOmwFnum6YfW9F3nKuxJiR84CdIRN5nfHJ7gyvGpXWqL/AaW0k3Po0+wm93ARAsOdzlZDPCcXg==",
"dev": true "dev": true
}, },
"@typescript-eslint/typescript-estree": { "@typescript-eslint/typescript-estree": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.8.0.tgz",
"integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==", "integrity": "sha512-srfeZ3URdEcUsSLbkOFqS7WoxOqn8JNil2NSLO9O+I2/Uyc85+UlfpEvQHIpj5dVts7KKOZnftoJD/Fdv0L7nQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.5.0", "@typescript-eslint/types": "5.8.0",
"@typescript-eslint/visitor-keys": "5.5.0", "@typescript-eslint/visitor-keys": "5.8.0",
"debug": "^4.3.2", "debug": "^4.3.2",
"globby": "^11.0.4", "globby": "^11.0.4",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -28566,12 +28567,12 @@
} }
}, },
"@typescript-eslint/visitor-keys": { "@typescript-eslint/visitor-keys": {
"version": "5.5.0", "version": "5.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.8.0.tgz",
"integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==", "integrity": "sha512-+HDIGOEMnqbxdAHegxvnOqESUH6RWFRR2b8qxP1W9CZnnYh4Usz6MBL+2KMAgPk/P0o9c1HqnYtwzVH6GTIqug==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.5.0", "@typescript-eslint/types": "5.8.0",
"eslint-visitor-keys": "^3.0.0" "eslint-visitor-keys": "^3.0.0"
} }
}, },
@ -28609,9 +28610,9 @@
} }
}, },
"eslint": { "eslint": {
"version": "8.4.0", "version": "8.4.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.4.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.4.1.tgz",
"integrity": "sha512-kv0XQcAQJL/VD9THQKhTQZVqkJKA+tIj/v2ZKNaIHRAADcJWFb+B/BAewUYuF6UVg1s2xC5qXVoDk0G8sKGeTA==", "integrity": "sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@eslint/eslintrc": "^1.0.5", "@eslint/eslintrc": "^1.0.5",
@ -29692,11 +29693,11 @@
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",
"@types/react-resize-detector": "^6.1.0", "@types/react-resize-detector": "^6.1.0",
"@types/react-router-dom": "^5.3.2", "@types/react-router-dom": "^5.3.2",
"@types/sanitize-html": "^2.5.0", "@types/sanitize-html": "^2.6.1",
"@types/sinon": "^10.0.6", "@types/sinon": "^10.0.6",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.5", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.5",
"bootstrap": "^4.6.1", "bootstrap": "^4.6.1",
"codemirror-promql": "0.18.0", "codemirror-promql": "0.19.0",
"css.escape": "^1.5.1", "css.escape": "^1.5.1",
"downshift": "^6.1.7", "downshift": "^6.1.7",
"enzyme": "^3.11.0", "enzyme": "^3.11.0",
@ -29705,7 +29706,6 @@
"eslint-config-react-app": "^6.0.0", "eslint-config-react-app": "^6.0.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"fsevents": "^2.3.2", "fsevents": "^2.3.2",
"i": "^0.3.7",
"jest-canvas-mock": "^2.3.1", "jest-canvas-mock": "^2.3.1",
"jest-fetch-mock": "^3.0.3", "jest-fetch-mock": "^3.0.3",
"jquery": "^3.5.1", "jquery": "^3.5.1",
@ -43287,9 +43287,6 @@
"debug": "4" "debug": "4"
} }
}, },
"i": {
"version": "0.3.7"
},
"ignore": { "ignore": {
"version": "4.0.6", "version": "4.0.6",
"dev": true "dev": true

View file

@ -21,10 +21,9 @@
"@fortawesome/react-fontawesome": "^0.1.16", "@fortawesome/react-fontawesome": "^0.1.16",
"@nexucis/fuzzy": "^0.3.0", "@nexucis/fuzzy": "^0.3.0",
"bootstrap": "^4.6.1", "bootstrap": "^4.6.1",
"codemirror-promql": "0.18.0", "codemirror-promql": "0.19.0",
"css.escape": "^1.5.1", "css.escape": "^1.5.1",
"downshift": "^6.1.7", "downshift": "^6.1.7",
"i": "^0.3.7",
"jquery": "^3.5.1", "jquery": "^3.5.1",
"jquery.flot.tooltip": "^0.9.0", "jquery.flot.tooltip": "^0.9.0",
"moment": "^2.24.0", "moment": "^2.24.0",
@ -75,7 +74,7 @@
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",
"@types/react-resize-detector": "^6.1.0", "@types/react-resize-detector": "^6.1.0",
"@types/react-router-dom": "^5.3.2", "@types/react-router-dom": "^5.3.2",
"@types/sanitize-html": "^2.5.0", "@types/sanitize-html": "^2.6.1",
"@types/sinon": "^10.0.6", "@types/sinon": "^10.0.6",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.5", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.5",
"enzyme": "^3.11.0", "enzyme": "^3.11.0",

View file

@ -103,7 +103,7 @@ const App: FC<AppProps> = ({ consolesLink, agentMode }) => {
<ServiceDiscoveryPage /> <ServiceDiscoveryPage />
</Route> </Route>
<Route path="/status"> <Route path="/status">
<StatusPage /> <StatusPage agentMode={agentMode} />
</Route> </Route>
<Route path="/tsdb-status"> <Route path="/tsdb-status">
<TSDBStatusPage /> <TSDBStatusPage />

View file

@ -6,7 +6,7 @@ const Agent: FC = () => {
<h2>Prometheus Agent</h2> <h2>Prometheus Agent</h2>
<p> <p>
This Prometheus instance is running in <strong>agent mode</strong>. In this mode, Prometheus is only used to scrape This Prometheus instance is running in <strong>agent mode</strong>. In this mode, Prometheus is only used to scrape
discovered targets and forward them to remote write endpoints. discovered targets and forward the scraped metrics to remote write endpoints.
</p> </p>
<p>Some features are not available in this mode, such as querying and alerting.</p> <p>Some features are not available in this mode, such as querying and alerting.</p>
</> </>

View file

@ -83,28 +83,35 @@ const StatusWithStatusIndicator = withStatusIndicator(StatusContent);
StatusContent.displayName = 'Status'; StatusContent.displayName = 'Status';
const Status: FC = () => { const StatusResult: FC<{ fetchPath: string; title: string }> = ({ fetchPath, title }) => {
const { response, isLoading, error } = useFetch(fetchPath);
return (
<StatusWithStatusIndicator
key={title}
data={response.data}
title={title}
isLoading={isLoading}
error={error}
componentTitle={title}
/>
);
};
const Status: FC<{ agentMode: boolean }> = ({ agentMode }) => {
const pathPrefix = usePathPrefix(); const pathPrefix = usePathPrefix();
const path = `${pathPrefix}/${API_PATH}`; const path = `${pathPrefix}/${API_PATH}`;
return ( return (
<> <>
{[ {[
{ fetchResult: useFetch<Record<string, string>>(`${path}/status/runtimeinfo`), title: 'Runtime Information' }, { fetchPath: `${path}/status/runtimeinfo`, title: 'Runtime Information' },
{ fetchResult: useFetch<Record<string, string>>(`${path}/status/buildinfo`), title: 'Build Information' }, { fetchPath: `${path}/status/buildinfo`, title: 'Build Information' },
{ fetchResult: useFetch<Record<string, string>>(`${path}/alertmanagers`), title: 'Alertmanagers' }, { fetchPath: `${path}/alertmanagers`, title: 'Alertmanagers' },
].map(({ fetchResult, title }) => { ].map(({ fetchPath, title }) => {
const { response, isLoading, error } = fetchResult; if (agentMode && title === 'Alertmanagers') {
return ( return null;
<StatusWithStatusIndicator }
key={title} return <StatusResult fetchPath={fetchPath} title={title} />;
data={response.data}
title={title}
isLoading={isLoading}
error={error}
componentTitle={title}
/>
);
})} })}
</> </>
); );

View file

@ -116,7 +116,9 @@ func TestReadyAndHealthy(t *testing.T) {
db, err := tsdb.Open(dbDir, nil, nil, nil, nil) db, err := tsdb.Open(dbDir, nil, nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, db.Close())
})
port := fmt.Sprintf(":%d", testutil.RandomUnprivilegedPort(t)) port := fmt.Sprintf(":%d", testutil.RandomUnprivilegedPort(t))
opts := &Options{ opts := &Options{
@ -237,6 +239,9 @@ func TestRoutePrefix(t *testing.T) {
db, err := tsdb.Open(dbDir, nil, nil, nil, nil) db, err := tsdb.Open(dbDir, nil, nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, db.Close())
})
port := fmt.Sprintf(":%d", testutil.RandomUnprivilegedPort(t)) port := fmt.Sprintf(":%d", testutil.RandomUnprivilegedPort(t))
@ -404,7 +409,9 @@ func TestShutdownWithStaleConnection(t *testing.T) {
db, err := tsdb.Open(dbDir, nil, nil, nil, nil) db, err := tsdb.Open(dbDir, nil, nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, db.Close())
})
timeout := 10 * time.Second timeout := 10 * time.Second
port := fmt.Sprintf(":%d", testutil.RandomUnprivilegedPort(t)) port := fmt.Sprintf(":%d", testutil.RandomUnprivilegedPort(t))
@ -567,39 +574,68 @@ func TestAgentAPIEndPoints(t *testing.T) {
webHandler := New(nil, opts) webHandler := New(nil, opts)
webHandler.Ready() webHandler.Ready()
webHandler.config = &config.Config{}
baseURL := "http://localhost" + port webHandler.notifier = &notifier.Manager{}
l, err := webHandler.Listener()
// Test for non-available endpoints in the Agent mode. if err != nil {
for _, u := range []string{ panic(fmt.Sprintf("Unable to start web listener: %s", err))
"/-/labels",
"/label",
"/series",
"/alertmanagers",
"/query",
"/query_range",
"/query_exemplars",
"/graph",
"/rules",
} {
w := httptest.NewRecorder()
req, err := http.NewRequest("GET", baseURL+u, nil)
require.NoError(t, err)
webHandler.router.ServeHTTP(w, req)
require.Equal(t, http.StatusNotFound, w.Code)
} }
// Test for available endpoints in the Agent mode. ctx, cancel := context.WithCancel(context.Background())
for _, u := range []string{ defer cancel()
"/agent", go func() {
"/targets", err := webHandler.Run(ctx, l, "")
"/status", if err != nil {
panic(fmt.Sprintf("Can't start web handler:%s", err))
}
}()
// Give some time for the web goroutine to run since we need the server
// to be up before starting tests.
time.Sleep(5 * time.Second)
baseURL := "http://localhost" + port + "/api/v1"
// Test for non-available endpoints in the Agent mode.
for path, methods := range map[string][]string{
"/labels": {http.MethodGet, http.MethodPost},
"/label/:name/values": {http.MethodGet},
"/series": {http.MethodGet, http.MethodPost, http.MethodDelete},
"/alertmanagers": {http.MethodGet},
"/query": {http.MethodGet, http.MethodPost},
"/query_range": {http.MethodGet, http.MethodPost},
"/query_exemplars": {http.MethodGet, http.MethodPost},
"/status/tsdb": {http.MethodGet},
"/alerts": {http.MethodGet},
"/rules": {http.MethodGet},
"/admin/tsdb/delete_series": {http.MethodPost, http.MethodPut},
"/admin/tsdb/clean_tombstones": {http.MethodPost, http.MethodPut},
"/admin/tsdb/snapshot": {http.MethodPost, http.MethodPut},
} { } {
w := httptest.NewRecorder() for _, m := range methods {
req, err := http.NewRequest("GET", baseURL+u, nil) req, err := http.NewRequest(m, baseURL+path, nil)
require.NoError(t, err) require.NoError(t, err)
webHandler.router.ServeHTTP(w, req) resp, err := http.DefaultClient.Do(req)
require.Equal(t, http.StatusOK, w.Code) require.NoError(t, err)
require.Equal(t, http.StatusUnprocessableEntity, resp.StatusCode)
}
}
// Test for some of available endpoints in the Agent mode.
for path, methods := range map[string][]string{
"/targets": {http.MethodGet},
"/targets/metadata": {http.MethodGet},
"/metadata": {http.MethodGet},
"/status/config": {http.MethodGet},
"/status/runtimeinfo": {http.MethodGet},
"/status/flags": {http.MethodGet},
} {
for _, m := range methods {
req, err := http.NewRequest(m, baseURL+path, nil)
require.NoError(t, err)
resp, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
}
} }
} }