mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-25 05:34:05 -08:00
Merge remote-tracking branch 'origin/main' into pr/13461
This commit is contained in:
commit
080d440bf8
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
@ -1,7 +1,7 @@
|
|||
/web/ui @juliusv
|
||||
/web/ui/module @juliusv @nexucis
|
||||
/storage/remote @cstyan @bwplotka @tomwilkie
|
||||
/storage/remote/otlptranslator @gouthamve @jesusvazquez
|
||||
/storage/remote/otlptranslator @aknuds1 @jesusvazquez
|
||||
/discovery/kubernetes @brancz
|
||||
/tsdb @jesusvazquez
|
||||
/promql @roidelapluie
|
||||
|
|
8
.github/dependabot.yml
vendored
8
.github/dependabot.yml
vendored
|
@ -6,11 +6,11 @@ updates:
|
|||
interval: "monthly"
|
||||
groups:
|
||||
k8s.io:
|
||||
patterns:
|
||||
- "k8s.io/*"
|
||||
patterns:
|
||||
- "k8s.io/*"
|
||||
go.opentelemetry.io:
|
||||
patterns:
|
||||
- "go.opentelemetry.io/*"
|
||||
patterns:
|
||||
- "go.opentelemetry.io/*"
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/documentation/examples/remote_storage"
|
||||
schedule:
|
||||
|
|
4
.github/workflows/buf-lint.yml
vendored
4
.github/workflows/buf-lint.yml
vendored
|
@ -13,10 +13,10 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: bufbuild/buf-setup-action@382440cdb8ec7bc25a68d7b4711163d95f7cc3aa # v1.28.1
|
||||
- uses: bufbuild/buf-setup-action@517ee23296d5caf38df31c21945e6a54bbc8a89f # v1.30.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: bufbuild/buf-lint-action@bd48f53224baaaf0fc55de9a913e7680ca6dbea4 # v1.0.3
|
||||
- uses: bufbuild/buf-lint-action@044d13acb1f155179c606aaa2e53aea304d22058 # v1.1.0
|
||||
with:
|
||||
input: 'prompb'
|
||||
- uses: bufbuild/buf-breaking-action@f47418c81c00bfd65394628385593542f64db477 # v1.1.2
|
||||
|
|
6
.github/workflows/buf.yml
vendored
6
.github/workflows/buf.yml
vendored
|
@ -13,17 +13,17 @@ jobs:
|
|||
if: github.repository_owner == 'prometheus'
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: bufbuild/buf-setup-action@382440cdb8ec7bc25a68d7b4711163d95f7cc3aa # v1.28.1
|
||||
- uses: bufbuild/buf-setup-action@517ee23296d5caf38df31c21945e6a54bbc8a89f # v1.30.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: bufbuild/buf-lint-action@bd48f53224baaaf0fc55de9a913e7680ca6dbea4 # v1.0.3
|
||||
- uses: bufbuild/buf-lint-action@044d13acb1f155179c606aaa2e53aea304d22058 # v1.1.0
|
||||
with:
|
||||
input: 'prompb'
|
||||
- uses: bufbuild/buf-breaking-action@f47418c81c00bfd65394628385593542f64db477 # v1.1.2
|
||||
with:
|
||||
input: 'prompb'
|
||||
against: 'https://github.com/prometheus/prometheus.git#branch=main,ref=HEAD~1,subdir=prompb'
|
||||
- uses: bufbuild/buf-push-action@342fc4cdcf29115a01cf12a2c6dd6aac68dc51e1 # v1.1.1
|
||||
- uses: bufbuild/buf-push-action@a654ff18effe4641ebea4a4ce242c49800728459 # v1.1.1
|
||||
with:
|
||||
input: 'prompb'
|
||||
buf_token: ${{ secrets.BUF_TOKEN }}
|
||||
|
|
66
.github/workflows/ci.yml
vendored
66
.github/workflows/ci.yml
vendored
|
@ -8,31 +8,53 @@ jobs:
|
|||
test_go:
|
||||
name: Go tests
|
||||
runs-on: ubuntu-latest
|
||||
# Whenever the Go version is updated here, .promu.yml
|
||||
# should also be updated.
|
||||
container:
|
||||
image: quay.io/prometheus/golang-builder:1.21-base
|
||||
# Whenever the Go version is updated here, .promu.yml
|
||||
# should also be updated.
|
||||
image: quay.io/prometheus/golang-builder:1.22-base
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: prometheus/promci@3cb0c3871f223bd5ce1226995bd52ffb314798b6 # v0.1.0
|
||||
- uses: ./.github/promci/actions/setup_environment
|
||||
- run: make GO_ONLY=1 SKIP_GOLANGCI_LINT=1
|
||||
- run: go test ./tsdb/ -test.tsdb-isolation=false
|
||||
- run: go test --tags=stringlabels ./...
|
||||
- run: GOARCH=386 go test ./cmd/prometheus
|
||||
- run: make GOOPTS=--tags=stringlabels GO_ONLY=1 SKIP_GOLANGCI_LINT=1
|
||||
- run: go test --tags=stringlabels ./tsdb/ -test.tsdb-isolation=false
|
||||
- run: make -C documentation/examples/remote_storage
|
||||
- run: make -C documentation/examples
|
||||
|
||||
test_go_more:
|
||||
name: More Go tests
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: quay.io/prometheus/golang-builder:1.22-base
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: prometheus/promci@3cb0c3871f223bd5ce1226995bd52ffb314798b6 # v0.1.0
|
||||
- uses: ./.github/promci/actions/setup_environment
|
||||
- run: go test --tags=dedupelabels ./...
|
||||
- run: GOARCH=386 go test ./cmd/prometheus
|
||||
- uses: ./.github/promci/actions/check_proto
|
||||
with:
|
||||
version: "3.15.8"
|
||||
|
||||
test_go_oldest:
|
||||
name: Go tests with previous Go version
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
# The go version in this image should be N-1 wrt test_go.
|
||||
image: quay.io/prometheus/golang-builder:1.21-base
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- run: make build
|
||||
# Don't run NPM build; don't run race-detector.
|
||||
- run: make test GO_ONLY=1 test-flags=""
|
||||
|
||||
test_ui:
|
||||
name: UI tests
|
||||
runs-on: ubuntu-latest
|
||||
# Whenever the Go version is updated here, .promu.yml
|
||||
# should also be updated.
|
||||
container:
|
||||
image: quay.io/prometheus/golang-builder:1.21-base
|
||||
image: quay.io/prometheus/golang-builder:1.22-base
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
@ -53,33 +75,21 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
go-version: 1.22.x
|
||||
- run: |
|
||||
$TestTargets = go list ./... | Where-Object { $_ -NotMatch "(github.com/prometheus/prometheus/discovery.*|github.com/prometheus/prometheus/config|github.com/prometheus/prometheus/web)"}
|
||||
go test $TestTargets -vet=off -v
|
||||
shell: powershell
|
||||
|
||||
test_golang_oldest:
|
||||
name: Go tests with previous Go version
|
||||
runs-on: ubuntu-latest
|
||||
# The go verson in this image should be N-1 wrt test_go.
|
||||
container:
|
||||
image: quay.io/prometheus/golang-builder:1.20-base
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- run: make build
|
||||
- run: go test ./tsdb/...
|
||||
- run: go test ./tsdb/ -test.tsdb-isolation=false
|
||||
|
||||
test_mixins:
|
||||
name: Mixins tests
|
||||
runs-on: ubuntu-latest
|
||||
# Whenever the Go version is updated here, .promu.yml
|
||||
# should also be updated.
|
||||
container:
|
||||
image: quay.io/prometheus/golang-builder:1.20-base
|
||||
image: quay.io/prometheus/golang-builder:1.22-base
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- run: go install ./cmd/promtool/.
|
||||
|
@ -140,19 +150,19 @@ jobs:
|
|||
- name: Checkout repository
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
with:
|
||||
cache: false
|
||||
go-version: 1.21.x
|
||||
go-version: 1.22.x
|
||||
- name: Install snmp_exporter/generator dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install libsnmp-dev
|
||||
if: github.repository == 'prometheus/snmp_exporter'
|
||||
- name: Lint
|
||||
uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0
|
||||
uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v4.0.0
|
||||
with:
|
||||
args: --verbose
|
||||
# Make sure to sync this with Makefile.common and scripts/golangci-lint.yml.
|
||||
version: v1.55.2
|
||||
version: v1.56.2
|
||||
fuzzing:
|
||||
uses: ./.github/workflows/fuzzing.yml
|
||||
if: github.event_name == 'pull_request'
|
||||
|
@ -201,7 +211,7 @@ jobs:
|
|||
with:
|
||||
node-version-file: "web/ui/.nvmrc"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
|
||||
- uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
|
|
5
.github/workflows/codeql-analysis.yml
vendored
5
.github/workflows/codeql-analysis.yml
vendored
|
@ -20,14 +20,11 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ["go", "javascript"]
|
||||
language: ["javascript"]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12
|
||||
|
|
52
.github/workflows/container_description.yml
vendored
Normal file
52
.github/workflows/container_description.yml
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
name: Push README to Docker Hub
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "README.md"
|
||||
- ".github/workflows/container_description.yml"
|
||||
branches: [ main, master ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
PushDockerHubReadme:
|
||||
runs-on: ubuntu-latest
|
||||
name: Push README to Docker Hub
|
||||
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
|
||||
steps:
|
||||
- name: git checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- name: Set docker hub repo name
|
||||
run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV
|
||||
- name: Push README to Dockerhub
|
||||
uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8 # v1
|
||||
env:
|
||||
DOCKER_USER: ${{ secrets.DOCKER_HUB_LOGIN }}
|
||||
DOCKER_PASS: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
with:
|
||||
destination_container_repo: ${{ env.DOCKER_REPO_NAME }}
|
||||
provider: dockerhub
|
||||
short_description: ${{ env.DOCKER_REPO_NAME }}
|
||||
readme_file: 'README.md'
|
||||
|
||||
PushQuayIoReadme:
|
||||
runs-on: ubuntu-latest
|
||||
name: Push README to quay.io
|
||||
if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
|
||||
steps:
|
||||
- name: git checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- name: Set quay.io org name
|
||||
run: echo "DOCKER_REPO=$(echo quay.io/${GITHUB_REPOSITORY_OWNER} | tr -d '-')" >> $GITHUB_ENV
|
||||
- name: Set quay.io repo name
|
||||
run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV
|
||||
- name: Push README to quay.io
|
||||
uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8 # v1
|
||||
env:
|
||||
DOCKER_APIKEY: ${{ secrets.QUAY_IO_API_TOKEN }}
|
||||
with:
|
||||
destination_container_repo: ${{ env.DOCKER_REPO_NAME }}
|
||||
provider: quay
|
||||
readme_file: 'README.md'
|
2
.github/workflows/fuzzing.yml
vendored
2
.github/workflows/fuzzing.yml
vendored
|
@ -21,7 +21,7 @@ jobs:
|
|||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
|
|
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
|
@ -37,7 +37,7 @@ jobs:
|
|||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3.1.3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # tag=v4.3.1
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
|
|
|
@ -48,18 +48,24 @@ linters-settings:
|
|||
rules:
|
||||
main:
|
||||
deny:
|
||||
- pkg: "sync/atomic"
|
||||
desc: "Use go.uber.org/atomic instead of sync/atomic"
|
||||
- pkg: "github.com/stretchr/testify/assert"
|
||||
desc: "Use github.com/stretchr/testify/require instead of github.com/stretchr/testify/assert"
|
||||
- pkg: "github.com/go-kit/kit/log"
|
||||
desc: "Use github.com/go-kit/log instead of github.com/go-kit/kit/log"
|
||||
- pkg: "io/ioutil"
|
||||
desc: "Use corresponding 'os' or 'io' functions instead."
|
||||
- pkg: "regexp"
|
||||
desc: "Use github.com/grafana/regexp instead of regexp"
|
||||
- pkg: "github.com/pkg/errors"
|
||||
desc: "Use 'errors' or 'fmt' instead of github.com/pkg/errors"
|
||||
- pkg: "sync/atomic"
|
||||
desc: "Use go.uber.org/atomic instead of sync/atomic"
|
||||
- pkg: "github.com/stretchr/testify/assert"
|
||||
desc: "Use github.com/stretchr/testify/require instead of github.com/stretchr/testify/assert"
|
||||
- pkg: "github.com/go-kit/kit/log"
|
||||
desc: "Use github.com/go-kit/log instead of github.com/go-kit/kit/log"
|
||||
- pkg: "io/ioutil"
|
||||
desc: "Use corresponding 'os' or 'io' functions instead."
|
||||
- pkg: "regexp"
|
||||
desc: "Use github.com/grafana/regexp instead of regexp"
|
||||
- pkg: "github.com/pkg/errors"
|
||||
desc: "Use 'errors' or 'fmt' instead of github.com/pkg/errors"
|
||||
- pkg: "gzip"
|
||||
desc: "Use github.com/klauspost/compress instead of gzip"
|
||||
- pkg: "zlib"
|
||||
desc: "Use github.com/klauspost/compress instead of zlib"
|
||||
- pkg: "golang.org/x/exp/slices"
|
||||
desc: "Use 'slices' instead."
|
||||
errcheck:
|
||||
exclude-functions:
|
||||
# Don't flag lines such as "io.Copy(io.Discard, resp.Body)".
|
||||
|
@ -129,4 +135,3 @@ linters-settings:
|
|||
- require-error
|
||||
- suite-dont-use-pkg
|
||||
- suite-extra-assert-call
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
go:
|
||||
# Whenever the Go version is updated here,
|
||||
# .circle/config.yml should also be updated.
|
||||
version: 1.21
|
||||
# .github/workflows should also be updated.
|
||||
version: 1.22
|
||||
repository:
|
||||
path: github.com/prometheus/prometheus
|
||||
build:
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
---
|
||||
extends: default
|
||||
ignore: |
|
||||
ui/react-app/node_modules
|
||||
|
||||
rules:
|
||||
braces:
|
||||
|
|
69
CHANGELOG.md
69
CHANGELOG.md
|
@ -2,8 +2,73 @@
|
|||
|
||||
## unreleased
|
||||
|
||||
* [ENHANCEMENT] TSDB: Make the wlog watcher read segments synchronously when not tailing. #13224
|
||||
* [BUGFIX] Agent: Participate in notify calls. #13223
|
||||
* [CHANGE] TSDB: Fix the predicate checking for blocks which are beyond the retention period to include the ones right at the retention boundary. #9633
|
||||
|
||||
## 2.51.0 / 2024-03-18
|
||||
|
||||
This version is built with Go 1.22.1.
|
||||
|
||||
There is a new optional build tag "dedupelabels", which should reduce memory consumption (#12304).
|
||||
It is off by default; there will be an optional alternative image to try it out.
|
||||
|
||||
* [CHANGE] Scraping: Do experimental timestamp alignment even if tolerance is bigger than 1% of scrape interval #13624, #13737
|
||||
* [FEATURE] Alerting: Relabel rules for AlertManagerConfig; allows routing alerts to different alertmanagers #12551, #13735
|
||||
* [FEATURE] API: add limit param to series, label-names and label-values APIs #13396
|
||||
* [FEATURE] UI (experimental native histograms): Add native histogram chart to Table view #13658
|
||||
* [FEATURE] Promtool: Add a "tsdb dump-openmetrics" to dump in OpenMetrics format. #13194
|
||||
* [FEATURE] PromQL (experimental native histograms): Add histogram_avg function #13467
|
||||
* [ENHANCEMENT] Rules: Evaluate independent rules concurrently #12946, #13527
|
||||
* [ENHANCEMENT] Scraping (experimental native histograms): Support exemplars #13488
|
||||
* [ENHANCEMENT] Remote Write: Disable resharding during active retry backoffs #13562
|
||||
* [ENHANCEMENT] Observability: Add native histograms to latency/duration metrics #13681
|
||||
* [ENHANCEMENT] Observability: Add 'type' label to prometheus_tsdb_head_out_of_order_samples_appended_total #13607
|
||||
* [ENHANCEMENT] API: Faster generation of targets into JSON #13469, #13484
|
||||
* [ENHANCEMENT] Scraping, API: Use faster compression library #10782
|
||||
* [ENHANCEMENT] OpenTelemetry: Performance improvements in OTLP parsing #13627
|
||||
* [ENHANCEMENT] PromQL: Optimisations to reduce CPU and memory #13448, #13536
|
||||
* [BUGFIX] PromQL: Constrain extrapolation in rate() to half of sample interval #13725
|
||||
* [BUGFIX] Remote Write: Stop slowing down when a new WAL segment is created #13583, #13628
|
||||
* [BUGFIX] PromQL: Fix wrongly scoped range vectors with @ modifier #13559
|
||||
* [BUGFIX] Kubernetes SD: Pod status changes were not discovered by Endpoints service discovery #13337
|
||||
* [BUGFIX] Azure SD: Fix 'error: parameter virtualMachineScaleSetName cannot be empty' (#13702)
|
||||
* [BUGFIX] Remote Write: Fix signing for AWS sigv4 transport #13497
|
||||
* [BUGFIX] Observability: Exemplars emitted by Prometheus use "trace_id" not "traceID" #13589
|
||||
|
||||
## 2.50.1 / 2024-02-26
|
||||
|
||||
* [BUGFIX] API: Fix metadata API using wrong field names. #13633
|
||||
|
||||
## 2.50.0 / 2024-02-22
|
||||
|
||||
* [CHANGE] Remote Write: Error `storage.ErrTooOldSample` is now generating HTTP error 400 instead of HTTP error 500. #13335
|
||||
* [FEATURE] Remote Write: Drop old inmemory samples. Activated using the config entry `sample_age_limit`. #13002
|
||||
* [FEATURE] **Experimental**: Add support for ingesting zeros as created timestamps. (enabled under the feature-flag `created-timestamp-zero-ingestion`). #12733 #13279
|
||||
* [FEATURE] Promtool: Add `analyze` histograms command. #12331
|
||||
* [FEATURE] TSDB/compaction: Add a way to enable overlapping compaction. #13282 #13393 #13398
|
||||
* [FEATURE] Add automatic memory limit handling. Activated using the feature flag. `auto-gomemlimit` #13395
|
||||
* [ENHANCEMENT] Promtool: allow specifying multiple matchers in `promtool tsdb dump`. #13296
|
||||
* [ENHANCEMENT] PromQL: Restore more efficient version of `NewPossibleNonCounterInfo` annotation. #13022
|
||||
* [ENHANCEMENT] Kuma SD: Extend configuration to allow users to specify client ID. #13278
|
||||
* [ENHANCEMENT] PromQL: Use natural sort in `sort_by_label` and `sort_by_label_desc`. This is **experimental**. #13411
|
||||
* [ENHANCEMENT] Native Histograms: support `native_histogram_min_bucket_factor` in scrape_config. #13222
|
||||
* [ENHANCEMENT] Native Histograms: Issue warning if histogramRate is applied to the wrong kind of histogram. #13392
|
||||
* [ENHANCEMENT] TSDB: Make transaction isolation data structures smaller. #13015
|
||||
* [ENHANCEMENT] TSDB/postings: Optimize merge using Loser Tree. #12878
|
||||
* [ENHANCEMENT] TSDB: Simplify internal series delete function. #13261
|
||||
* [ENHANCEMENT] Agent: Performance improvement by making the global hash lookup table smaller. #13262
|
||||
* [ENHANCEMENT] PromQL: faster execution of metric functions, e.g. abs(), rate() #13446
|
||||
* [ENHANCEMENT] TSDB: Optimize label values with matchers by taking shortcuts. #13426
|
||||
* [ENHANCEMENT] Kubernetes SD: Check preconditions earlier and avoid unnecessary checks or iterations in kube_sd. #13408
|
||||
* [ENHANCEMENT] Promtool: Improve visibility for `promtool test rules` with JSON colored formatting. #13342
|
||||
* [ENHANCEMENT] Consoles: Exclude iowait and steal from CPU Utilisation. #9593
|
||||
* [ENHANCEMENT] Various improvements and optimizations on Native Histograms. #13267, #13215, #13276 #13289, #13340
|
||||
* [BUGFIX] Scraping: Fix quality value in HTTP Accept header. #13313
|
||||
* [BUGFIX] UI: Fix usage of the function `time()` that was crashing. #13371
|
||||
* [BUGFIX] Azure SD: Fix SD crashing when it finds a VM scale set. #13578
|
||||
|
||||
## 2.49.1 / 2024-01-15
|
||||
|
||||
* [BUGFIX] TSDB: Fixed a wrong `q=` value in scrape accept header #13313
|
||||
|
||||
## 2.49.0 / 2024-01-15
|
||||
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
# Maintainers
|
||||
|
||||
Julien Pivotto (<roidelapluie@prometheus.io> / @roidelapluie) and Levi Harrison (<levi@leviharrison.dev> / @LeviHarrison) are the main/default maintainers, some parts of the codebase have other maintainers:
|
||||
General maintainers:
|
||||
* Bryan Boreham (bjboreham@gmail.com / @bboreham)
|
||||
* Levi Harrison (levi@leviharrison.dev / @LeviHarrison)
|
||||
* Ayoub Mrini (ayoubmrini424@gmail.com / @machine424)
|
||||
* Julien Pivotto (roidelapluie@prometheus.io / @roidelapluie)
|
||||
|
||||
Maintainers for specific parts of the codebase:
|
||||
* `cmd`
|
||||
* `promtool`: David Leadbeater (<dgl@dgl.cx> / @dgl)
|
||||
* `discovery`
|
||||
* `k8s`: Frederic Branczyk (<fbranczyk@gmail.com> / @brancz)
|
||||
* `documentation`
|
||||
* `prometheus-mixin`: Matthias Loibl (<mail@matthiasloibl.com> / @metalmatze)
|
||||
* `model/histogram` and other code related to native histograms: Björn Rabenstein (<beorn@grafana.com> / @beorn7),
|
||||
George Krajcsovits (<gyorgy.krajcsovits@grafana.com> / @krajorama)
|
||||
* `storage`
|
||||
* `remote`: Callum Styan (<callumstyan@gmail.com> / @cstyan), Bartłomiej Płotka (<bwplotka@gmail.com> / @bwplotka), Tom Wilkie (<tom.wilkie@gmail.com> / @tomwilkie)
|
||||
* `otlptranslator`: Arve Knudsen (<arve.knudsen@gmail.com> / @aknuds1), Jesús Vázquez (<jesus.vazquez@grafana.com> / @jesusvazquez)
|
||||
* `tsdb`: Ganesh Vernekar (<ganesh@grafana.com> / @codesome), Bartłomiej Płotka (<bwplotka@gmail.com> / @bwplotka), Jesús Vázquez (<jesus.vazquez@grafana.com> / @jesusvazquez)
|
||||
* `agent`: Robert Fratto (<robert.fratto@grafana.com> / @rfratto)
|
||||
* `web`
|
||||
|
|
2
Makefile
2
Makefile
|
@ -82,7 +82,7 @@ assets-tarball: assets
|
|||
.PHONY: parser
|
||||
parser:
|
||||
@echo ">> running goyacc to generate the .go file."
|
||||
ifeq (, $(shell command -v goyacc > /dev/null))
|
||||
ifeq (, $(shell command -v goyacc 2> /dev/null))
|
||||
@echo "goyacc not installed so skipping"
|
||||
@echo "To install: go install golang.org/x/tools/cmd/goyacc@v0.6.0"
|
||||
else
|
||||
|
|
|
@ -49,7 +49,7 @@ endif
|
|||
GOTEST := $(GO) test
|
||||
GOTEST_DIR :=
|
||||
ifneq ($(CIRCLE_JOB),)
|
||||
ifneq ($(shell command -v gotestsum > /dev/null),)
|
||||
ifneq ($(shell command -v gotestsum 2> /dev/null),)
|
||||
GOTEST_DIR := test-results
|
||||
GOTEST := gotestsum --junitfile $(GOTEST_DIR)/unit-tests.xml --
|
||||
endif
|
||||
|
@ -61,11 +61,11 @@ PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_
|
|||
SKIP_GOLANGCI_LINT :=
|
||||
GOLANGCI_LINT :=
|
||||
GOLANGCI_LINT_OPTS ?=
|
||||
GOLANGCI_LINT_VERSION ?= v1.55.2
|
||||
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64.
|
||||
GOLANGCI_LINT_VERSION ?= v1.56.2
|
||||
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
|
||||
# windows isn't included here because of the path separator being different.
|
||||
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
|
||||
ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386))
|
||||
ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386 arm64))
|
||||
# If we're in CI and there is an Actions file, that means the linter
|
||||
# is being run in Actions, so we don't need to run it here.
|
||||
ifneq (,$(SKIP_GOLANGCI_LINT))
|
||||
|
@ -169,16 +169,20 @@ common-vet:
|
|||
common-lint: $(GOLANGCI_LINT)
|
||||
ifdef GOLANGCI_LINT
|
||||
@echo ">> running golangci-lint"
|
||||
# 'go list' needs to be executed before staticcheck to prepopulate the modules cache.
|
||||
# Otherwise staticcheck might fail randomly for some reason not yet explained.
|
||||
$(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null
|
||||
$(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs)
|
||||
endif
|
||||
|
||||
.PHONY: common-lint-fix
|
||||
common-lint-fix: $(GOLANGCI_LINT)
|
||||
ifdef GOLANGCI_LINT
|
||||
@echo ">> running golangci-lint fix"
|
||||
$(GOLANGCI_LINT) run --fix $(GOLANGCI_LINT_OPTS) $(pkgs)
|
||||
endif
|
||||
|
||||
.PHONY: common-yamllint
|
||||
common-yamllint:
|
||||
@echo ">> running yamllint on all YAML files in the repository"
|
||||
ifeq (, $(shell command -v yamllint > /dev/null))
|
||||
ifeq (, $(shell command -v yamllint 2> /dev/null))
|
||||
@echo "yamllint not installed so skipping"
|
||||
else
|
||||
yamllint .
|
||||
|
@ -204,6 +208,10 @@ common-tarball: promu
|
|||
@echo ">> building release tarball"
|
||||
$(PROMU) tarball --prefix $(PREFIX) $(BIN_DIR)
|
||||
|
||||
.PHONY: common-docker-repo-name
|
||||
common-docker-repo-name:
|
||||
@echo "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)"
|
||||
|
||||
.PHONY: common-docker $(BUILD_DOCKER_ARCHS)
|
||||
common-docker: $(BUILD_DOCKER_ARCHS)
|
||||
$(BUILD_DOCKER_ARCHS): common-docker-%:
|
||||
|
|
|
@ -149,7 +149,7 @@ We are publishing our Remote Write protobuf independently at
|
|||
You can use that as a library:
|
||||
|
||||
```shell
|
||||
go get go.buf.build/protocolbuffers/go/prometheus/prometheus
|
||||
go get buf.build/gen/go/prometheus/prometheus/protocolbuffers/go@latest
|
||||
```
|
||||
|
||||
This is experimental.
|
||||
|
|
|
@ -55,7 +55,7 @@ Release cadence of first pre-releases being cut is 6 weeks.
|
|||
| v2.48 | 2023-10-04 | Levi Harrison (GitHub: @LeviHarrison) |
|
||||
| v2.49 | 2023-12-05 | Bartek Plotka (GitHub: @bwplotka) |
|
||||
| v2.50 | 2024-01-16 | Augustin Husson (GitHub: @nexucis) |
|
||||
| v2.51 | 2024-02-13 | **searching for volunteer** |
|
||||
| v2.51 | 2024-03-07 | Bryan Boreham (GitHub: @bboreham) |
|
||||
|
||||
If you are interested in volunteering please create a pull request against the [prometheus/prometheus](https://github.com/prometheus/prometheus) repository and propose yourself for the release series of your choice.
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import (
|
|||
"github.com/mwitkow/go-conntrack"
|
||||
"github.com/oklog/run"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
versioncollector "github.com/prometheus/client_golang/prometheus/collectors/version"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/prometheus/common/promlog"
|
||||
promlogflag "github.com/prometheus/common/promlog/flag"
|
||||
|
@ -99,7 +100,7 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
prometheus.MustRegister(version.NewCollector(strings.ReplaceAll(appName, "-", "_")))
|
||||
prometheus.MustRegister(versioncollector.NewCollector(strings.ReplaceAll(appName, "-", "_")))
|
||||
|
||||
var err error
|
||||
defaultRetentionDuration, err = model.ParseDuration(defaultRetentionString)
|
||||
|
@ -137,6 +138,7 @@ type flagConfig struct {
|
|||
forGracePeriod model.Duration
|
||||
outageTolerance model.Duration
|
||||
resendDelay model.Duration
|
||||
maxConcurrentEvals int64
|
||||
web web.Options
|
||||
scrape scrape.Options
|
||||
tsdb tsdbOptions
|
||||
|
@ -157,6 +159,7 @@ type flagConfig struct {
|
|||
enablePerStepStats bool
|
||||
enableAutoGOMAXPROCS bool
|
||||
enableAutoGOMEMLIMIT bool
|
||||
enableConcurrentRuleEval bool
|
||||
|
||||
prometheusURL string
|
||||
corsRegexString string
|
||||
|
@ -203,6 +206,9 @@ func (c *flagConfig) setFeatureListOptions(logger log.Logger) error {
|
|||
case "auto-gomemlimit":
|
||||
c.enableAutoGOMEMLIMIT = true
|
||||
level.Info(logger).Log("msg", "Automatically set GOMEMLIMIT to match Linux container or system memory limit")
|
||||
case "concurrent-rule-eval":
|
||||
c.enableConcurrentRuleEval = true
|
||||
level.Info(logger).Log("msg", "Experimental concurrent rule evaluation enabled.")
|
||||
case "no-default-scrape-port":
|
||||
c.scrape.NoDefaultPort = true
|
||||
level.Info(logger).Log("msg", "No default port will be appended to scrape targets' addresses.")
|
||||
|
@ -411,6 +417,9 @@ func main() {
|
|||
serverOnlyFlag(a, "rules.alert.resend-delay", "Minimum amount of time to wait before resending an alert to Alertmanager.").
|
||||
Default("1m").SetValue(&cfg.resendDelay)
|
||||
|
||||
serverOnlyFlag(a, "rules.max-concurrent-evals", "Global concurrency limit for independent rules that can run concurrently.").
|
||||
Default("4").Int64Var(&cfg.maxConcurrentEvals)
|
||||
|
||||
a.Flag("scrape.adjust-timestamps", "Adjust scrape timestamps by up to `scrape.timestamp-tolerance` to align them to the intended schedule. See https://github.com/prometheus/prometheus/issues/7846 for more context. Experimental. This flag will be removed in a future release.").
|
||||
Hidden().Default("true").BoolVar(&scrape.AlignScrapeTimestamps)
|
||||
|
||||
|
@ -749,17 +758,19 @@ func main() {
|
|||
queryEngine = promql.NewEngine(opts)
|
||||
|
||||
ruleManager = rules.NewManager(&rules.ManagerOptions{
|
||||
Appendable: fanoutStorage,
|
||||
Queryable: localStorage,
|
||||
QueryFunc: rules.EngineQueryFunc(queryEngine, fanoutStorage),
|
||||
NotifyFunc: rules.SendAlerts(notifierManager, cfg.web.ExternalURL.String()),
|
||||
Context: ctxRule,
|
||||
ExternalURL: cfg.web.ExternalURL,
|
||||
Registerer: prometheus.DefaultRegisterer,
|
||||
Logger: log.With(logger, "component", "rule manager"),
|
||||
OutageTolerance: time.Duration(cfg.outageTolerance),
|
||||
ForGracePeriod: time.Duration(cfg.forGracePeriod),
|
||||
ResendDelay: time.Duration(cfg.resendDelay),
|
||||
Appendable: fanoutStorage,
|
||||
Queryable: localStorage,
|
||||
QueryFunc: rules.EngineQueryFunc(queryEngine, fanoutStorage),
|
||||
NotifyFunc: rules.SendAlerts(notifierManager, cfg.web.ExternalURL.String()),
|
||||
Context: ctxRule,
|
||||
ExternalURL: cfg.web.ExternalURL,
|
||||
Registerer: prometheus.DefaultRegisterer,
|
||||
Logger: log.With(logger, "component", "rule manager"),
|
||||
OutageTolerance: time.Duration(cfg.outageTolerance),
|
||||
ForGracePeriod: time.Duration(cfg.forGracePeriod),
|
||||
ResendDelay: time.Duration(cfg.resendDelay),
|
||||
MaxConcurrentEvals: cfg.maxConcurrentEvals,
|
||||
ConcurrentEvalsEnabled: cfg.enableConcurrentRuleEval,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -949,8 +960,8 @@ func main() {
|
|||
func() error {
|
||||
// Don't forget to release the reloadReady channel so that waiting blocks can exit normally.
|
||||
select {
|
||||
case <-term:
|
||||
level.Warn(logger).Log("msg", "Received SIGTERM, exiting gracefully...")
|
||||
case sig := <-term:
|
||||
level.Warn(logger).Log("msg", "Received an OS signal, exiting gracefully...", "signal", sig.String())
|
||||
reloadReady.Close()
|
||||
case <-webHandler.Quit():
|
||||
level.Warn(logger).Log("msg", "Received termination request via web service, exiting gracefully...")
|
||||
|
|
|
@ -126,12 +126,9 @@ func TestFailedStartupExitCode(t *testing.T) {
|
|||
require.Error(t, err)
|
||||
|
||||
var exitError *exec.ExitError
|
||||
if errors.As(err, &exitError) {
|
||||
status := exitError.Sys().(syscall.WaitStatus)
|
||||
require.Equal(t, expectedExitStatus, status.ExitStatus())
|
||||
} else {
|
||||
t.Errorf("unable to retrieve the exit status for prometheus: %v", err)
|
||||
}
|
||||
require.ErrorAs(t, err, &exitError)
|
||||
status := exitError.Sys().(syscall.WaitStatus)
|
||||
require.Equal(t, expectedExitStatus, status.ExitStatus())
|
||||
}
|
||||
|
||||
type senderFunc func(alerts ...*notifier.Alert)
|
||||
|
@ -194,9 +191,7 @@ func TestSendAlerts(t *testing.T) {
|
|||
tc := tc
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
senderFunc := senderFunc(func(alerts ...*notifier.Alert) {
|
||||
if len(tc.in) == 0 {
|
||||
t.Fatalf("sender called with 0 alert")
|
||||
}
|
||||
require.NotEmpty(t, tc.in, "sender called with 0 alert")
|
||||
require.Equal(t, tc.exp, alerts)
|
||||
})
|
||||
rules.SendAlerts(senderFunc, "http://localhost:9090")(context.TODO(), "up", tc.in...)
|
||||
|
@ -228,7 +223,7 @@ func TestWALSegmentSizeBounds(t *testing.T) {
|
|||
go func() { done <- prom.Wait() }()
|
||||
select {
|
||||
case err := <-done:
|
||||
t.Errorf("prometheus should be still running: %v", err)
|
||||
require.Fail(t, "prometheus should be still running: %v", err)
|
||||
case <-time.After(startupTime):
|
||||
prom.Process.Kill()
|
||||
<-done
|
||||
|
@ -239,12 +234,9 @@ func TestWALSegmentSizeBounds(t *testing.T) {
|
|||
err = prom.Wait()
|
||||
require.Error(t, err)
|
||||
var exitError *exec.ExitError
|
||||
if errors.As(err, &exitError) {
|
||||
status := exitError.Sys().(syscall.WaitStatus)
|
||||
require.Equal(t, expectedExitStatus, status.ExitStatus())
|
||||
} else {
|
||||
t.Errorf("unable to retrieve the exit status for prometheus: %v", err)
|
||||
}
|
||||
require.ErrorAs(t, err, &exitError)
|
||||
status := exitError.Sys().(syscall.WaitStatus)
|
||||
require.Equal(t, expectedExitStatus, status.ExitStatus())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,7 +266,7 @@ func TestMaxBlockChunkSegmentSizeBounds(t *testing.T) {
|
|||
go func() { done <- prom.Wait() }()
|
||||
select {
|
||||
case err := <-done:
|
||||
t.Errorf("prometheus should be still running: %v", err)
|
||||
require.Fail(t, "prometheus should be still running: %v", err)
|
||||
case <-time.After(startupTime):
|
||||
prom.Process.Kill()
|
||||
<-done
|
||||
|
@ -285,12 +277,9 @@ func TestMaxBlockChunkSegmentSizeBounds(t *testing.T) {
|
|||
err = prom.Wait()
|
||||
require.Error(t, err)
|
||||
var exitError *exec.ExitError
|
||||
if errors.As(err, &exitError) {
|
||||
status := exitError.Sys().(syscall.WaitStatus)
|
||||
require.Equal(t, expectedExitStatus, status.ExitStatus())
|
||||
} else {
|
||||
t.Errorf("unable to retrieve the exit status for prometheus: %v", err)
|
||||
}
|
||||
require.ErrorAs(t, err, &exitError)
|
||||
status := exitError.Sys().(syscall.WaitStatus)
|
||||
require.Equal(t, expectedExitStatus, status.ExitStatus())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,10 +336,8 @@ func getCurrentGaugeValuesFor(t *testing.T, reg prometheus.Gatherer, metricNames
|
|||
}
|
||||
|
||||
require.Len(t, g.GetMetric(), 1)
|
||||
if _, ok := res[m]; ok {
|
||||
t.Error("expected only one metric family for", m)
|
||||
t.FailNow()
|
||||
}
|
||||
_, ok := res[m]
|
||||
require.False(t, ok, "expected only one metric family for", m)
|
||||
res[m] = *g.GetMetric()[0].GetGauge().Value
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/prometheus/prometheus/util/testutil"
|
||||
)
|
||||
|
||||
|
@ -37,9 +39,7 @@ func TestStartupInterrupt(t *testing.T) {
|
|||
|
||||
prom := exec.Command(promPath, "-test.main", "--config.file="+promConfig, "--storage.tsdb.path="+t.TempDir(), "--web.listen-address=0.0.0.0"+port)
|
||||
err := prom.Start()
|
||||
if err != nil {
|
||||
t.Fatalf("execution error: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
|
@ -68,14 +68,11 @@ Loop:
|
|||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
|
||||
if !startedOk {
|
||||
t.Fatal("prometheus didn't start in the specified timeout")
|
||||
}
|
||||
switch err := prom.Process.Kill(); {
|
||||
case err == nil:
|
||||
t.Errorf("prometheus didn't shutdown gracefully after sending the Interrupt signal")
|
||||
case stoppedErr != nil && stoppedErr.Error() != "signal: interrupt":
|
||||
// TODO: find a better way to detect when the process didn't exit as expected!
|
||||
t.Errorf("prometheus exited with an unexpected error: %v", stoppedErr)
|
||||
require.True(t, startedOk, "prometheus didn't start in the specified timeout")
|
||||
err = prom.Process.Kill()
|
||||
require.Error(t, err, "prometheus didn't shutdown gracefully after sending the Interrupt signal")
|
||||
// TODO - find a better way to detect when the process didn't exit as expected!
|
||||
if stoppedErr != nil {
|
||||
require.EqualError(t, stoppedErr, "signal: interrupt", "prometheus exit")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,10 @@ package main
|
|||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/klauspost/compress/gzip"
|
||||
)
|
||||
|
||||
const filePerm = 0o666
|
||||
|
|
|
@ -127,7 +127,8 @@ func createBlocks(input []byte, mint, maxt, maxBlockDuration int64, maxSamplesIn
|
|||
|
||||
ctx := context.Background()
|
||||
app := w.Appender(ctx)
|
||||
p := textparse.NewOpenMetricsParser(input)
|
||||
symbolTable := labels.NewSymbolTable() // One table per block means it won't grow too large.
|
||||
p := textparse.NewOpenMetricsParser(input, symbolTable)
|
||||
samplesCount := 0
|
||||
for {
|
||||
e, err := p.Next()
|
||||
|
@ -216,7 +217,7 @@ func createBlocks(input []byte, mint, maxt, maxBlockDuration int64, maxSamplesIn
|
|||
}
|
||||
|
||||
func backfill(maxSamplesInAppender int, input []byte, outputDir string, humanReadable, quiet bool, maxBlockDuration time.Duration) (err error) {
|
||||
p := textparse.NewOpenMetricsParser(input)
|
||||
p := textparse.NewOpenMetricsParser(input, nil) // Don't need a SymbolTable to get max and min timestamps.
|
||||
maxt, mint, err := getMinAndMaxTimestamps(p)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting min and max timestamp: %w", err)
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/prometheus/prometheus/storage"
|
||||
"github.com/prometheus/prometheus/tsdb"
|
||||
"github.com/prometheus/prometheus/tsdb/chunkenc"
|
||||
"github.com/prometheus/prometheus/util/testutil"
|
||||
)
|
||||
|
||||
type backfillSample struct {
|
||||
|
@ -76,7 +77,7 @@ func testBlocks(t *testing.T, db *tsdb.DB, expectedMinTime, expectedMaxTime, exp
|
|||
allSamples := queryAllSeries(t, q, expectedMinTime, expectedMaxTime)
|
||||
sortSamples(allSamples)
|
||||
sortSamples(expectedSamples)
|
||||
require.Equal(t, expectedSamples, allSamples, "did not create correct samples")
|
||||
testutil.RequireEqual(t, expectedSamples, allSamples, "did not create correct samples")
|
||||
|
||||
if len(allSamples) > 0 {
|
||||
require.Equal(t, expectedMinTime, allSamples[0].Timestamp, "timestamp of first sample is not the expected minimum time")
|
||||
|
|
|
@ -239,6 +239,12 @@ func main() {
|
|||
dumpMaxTime := tsdbDumpCmd.Flag("max-time", "Maximum timestamp to dump.").Default(strconv.FormatInt(math.MaxInt64, 10)).Int64()
|
||||
dumpMatch := tsdbDumpCmd.Flag("match", "Series selector. Can be specified multiple times.").Default("{__name__=~'(?s:.*)'}").Strings()
|
||||
|
||||
tsdbDumpOpenMetricsCmd := tsdbCmd.Command("dump-openmetrics", "[Experimental] Dump samples from a TSDB into OpenMetrics format. Native histograms are not dumped.")
|
||||
dumpOpenMetricsPath := tsdbDumpOpenMetricsCmd.Arg("db path", "Database path (default is "+defaultDBPath+").").Default(defaultDBPath).String()
|
||||
dumpOpenMetricsMinTime := tsdbDumpOpenMetricsCmd.Flag("min-time", "Minimum timestamp to dump.").Default(strconv.FormatInt(math.MinInt64, 10)).Int64()
|
||||
dumpOpenMetricsMaxTime := tsdbDumpOpenMetricsCmd.Flag("max-time", "Maximum timestamp to dump.").Default(strconv.FormatInt(math.MaxInt64, 10)).Int64()
|
||||
dumpOpenMetricsMatch := tsdbDumpOpenMetricsCmd.Flag("match", "Series selector. Can be specified multiple times.").Default("{__name__=~'(?s:.*)'}").Strings()
|
||||
|
||||
importCmd := tsdbCmd.Command("create-blocks-from", "[Experimental] Import samples from input and produce TSDB blocks. Please refer to the storage docs for more details.")
|
||||
importHumanReadable := importCmd.Flag("human-readable", "Print human readable values.").Short('r').Bool()
|
||||
importQuiet := importCmd.Flag("quiet", "Do not print created blocks.").Short('q').Bool()
|
||||
|
@ -390,7 +396,9 @@ func main() {
|
|||
os.Exit(checkErr(listBlocks(*listPath, *listHumanReadable)))
|
||||
|
||||
case tsdbDumpCmd.FullCommand():
|
||||
os.Exit(checkErr(dumpSamples(ctx, *dumpPath, *dumpMinTime, *dumpMaxTime, *dumpMatch)))
|
||||
os.Exit(checkErr(dumpSamples(ctx, *dumpPath, *dumpMinTime, *dumpMaxTime, *dumpMatch, formatSeriesSet)))
|
||||
case tsdbDumpOpenMetricsCmd.FullCommand():
|
||||
os.Exit(checkErr(dumpSamples(ctx, *dumpOpenMetricsPath, *dumpOpenMetricsMinTime, *dumpOpenMetricsMaxTime, *dumpOpenMetricsMatch, formatSeriesSetOpenMetrics)))
|
||||
// TODO(aSquare14): Work on adding support for custom block size.
|
||||
case openMetricsImportCmd.FullCommand():
|
||||
os.Exit(backfillOpenMetrics(*importFilePath, *importDBPath, *importHumanReadable, *importQuiet, *maxBlockDuration))
|
||||
|
|
|
@ -18,10 +18,10 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"github.com/prometheus/prometheus/config"
|
||||
|
@ -153,7 +153,7 @@ func getSDCheckResult(targetGroups []*targetgroup.Group, scrapeConfig *config.Sc
|
|||
|
||||
duplicateRes := false
|
||||
for _, sdCheckRes := range sdCheckResults {
|
||||
if reflect.DeepEqual(sdCheckRes, result) {
|
||||
if cmp.Equal(sdCheckRes, result, cmp.Comparer(labels.Equal)) {
|
||||
duplicateRes = true
|
||||
break
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
"github.com/prometheus/prometheus/model/relabel"
|
||||
"github.com/prometheus/prometheus/util/testutil"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -69,5 +70,5 @@ func TestSDCheckResult(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
require.Equal(t, expectedSDCheckResult, getSDCheckResult(targetGroups, scrapeConfig, true))
|
||||
testutil.RequireEqual(t, expectedSDCheckResult, getSDCheckResult(targetGroups, scrapeConfig, true))
|
||||
}
|
||||
|
|
15
cmd/promtool/testdata/dump-openmetrics-roundtrip-test.prom
vendored
Normal file
15
cmd/promtool/testdata/dump-openmetrics-roundtrip-test.prom
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
my_histogram_bucket{instance="localhost:8000",job="example2",le="+Inf"} 1.0267820369e+10 1700215884.373
|
||||
my_histogram_bucket{instance="localhost:8000",job="example2",le="+Inf"} 1.026872507e+10 1700215889.373
|
||||
my_histogram_bucket{instance="localhost:8000",job="example2",le="0.01"} 0 1700215884.373
|
||||
my_histogram_bucket{instance="localhost:8000",job="example2",le="0.01"} 0 1700215889.373
|
||||
my_histogram_count{instance="localhost:8000",job="example2"} 1.0267820369e+10 1700215884.373
|
||||
my_histogram_count{instance="localhost:8000",job="example2"} 1.026872507e+10 1700215889.373
|
||||
my_summary_count{instance="localhost:8000",job="example5"} 9.518161497e+09 1700211684.981
|
||||
my_summary_count{instance="localhost:8000",job="example5"} 9.519048034e+09 1700211689.984
|
||||
my_summary_sum{instance="localhost:8000",job="example5"} 5.2349889185e+10 1700211684.981
|
||||
my_summary_sum{instance="localhost:8000",job="example5"} 5.2354761848e+10 1700211689.984
|
||||
up{instance="localhost:8000",job="example2"} 1 1700226034.330
|
||||
up{instance="localhost:8000",job="example2"} 1 1700226094.329
|
||||
up{instance="localhost:8000",job="example3"} 1 1700210681.366
|
||||
up{instance="localhost:8000",job="example3"} 1 1700210686.366
|
||||
# EOF
|
11
cmd/promtool/testdata/dump-openmetrics-test.prom
vendored
Normal file
11
cmd/promtool/testdata/dump-openmetrics-test.prom
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
my_counter{baz="abc",foo="bar"} 1 0.000
|
||||
my_counter{baz="abc",foo="bar"} 2 60.000
|
||||
my_counter{baz="abc",foo="bar"} 3 120.000
|
||||
my_counter{baz="abc",foo="bar"} 4 180.000
|
||||
my_counter{baz="abc",foo="bar"} 5 240.000
|
||||
my_gauge{abc="baz",bar="foo"} 9 0.000
|
||||
my_gauge{abc="baz",bar="foo"} 8 60.000
|
||||
my_gauge{abc="baz",bar="foo"} 0 120.000
|
||||
my_gauge{abc="baz",bar="foo"} 4 180.000
|
||||
my_gauge{abc="baz",bar="foo"} 7 240.000
|
||||
# EOF
|
|
@ -12,4 +12,4 @@ tests:
|
|||
eval_time: 1m
|
||||
exp_samples:
|
||||
- value: 1
|
||||
labels: test
|
||||
labels: test
|
||||
|
|
|
@ -15,6 +15,7 @@ package main
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -23,6 +24,7 @@ import (
|
|||
"path/filepath"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -31,7 +33,6 @@ import (
|
|||
|
||||
"github.com/alecthomas/units"
|
||||
"github.com/go-kit/log"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
"github.com/prometheus/prometheus/promql/parser"
|
||||
|
@ -706,7 +707,9 @@ func analyzeCompaction(ctx context.Context, block tsdb.BlockReader, indexr tsdb.
|
|||
return nil
|
||||
}
|
||||
|
||||
func dumpSamples(ctx context.Context, path string, mint, maxt int64, match []string) (err error) {
|
||||
type SeriesSetFormatter func(series storage.SeriesSet) error
|
||||
|
||||
func dumpSamples(ctx context.Context, path string, mint, maxt int64, match []string, formatter SeriesSetFormatter) (err error) {
|
||||
db, err := tsdb.OpenDBReadOnly(path, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -736,6 +739,22 @@ func dumpSamples(ctx context.Context, path string, mint, maxt int64, match []str
|
|||
ss = q.Select(ctx, false, nil, matcherSets[0]...)
|
||||
}
|
||||
|
||||
err = formatter(ss)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ws := ss.Warnings(); len(ws) > 0 {
|
||||
return tsdb_errors.NewMulti(ws.AsErrors()...).Err()
|
||||
}
|
||||
|
||||
if ss.Err() != nil {
|
||||
return ss.Err()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatSeriesSet(ss storage.SeriesSet) error {
|
||||
for ss.Next() {
|
||||
series := ss.At()
|
||||
lbs := series.Labels()
|
||||
|
@ -756,14 +775,44 @@ func dumpSamples(ctx context.Context, path string, mint, maxt int64, match []str
|
|||
return ss.Err()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if ws := ss.Warnings(); len(ws) > 0 {
|
||||
return tsdb_errors.NewMulti(ws.AsErrors()...).Err()
|
||||
}
|
||||
// CondensedString is labels.Labels.String() without spaces after the commas.
|
||||
func CondensedString(ls labels.Labels) string {
|
||||
var b bytes.Buffer
|
||||
|
||||
if ss.Err() != nil {
|
||||
return ss.Err()
|
||||
b.WriteByte('{')
|
||||
i := 0
|
||||
ls.Range(func(l labels.Label) {
|
||||
if i > 0 {
|
||||
b.WriteByte(',')
|
||||
}
|
||||
b.WriteString(l.Name)
|
||||
b.WriteByte('=')
|
||||
b.WriteString(strconv.Quote(l.Value))
|
||||
i++
|
||||
})
|
||||
b.WriteByte('}')
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func formatSeriesSetOpenMetrics(ss storage.SeriesSet) error {
|
||||
for ss.Next() {
|
||||
series := ss.At()
|
||||
lbs := series.Labels()
|
||||
metricName := lbs.Get(labels.MetricName)
|
||||
lbs = lbs.DropMetricName()
|
||||
it := series.Iterator(nil)
|
||||
for it.Next() == chunkenc.ValFloat {
|
||||
ts, val := it.At()
|
||||
fmt.Printf("%s%s %g %.3f\n", metricName, CondensedString(lbs), val, float64(ts)/1000)
|
||||
}
|
||||
if it.Err() != nil {
|
||||
return ss.Err()
|
||||
}
|
||||
}
|
||||
fmt.Println("# EOF")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,12 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/prometheus/prometheus/promql"
|
||||
"github.com/prometheus/prometheus/tsdb"
|
||||
)
|
||||
|
||||
func TestGenerateBucket(t *testing.T) {
|
||||
|
@ -52,7 +54,7 @@ func TestGenerateBucket(t *testing.T) {
|
|||
}
|
||||
|
||||
// getDumpedSamples dumps samples and returns them.
|
||||
func getDumpedSamples(t *testing.T, path string, mint, maxt int64, match []string) string {
|
||||
func getDumpedSamples(t *testing.T, path string, mint, maxt int64, match []string, formatter SeriesSetFormatter) string {
|
||||
t.Helper()
|
||||
|
||||
oldStdout := os.Stdout
|
||||
|
@ -65,6 +67,7 @@ func getDumpedSamples(t *testing.T, path string, mint, maxt int64, match []strin
|
|||
mint,
|
||||
maxt,
|
||||
match,
|
||||
formatter,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -76,6 +79,14 @@ func getDumpedSamples(t *testing.T, path string, mint, maxt int64, match []strin
|
|||
return buf.String()
|
||||
}
|
||||
|
||||
func normalizeNewLine(b []byte) []byte {
|
||||
if strings.Contains(runtime.GOOS, "windows") {
|
||||
// We use "/n" while dumping on windows as well.
|
||||
return bytes.ReplaceAll(b, []byte("\r\n"), []byte("\n"))
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestTSDBDump(t *testing.T) {
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
|
@ -136,15 +147,48 @@ func TestTSDBDump(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dumpedMetrics := getDumpedSamples(t, storage.Dir(), tt.mint, tt.maxt, tt.match)
|
||||
dumpedMetrics := getDumpedSamples(t, storage.Dir(), tt.mint, tt.maxt, tt.match, formatSeriesSet)
|
||||
expectedMetrics, err := os.ReadFile(tt.expectedDump)
|
||||
require.NoError(t, err)
|
||||
if strings.Contains(runtime.GOOS, "windows") {
|
||||
// We use "/n" while dumping on windows as well.
|
||||
expectedMetrics = bytes.ReplaceAll(expectedMetrics, []byte("\r\n"), []byte("\n"))
|
||||
}
|
||||
expectedMetrics = normalizeNewLine(expectedMetrics)
|
||||
// even though in case of one matcher samples are not sorted, the order in the cases above should stay the same.
|
||||
require.Equal(t, string(expectedMetrics), dumpedMetrics)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTSDBDumpOpenMetrics(t *testing.T) {
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
my_counter{foo="bar", baz="abc"} 1 2 3 4 5
|
||||
my_gauge{bar="foo", abc="baz"} 9 8 0 4 7
|
||||
`)
|
||||
|
||||
expectedMetrics, err := os.ReadFile("testdata/dump-openmetrics-test.prom")
|
||||
require.NoError(t, err)
|
||||
expectedMetrics = normalizeNewLine(expectedMetrics)
|
||||
dumpedMetrics := getDumpedSamples(t, storage.Dir(), math.MinInt64, math.MaxInt64, []string{"{__name__=~'(?s:.*)'}"}, formatSeriesSetOpenMetrics)
|
||||
require.Equal(t, string(expectedMetrics), dumpedMetrics)
|
||||
}
|
||||
|
||||
func TestTSDBDumpOpenMetricsRoundTrip(t *testing.T) {
|
||||
initialMetrics, err := os.ReadFile("testdata/dump-openmetrics-roundtrip-test.prom")
|
||||
require.NoError(t, err)
|
||||
initialMetrics = normalizeNewLine(initialMetrics)
|
||||
|
||||
dbDir := t.TempDir()
|
||||
// Import samples from OM format
|
||||
err = backfill(5000, initialMetrics, dbDir, false, false, 2*time.Hour)
|
||||
require.NoError(t, err)
|
||||
db, err := tsdb.Open(dbDir, nil, nil, tsdb.DefaultOptions(), nil)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, db.Close())
|
||||
})
|
||||
|
||||
// Dump the blocks into OM format
|
||||
dumpedMetrics := getDumpedSamples(t, dbDir, math.MinInt64, math.MaxInt64, []string{"{__name__=~'(?s:.*)'}"}, formatSeriesSetOpenMetrics)
|
||||
|
||||
// Should get back the initial metrics.
|
||||
require.Equal(t, string(initialMetrics), dumpedMetrics)
|
||||
}
|
||||
|
|
|
@ -20,13 +20,13 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/grafana/regexp"
|
||||
"github.com/nsf/jsondiff"
|
||||
"github.com/prometheus/common/model"
|
||||
|
@ -175,13 +175,18 @@ type testGroup struct {
|
|||
}
|
||||
|
||||
// test performs the unit tests.
|
||||
func (tg *testGroup) test(evalInterval time.Duration, groupOrderMap map[string]int, queryOpts promql.LazyLoaderOpts, diffFlag bool, ruleFiles ...string) []error {
|
||||
func (tg *testGroup) test(evalInterval time.Duration, groupOrderMap map[string]int, queryOpts promql.LazyLoaderOpts, diffFlag bool, ruleFiles ...string) (outErr []error) {
|
||||
// Setup testing suite.
|
||||
suite, err := promql.NewLazyLoader(nil, tg.seriesLoadingString(), queryOpts)
|
||||
suite, err := promql.NewLazyLoader(tg.seriesLoadingString(), queryOpts)
|
||||
if err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
defer suite.Close()
|
||||
defer func() {
|
||||
err := suite.Close()
|
||||
if err != nil {
|
||||
outErr = append(outErr, err)
|
||||
}
|
||||
}()
|
||||
suite.SubqueryInterval = evalInterval
|
||||
|
||||
// Load the rule files.
|
||||
|
@ -340,7 +345,7 @@ func (tg *testGroup) test(evalInterval time.Duration, groupOrderMap map[string]i
|
|||
sort.Sort(gotAlerts)
|
||||
sort.Sort(expAlerts)
|
||||
|
||||
if !reflect.DeepEqual(expAlerts, gotAlerts) {
|
||||
if !cmp.Equal(expAlerts, gotAlerts, cmp.Comparer(labels.Equal)) {
|
||||
var testName string
|
||||
if tg.TestGroupName != "" {
|
||||
testName = fmt.Sprintf(" name: %s,\n", tg.TestGroupName)
|
||||
|
@ -448,7 +453,7 @@ Outer:
|
|||
sort.Slice(gotSamples, func(i, j int) bool {
|
||||
return labels.Compare(gotSamples[i].Labels, gotSamples[j].Labels) <= 0
|
||||
})
|
||||
if !reflect.DeepEqual(expSamples, gotSamples) {
|
||||
if !cmp.Equal(expSamples, gotSamples, cmp.Comparer(labels.Equal)) {
|
||||
errs = append(errs, fmt.Errorf(" expr: %q, time: %s,\n exp: %v\n got: %v", testCase.Expr,
|
||||
testCase.EvalTime.String(), parsedSamplesString(expSamples), parsedSamplesString(gotSamples)))
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ package main
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/prometheus/prometheus/promql"
|
||||
)
|
||||
|
||||
|
@ -178,9 +180,8 @@ func TestRulesUnitTestRun(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := RulesUnitTest(tt.queryOpts, tt.args.run, false, tt.args.files...); got != tt.want {
|
||||
t.Errorf("RulesUnitTest() = %v, want %v", got, tt.want)
|
||||
}
|
||||
got := RulesUnitTest(tt.queryOpts, tt.args.run, false, tt.args.files...)
|
||||
require.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ func Load(s string, expandExternalLabels bool, logger log.Logger) (*Config, erro
|
|||
return cfg, nil
|
||||
}
|
||||
|
||||
b := labels.ScratchBuilder{}
|
||||
b := labels.NewScratchBuilder(0)
|
||||
cfg.GlobalConfig.ExternalLabels.Range(func(v labels.Label) {
|
||||
newV := os.Expand(v.Value, func(s string) string {
|
||||
if s == "$" {
|
||||
|
@ -97,6 +97,7 @@ func Load(s string, expandExternalLabels bool, logger log.Logger) (*Config, erro
|
|||
if newV != v.Value {
|
||||
level.Debug(logger).Log("msg", "External label replaced", "label", v.Name, "input", v.Value, "output", newV)
|
||||
}
|
||||
// Note newV can be blank. https://github.com/prometheus/prometheus/issues/11024
|
||||
b.Add(v.Name, newV)
|
||||
})
|
||||
cfg.GlobalConfig.ExternalLabels = b.Labels()
|
||||
|
@ -940,6 +941,8 @@ type AlertmanagerConfig struct {
|
|||
|
||||
// List of Alertmanager relabel configurations.
|
||||
RelabelConfigs []*relabel.Config `yaml:"relabel_configs,omitempty"`
|
||||
// Relabel alerts before sending to the specific alertmanager.
|
||||
AlertRelabelConfigs []*relabel.Config `yaml:"alert_relabel_configs,omitempty"`
|
||||
}
|
||||
|
||||
// SetDirectory joins any relative file paths with dir.
|
||||
|
@ -982,6 +985,12 @@ func (c *AlertmanagerConfig) UnmarshalYAML(unmarshal func(interface{}) error) er
|
|||
}
|
||||
}
|
||||
|
||||
for _, rlcfg := range c.AlertRelabelConfigs {
|
||||
if rlcfg == nil {
|
||||
return errors.New("empty or null Alertmanager alert relabeling rule")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ import (
|
|||
"github.com/prometheus/prometheus/discovery/zookeeper"
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
"github.com/prometheus/prometheus/model/relabel"
|
||||
"github.com/prometheus/prometheus/util/testutil"
|
||||
)
|
||||
|
||||
func mustParseURL(u string) *config.URL {
|
||||
|
@ -1839,7 +1840,7 @@ var expectedErrors = []struct {
|
|||
},
|
||||
{
|
||||
filename: "azure_authentication_method.bad.yml",
|
||||
errMsg: "unknown authentication_type \"invalid\". Supported types are \"OAuth\" or \"ManagedIdentity\"",
|
||||
errMsg: "unknown authentication_type \"invalid\". Supported types are \"OAuth\", \"ManagedIdentity\" or \"SDK\"",
|
||||
},
|
||||
{
|
||||
filename: "azure_bearertoken_basicauth.bad.yml",
|
||||
|
@ -2037,16 +2038,16 @@ func TestExpandExternalLabels(t *testing.T) {
|
|||
|
||||
c, err := LoadFile("testdata/external_labels.good.yml", false, false, log.NewNopLogger())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, labels.FromStrings("bar", "foo", "baz", "foo${TEST}bar", "foo", "${TEST}", "qux", "foo$${TEST}", "xyz", "foo$$bar"), c.GlobalConfig.ExternalLabels)
|
||||
testutil.RequireEqual(t, labels.FromStrings("bar", "foo", "baz", "foo${TEST}bar", "foo", "${TEST}", "qux", "foo$${TEST}", "xyz", "foo$$bar"), c.GlobalConfig.ExternalLabels)
|
||||
|
||||
c, err = LoadFile("testdata/external_labels.good.yml", false, true, log.NewNopLogger())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, labels.FromStrings("bar", "foo", "baz", "foobar", "foo", "", "qux", "foo${TEST}", "xyz", "foo$bar"), c.GlobalConfig.ExternalLabels)
|
||||
testutil.RequireEqual(t, labels.FromStrings("bar", "foo", "baz", "foobar", "foo", "", "qux", "foo${TEST}", "xyz", "foo$bar"), c.GlobalConfig.ExternalLabels)
|
||||
|
||||
os.Setenv("TEST", "TestValue")
|
||||
c, err = LoadFile("testdata/external_labels.good.yml", false, true, log.NewNopLogger())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, labels.FromStrings("bar", "foo", "baz", "fooTestValuebar", "foo", "TestValue", "qux", "foo${TEST}", "xyz", "foo$bar"), c.GlobalConfig.ExternalLabels)
|
||||
testutil.RequireEqual(t, labels.FromStrings("bar", "foo", "baz", "fooTestValuebar", "foo", "TestValue", "qux", "foo${TEST}", "xyz", "foo$bar"), c.GlobalConfig.ExternalLabels)
|
||||
}
|
||||
|
||||
func TestAgentMode(t *testing.T) {
|
||||
|
|
|
@ -65,6 +65,7 @@ const (
|
|||
azureLabelMachineSize = azureLabel + "machine_size"
|
||||
|
||||
authMethodOAuth = "OAuth"
|
||||
authMethodSDK = "SDK"
|
||||
authMethodManagedIdentity = "ManagedIdentity"
|
||||
)
|
||||
|
||||
|
@ -164,8 +165,8 @@ func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||
}
|
||||
}
|
||||
|
||||
if c.AuthenticationMethod != authMethodOAuth && c.AuthenticationMethod != authMethodManagedIdentity {
|
||||
return fmt.Errorf("unknown authentication_type %q. Supported types are %q or %q", c.AuthenticationMethod, authMethodOAuth, authMethodManagedIdentity)
|
||||
if c.AuthenticationMethod != authMethodOAuth && c.AuthenticationMethod != authMethodManagedIdentity && c.AuthenticationMethod != authMethodSDK {
|
||||
return fmt.Errorf("unknown authentication_type %q. Supported types are %q, %q or %q", c.AuthenticationMethod, authMethodOAuth, authMethodManagedIdentity, authMethodSDK)
|
||||
}
|
||||
|
||||
return c.HTTPClientConfig.Validate()
|
||||
|
@ -294,6 +295,16 @@ func newCredential(cfg SDConfig, policyClientOptions policy.ClientOptions) (azco
|
|||
return nil, err
|
||||
}
|
||||
credential = azcore.TokenCredential(secretCredential)
|
||||
case authMethodSDK:
|
||||
options := &azidentity.DefaultAzureCredentialOptions{ClientOptions: policyClientOptions}
|
||||
if len(cfg.TenantID) != 0 {
|
||||
options.TenantID = cfg.TenantID
|
||||
}
|
||||
sdkCredential, err := azidentity.NewDefaultAzureCredential(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
credential = azcore.TokenCredential(sdkCredential)
|
||||
}
|
||||
return credential, nil
|
||||
}
|
||||
|
@ -413,26 +424,20 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
|
|||
} else {
|
||||
networkInterface, err = client.getVMScaleSetVMNetworkInterfaceByID(ctx, nicID, vm.ScaleSet, vm.InstanceID)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, errorNotFound) {
|
||||
level.Warn(d.logger).Log("msg", "Network interface does not exist", "name", nicID, "err", err)
|
||||
} else {
|
||||
ch <- target{labelSet: nil, err: err}
|
||||
}
|
||||
d.addToCache(nicID, networkInterface)
|
||||
} else {
|
||||
networkInterface, err = client.getVMScaleSetVMNetworkInterfaceByID(ctx, nicID, vm.ScaleSet, vm.InstanceID)
|
||||
if err != nil {
|
||||
if errors.Is(err, errorNotFound) {
|
||||
level.Warn(d.logger).Log("msg", "Network interface does not exist", "name", nicID, "err", err)
|
||||
} else {
|
||||
ch <- target{labelSet: nil, err: err}
|
||||
}
|
||||
// Get out of this routine because we cannot continue without a network interface.
|
||||
return
|
||||
}
|
||||
d.addToCache(nicID, networkInterface)
|
||||
|
||||
// Get out of this routine because we cannot continue without a network interface.
|
||||
return
|
||||
}
|
||||
|
||||
// Continue processing with the network interface
|
||||
d.addToCache(nicID, networkInterface)
|
||||
}
|
||||
|
||||
if networkInterface.Properties == nil {
|
||||
|
@ -569,7 +574,7 @@ func (client *azureClient) getScaleSetVMs(ctx context.Context, scaleSet armcompu
|
|||
}
|
||||
|
||||
func mapFromVM(vm armcompute.VirtualMachine) virtualMachine {
|
||||
osType := string(*vm.Properties.StorageProfile.OSDisk.OSType)
|
||||
var osType string
|
||||
tags := map[string]*string{}
|
||||
networkInterfaces := []string{}
|
||||
var computerName string
|
||||
|
@ -580,6 +585,12 @@ func mapFromVM(vm armcompute.VirtualMachine) virtualMachine {
|
|||
}
|
||||
|
||||
if vm.Properties != nil {
|
||||
if vm.Properties.StorageProfile != nil &&
|
||||
vm.Properties.StorageProfile.OSDisk != nil &&
|
||||
vm.Properties.StorageProfile.OSDisk.OSType != nil {
|
||||
osType = string(*vm.Properties.StorageProfile.OSDisk.OSType)
|
||||
}
|
||||
|
||||
if vm.Properties.NetworkProfile != nil {
|
||||
for _, vmNIC := range vm.Properties.NetworkProfile.NetworkInterfaces {
|
||||
networkInterfaces = append(networkInterfaces, *vmNIC.ID)
|
||||
|
@ -608,7 +619,7 @@ func mapFromVM(vm armcompute.VirtualMachine) virtualMachine {
|
|||
}
|
||||
|
||||
func mapFromVMScaleSetVM(vm armcompute.VirtualMachineScaleSetVM, scaleSetName string) virtualMachine {
|
||||
osType := string(*vm.Properties.StorageProfile.OSDisk.OSType)
|
||||
var osType string
|
||||
tags := map[string]*string{}
|
||||
networkInterfaces := []string{}
|
||||
var computerName string
|
||||
|
@ -619,6 +630,12 @@ func mapFromVMScaleSetVM(vm armcompute.VirtualMachineScaleSetVM, scaleSetName st
|
|||
}
|
||||
|
||||
if vm.Properties != nil {
|
||||
if vm.Properties.StorageProfile != nil &&
|
||||
vm.Properties.StorageProfile.OSDisk != nil &&
|
||||
vm.Properties.StorageProfile.OSDisk.OSType != nil {
|
||||
osType = string(*vm.Properties.StorageProfile.OSDisk.OSType)
|
||||
}
|
||||
|
||||
if vm.Properties.NetworkProfile != nil {
|
||||
for _, vmNIC := range vm.Properties.NetworkProfile.NetworkInterfaces {
|
||||
networkInterfaces = append(networkInterfaces, *vmNIC.ID)
|
||||
|
|
|
@ -79,6 +79,55 @@ func TestMapFromVMWithEmptyTags(t *testing.T) {
|
|||
require.Equal(t, expectedVM, actualVM)
|
||||
}
|
||||
|
||||
func TestMapFromVMWithEmptyOSType(t *testing.T) {
|
||||
id := "test"
|
||||
name := "name"
|
||||
size := "size"
|
||||
vmSize := armcompute.VirtualMachineSizeTypes(size)
|
||||
vmType := "type"
|
||||
location := "westeurope"
|
||||
computerName := "computer_name"
|
||||
networkProfile := armcompute.NetworkProfile{
|
||||
NetworkInterfaces: []*armcompute.NetworkInterfaceReference{},
|
||||
}
|
||||
properties := &armcompute.VirtualMachineProperties{
|
||||
OSProfile: &armcompute.OSProfile{
|
||||
ComputerName: &computerName,
|
||||
},
|
||||
StorageProfile: &armcompute.StorageProfile{
|
||||
OSDisk: &armcompute.OSDisk{},
|
||||
},
|
||||
NetworkProfile: &networkProfile,
|
||||
HardwareProfile: &armcompute.HardwareProfile{
|
||||
VMSize: &vmSize,
|
||||
},
|
||||
}
|
||||
|
||||
testVM := armcompute.VirtualMachine{
|
||||
ID: &id,
|
||||
Name: &name,
|
||||
Type: &vmType,
|
||||
Location: &location,
|
||||
Tags: nil,
|
||||
Properties: properties,
|
||||
}
|
||||
|
||||
expectedVM := virtualMachine{
|
||||
ID: id,
|
||||
Name: name,
|
||||
ComputerName: computerName,
|
||||
Type: vmType,
|
||||
Location: location,
|
||||
Tags: map[string]*string{},
|
||||
NetworkInterfaces: []string{},
|
||||
Size: size,
|
||||
}
|
||||
|
||||
actualVM := mapFromVM(testVM)
|
||||
|
||||
require.Equal(t, expectedVM, actualVM)
|
||||
}
|
||||
|
||||
func TestMapFromVMWithTags(t *testing.T) {
|
||||
id := "test"
|
||||
name := "name"
|
||||
|
@ -193,6 +242,58 @@ func TestMapFromVMScaleSetVMWithEmptyTags(t *testing.T) {
|
|||
require.Equal(t, expectedVM, actualVM)
|
||||
}
|
||||
|
||||
func TestMapFromVMScaleSetVMWithEmptyOSType(t *testing.T) {
|
||||
id := "test"
|
||||
name := "name"
|
||||
size := "size"
|
||||
vmSize := armcompute.VirtualMachineSizeTypes(size)
|
||||
vmType := "type"
|
||||
instanceID := "123"
|
||||
location := "westeurope"
|
||||
computerName := "computer_name"
|
||||
networkProfile := armcompute.NetworkProfile{
|
||||
NetworkInterfaces: []*armcompute.NetworkInterfaceReference{},
|
||||
}
|
||||
properties := &armcompute.VirtualMachineScaleSetVMProperties{
|
||||
OSProfile: &armcompute.OSProfile{
|
||||
ComputerName: &computerName,
|
||||
},
|
||||
StorageProfile: &armcompute.StorageProfile{},
|
||||
NetworkProfile: &networkProfile,
|
||||
HardwareProfile: &armcompute.HardwareProfile{
|
||||
VMSize: &vmSize,
|
||||
},
|
||||
}
|
||||
|
||||
testVM := armcompute.VirtualMachineScaleSetVM{
|
||||
ID: &id,
|
||||
Name: &name,
|
||||
Type: &vmType,
|
||||
InstanceID: &instanceID,
|
||||
Location: &location,
|
||||
Tags: nil,
|
||||
Properties: properties,
|
||||
}
|
||||
|
||||
scaleSet := "testSet"
|
||||
expectedVM := virtualMachine{
|
||||
ID: id,
|
||||
Name: name,
|
||||
ComputerName: computerName,
|
||||
Type: vmType,
|
||||
Location: location,
|
||||
Tags: map[string]*string{},
|
||||
NetworkInterfaces: []string{},
|
||||
ScaleSet: scaleSet,
|
||||
InstanceID: instanceID,
|
||||
Size: size,
|
||||
}
|
||||
|
||||
actualVM := mapFromVMScaleSetVM(testVM, scaleSet)
|
||||
|
||||
require.Equal(t, expectedVM, actualVM)
|
||||
}
|
||||
|
||||
func TestMapFromVMScaleSetVMWithTags(t *testing.T) {
|
||||
id := "test"
|
||||
name := "name"
|
||||
|
|
|
@ -56,15 +56,11 @@ func TestConfiguredService(t *testing.T) {
|
|||
metrics := NewTestMetrics(t, conf, prometheus.NewRegistry())
|
||||
|
||||
consulDiscovery, err := NewDiscovery(conf, nil, metrics)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when initializing discovery %v", err)
|
||||
}
|
||||
if !consulDiscovery.shouldWatch("configuredServiceName", []string{""}) {
|
||||
t.Errorf("Expected service %s to be watched", "configuredServiceName")
|
||||
}
|
||||
if consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}) {
|
||||
t.Errorf("Expected service %s to not be watched", "nonConfiguredServiceName")
|
||||
}
|
||||
require.NoError(t, err, "when initializing discovery")
|
||||
require.True(t, consulDiscovery.shouldWatch("configuredServiceName", []string{""}),
|
||||
"Expected service %s to be watched", "configuredServiceName")
|
||||
require.False(t, consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}),
|
||||
"Expected service %s to not be watched", "nonConfiguredServiceName")
|
||||
}
|
||||
|
||||
func TestConfiguredServiceWithTag(t *testing.T) {
|
||||
|
@ -76,21 +72,18 @@ func TestConfiguredServiceWithTag(t *testing.T) {
|
|||
metrics := NewTestMetrics(t, conf, prometheus.NewRegistry())
|
||||
|
||||
consulDiscovery, err := NewDiscovery(conf, nil, metrics)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when initializing discovery %v", err)
|
||||
}
|
||||
if consulDiscovery.shouldWatch("configuredServiceName", []string{""}) {
|
||||
t.Errorf("Expected service %s to not be watched without tag", "configuredServiceName")
|
||||
}
|
||||
if !consulDiscovery.shouldWatch("configuredServiceName", []string{"http"}) {
|
||||
t.Errorf("Expected service %s to be watched with tag %s", "configuredServiceName", "http")
|
||||
}
|
||||
if consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}) {
|
||||
t.Errorf("Expected service %s to not be watched without tag", "nonConfiguredServiceName")
|
||||
}
|
||||
if consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{"http"}) {
|
||||
t.Errorf("Expected service %s to not be watched with tag %s", "nonConfiguredServiceName", "http")
|
||||
}
|
||||
require.NoError(t, err, "when initializing discovery")
|
||||
require.False(t, consulDiscovery.shouldWatch("configuredServiceName", []string{""}),
|
||||
"Expected service %s to not be watched without tag", "configuredServiceName")
|
||||
|
||||
require.True(t, consulDiscovery.shouldWatch("configuredServiceName", []string{"http"}),
|
||||
"Expected service %s to be watched with tag %s", "configuredServiceName", "http")
|
||||
|
||||
require.False(t, consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}),
|
||||
"Expected service %s to not be watched without tag", "nonConfiguredServiceName")
|
||||
|
||||
require.False(t, consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{"http"}),
|
||||
"Expected service %s to not be watched with tag %s", "nonConfiguredServiceName", "http")
|
||||
}
|
||||
|
||||
func TestConfiguredServiceWithTags(t *testing.T) {
|
||||
|
@ -173,13 +166,10 @@ func TestConfiguredServiceWithTags(t *testing.T) {
|
|||
metrics := NewTestMetrics(t, tc.conf, prometheus.NewRegistry())
|
||||
|
||||
consulDiscovery, err := NewDiscovery(tc.conf, nil, metrics)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when initializing discovery %v", err)
|
||||
}
|
||||
require.NoError(t, err, "when initializing discovery")
|
||||
ret := consulDiscovery.shouldWatch(tc.serviceName, tc.serviceTags)
|
||||
if ret != tc.shouldWatch {
|
||||
t.Errorf("Expected should watch? %t, got %t. Watched service and tags: %s %+v, input was %s %+v", tc.shouldWatch, ret, tc.conf.Services, tc.conf.ServiceTags, tc.serviceName, tc.serviceTags)
|
||||
}
|
||||
require.Equal(t, tc.shouldWatch, ret, "Watched service and tags: %s %+v, input was %s %+v",
|
||||
tc.conf.Services, tc.conf.ServiceTags, tc.serviceName, tc.serviceTags)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,12 +179,8 @@ func TestNonConfiguredService(t *testing.T) {
|
|||
metrics := NewTestMetrics(t, conf, prometheus.NewRegistry())
|
||||
|
||||
consulDiscovery, err := NewDiscovery(conf, nil, metrics)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when initializing discovery %v", err)
|
||||
}
|
||||
if !consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}) {
|
||||
t.Errorf("Expected service %s to be watched", "nonConfiguredServiceName")
|
||||
}
|
||||
require.NoError(t, err, "when initializing discovery")
|
||||
require.True(t, consulDiscovery.shouldWatch("nonConfiguredServiceName", []string{""}), "Expected service %s to be watched", "nonConfiguredServiceName")
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -502,13 +488,10 @@ oauth2:
|
|||
var config SDConfig
|
||||
err := config.UnmarshalYAML(unmarshal([]byte(test.config)))
|
||||
if err != nil {
|
||||
require.Equalf(t, err.Error(), test.errMessage, "Expected error '%s', got '%v'", test.errMessage, err)
|
||||
return
|
||||
}
|
||||
if test.errMessage != "" {
|
||||
t.Errorf("Expected error %s, got none", test.errMessage)
|
||||
require.EqualError(t, err, test.errMessage)
|
||||
return
|
||||
}
|
||||
require.Empty(t, test.errMessage, "Expected error.")
|
||||
|
||||
require.Equal(t, test.expected, config)
|
||||
})
|
||||
|
|
|
@ -358,9 +358,7 @@ func TestInvalidFile(t *testing.T) {
|
|||
|
||||
// Verify that we've received nothing.
|
||||
time.Sleep(defaultWait)
|
||||
if runner.lastReceive().After(now) {
|
||||
t.Fatalf("unexpected targets received: %v", runner.targets())
|
||||
}
|
||||
require.False(t, runner.lastReceive().After(now), "unexpected targets received: %v", runner.targets())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,8 @@ func NewEndpoints(l log.Logger, eps cache.SharedIndexInformer, svc, pod, node ca
|
|||
svcUpdateCount := eventCount.WithLabelValues(RoleService.String(), MetricLabelRoleUpdate)
|
||||
svcDeleteCount := eventCount.WithLabelValues(RoleService.String(), MetricLabelRoleDelete)
|
||||
|
||||
podUpdateCount := eventCount.WithLabelValues(RolePod.String(), MetricLabelRoleUpdate)
|
||||
|
||||
e := &Endpoints{
|
||||
logger: l,
|
||||
endpointsInf: eps,
|
||||
|
@ -131,6 +133,29 @@ func NewEndpoints(l log.Logger, eps cache.SharedIndexInformer, svc, pod, node ca
|
|||
if err != nil {
|
||||
level.Error(l).Log("msg", "Error adding services event handler.", "err", err)
|
||||
}
|
||||
_, err = e.podInf.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
UpdateFunc: func(old, cur interface{}) {
|
||||
podUpdateCount.Inc()
|
||||
oldPod, ok := old.(*apiv1.Pod)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
curPod, ok := cur.(*apiv1.Pod)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// the Pod's phase may change without triggering an update on the Endpoints/Service.
|
||||
// https://github.com/prometheus/prometheus/issues/11305.
|
||||
if curPod.Status.Phase != oldPod.Status.Phase {
|
||||
e.enqueuePod(namespacedName(curPod.Namespace, curPod.Name))
|
||||
}
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
level.Error(l).Log("msg", "Error adding pods event handler.", "err", err)
|
||||
}
|
||||
if e.withNodeMetadata {
|
||||
_, err = e.nodeInf.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(o interface{}) {
|
||||
|
@ -166,6 +191,18 @@ func (e *Endpoints) enqueueNode(nodeName string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (e *Endpoints) enqueuePod(podNamespacedName string) {
|
||||
endpoints, err := e.endpointsInf.GetIndexer().ByIndex(podIndex, podNamespacedName)
|
||||
if err != nil {
|
||||
level.Error(e.logger).Log("msg", "Error getting endpoints for pod", "pod", podNamespacedName, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, endpoint := range endpoints {
|
||||
e.enqueue(endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Endpoints) enqueue(obj interface{}) {
|
||||
key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj)
|
||||
if err != nil {
|
||||
|
@ -312,7 +349,7 @@ func (e *Endpoints) buildEndpoints(eps *apiv1.Endpoints) *targetgroup.Group {
|
|||
tg.Targets = append(tg.Targets, target)
|
||||
return
|
||||
}
|
||||
s := pod.Namespace + "/" + pod.Name
|
||||
s := namespacedName(pod.Namespace, pod.Name)
|
||||
|
||||
sp, ok := seenPods[s]
|
||||
if !ok {
|
||||
|
|
|
@ -969,3 +969,123 @@ func TestEndpointsDiscoveryEmptyPodStatus(t *testing.T) {
|
|||
expectedRes: map[string]*targetgroup.Group{},
|
||||
}.Run(t)
|
||||
}
|
||||
|
||||
// TestEndpointsUpdatePod makes sure that Endpoints discovery detects underlying Pods changes.
|
||||
// See https://github.com/prometheus/prometheus/issues/11305 for more details.
|
||||
func TestEndpointsDiscoveryUpdatePod(t *testing.T) {
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "testpod",
|
||||
Namespace: "default",
|
||||
UID: types.UID("deadbeef"),
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
NodeName: "testnode",
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "c1",
|
||||
Image: "c1:latest",
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
Name: "mainport",
|
||||
ContainerPort: 9000,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: v1.PodStatus{
|
||||
// Pod is in Pending phase when discovered for first time.
|
||||
Phase: "Pending",
|
||||
Conditions: []v1.PodCondition{
|
||||
{
|
||||
Type: v1.PodReady,
|
||||
Status: v1.ConditionFalse,
|
||||
},
|
||||
},
|
||||
HostIP: "2.3.4.5",
|
||||
PodIP: "4.3.2.1",
|
||||
},
|
||||
}
|
||||
objs := []runtime.Object{
|
||||
&v1.Endpoints{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "testendpoints",
|
||||
Namespace: "default",
|
||||
},
|
||||
Subsets: []v1.EndpointSubset{
|
||||
{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{
|
||||
IP: "4.3.2.1",
|
||||
// The Pending Pod may be included because the Endpoints was created manually.
|
||||
// Or because the corresponding service has ".spec.publishNotReadyAddresses: true".
|
||||
TargetRef: &v1.ObjectReference{
|
||||
Kind: "Pod",
|
||||
Name: "testpod",
|
||||
Namespace: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
Ports: []v1.EndpointPort{
|
||||
{
|
||||
Name: "mainport",
|
||||
Port: 9000,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pod,
|
||||
}
|
||||
n, c := makeDiscovery(RoleEndpoint, NamespaceDiscovery{}, objs...)
|
||||
|
||||
k8sDiscoveryTest{
|
||||
discovery: n,
|
||||
afterStart: func() {
|
||||
// the Pod becomes Ready.
|
||||
pod.Status.Phase = "Running"
|
||||
pod.Status.Conditions = []v1.PodCondition{
|
||||
{
|
||||
Type: v1.PodReady,
|
||||
Status: v1.ConditionTrue,
|
||||
},
|
||||
}
|
||||
c.CoreV1().Pods(pod.Namespace).Update(context.Background(), pod, metav1.UpdateOptions{})
|
||||
},
|
||||
expectedMaxItems: 2,
|
||||
expectedRes: map[string]*targetgroup.Group{
|
||||
"endpoints/default/testendpoints": {
|
||||
Targets: []model.LabelSet{
|
||||
{
|
||||
"__address__": "4.3.2.1:9000",
|
||||
"__meta_kubernetes_endpoint_port_name": "mainport",
|
||||
"__meta_kubernetes_endpoint_port_protocol": "TCP",
|
||||
"__meta_kubernetes_endpoint_ready": "true",
|
||||
"__meta_kubernetes_endpoint_address_target_kind": "Pod",
|
||||
"__meta_kubernetes_endpoint_address_target_name": "testpod",
|
||||
"__meta_kubernetes_pod_name": "testpod",
|
||||
"__meta_kubernetes_pod_ip": "4.3.2.1",
|
||||
"__meta_kubernetes_pod_ready": "true",
|
||||
"__meta_kubernetes_pod_phase": "Running",
|
||||
"__meta_kubernetes_pod_node_name": "testnode",
|
||||
"__meta_kubernetes_pod_host_ip": "2.3.4.5",
|
||||
"__meta_kubernetes_pod_container_name": "c1",
|
||||
"__meta_kubernetes_pod_container_image": "c1:latest",
|
||||
"__meta_kubernetes_pod_container_port_name": "mainport",
|
||||
"__meta_kubernetes_pod_container_port_number": "9000",
|
||||
"__meta_kubernetes_pod_container_port_protocol": "TCP",
|
||||
"__meta_kubernetes_pod_uid": "deadbeef",
|
||||
},
|
||||
},
|
||||
Labels: model.LabelSet{
|
||||
"__meta_kubernetes_namespace": "default",
|
||||
"__meta_kubernetes_endpoints_name": "testendpoints",
|
||||
},
|
||||
Source: "endpoints/default/testendpoints",
|
||||
},
|
||||
},
|
||||
}.Run(t)
|
||||
}
|
||||
|
|
|
@ -358,7 +358,7 @@ func (e *EndpointSlice) buildEndpointSlice(eps endpointSliceAdaptor) *targetgrou
|
|||
tg.Targets = append(tg.Targets, target)
|
||||
return
|
||||
}
|
||||
s := pod.Namespace + "/" + pod.Name
|
||||
s := namespacedName(pod.Namespace, pod.Name)
|
||||
|
||||
sp, ok := seenPods[s]
|
||||
if !ok {
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/discovery/v1"
|
||||
"k8s.io/api/discovery/v1beta1"
|
||||
|
@ -1405,3 +1406,41 @@ func TestEndpointSliceDiscoveryEmptyPodStatus(t *testing.T) {
|
|||
expectedRes: map[string]*targetgroup.Group{},
|
||||
}.Run(t)
|
||||
}
|
||||
|
||||
// TestEndpointSliceInfIndexersCount makes sure that RoleEndpointSlice discovery
|
||||
// sets up indexing for the main Kube informer only when needed.
|
||||
// See: https://github.com/prometheus/prometheus/pull/13554#discussion_r1490965817
|
||||
func TestEndpointSliceInfIndexersCount(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
withNodeMetadata bool
|
||||
}{
|
||||
{"with node metadata", true},
|
||||
{"without node metadata", false},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var (
|
||||
n *Discovery
|
||||
mainInfIndexersCount int
|
||||
)
|
||||
if tc.withNodeMetadata {
|
||||
mainInfIndexersCount = 1
|
||||
n, _ = makeDiscoveryWithMetadata(RoleEndpointSlice, NamespaceDiscovery{}, AttachMetadataConfig{Node: true})
|
||||
} else {
|
||||
n, _ = makeDiscovery(RoleEndpointSlice, NamespaceDiscovery{})
|
||||
}
|
||||
|
||||
k8sDiscoveryTest{
|
||||
discovery: n,
|
||||
afterStart: func() {
|
||||
n.RLock()
|
||||
defer n.RUnlock()
|
||||
require.Len(t, n.discoverers, 1)
|
||||
require.Len(t, n.discoverers[0].(*EndpointSlice).endpointSliceInf.GetIndexer().GetIndexers(), mainInfIndexersCount)
|
||||
},
|
||||
}.Run(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -767,6 +767,21 @@ func (d *Discovery) newPodsByNodeInformer(plw *cache.ListWatch) cache.SharedInde
|
|||
|
||||
func (d *Discovery) newEndpointsByNodeInformer(plw *cache.ListWatch) cache.SharedIndexInformer {
|
||||
indexers := make(map[string]cache.IndexFunc)
|
||||
indexers[podIndex] = func(obj interface{}) ([]string, error) {
|
||||
e, ok := obj.(*apiv1.Endpoints)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("object is not endpoints")
|
||||
}
|
||||
var pods []string
|
||||
for _, target := range e.Subsets {
|
||||
for _, addr := range target.Addresses {
|
||||
if addr.TargetRef != nil && addr.TargetRef.Kind == "Pod" {
|
||||
pods = append(pods, namespacedName(addr.TargetRef.Namespace, addr.TargetRef.Name))
|
||||
}
|
||||
}
|
||||
}
|
||||
return pods, nil
|
||||
}
|
||||
if !d.attachMetadata.Node {
|
||||
return cache.NewSharedIndexInformer(plw, &apiv1.Endpoints{}, resyncDisabled, indexers)
|
||||
}
|
||||
|
@ -800,7 +815,7 @@ func (d *Discovery) newEndpointsByNodeInformer(plw *cache.ListWatch) cache.Share
|
|||
func (d *Discovery) newEndpointSlicesByNodeInformer(plw *cache.ListWatch, object runtime.Object) cache.SharedIndexInformer {
|
||||
indexers := make(map[string]cache.IndexFunc)
|
||||
if !d.attachMetadata.Node {
|
||||
cache.NewSharedIndexInformer(plw, &disv1.EndpointSlice{}, resyncDisabled, indexers)
|
||||
return cache.NewSharedIndexInformer(plw, object, resyncDisabled, indexers)
|
||||
}
|
||||
|
||||
indexers[nodeIndex] = func(obj interface{}) ([]string, error) {
|
||||
|
@ -872,3 +887,7 @@ func addObjectMetaLabels(labelSet model.LabelSet, objectMeta metav1.ObjectMeta,
|
|||
labelSet[model.LabelName(metaLabelPrefix+string(role)+"_annotationpresent_"+ln)] = presentValue
|
||||
}
|
||||
}
|
||||
|
||||
func namespacedName(namespace, name string) string {
|
||||
return namespace + "/" + name
|
||||
}
|
||||
|
|
|
@ -128,17 +128,11 @@ func (d k8sDiscoveryTest) Run(t *testing.T) {
|
|||
}
|
||||
|
||||
resChan := make(chan map[string]*targetgroup.Group)
|
||||
go readResultWithTimeout(t, ch, d.expectedMaxItems, time.Second, resChan)
|
||||
go readResultWithTimeout(t, ctx, ch, d.expectedMaxItems, time.Second, resChan)
|
||||
|
||||
dd, ok := d.discovery.(hasSynced)
|
||||
if !ok {
|
||||
t.Errorf("discoverer does not implement hasSynced interface")
|
||||
return
|
||||
}
|
||||
if !cache.WaitForCacheSync(ctx.Done(), dd.hasSynced) {
|
||||
t.Errorf("discoverer failed to sync: %v", dd)
|
||||
return
|
||||
}
|
||||
require.True(t, ok, "discoverer does not implement hasSynced interface")
|
||||
require.True(t, cache.WaitForCacheSync(ctx.Done(), dd.hasSynced), "discoverer failed to sync: %v", dd)
|
||||
|
||||
if d.afterStart != nil {
|
||||
d.afterStart()
|
||||
|
@ -147,13 +141,18 @@ func (d k8sDiscoveryTest) Run(t *testing.T) {
|
|||
if d.expectedRes != nil {
|
||||
res := <-resChan
|
||||
requireTargetGroups(t, d.expectedRes, res)
|
||||
} else {
|
||||
// Stop readResultWithTimeout and wait for it.
|
||||
cancel()
|
||||
<-resChan
|
||||
}
|
||||
}
|
||||
|
||||
// readResultWithTimeout reads all targetgroups from channel with timeout.
|
||||
// It merges targetgroups by source and sends the result to result channel.
|
||||
func readResultWithTimeout(t *testing.T, ch <-chan []*targetgroup.Group, max int, timeout time.Duration, resChan chan<- map[string]*targetgroup.Group) {
|
||||
func readResultWithTimeout(t *testing.T, ctx context.Context, ch <-chan []*targetgroup.Group, max int, stopAfter time.Duration, resChan chan<- map[string]*targetgroup.Group) {
|
||||
res := make(map[string]*targetgroup.Group)
|
||||
timeout := time.After(stopAfter)
|
||||
Loop:
|
||||
for {
|
||||
select {
|
||||
|
@ -168,12 +167,15 @@ Loop:
|
|||
// Reached max target groups we may get, break fast.
|
||||
break Loop
|
||||
}
|
||||
case <-time.After(timeout):
|
||||
case <-timeout:
|
||||
// Because we use queue, an object that is created then
|
||||
// deleted or updated may be processed only once.
|
||||
// So possibly we may skip events, timed out here.
|
||||
t.Logf("timed out, got %d (max: %d) items, some events are skipped", len(res), max)
|
||||
break Loop
|
||||
case <-ctx.Done():
|
||||
t.Logf("stopped, got %d (max: %d) items", len(res), max)
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,10 @@ import (
|
|||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||
)
|
||||
|
||||
const nodeIndex = "node"
|
||||
const (
|
||||
nodeIndex = "node"
|
||||
podIndex = "pod"
|
||||
)
|
||||
|
||||
// Pod discovers new pod targets.
|
||||
type Pod struct {
|
||||
|
@ -326,7 +329,7 @@ func podSource(pod *apiv1.Pod) string {
|
|||
}
|
||||
|
||||
func podSourceFromNamespaceAndName(namespace, name string) string {
|
||||
return "pod/" + namespace + "/" + name
|
||||
return "pod/" + namespacedName(namespace, name)
|
||||
}
|
||||
|
||||
func podReady(pod *apiv1.Pod) model.LabelValue {
|
||||
|
|
|
@ -694,7 +694,7 @@ func TestTargetUpdatesOrder(t *testing.T) {
|
|||
for x := 0; x < totalUpdatesCount; x++ {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Fatalf("%d: no update arrived within the timeout limit", x)
|
||||
require.FailNow(t, "%d: no update arrived within the timeout limit", x)
|
||||
case tgs := <-provUpdates:
|
||||
discoveryManager.updateGroup(poolKey{setName: strconv.Itoa(i), provider: tc.title}, tgs)
|
||||
for _, got := range discoveryManager.allGroups() {
|
||||
|
@ -756,10 +756,8 @@ func verifySyncedPresence(t *testing.T, tGroups map[string][]*targetgroup.Group,
|
|||
|
||||
func verifyPresence(t *testing.T, tSets map[poolKey]map[string]*targetgroup.Group, poolKey poolKey, label string, present bool) {
|
||||
t.Helper()
|
||||
if _, ok := tSets[poolKey]; !ok {
|
||||
t.Fatalf("'%s' should be present in Pool keys: %v", poolKey, tSets)
|
||||
return
|
||||
}
|
||||
_, ok := tSets[poolKey]
|
||||
require.True(t, ok, "'%s' should be present in Pool keys: %v", poolKey, tSets)
|
||||
|
||||
match := false
|
||||
var mergedTargets string
|
||||
|
@ -776,7 +774,7 @@ func verifyPresence(t *testing.T, tSets map[poolKey]map[string]*targetgroup.Grou
|
|||
if !present {
|
||||
msg = "not"
|
||||
}
|
||||
t.Fatalf("%q should %s be present in Targets labels: %q", label, msg, mergedTargets)
|
||||
require.FailNow(t, "%q should %s be present in Targets labels: %q", label, msg, mergedTargets)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1088,22 +1086,14 @@ func TestTargetSetRecreatesEmptyStaticConfigs(t *testing.T) {
|
|||
syncedTargets = <-discoveryManager.SyncCh()
|
||||
p = pk("static", "prometheus", 1)
|
||||
targetGroups, ok := discoveryManager.targets[p]
|
||||
if !ok {
|
||||
t.Fatalf("'%v' should be present in target groups", p)
|
||||
}
|
||||
require.True(t, ok, "'%v' should be present in target groups", p)
|
||||
group, ok := targetGroups[""]
|
||||
if !ok {
|
||||
t.Fatalf("missing '' key in target groups %v", targetGroups)
|
||||
}
|
||||
require.True(t, ok, "missing '' key in target groups %v", targetGroups)
|
||||
|
||||
if len(group.Targets) != 0 {
|
||||
t.Fatalf("Invalid number of targets: expected 0, got %d", len(group.Targets))
|
||||
}
|
||||
require.Empty(t, group.Targets, "Invalid number of targets.")
|
||||
require.Len(t, syncedTargets, 1)
|
||||
require.Len(t, syncedTargets["prometheus"], 1)
|
||||
if lbls := syncedTargets["prometheus"][0].Labels; lbls != nil {
|
||||
t.Fatalf("Unexpected Group: expected nil Labels, got %v", lbls)
|
||||
}
|
||||
require.Nil(t, syncedTargets["prometheus"][0].Labels)
|
||||
}
|
||||
|
||||
func TestIdenticalConfigurationsAreCoalesced(t *testing.T) {
|
||||
|
@ -1131,9 +1121,7 @@ func TestIdenticalConfigurationsAreCoalesced(t *testing.T) {
|
|||
syncedTargets := <-discoveryManager.SyncCh()
|
||||
verifyPresence(t, discoveryManager.targets, pk("static", "prometheus", 0), "{__address__=\"foo:9090\"}", true)
|
||||
verifyPresence(t, discoveryManager.targets, pk("static", "prometheus2", 0), "{__address__=\"foo:9090\"}", true)
|
||||
if len(discoveryManager.providers) != 1 {
|
||||
t.Fatalf("Invalid number of providers: expected 1, got %d", len(discoveryManager.providers))
|
||||
}
|
||||
require.Len(t, discoveryManager.providers, 1, "Invalid number of providers.")
|
||||
require.Len(t, syncedTargets, 2)
|
||||
verifySyncedPresence(t, syncedTargets, "prometheus", "{__address__=\"foo:9090\"}", true)
|
||||
require.Len(t, syncedTargets["prometheus"], 1)
|
||||
|
@ -1231,9 +1219,7 @@ func TestGaugeFailedConfigs(t *testing.T) {
|
|||
<-discoveryManager.SyncCh()
|
||||
|
||||
failedCount := client_testutil.ToFloat64(discoveryManager.metrics.FailedConfigs)
|
||||
if failedCount != 3 {
|
||||
t.Fatalf("Expected to have 3 failed configs, got: %v", failedCount)
|
||||
}
|
||||
require.Equal(t, 3.0, failedCount, "Expected to have 3 failed configs.")
|
||||
|
||||
c["prometheus"] = Configs{
|
||||
staticConfig("foo:9090"),
|
||||
|
@ -1242,9 +1228,7 @@ func TestGaugeFailedConfigs(t *testing.T) {
|
|||
<-discoveryManager.SyncCh()
|
||||
|
||||
failedCount = client_testutil.ToFloat64(discoveryManager.metrics.FailedConfigs)
|
||||
if failedCount != 0 {
|
||||
t.Fatalf("Expected to get no failed config, got: %v", failedCount)
|
||||
}
|
||||
require.Equal(t, 0.0, failedCount, "Expected to get no failed config.")
|
||||
}
|
||||
|
||||
func TestCoordinationWithReceiver(t *testing.T) {
|
||||
|
@ -1388,19 +1372,14 @@ func TestCoordinationWithReceiver(t *testing.T) {
|
|||
time.Sleep(expected.delay)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Fatalf("step %d: no update received in the expected timeframe", i)
|
||||
require.FailNow(t, "step %d: no update received in the expected timeframe", i)
|
||||
case tgs, ok := <-mgr.SyncCh():
|
||||
if !ok {
|
||||
t.Fatalf("step %d: discovery manager channel is closed", i)
|
||||
}
|
||||
if len(tgs) != len(expected.tgs) {
|
||||
t.Fatalf("step %d: target groups mismatch, got: %d, expected: %d\ngot: %#v\nexpected: %#v",
|
||||
i, len(tgs), len(expected.tgs), tgs, expected.tgs)
|
||||
}
|
||||
require.True(t, ok, "step %d: discovery manager channel is closed", i)
|
||||
require.Equal(t, len(expected.tgs), len(tgs), "step %d: targets mismatch", i)
|
||||
|
||||
for k := range expected.tgs {
|
||||
if _, ok := tgs[k]; !ok {
|
||||
t.Fatalf("step %d: target group not found: %s\ngot: %#v", i, k, tgs)
|
||||
}
|
||||
_, ok := tgs[k]
|
||||
require.True(t, ok, "step %d: target group not found: %s", i, k)
|
||||
assertEqualGroups(t, tgs[k], expected.tgs[k])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,23 +69,15 @@ func TestMarathonSDHandleError(t *testing.T) {
|
|||
}
|
||||
)
|
||||
tgs, err := testUpdateServices(client)
|
||||
if !errors.Is(err, errTesting) {
|
||||
t.Fatalf("Expected error: %s", err)
|
||||
}
|
||||
if len(tgs) != 0 {
|
||||
t.Fatalf("Got group: %s", tgs)
|
||||
}
|
||||
require.ErrorIs(t, err, errTesting)
|
||||
require.Empty(t, tgs, "Expected no target groups.")
|
||||
}
|
||||
|
||||
func TestMarathonSDEmptyList(t *testing.T) {
|
||||
client := func(_ context.Context, _ *http.Client, _ string) (*appList, error) { return &appList{}, nil }
|
||||
tgs, err := testUpdateServices(client)
|
||||
if err != nil {
|
||||
t.Fatalf("Got error: %s", err)
|
||||
}
|
||||
if len(tgs) > 0 {
|
||||
t.Fatalf("Got group: %v", tgs)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, tgs, "Expected no target groups.")
|
||||
}
|
||||
|
||||
func marathonTestAppList(labels map[string]string, runningTasks int) *appList {
|
||||
|
@ -119,28 +111,16 @@ func TestMarathonSDSendGroup(t *testing.T) {
|
|||
return marathonTestAppList(marathonValidLabel, 1), nil
|
||||
}
|
||||
tgs, err := testUpdateServices(client)
|
||||
if err != nil {
|
||||
t.Fatalf("Got error: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 target group, got", len(tgs))
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tgs, 1, "Expected 1 target group.")
|
||||
|
||||
tg := tgs[0]
|
||||
require.Equal(t, "test-service", tg.Source, "Wrong target group name.")
|
||||
require.Len(t, tg.Targets, 1, "Expected 1 target.")
|
||||
|
||||
if tg.Source != "test-service" {
|
||||
t.Fatalf("Wrong target group name: %s", tg.Source)
|
||||
}
|
||||
if len(tg.Targets) != 1 {
|
||||
t.Fatalf("Wrong number of targets: %v", tg.Targets)
|
||||
}
|
||||
tgt := tg.Targets[0]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:31000" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "yes" {
|
||||
t.Fatalf("Wrong first portMappings label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:31000", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "yes", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the first port.")
|
||||
}
|
||||
|
||||
func TestMarathonSDRemoveApp(t *testing.T) {
|
||||
|
@ -153,40 +133,27 @@ func TestMarathonSDRemoveApp(t *testing.T) {
|
|||
defer refreshMetrics.Unregister()
|
||||
|
||||
md, err := NewDiscovery(cfg, nil, metrics)
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
md.appsClient = func(_ context.Context, _ *http.Client, _ string) (*appList, error) {
|
||||
return marathonTestAppList(marathonValidLabel, 1), nil
|
||||
}
|
||||
tgs, err := md.refresh(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("Got error on first update: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 targetgroup, got", len(tgs))
|
||||
}
|
||||
require.NoError(t, err, "Got error on first update.")
|
||||
require.Len(t, tgs, 1, "Expected 1 targetgroup.")
|
||||
tg1 := tgs[0]
|
||||
|
||||
md.appsClient = func(_ context.Context, _ *http.Client, _ string) (*appList, error) {
|
||||
return marathonTestAppList(marathonValidLabel, 0), nil
|
||||
}
|
||||
tgs, err = md.refresh(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("Got error on second update: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 targetgroup, got", len(tgs))
|
||||
}
|
||||
require.NoError(t, err, "Got error on second update.")
|
||||
require.Len(t, tgs, 1, "Expected 1 targetgroup.")
|
||||
|
||||
tg2 := tgs[0]
|
||||
|
||||
if tg2.Source != tg1.Source {
|
||||
if len(tg2.Targets) > 0 {
|
||||
t.Errorf("Got a non-empty target set: %s", tg2.Targets)
|
||||
}
|
||||
t.Fatalf("Source is different: %s != %s", tg1.Source, tg2.Source)
|
||||
}
|
||||
require.NotEmpty(t, tg2.Targets, "Got a non-empty target set.")
|
||||
require.Equal(t, tg1.Source, tg2.Source, "Source is different.")
|
||||
}
|
||||
|
||||
func marathonTestAppListWithMultiplePorts(labels map[string]string, runningTasks int) *appList {
|
||||
|
@ -221,34 +188,22 @@ func TestMarathonSDSendGroupWithMultiplePort(t *testing.T) {
|
|||
return marathonTestAppListWithMultiplePorts(marathonValidLabel, 1), nil
|
||||
}
|
||||
tgs, err := testUpdateServices(client)
|
||||
if err != nil {
|
||||
t.Fatalf("Got error: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 target group, got", len(tgs))
|
||||
}
|
||||
tg := tgs[0]
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tgs, 1, "Expected 1 target group.")
|
||||
|
||||
tg := tgs[0]
|
||||
require.Equal(t, "test-service", tg.Source, "Wrong target group name.")
|
||||
require.Len(t, tg.Targets, 2, "Wrong number of targets.")
|
||||
|
||||
if tg.Source != "test-service" {
|
||||
t.Fatalf("Wrong target group name: %s", tg.Source)
|
||||
}
|
||||
if len(tg.Targets) != 2 {
|
||||
t.Fatalf("Wrong number of targets: %v", tg.Targets)
|
||||
}
|
||||
tgt := tg.Targets[0]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:31000" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "yes" {
|
||||
t.Fatalf("Wrong first portMappings label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:31000", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "yes", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]),
|
||||
"Wrong portMappings label from the first port: %s", tgt[model.AddressLabel])
|
||||
|
||||
tgt = tg.Targets[1]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:32000" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portMappings label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:32000", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]),
|
||||
"Wrong portMappings label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
|
||||
func marathonTestZeroTaskPortAppList(labels map[string]string, runningTasks int) *appList {
|
||||
|
@ -278,20 +233,12 @@ func TestMarathonZeroTaskPorts(t *testing.T) {
|
|||
return marathonTestZeroTaskPortAppList(marathonValidLabel, 1), nil
|
||||
}
|
||||
tgs, err := testUpdateServices(client)
|
||||
if err != nil {
|
||||
t.Fatalf("Got error: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 target group, got", len(tgs))
|
||||
}
|
||||
tg := tgs[0]
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tgs, 1, "Expected 1 target group.")
|
||||
|
||||
if tg.Source != "test-service-zero-ports" {
|
||||
t.Fatalf("Wrong target group name: %s", tg.Source)
|
||||
}
|
||||
if len(tg.Targets) != 0 {
|
||||
t.Fatalf("Wrong number of targets: %v", tg.Targets)
|
||||
}
|
||||
tg := tgs[0]
|
||||
require.Equal(t, "test-service-zero-ports", tg.Source, "Wrong target group name.")
|
||||
require.Empty(t, tg.Targets, "Wrong number of targets.")
|
||||
}
|
||||
|
||||
func Test500ErrorHttpResponseWithValidJSONBody(t *testing.T) {
|
||||
|
@ -306,9 +253,7 @@ func Test500ErrorHttpResponseWithValidJSONBody(t *testing.T) {
|
|||
defer ts.Close()
|
||||
// Execute test case and validate behavior.
|
||||
_, err := testUpdateServices(nil)
|
||||
if err == nil {
|
||||
t.Fatalf("Expected error for 5xx HTTP response from marathon server, got nil")
|
||||
}
|
||||
require.Error(t, err, "Expected error for 5xx HTTP response from marathon server.")
|
||||
}
|
||||
|
||||
func marathonTestAppListWithPortDefinitions(labels map[string]string, runningTasks int) *appList {
|
||||
|
@ -346,40 +291,24 @@ func TestMarathonSDSendGroupWithPortDefinitions(t *testing.T) {
|
|||
return marathonTestAppListWithPortDefinitions(marathonValidLabel, 1), nil
|
||||
}
|
||||
tgs, err := testUpdateServices(client)
|
||||
if err != nil {
|
||||
t.Fatalf("Got error: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 target group, got", len(tgs))
|
||||
}
|
||||
tg := tgs[0]
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tgs, 1, "Expected 1 target group.")
|
||||
|
||||
tg := tgs[0]
|
||||
require.Equal(t, "test-service", tg.Source, "Wrong target group name.")
|
||||
require.Len(t, tg.Targets, 2, "Wrong number of targets.")
|
||||
|
||||
if tg.Source != "test-service" {
|
||||
t.Fatalf("Wrong target group name: %s", tg.Source)
|
||||
}
|
||||
if len(tg.Targets) != 2 {
|
||||
t.Fatalf("Wrong number of targets: %v", tg.Targets)
|
||||
}
|
||||
tgt := tg.Targets[0]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:1234" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong first portMappings label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong first portDefinitions label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:1234", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]),
|
||||
"Wrong portMappings label from the first port.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]),
|
||||
"Wrong portDefinitions label from the first port.")
|
||||
|
||||
tgt = tg.Targets[1]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:5678" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portMappings label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "yes" {
|
||||
t.Fatalf("Wrong portDefinitions label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:5678", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Empty(t, tgt[model.LabelName(portMappingLabelPrefix+"prometheus")], "Wrong portMappings label from the second port.")
|
||||
require.Equal(t, "yes", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the second port.")
|
||||
}
|
||||
|
||||
func marathonTestAppListWithPortDefinitionsRequirePorts(labels map[string]string, runningTasks int) *appList {
|
||||
|
@ -416,40 +345,22 @@ func TestMarathonSDSendGroupWithPortDefinitionsRequirePorts(t *testing.T) {
|
|||
return marathonTestAppListWithPortDefinitionsRequirePorts(marathonValidLabel, 1), nil
|
||||
}
|
||||
tgs, err := testUpdateServices(client)
|
||||
if err != nil {
|
||||
t.Fatalf("Got error: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 target group, got", len(tgs))
|
||||
}
|
||||
tg := tgs[0]
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tgs, 1, "Expected 1 target group.")
|
||||
|
||||
tg := tgs[0]
|
||||
require.Equal(t, "test-service", tg.Source, "Wrong target group name.")
|
||||
require.Len(t, tg.Targets, 2, "Wrong number of targets.")
|
||||
|
||||
if tg.Source != "test-service" {
|
||||
t.Fatalf("Wrong target group name: %s", tg.Source)
|
||||
}
|
||||
if len(tg.Targets) != 2 {
|
||||
t.Fatalf("Wrong number of targets: %v", tg.Targets)
|
||||
}
|
||||
tgt := tg.Targets[0]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:31000" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong first portMappings label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong first portDefinitions label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:31000", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the first port.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the first port.")
|
||||
|
||||
tgt = tg.Targets[1]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:32000" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portMappings label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "yes" {
|
||||
t.Fatalf("Wrong portDefinitions label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:32000", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the second port.")
|
||||
require.Equal(t, "yes", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the second port.")
|
||||
}
|
||||
|
||||
func marathonTestAppListWithPorts(labels map[string]string, runningTasks int) *appList {
|
||||
|
@ -481,40 +392,22 @@ func TestMarathonSDSendGroupWithPorts(t *testing.T) {
|
|||
return marathonTestAppListWithPorts(marathonValidLabel, 1), nil
|
||||
}
|
||||
tgs, err := testUpdateServices(client)
|
||||
if err != nil {
|
||||
t.Fatalf("Got error: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 target group, got", len(tgs))
|
||||
}
|
||||
tg := tgs[0]
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tgs, 1, "Expected 1 target group.")
|
||||
|
||||
tg := tgs[0]
|
||||
require.Equal(t, "test-service", tg.Source, "Wrong target group name.")
|
||||
require.Len(t, tg.Targets, 2, "Wrong number of targets.")
|
||||
|
||||
if tg.Source != "test-service" {
|
||||
t.Fatalf("Wrong target group name: %s", tg.Source)
|
||||
}
|
||||
if len(tg.Targets) != 2 {
|
||||
t.Fatalf("Wrong number of targets: %v", tg.Targets)
|
||||
}
|
||||
tgt := tg.Targets[0]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:31000" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong first portMappings label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong first portDefinitions label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:31000", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the first port.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the first port.")
|
||||
|
||||
tgt = tg.Targets[1]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:32000" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portMappings label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portDefinitions label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:32000", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the second port.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the second port.")
|
||||
}
|
||||
|
||||
func marathonTestAppListWithContainerPortMappings(labels map[string]string, runningTasks int) *appList {
|
||||
|
@ -555,40 +448,22 @@ func TestMarathonSDSendGroupWithContainerPortMappings(t *testing.T) {
|
|||
return marathonTestAppListWithContainerPortMappings(marathonValidLabel, 1), nil
|
||||
}
|
||||
tgs, err := testUpdateServices(client)
|
||||
if err != nil {
|
||||
t.Fatalf("Got error: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 target group, got", len(tgs))
|
||||
}
|
||||
tg := tgs[0]
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tgs, 1, "Expected 1 target group.")
|
||||
|
||||
tg := tgs[0]
|
||||
require.Equal(t, "test-service", tg.Source, "Wrong target group name.")
|
||||
require.Len(t, tg.Targets, 2, "Wrong number of targets.")
|
||||
|
||||
if tg.Source != "test-service" {
|
||||
t.Fatalf("Wrong target group name: %s", tg.Source)
|
||||
}
|
||||
if len(tg.Targets) != 2 {
|
||||
t.Fatalf("Wrong number of targets: %v", tg.Targets)
|
||||
}
|
||||
tgt := tg.Targets[0]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:12345" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "yes" {
|
||||
t.Fatalf("Wrong first portMappings label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong first portDefinitions label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:12345", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "yes", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the first port.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the first port.")
|
||||
|
||||
tgt = tg.Targets[1]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:32000" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portMappings label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portDefinitions label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:32000", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the second port.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the second port.")
|
||||
}
|
||||
|
||||
func marathonTestAppListWithDockerContainerPortMappings(labels map[string]string, runningTasks int) *appList {
|
||||
|
@ -629,40 +504,22 @@ func TestMarathonSDSendGroupWithDockerContainerPortMappings(t *testing.T) {
|
|||
return marathonTestAppListWithDockerContainerPortMappings(marathonValidLabel, 1), nil
|
||||
}
|
||||
tgs, err := testUpdateServices(client)
|
||||
if err != nil {
|
||||
t.Fatalf("Got error: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 target group, got", len(tgs))
|
||||
}
|
||||
tg := tgs[0]
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tgs, 1, "Expected 1 target group.")
|
||||
|
||||
tg := tgs[0]
|
||||
require.Equal(t, "test-service", tg.Source, "Wrong target group name.")
|
||||
require.Len(t, tg.Targets, 2, "Wrong number of targets.")
|
||||
|
||||
if tg.Source != "test-service" {
|
||||
t.Fatalf("Wrong target group name: %s", tg.Source)
|
||||
}
|
||||
if len(tg.Targets) != 2 {
|
||||
t.Fatalf("Wrong number of targets: %v", tg.Targets)
|
||||
}
|
||||
tgt := tg.Targets[0]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:31000" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "yes" {
|
||||
t.Fatalf("Wrong first portMappings label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong first portDefinitions label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:31000", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "yes", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the first port.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the first port.")
|
||||
|
||||
tgt = tg.Targets[1]
|
||||
if tgt[model.AddressLabel] != "mesos-slave1:12345" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portMappings label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portDefinitions label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "mesos-slave1:12345", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the second port.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the second port.")
|
||||
}
|
||||
|
||||
func marathonTestAppListWithContainerNetworkAndPortMappings(labels map[string]string, runningTasks int) *appList {
|
||||
|
@ -707,38 +564,20 @@ func TestMarathonSDSendGroupWithContainerNetworkAndPortMapping(t *testing.T) {
|
|||
return marathonTestAppListWithContainerNetworkAndPortMappings(marathonValidLabel, 1), nil
|
||||
}
|
||||
tgs, err := testUpdateServices(client)
|
||||
if err != nil {
|
||||
t.Fatalf("Got error: %s", err)
|
||||
}
|
||||
if len(tgs) != 1 {
|
||||
t.Fatal("Expected 1 target group, got", len(tgs))
|
||||
}
|
||||
tg := tgs[0]
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tgs, 1, "Expected 1 target group.")
|
||||
|
||||
tg := tgs[0]
|
||||
require.Equal(t, "test-service", tg.Source, "Wrong target group name.")
|
||||
require.Len(t, tg.Targets, 2, "Wrong number of targets.")
|
||||
|
||||
if tg.Source != "test-service" {
|
||||
t.Fatalf("Wrong target group name: %s", tg.Source)
|
||||
}
|
||||
if len(tg.Targets) != 2 {
|
||||
t.Fatalf("Wrong number of targets: %v", tg.Targets)
|
||||
}
|
||||
tgt := tg.Targets[0]
|
||||
if tgt[model.AddressLabel] != "1.2.3.4:8080" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "yes" {
|
||||
t.Fatalf("Wrong first portMappings label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong first portDefinitions label from the first port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "1.2.3.4:8080", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "yes", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the first port.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the first port.")
|
||||
|
||||
tgt = tg.Targets[1]
|
||||
if tgt[model.AddressLabel] != "1.2.3.4:1234" {
|
||||
t.Fatalf("Wrong target address: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portMappingLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portMappings label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
if tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")] != "" {
|
||||
t.Fatalf("Wrong portDefinitions label from the second port: %s", tgt[model.AddressLabel])
|
||||
}
|
||||
require.Equal(t, "1.2.3.4:1234", string(tgt[model.AddressLabel]), "Wrong target address.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portMappingLabelPrefix+"prometheus")]), "Wrong portMappings label from the second port.")
|
||||
require.Equal(t, "", string(tgt[model.LabelName(portDefinitionLabelPrefix+"prometheus")]), "Wrong portDefinitions label from the second port.")
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// SDMock is the interface for the OpenStack mock.
|
||||
|
@ -49,15 +51,13 @@ func (m *SDMock) Setup() {
|
|||
const tokenID = "cbc36478b0bd8e67e89469c7749d4127"
|
||||
|
||||
func testMethod(t *testing.T, r *http.Request, expected string) {
|
||||
if expected != r.Method {
|
||||
t.Errorf("Request method = %v, expected %v", r.Method, expected)
|
||||
}
|
||||
require.Equal(t, expected, r.Method, "Unexpected request method.")
|
||||
}
|
||||
|
||||
func testHeader(t *testing.T, r *http.Request, header, expected string) {
|
||||
if actual := r.Header.Get(header); expected != actual {
|
||||
t.Errorf("Header %s = %s, expected %s", header, actual, expected)
|
||||
}
|
||||
t.Helper()
|
||||
actual := r.Header.Get(header)
|
||||
require.Equal(t, expected, actual, "Unexpected value for request header %s.", header)
|
||||
}
|
||||
|
||||
// HandleVersionsSuccessfully mocks version call.
|
||||
|
|
|
@ -171,7 +171,7 @@ func NewDiscovery(conf *SDConfig, logger log.Logger, metrics discovery.Discovere
|
|||
d.Discovery = refresh.NewDiscovery(
|
||||
refresh.Options{
|
||||
Logger: logger,
|
||||
Mech: "http",
|
||||
Mech: "puppetdb",
|
||||
Interval: time.Duration(conf.RefreshInterval),
|
||||
RefreshF: d.refresh,
|
||||
MetricsInstantiator: m.refreshMetrics,
|
||||
|
|
|
@ -97,7 +97,7 @@ func TestRefresh(t *testing.T) {
|
|||
defer tick.Stop()
|
||||
select {
|
||||
case <-ch:
|
||||
t.Fatal("Unexpected target group")
|
||||
require.FailNow(t, "Unexpected target group")
|
||||
case <-tick.C:
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
)
|
||||
|
||||
|
@ -31,7 +32,5 @@ func TestNewDiscoveryError(t *testing.T) {
|
|||
time.Second, []string{"/"},
|
||||
nil,
|
||||
func(data []byte, path string) (model.LabelSet, error) { return nil, nil })
|
||||
if err == nil {
|
||||
t.Fatalf("expected error, got nil")
|
||||
}
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ The Prometheus monitoring server
|
|||
| <code class="text-nowrap">--rules.alert.for-outage-tolerance</code> | Max time to tolerate prometheus outage for restoring "for" state of alert. Use with server mode only. | `1h` |
|
||||
| <code class="text-nowrap">--rules.alert.for-grace-period</code> | Minimum duration between alert and restored "for" state. This is maintained only for alerts with configured "for" time greater than grace period. Use with server mode only. | `10m` |
|
||||
| <code class="text-nowrap">--rules.alert.resend-delay</code> | Minimum amount of time to wait before resending an alert to Alertmanager. Use with server mode only. | `1m` |
|
||||
| <code class="text-nowrap">--rules.max-concurrent-evals</code> | Global concurrency limit for independent rules that can run concurrently. Use with server mode only. | `4` |
|
||||
| <code class="text-nowrap">--alertmanager.notification-queue-capacity</code> | The capacity of the queue for pending Alertmanager notifications. Use with server mode only. | `10000` |
|
||||
| <code class="text-nowrap">--query.lookback-delta</code> | The maximum lookback duration for retrieving metrics during expression evaluations and federation. Use with server mode only. | `5m` |
|
||||
| <code class="text-nowrap">--query.timeout</code> | Maximum time a query may take before being aborted. Use with server mode only. | `2m` |
|
||||
|
|
|
@ -582,6 +582,32 @@ Dump samples from a TSDB.
|
|||
|
||||
|
||||
|
||||
##### `promtool tsdb dump-openmetrics`
|
||||
|
||||
[Experimental] Dump samples from a TSDB into OpenMetrics format. Native histograms are not dumped.
|
||||
|
||||
|
||||
|
||||
###### Flags
|
||||
|
||||
| Flag | Description | Default |
|
||||
| --- | --- | --- |
|
||||
| <code class="text-nowrap">--min-time</code> | Minimum timestamp to dump. | `-9223372036854775808` |
|
||||
| <code class="text-nowrap">--max-time</code> | Maximum timestamp to dump. | `9223372036854775807` |
|
||||
| <code class="text-nowrap">--match</code> | Series selector. Can be specified multiple times. | `{__name__=~'(?s:.*)'}` |
|
||||
|
||||
|
||||
|
||||
|
||||
###### Arguments
|
||||
|
||||
| Argument | Description | Default |
|
||||
| --- | --- | --- |
|
||||
| db path | Database path (default is data/). | `data/` |
|
||||
|
||||
|
||||
|
||||
|
||||
##### `promtool tsdb create-blocks-from`
|
||||
|
||||
[Experimental] Import samples from input and produce TSDB blocks. Please refer to the storage docs for more details.
|
||||
|
|
|
@ -600,8 +600,10 @@ See below for the configuration options for Azure discovery:
|
|||
# The Azure environment.
|
||||
[ environment: <string> | default = AzurePublicCloud ]
|
||||
|
||||
# The authentication method, either OAuth or ManagedIdentity.
|
||||
# The authentication method, either OAuth, ManagedIdentity or SDK.
|
||||
# See https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
|
||||
# SDK authentication method uses environment variables by default.
|
||||
# See https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication
|
||||
[ authentication_method: <string> | default = OAuth]
|
||||
# The subscription ID. Always required.
|
||||
subscription_id: <string>
|
||||
|
@ -3518,6 +3520,10 @@ static_configs:
|
|||
# List of Alertmanager relabel configurations.
|
||||
relabel_configs:
|
||||
[ - <relabel_config> ... ]
|
||||
|
||||
# List of alert relabel configurations.
|
||||
alert_relabel_configs:
|
||||
[ - <relabel_config> ... ]
|
||||
```
|
||||
|
||||
### `<remote_write>`
|
||||
|
@ -3615,6 +3621,11 @@ azuread:
|
|||
[ client_secret: <string> ]
|
||||
[ tenant_id: <string> ] ]
|
||||
|
||||
# Azure SDK auth.
|
||||
# See https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication
|
||||
[ sdk:
|
||||
[ tenant_id: <string> ] ]
|
||||
|
||||
# Configures the remote write request's TLS settings.
|
||||
tls_config:
|
||||
[ <tls_config> ]
|
||||
|
@ -3643,13 +3654,13 @@ queue_config:
|
|||
# samples from the WAL. It is recommended to have enough capacity in each
|
||||
# shard to buffer several requests to keep throughput up while processing
|
||||
# occasional slow remote requests.
|
||||
[ capacity: <int> | default = 2500 ]
|
||||
[ capacity: <int> | default = 10000 ]
|
||||
# Maximum number of shards, i.e. amount of concurrency.
|
||||
[ max_shards: <int> | default = 200 ]
|
||||
[ max_shards: <int> | default = 50 ]
|
||||
# Minimum number of shards, i.e. amount of concurrency.
|
||||
[ min_shards: <int> | default = 1 ]
|
||||
# Maximum number of samples per send.
|
||||
[ max_samples_per_send: <int> | default = 500]
|
||||
[ max_samples_per_send: <int> | default = 2000]
|
||||
# Maximum time a sample will wait in buffer.
|
||||
[ batch_send_deadline: <duration> | default = 5s ]
|
||||
# Initial retry delay. Gets doubled for every retry.
|
||||
|
|
|
@ -34,7 +34,7 @@ Activating the remote write receiver via a feature flag is deprecated. Use `--we
|
|||
|
||||
[OpenMetrics](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#exemplars) introduces the ability for scrape targets to add exemplars to certain metrics. Exemplars are references to data outside of the MetricSet. A common use case are IDs of program traces.
|
||||
|
||||
Exemplar storage is implemented as a fixed size circular buffer that stores exemplars in memory for all series. Enabling this feature will enable the storage of exemplars scraped by Prometheus. The config file block [storage](configuration/configuration.md#configuration-file)/[exemplars](configuration/configuration.md#exemplars) can be used to control the size of circular buffer by # of exemplars. An exemplar with just a `traceID=<jaeger-trace-id>` uses roughly 100 bytes of memory via the in-memory exemplar storage. If the exemplar storage is enabled, we will also append the exemplars to WAL for local persistence (for WAL duration).
|
||||
Exemplar storage is implemented as a fixed size circular buffer that stores exemplars in memory for all series. Enabling this feature will enable the storage of exemplars scraped by Prometheus. The config file block [storage](configuration/configuration.md#configuration-file)/[exemplars](configuration/configuration.md#exemplars) can be used to control the size of circular buffer by # of exemplars. An exemplar with just a `trace_id=<jaeger-trace-id>` uses roughly 100 bytes of memory via the in-memory exemplar storage. If the exemplar storage is enabled, we will also append the exemplars to WAL for local persistence (for WAL duration).
|
||||
|
||||
## Memory snapshot on shutdown
|
||||
|
||||
|
@ -99,9 +99,9 @@ When enabled, GOMAXPROCS variable is automatically set to match Linux container
|
|||
|
||||
`--enable-feature=auto-gomemlimit`
|
||||
|
||||
When enabled, the GOMEMLIMIT variable is automatically set to match the Linux container memory limit. If there is no container limit, or the process is runing outside of containers, the system memory total is used.
|
||||
When enabled, the GOMEMLIMIT variable is automatically set to match the Linux container memory limit. If there is no container limit, or the process is running outside of containers, the system memory total is used.
|
||||
|
||||
There is also an additional tuning flag, `--auto-gomemlimit.ratio`, which allows controling how much of the memory is used for Prometheus. The remainder is reserved for memory outside the process. For example, kernel page cache. Page cache is important for Prometheus TSDB query performance. The default is `0.9`, which means 90% of the memory limit will be used for Prometheus.
|
||||
There is also an additional tuning flag, `--auto-gomemlimit.ratio`, which allows controlling how much of the memory is used for Prometheus. The remainder is reserved for memory outside the process. For example, kernel page cache. Page cache is important for Prometheus TSDB query performance. The default is `0.9`, which means 90% of the memory limit will be used for Prometheus.
|
||||
|
||||
## No default scrape port
|
||||
|
||||
|
@ -212,3 +212,15 @@ Enables ingestion of created timestamp. Created timestamps are injected as 0 val
|
|||
Currently Prometheus supports created timestamps only on the traditional Prometheus Protobuf protocol (WIP for other protocols). As a result, when enabling this feature, the Prometheus protobuf scrape protocol will be prioritized (See `scrape_config.scrape_protocols` settings for more details).
|
||||
|
||||
Besides enabling this feature in Prometheus, created timestamps need to be exposed by the application being scraped.
|
||||
|
||||
## Concurrent evaluation of independent rules
|
||||
|
||||
`--enable-feature=concurrent-rule-eval`
|
||||
|
||||
By default, rule groups execute concurrently, but the rules within a group execute sequentially; this is because rules can use the
|
||||
output of a preceding rule as its input. However, if there is no detectable relationship between rules then there is no
|
||||
reason to run them sequentially.
|
||||
When the `concurrent-rule-eval` feature flag is enabled, rules without any dependency on other rules within a rule group will be evaluated concurrently.
|
||||
This has the potential to improve rule group evaluation latency and resource utilization at the expense of adding more concurrent query load.
|
||||
|
||||
The number of concurrent rule evaluations can be configured with `--rules.max-concurrent-rule-evals`, which is set to `4` by default.
|
||||
|
|
|
@ -256,6 +256,7 @@ URL query parameters:
|
|||
series to return. At least one `match[]` argument must be provided.
|
||||
- `start=<rfc3339 | unix_timestamp>`: Start timestamp.
|
||||
- `end=<rfc3339 | unix_timestamp>`: End timestamp.
|
||||
- `limit=<number>`: Maximum number of returned series. Optional.
|
||||
|
||||
You can URL-encode these parameters directly in the request body by using the `POST` method and
|
||||
`Content-Type: application/x-www-form-urlencoded` header. This is useful when specifying a large
|
||||
|
@ -306,6 +307,7 @@ URL query parameters:
|
|||
- `end=<rfc3339 | unix_timestamp>`: End timestamp. Optional.
|
||||
- `match[]=<series_selector>`: Repeated series selector argument that selects the
|
||||
series from which to read the label names. Optional.
|
||||
- `limit=<number>`: Maximum number of returned series. Optional.
|
||||
|
||||
|
||||
The `data` section of the JSON response is a list of string label names.
|
||||
|
@ -356,6 +358,7 @@ URL query parameters:
|
|||
- `end=<rfc3339 | unix_timestamp>`: End timestamp. Optional.
|
||||
- `match[]=<series_selector>`: Repeated series selector argument that selects the
|
||||
series from which to read the label values. Optional.
|
||||
- `limit=<number>`: Maximum number of returned series. Optional.
|
||||
|
||||
|
||||
The `data` section of the JSON response is a list of string label values.
|
||||
|
@ -404,7 +407,7 @@ $ curl -g 'http://localhost:9090/api/v1/query_exemplars?query=test_exemplar_metr
|
|||
"exemplars": [
|
||||
{
|
||||
"labels": {
|
||||
"traceID": "EpTxMJ40fUus7aGY"
|
||||
"trace_id": "EpTxMJ40fUus7aGY"
|
||||
},
|
||||
"value": "6",
|
||||
"timestamp": 1600096945.479
|
||||
|
@ -421,14 +424,14 @@ $ curl -g 'http://localhost:9090/api/v1/query_exemplars?query=test_exemplar_metr
|
|||
"exemplars": [
|
||||
{
|
||||
"labels": {
|
||||
"traceID": "Olp9XHlq763ccsfa"
|
||||
"trace_id": "Olp9XHlq763ccsfa"
|
||||
},
|
||||
"value": "19",
|
||||
"timestamp": 1600096955.479
|
||||
},
|
||||
{
|
||||
"labels": {
|
||||
"traceID": "hCtjygkIHwAN9vs4"
|
||||
"trace_id": "hCtjygkIHwAN9vs4"
|
||||
},
|
||||
"value": "20",
|
||||
"timestamp": 1600096965.489
|
||||
|
|
|
@ -14,7 +14,7 @@ systems via the [HTTP API](api.md).
|
|||
|
||||
## Examples
|
||||
|
||||
This document is meant as a reference. For learning, it might be easier to
|
||||
This document is a Prometheus basic language reference. For learning, it may be easier to
|
||||
start with a couple of [examples](examples.md).
|
||||
|
||||
## Expression language data types
|
||||
|
@ -28,9 +28,9 @@ evaluate to one of four types:
|
|||
* **String** - a simple string value; currently unused
|
||||
|
||||
Depending on the use-case (e.g. when graphing vs. displaying the output of an
|
||||
expression), only some of these types are legal as the result from a
|
||||
expression), only some of these types are legal as the result of a
|
||||
user-specified expression. For example, an expression that returns an instant
|
||||
vector is the only type that can be directly graphed.
|
||||
vector is the only type which can be graphed.
|
||||
|
||||
_Notes about the experimental native histograms:_
|
||||
|
||||
|
@ -46,16 +46,15 @@ _Notes about the experimental native histograms:_
|
|||
|
||||
### String literals
|
||||
|
||||
Strings may be specified as literals in single quotes, double quotes or
|
||||
backticks.
|
||||
String literals are designated by single quotes, double quotes or backticks.
|
||||
|
||||
PromQL follows the same [escaping rules as
|
||||
Go](https://golang.org/ref/spec#String_literals). In single or double quotes a
|
||||
Go](https://golang.org/ref/spec#String_literals). For string literals in single or double quotes, a
|
||||
backslash begins an escape sequence, which may be followed by `a`, `b`, `f`,
|
||||
`n`, `r`, `t`, `v` or `\`. Specific characters can be provided using octal
|
||||
(`\nnn`) or hexadecimal (`\xnn`, `\unnnn` and `\Unnnnnnnn`).
|
||||
`n`, `r`, `t`, `v` or `\`. Specific characters can be provided using octal
|
||||
(`\nnn`) or hexadecimal (`\xnn`, `\unnnn` and `\Unnnnnnnn`) notations.
|
||||
|
||||
No escaping is processed inside backticks. Unlike Go, Prometheus does not discard newlines inside backticks.
|
||||
Conversely, escape characters are not parsed in string literals designated by backticks. It is important to note that, unlike Go, Prometheus does not discard newlines inside backticks.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -83,13 +82,17 @@ Examples:
|
|||
-Inf
|
||||
NaN
|
||||
|
||||
## Time series Selectors
|
||||
## Time series selectors
|
||||
|
||||
Time series selectors are responsible for selecting the times series and raw or inferred sample timestamps and values.
|
||||
|
||||
Time series *selectors* are not to be confused with higher level concept of instant and range *queries* that can execute the time series *selectors*. A higher level instant query would evaluate the given selector at one point in time, however the range query would evaluate the selector at multiple different times in between a minimum and maximum timestamp at regular steps.
|
||||
|
||||
### Instant vector selectors
|
||||
|
||||
Instant vector selectors allow the selection of a set of time series and a
|
||||
single sample value for each at a given timestamp (instant): in the simplest
|
||||
form, only a metric name is specified. This results in an instant vector
|
||||
single sample value for each at a given timestamp (point in time). In the simplest
|
||||
form, only a metric name is specified, which results in an instant vector
|
||||
containing elements for all time series that have this metric name.
|
||||
|
||||
This example selects all time series that have the `http_requests_total` metric
|
||||
|
@ -97,7 +100,7 @@ name:
|
|||
|
||||
http_requests_total
|
||||
|
||||
It is possible to filter these time series further by appending a comma separated list of label
|
||||
It is possible to filter these time series further by appending a comma-separated list of label
|
||||
matchers in curly braces (`{}`).
|
||||
|
||||
This example selects only those time series with the `http_requests_total`
|
||||
|
@ -124,6 +127,33 @@ For example, this selects all `http_requests_total` time series for `staging`,
|
|||
Label matchers that match empty label values also select all time series that
|
||||
do not have the specific label set at all. It is possible to have multiple matchers for the same label name.
|
||||
|
||||
For example, given the dataset:
|
||||
|
||||
http_requests_total
|
||||
http_requests_total{replica="rep-a"}
|
||||
http_requests_total{replica="rep-b"}
|
||||
http_requests_total{environment="development"}
|
||||
|
||||
The query `http_requests_total{environment=""}` would match and return:
|
||||
|
||||
http_requests_total
|
||||
http_requests_total{replica="rep-a"}
|
||||
http_requests_total{replica="rep-b"}
|
||||
|
||||
and would exclude:
|
||||
|
||||
http_requests_total{environment="development"}
|
||||
|
||||
Multiple matchers can be used for the same label name; they all must pass for a result to be returned.
|
||||
|
||||
The query:
|
||||
|
||||
http_requests_total{replica!="rep-a",replica=~"rep.*"}
|
||||
|
||||
Would then match:
|
||||
|
||||
http_requests_total{replica="rep-b"}
|
||||
|
||||
Vector selectors must either specify a name or at least one label matcher
|
||||
that does not match the empty string. The following expression is illegal:
|
||||
|
||||
|
@ -178,11 +208,13 @@ following units:
|
|||
* `s` - seconds
|
||||
* `m` - minutes
|
||||
* `h` - hours
|
||||
* `d` - days - assuming a day has always 24h
|
||||
* `w` - weeks - assuming a week has always 7d
|
||||
* `y` - years - assuming a year has always 365d
|
||||
* `d` - days - assuming a day always has 24h
|
||||
* `w` - weeks - assuming a week always has 7d
|
||||
* `y` - years - assuming a year always has 365d<sup>1</sup>
|
||||
|
||||
Time durations can be combined, by concatenation. Units must be ordered from the
|
||||
<sup>1</sup> For days in a year, the leap day is ignored, and conversely, for a minute, a leap second is ignored.
|
||||
|
||||
Time durations can be combined by concatenation. Units must be ordered from the
|
||||
longest to the shortest. A given unit must only appear once in a time duration.
|
||||
|
||||
Here are some examples of valid time durations:
|
||||
|
@ -217,8 +249,7 @@ that `http_requests_total` had a week ago:
|
|||
|
||||
rate(http_requests_total[5m] offset 1w)
|
||||
|
||||
For comparisons with temporal shifts forward in time, a negative offset
|
||||
can be specified:
|
||||
When querying for samples in the past, a negative offset will enable temporal comparisons forward in time:
|
||||
|
||||
rate(http_requests_total[5m] offset -1w)
|
||||
|
||||
|
@ -249,11 +280,11 @@ The same works for range vectors. This returns the 5-minute rate that
|
|||
|
||||
rate(http_requests_total[5m] @ 1609746000)
|
||||
|
||||
The `@` modifier supports all representation of float literals described
|
||||
above within the limits of `int64`. It can also be used along
|
||||
with the `offset` modifier where the offset is applied relative to the `@`
|
||||
modifier time irrespective of which modifier is written first.
|
||||
These 2 queries will produce the same result.
|
||||
The `@` modifier supports all representations of numeric literals described above.
|
||||
It works with the `offset` modifier where the offset is applied relative to the `@`
|
||||
modifier time. The results are the same irrespective of the order of the modifiers.
|
||||
|
||||
For example, these two queries will produce the same result:
|
||||
|
||||
# offset after @
|
||||
http_requests_total @ 1609746000 offset 5m
|
||||
|
@ -299,33 +330,35 @@ PromQL supports line comments that start with `#`. Example:
|
|||
|
||||
### Staleness
|
||||
|
||||
When queries are run, timestamps at which to sample data are selected
|
||||
The timestamps at which to sample data, during a query, are selected
|
||||
independently of the actual present time series data. This is mainly to support
|
||||
cases like aggregation (`sum`, `avg`, and so on), where multiple aggregated
|
||||
time series do not exactly align in time. Because of their independence,
|
||||
time series do not precisely align in time. Because of their independence,
|
||||
Prometheus needs to assign a value at those timestamps for each relevant time
|
||||
series. It does so by simply taking the newest sample before this timestamp.
|
||||
series. It does so by taking the newest sample before this timestamp within the lookback period.
|
||||
The lookback period is 5 minutes by default.
|
||||
|
||||
If a target scrape or rule evaluation no longer returns a sample for a time
|
||||
series that was previously present, that time series will be marked as stale.
|
||||
If a target is removed, its previously returned time series will be marked as
|
||||
stale soon afterwards.
|
||||
series that was previously present, this time series will be marked as stale.
|
||||
If a target is removed, the previously retrieved time series will be marked as
|
||||
stale soon after removal.
|
||||
|
||||
If a query is evaluated at a sampling timestamp after a time series is marked
|
||||
stale, then no value is returned for that time series. If new samples are
|
||||
subsequently ingested for that time series, they will be returned as normal.
|
||||
as stale, then no value is returned for that time series. If new samples are
|
||||
subsequently ingested for that time series, they will be returned as expected.
|
||||
|
||||
If no sample is found (by default) 5 minutes before a sampling timestamp,
|
||||
no value is returned for that time series at this point in time. This
|
||||
effectively means that time series "disappear" from graphs at times where their
|
||||
latest collected sample is older than 5 minutes or after they are marked stale.
|
||||
A time series will go stale when it is no longer exported, or the target no
|
||||
longer exists. Such time series will disappear from graphs
|
||||
at the times of their latest collected sample, and they will not be returned
|
||||
in queries after they are marked stale.
|
||||
|
||||
Staleness will not be marked for time series that have timestamps included in
|
||||
their scrapes. Only the 5 minute threshold will be applied in that case.
|
||||
Some exporters, which put their own timestamps on samples, get a different behaviour:
|
||||
series that stop being exported take the last value for (by default) 5 minutes before
|
||||
disappearing. The `track_timestamps_staleness` setting can change this.
|
||||
|
||||
### Avoiding slow queries and overloads
|
||||
|
||||
If a query needs to operate on a very large amount of data, graphing it might
|
||||
If a query needs to operate on a substantial amount of data, graphing it might
|
||||
time out or overload the server or browser. Thus, when constructing queries
|
||||
over unknown data, always start building the query in the tabular view of
|
||||
Prometheus's expression browser until the result set seems reasonable
|
||||
|
@ -336,7 +369,7 @@ rule](../configuration/recording_rules.md#recording-rules).
|
|||
|
||||
This is especially relevant for Prometheus's query language, where a bare
|
||||
metric name selector like `api_http_requests_total` could expand to thousands
|
||||
of time series with different labels. Also keep in mind that expressions which
|
||||
of time series with different labels. Also, keep in mind that expressions that
|
||||
aggregate over many time series will generate load on the server even if the
|
||||
output is only a small number of time series. This is similar to how it would
|
||||
be slow to sum all values of a column in a relational database, even if the
|
||||
|
|
|
@ -175,6 +175,27 @@ Special cases are:
|
|||
`floor(v instant-vector)` rounds the sample values of all elements in `v` down
|
||||
to the nearest integer.
|
||||
|
||||
## `histogram_avg()`
|
||||
|
||||
_This function only acts on native histograms, which are an experimental
|
||||
feature. The behavior of this function may change in future versions of
|
||||
Prometheus, including its removal from PromQL._
|
||||
|
||||
`histogram_avg(v instant-vector)` returns the arithmetic average of observed values stored in
|
||||
a native histogram. Samples that are not native histograms are ignored and do
|
||||
not show up in the returned vector.
|
||||
|
||||
Use `histogram_avg` as demonstrated below to compute the average request duration
|
||||
over a 5-minute window from a native histogram:
|
||||
|
||||
histogram_avg(rate(http_request_duration_seconds[5m]))
|
||||
|
||||
Which is equivalent to the following query:
|
||||
|
||||
histogram_sum(rate(http_request_duration_seconds[5m]))
|
||||
/
|
||||
histogram_count(rate(http_request_duration_seconds[5m]))
|
||||
|
||||
## `histogram_count()` and `histogram_sum()`
|
||||
|
||||
_Both functions only act on native histograms, which are an experimental
|
||||
|
@ -193,13 +214,6 @@ Use `histogram_count` in the following way to calculate a rate of observations
|
|||
|
||||
histogram_count(rate(http_request_duration_seconds[10m]))
|
||||
|
||||
The additional use of `histogram_sum` enables the calculation of the average of
|
||||
observed values (in this case corresponding to “average request duration”):
|
||||
|
||||
histogram_sum(rate(http_request_duration_seconds[10m]))
|
||||
/
|
||||
histogram_count(rate(http_request_duration_seconds[10m]))
|
||||
|
||||
## `histogram_fraction()`
|
||||
|
||||
_This function only acts on native histograms, which are an experimental
|
||||
|
|
|
@ -7,69 +7,74 @@ require (
|
|||
github.com/go-kit/log v0.2.1
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/snappy v0.0.4
|
||||
github.com/influxdata/influxdb v1.11.4
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/prometheus/common v0.46.0
|
||||
github.com/prometheus/prometheus v0.48.1
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/influxdata/influxdb v1.11.5
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/prometheus/common v0.50.0
|
||||
github.com/prometheus/prometheus v0.50.1
|
||||
github.com/stretchr/testify v1.9.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||
github.com/aws/aws-sdk-go v1.45.25 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
|
||||
github.com/aws/aws-sdk-go v1.50.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dennwc/varint v1.0.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/google/uuid v1.5.0 // indirect
|
||||
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jpillora/backoff v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.1 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.0 // indirect
|
||||
github.com/prometheus/common/sigv4 v0.1.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata v1.0.0-rcv0016 // indirect
|
||||
go.opentelemetry.io/collector/semconv v0.87.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect
|
||||
go.opentelemetry.io/otel v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.19.0 // indirect
|
||||
go.opentelemetry.io/collector/featuregate v1.0.1 // indirect
|
||||
go.opentelemetry.io/collector/pdata v1.0.1 // indirect
|
||||
go.opentelemetry.io/collector/semconv v0.93.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
|
||||
go.opentelemetry.io/otel v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.22.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
||||
golang.org/x/net v0.22.0 // indirect
|
||||
golang.org/x/oauth2 v0.18.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect
|
||||
google.golang.org/grpc v1.58.3 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect
|
||||
google.golang.org/grpc v1.61.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apimachinery v0.28.6 // indirect
|
||||
k8s.io/client-go v0.28.6 // indirect
|
||||
k8s.io/klog/v2 v2.120.1 // indirect
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
|
||||
)
|
||||
|
||||
exclude (
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1 h1:UPeCRD+XY7QlaGQte2EVI2iOcWvUYA2XY8w5T/8v0NQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1/go.mod h1:oGV6NlB0cvi1ZbYRR2UN44QHxWFyGk+iylgD0qaMXjA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 h1:QM6sE5k2ZT/vI5BEe0r7mqjsUSnhVBFbOsVkEuaEfiA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2 v2.2.1 h1:bWh0Z2rOEDfB/ywv/l0iHN1JgyazE6kW/aIA89+CEK0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2 v2.2.1/go.mod h1:Bzf34hhAE9NSxailk8xVeLEZbUjOXcC+GnU1mMKdhLw=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.4.0 h1:QfV5XZt6iNa2aWMAt96CZEbfJ7kgG/qYIpq465Shr5E=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.4.0/go.mod h1:uYt4CfhkJA9o0FN7jfE5minm/i4nUE4MjGUJkzB6Zs8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/Code-Hex/go-generics-cache v1.3.1 h1:i8rLwyhoyhaerr7JpjtYjJZUcCbWOdiYO3fZXLiEC4g=
|
||||
github.com/Code-Hex/go-generics-cache v1.3.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
|
||||
|
@ -20,13 +21,15 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
|||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 h1:ez/4by2iGztzR4L0zgAOR8lTQK9VlyBVVd7G4omaOQs=
|
||||
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
|
||||
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
||||
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/aws/aws-sdk-go v1.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4=
|
||||
github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||
github.com/aws/aws-sdk-go v1.50.0 h1:HBtrLeO+QyDKnc3t1+5DR1RxodOHCGr8ZcrHudpv7jI=
|
||||
github.com/aws/aws-sdk-go v1.50.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps=
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
|
@ -34,8 +37,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY=
|
||||
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -43,32 +46,34 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
|||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE=
|
||||
github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA=
|
||||
github.com/digitalocean/godo v1.104.1 h1:SZNxjAsskM/su0YW9P8Wx3gU0W1Z13b6tZlYNpl5BnA=
|
||||
github.com/digitalocean/godo v1.104.1/go.mod h1:VAI/L5YDzMuPRU01lEEUSQ/sp5Z//1HnnFv/RBTEdbg=
|
||||
github.com/digitalocean/godo v1.108.0 h1:fWyMENvtxpCpva1UbKzOFnyAS04N1FNuBWWfPeTGquQ=
|
||||
github.com/digitalocean/godo v1.108.0/go.mod h1:R6EmmWI8CT1+fCtjWY9UCB+L5uufuZH13wk3YhxycCs=
|
||||
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
||||
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE=
|
||||
github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v25.0.0+incompatible h1:g9b6wZTblhMgzOT2tspESstfw6ySZ9kdm94BLDKaZac=
|
||||
github.com/docker/docker v25.0.0+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/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
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/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE=
|
||||
github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM=
|
||||
github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=
|
||||
github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
||||
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM=
|
||||
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
|
@ -80,8 +85,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
|
|||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
|
||||
|
@ -90,16 +95,16 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv
|
|||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
||||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
||||
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
|
||||
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
|
||||
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
@ -111,6 +116,7 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
|
|||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
|
@ -129,16 +135,16 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17
|
|||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gophercloud/gophercloud v1.7.0 h1:fyJGKh0LBvIZKLvBWvQdIgkaV5yTM3Jh9EYUh+UNCAs=
|
||||
github.com/gophercloud/gophercloud v1.7.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gophercloud/gophercloud v1.8.0 h1:TM3Jawprb2NrdOnvcHhWJalmKmAmOGgfZElM/3oBYCk=
|
||||
github.com/gophercloud/gophercloud v1.8.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww=
|
||||
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A=
|
||||
github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE=
|
||||
github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g=
|
||||
github.com/hashicorp/consul/api v1.27.0 h1:gmJ6DPKQog1426xsdmgk5iqDyoRiNc+ipBdJOqKQFjc=
|
||||
github.com/hashicorp/consul/api v1.27.0/go.mod h1:JkekNRSou9lANFdt+4IKx3Za7XY0JzzpQjEb4Ivo1c8=
|
||||
github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=
|
||||
github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
|
@ -155,20 +161,22 @@ github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZn
|
|||
github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4=
|
||||
github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20230721134942-515895c7690c h1:Nc3Mt2BAnq0/VoLEntF/nipX+K1S7pG+RgwiitSv6v0=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20230721134942-515895c7690c/go.mod h1:O23qLAZuCx4htdY9zBaO4cJPXgleSFEdq6D/sezGgYE=
|
||||
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
|
||||
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
||||
github.com/hetznercloud/hcloud-go/v2 v2.4.0 h1:MqlAE+w125PLvJRCpAJmEwrIxoVdUdOyuFUhE/Ukbok=
|
||||
github.com/hetznercloud/hcloud-go/v2 v2.4.0/go.mod h1:l7fA5xsncFBzQTyw29/dw5Yr88yEGKKdc6BHf24ONS0=
|
||||
github.com/hetznercloud/hcloud-go/v2 v2.6.0 h1:RJOA2hHZ7rD1pScA4O1NF6qhkHyUdbbxjHgFNot8928=
|
||||
github.com/hetznercloud/hcloud-go/v2 v2.6.0/go.mod h1:4J1cSE57+g0WS93IiHLV7ubTHItcp+awzeBp5bM9mfA=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/influxdata/influxdb v1.11.4 h1:H3pVW+/tWQ4lkHhZxVQ13Ov1hmhHYaAzz8L5aq3ZNtw=
|
||||
github.com/influxdata/influxdb v1.11.4/go.mod h1:VO6X2zlamfmEf+Esc9dR+7UQhdE/krspWNEZPwxCrp0=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.1.9 h1:Iq3VIXzeEbc8EbButuACgfLMiY5TPVWUPNrF+Vsddo4=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.1.9/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k=
|
||||
github.com/influxdata/influxdb v1.11.5 h1:+em5VOl6lhAZubXj5o6SobCwvrRs3XDlBx/MUI4schI=
|
||||
github.com/influxdata/influxdb v1.11.5/go.mod h1:k8sWREQl1/9t46VrkrH5adUM4UNGIt206ipO3plbkw8=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.1.11 h1:J/uRN4UWO3wCyGOeDdMKv8LWRzKu6UIkLEaes38Kzh8=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.1.11/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
|
@ -186,8 +194,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
|||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g=
|
||||
github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
|
@ -202,8 +210,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/linode/linodego v1.23.0 h1:s0ReCZtuN9Z1IoUN9w1RLeYO1dMZUGPwOQ/IBFsBHtU=
|
||||
github.com/linode/linodego v1.23.0/go.mod h1:0U7wj/UQOqBNbKv1FYTXiBUXueR8DY4HvIotwE0ENgg=
|
||||
github.com/linode/linodego v1.27.1 h1:KoQm5g2fppw8qIClJqUEL0yKH0+f+7te3Mewagb5QKE=
|
||||
github.com/linode/linodego v1.27.1/go.mod h1:5oAsx+uinHtVo6U77nXXXtox7MWzUW6aEkTOKXxA9uo=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
|
@ -211,8 +219,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
|||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
|
||||
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
|
||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
|
@ -237,8 +245,8 @@ github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrB
|
|||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/ovh/go-ovh v1.4.3 h1:Gs3V823zwTFpzgGLZNI6ILS4rmxZgJwJCz54Er9LwD0=
|
||||
github.com/ovh/go-ovh v1.4.3/go.mod h1:AkPXVtgwB6xlKblMjRKJJmjRp+ogrE7fz2lVgcQY8SY=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
|
@ -250,19 +258,19 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
|||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
||||
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
|
||||
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
|
||||
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
|
||||
github.com/prometheus/common v0.50.0 h1:YSZE6aa9+luNa2da6/Tik0q0A5AbR+U003TItK57CPQ=
|
||||
github.com/prometheus/common v0.50.0/go.mod h1:wHFBCEVWVmHMUpg7pYcOm2QUR/ocQdYSJVQJKnHc3xQ=
|
||||
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/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
|
@ -271,12 +279,12 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
|||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/prometheus/prometheus v0.48.1 h1:CTszphSNTXkuCG6O0IfpKdHcJkvvnAAE1GbELKS+NFk=
|
||||
github.com/prometheus/prometheus v0.48.1/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g=
|
||||
github.com/prometheus/prometheus v0.50.1 h1:N2L+DYrxqPh4WZStU+o1p/gQlBaqFbcLBTjlp3vpdXw=
|
||||
github.com/prometheus/prometheus v0.50.1/go.mod h1:FvE8dtQ1Ww63IlyKBn1V4s+zMwF9kHkVNkQBR1pM4CU=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21 h1:yWfiTPwYxB0l5fGMhl/G+liULugVIHD9AU77iNLrURQ=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22 h1:wJrcTdddKOI8TFxs8cemnhKP2EmKy3yfUKHj3ZdfzYo=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
|
@ -284,14 +292,14 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
|||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
|
||||
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
|
||||
|
@ -299,22 +307,24 @@ github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtX
|
|||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opentelemetry.io/collector/pdata v1.0.0-rcv0016 h1:qCPXSQCoD3qeWFb1RuIks8fw9Atxpk78bmtVdi15KhE=
|
||||
go.opentelemetry.io/collector/pdata v1.0.0-rcv0016/go.mod h1:OdN0alYOlYhHXu6BDlGehrZWgtBuiDsz/rlNeJeXiNg=
|
||||
go.opentelemetry.io/collector/semconv v0.87.0 h1:BsG1jdLLRCBRlvUujk4QA86af7r/ZXnizczQpEs/gg8=
|
||||
go.opentelemetry.io/collector/semconv v0.87.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q=
|
||||
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
|
||||
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
|
||||
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
|
||||
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
|
||||
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
|
||||
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
|
||||
go.opentelemetry.io/collector/featuregate v1.0.1 h1:ok//hLSXttBbyu4sSV1pTx1nKdr5udSmrWy5sFMIIbM=
|
||||
go.opentelemetry.io/collector/featuregate v1.0.1/go.mod h1:QQXjP4etmJQhkQ20j4P/rapWuItYxoFozg/iIwuKnYg=
|
||||
go.opentelemetry.io/collector/pdata v1.0.1 h1:dGX2h7maA6zHbl5D3AsMnF1c3Nn+3EUftbVCLzeyNvA=
|
||||
go.opentelemetry.io/collector/pdata v1.0.1/go.mod h1:jutXeu0QOXYY8wcZ/hege+YAnSBP3+jpTqYU1+JTI5Y=
|
||||
go.opentelemetry.io/collector/semconv v0.93.0 h1:eBlMcVNTwYYsVdAsCVDs4wvVYs75K1xcIDpqj16PG4c=
|
||||
go.opentelemetry.io/collector/semconv v0.93.0/go.mod h1:gZ0uzkXsN+J5NpiRcdp9xOhNGQDDui8Y62p15sKrlzo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw=
|
||||
go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
|
||||
go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
|
||||
go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
|
||||
go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
|
||||
go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
|
||||
go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
|
@ -322,15 +332,15 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
|
||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -346,13 +356,12 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
|
||||
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -360,8 +369,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -377,50 +386,48 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
|
||||
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0=
|
||||
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a h1:myvhA4is3vrit1a6NZCWBIwN0kNEnX21DJOJX/NvIfI=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0=
|
||||
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
|
||||
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg=
|
||||
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac h1:OZkkudMUu9LVQMCoRUbI/1p5VCo9BOrlvkqMvWtqa6s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA=
|
||||
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
|
||||
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
|
||||
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-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -429,8 +436,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
|||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -451,22 +458,21 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw=
|
||||
k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg=
|
||||
k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ=
|
||||
k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU=
|
||||
k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY=
|
||||
k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY=
|
||||
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
|
||||
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
|
||||
k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc=
|
||||
k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/api v0.28.6 h1:yy6u9CuIhmg55YvF/BavPBBXB+5QicB64njJXxVnzLo=
|
||||
k8s.io/api v0.28.6/go.mod h1:AM6Ys6g9MY3dl/XNaNfg/GePI0FT7WBGu8efU/lirAo=
|
||||
k8s.io/apimachinery v0.28.6 h1:RsTeR4z6S07srPg6XYrwXpTJVMXsjPXn0ODakMytSW0=
|
||||
k8s.io/apimachinery v0.28.6/go.mod h1:QFNX/kCl/EMT2WTSz8k4WLCv2XnkOLMaL8GAVRMdpsA=
|
||||
k8s.io/client-go v0.28.6 h1:Gge6ziyIdafRchfoBKcpaARuz7jfrK1R1azuwORIsQI=
|
||||
k8s.io/client-go v0.28.6/go.mod h1:+nu0Yp21Oeo/cBCsprNVXB2BfJTV51lFfe5tXl2rUL8=
|
||||
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
||||
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
|
|
|
@ -83,9 +83,12 @@ var (
|
|||
)
|
||||
sentBatchDuration = prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "sent_batch_duration_seconds",
|
||||
Help: "Duration of sample batch send calls to the remote storage.",
|
||||
Buckets: prometheus.DefBuckets,
|
||||
Name: "sent_batch_duration_seconds",
|
||||
Help: "Duration of sample batch send calls to the remote storage.",
|
||||
Buckets: prometheus.DefBuckets,
|
||||
NativeHistogramBucketFactor: 1.1,
|
||||
NativeHistogramMaxBucketNumber: 100,
|
||||
NativeHistogramMinResetDuration: 1 * time.Hour,
|
||||
},
|
||||
[]string{"remote"},
|
||||
)
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
alert: 'PrometheusNotIngestingSamples',
|
||||
expr: |||
|
||||
(
|
||||
rate(prometheus_tsdb_head_samples_appended_total{%(prometheusSelector)s}[5m]) <= 0
|
||||
sum without(type) (rate(prometheus_tsdb_head_samples_appended_total{%(prometheusSelector)s}[5m])) <= 0
|
||||
and
|
||||
(
|
||||
sum without(scrape_job) (prometheus_target_metadata_cache_entries{%(prometheusSelector)s}) > 0
|
||||
|
|
129
go.mod
129
go.mod
|
@ -3,20 +3,20 @@ module github.com/prometheus/prometheus
|
|||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.4.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.5.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0
|
||||
github.com/Code-Hex/go-generics-cache v1.3.1
|
||||
github.com/KimMachineGun/automemlimit v0.5.0
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0
|
||||
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9
|
||||
github.com/aws/aws-sdk-go v1.50.0
|
||||
github.com/aws/aws-sdk-go v1.50.32
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3
|
||||
github.com/cespare/xxhash/v2 v2.2.0
|
||||
github.com/dennwc/varint v1.0.0
|
||||
github.com/digitalocean/godo v1.108.0
|
||||
github.com/docker/docker v25.0.0+incompatible
|
||||
github.com/digitalocean/godo v1.109.0
|
||||
github.com/docker/docker v25.0.3+incompatible
|
||||
github.com/edsrzf/mmap-go v1.1.0
|
||||
github.com/envoyproxy/go-control-plane v0.12.0
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4
|
||||
|
@ -24,23 +24,24 @@ require (
|
|||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/go-kit/log v0.2.1
|
||||
github.com/go-logfmt/logfmt v0.6.0
|
||||
github.com/go-openapi/strfmt v0.22.0
|
||||
github.com/go-openapi/strfmt v0.22.2
|
||||
github.com/go-zookeeper/zk v1.0.3
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/snappy v0.0.4
|
||||
github.com/google/pprof v0.0.0-20240117000934-35fc243c5815
|
||||
github.com/google/uuid v1.5.0
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gophercloud/gophercloud v1.8.0
|
||||
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
github.com/hashicorp/consul/api v1.27.0
|
||||
github.com/hashicorp/nomad/api v0.0.0-20230721134942-515895c7690c // Not upgrading this for now due to https://github.com/prometheus/prometheus/pull/13255#issuecomment-1845237409
|
||||
github.com/hashicorp/consul/api v1.28.2
|
||||
github.com/hashicorp/nomad/api v0.0.0-20240306004928-3e7191ccb702
|
||||
github.com/hetznercloud/hcloud-go/v2 v2.6.0
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.1.11
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/klauspost/compress v1.17.4
|
||||
github.com/klauspost/compress v1.17.7
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b
|
||||
github.com/linode/linodego v1.27.1
|
||||
github.com/linode/linodego v1.30.0
|
||||
github.com/miekg/dns v1.1.58
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
|
||||
|
@ -48,55 +49,55 @@ require (
|
|||
github.com/oklog/run v1.1.0
|
||||
github.com/oklog/ulid v1.3.1
|
||||
github.com/ovh/go-ovh v1.4.3
|
||||
github.com/prometheus/alertmanager v0.26.0
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/prometheus/client_model v0.5.0
|
||||
github.com/prometheus/common v0.46.0
|
||||
github.com/prometheus/alertmanager v0.27.0
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/prometheus/client_model v0.6.0
|
||||
github.com/prometheus/common v0.49.1-0.20240306132007-4199f18c3e92
|
||||
github.com/prometheus/common/assets v0.2.0
|
||||
github.com/prometheus/common/sigv4 v0.1.0
|
||||
github.com/prometheus/exporter-toolkit v0.11.0
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.25
|
||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/vultr/govultr/v2 v2.17.2
|
||||
go.opentelemetry.io/collector/featuregate v1.0.1
|
||||
go.opentelemetry.io/collector/pdata v1.0.1
|
||||
go.opentelemetry.io/collector/semconv v0.92.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0
|
||||
go.opentelemetry.io/otel v1.22.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0
|
||||
go.opentelemetry.io/otel/sdk v1.22.0
|
||||
go.opentelemetry.io/otel/trace v1.22.0
|
||||
go.opentelemetry.io/collector/featuregate v1.3.0
|
||||
go.opentelemetry.io/collector/pdata v1.3.0
|
||||
go.opentelemetry.io/collector/semconv v0.96.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0
|
||||
go.opentelemetry.io/otel v1.24.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0
|
||||
go.opentelemetry.io/otel/sdk v1.24.0
|
||||
go.opentelemetry.io/otel/trace v1.24.0
|
||||
go.uber.org/atomic v1.11.0
|
||||
go.uber.org/automaxprocs v1.5.3
|
||||
go.uber.org/goleak v1.3.0
|
||||
go.uber.org/multierr v1.11.0
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
|
||||
golang.org/x/net v0.20.0
|
||||
golang.org/x/oauth2 v0.16.0
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
||||
golang.org/x/net v0.22.0
|
||||
golang.org/x/oauth2 v0.18.0
|
||||
golang.org/x/sync v0.6.0
|
||||
golang.org/x/sys v0.16.0
|
||||
golang.org/x/sys v0.18.0
|
||||
golang.org/x/time v0.5.0
|
||||
golang.org/x/tools v0.17.0
|
||||
google.golang.org/api v0.157.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac
|
||||
google.golang.org/grpc v1.61.0
|
||||
google.golang.org/protobuf v1.32.0
|
||||
golang.org/x/tools v0.19.0
|
||||
google.golang.org/api v0.168.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8
|
||||
google.golang.org/grpc v1.62.1
|
||||
google.golang.org/protobuf v1.33.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.28.4
|
||||
k8s.io/apimachinery v0.28.4
|
||||
k8s.io/client-go v0.28.4
|
||||
k8s.io/api v0.29.3
|
||||
k8s.io/apimachinery v0.29.3
|
||||
k8s.io/client-go v0.29.3
|
||||
k8s.io/klog v1.0.0
|
||||
k8s.io/klog/v2 v2.120.1
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.23.3 // indirect
|
||||
cloud.google.com/go/compute v1.23.4 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
|
@ -104,7 +105,7 @@ require (
|
|||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cilium/ebpf v0.11.0 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect
|
||||
github.com/containerd/cgroups/v3 v3.0.3 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
|
@ -120,29 +121,28 @@ require (
|
|||
github.com/go-kit/kit v0.12.0 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.21.4 // indirect
|
||||
github.com/go-openapi/errors v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/loads v0.21.2 // indirect
|
||||
github.com/go-openapi/spec v0.20.9 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/go-openapi/validate v0.22.1 // indirect
|
||||
github.com/go-openapi/analysis v0.22.2 // indirect
|
||||
github.com/go-openapi/errors v0.21.1 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.2 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.4 // indirect
|
||||
github.com/go-openapi/loads v0.21.5 // indirect
|
||||
github.com/go-openapi/spec v0.20.14 // indirect
|
||||
github.com/go-openapi/swag v0.22.9 // indirect
|
||||
github.com/go-openapi/validate v0.23.0 // indirect
|
||||
github.com/go-resty/resty/v2 v2.11.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.0.4 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
|
||||
github.com/golang/glog v1.1.2 // indirect
|
||||
github.com/golang/glog v1.2.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.2 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
|
||||
github.com/hashicorp/cronexpr v1.1.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
|
@ -179,19 +179,18 @@ require (
|
|||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/objx v0.5.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.22.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/term v0.16.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gotest.tools/v3 v3.0.3 // indirect
|
||||
|
|
373
go.sum
373
go.sum
|
@ -18,8 +18,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf
|
|||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
|
||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||
cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw=
|
||||
cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
|
@ -34,14 +34,14 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
|||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0 h1:n1DH8TPV4qqPTje2RcUBYwtrTWlabVp4n46+74X2pn4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0/go.mod h1:HDcZnuGbiyppErN6lB+idp4CKhjbc8gwjto6OPpyggM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.4.0 h1:QfV5XZt6iNa2aWMAt96CZEbfJ7kgG/qYIpq465Shr5E=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.4.0/go.mod h1:uYt4CfhkJA9o0FN7jfE5minm/i4nUE4MjGUJkzB6Zs8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 h1:LqbJ/WzJUwBf8UiaSzgX7aMclParm9/5Vgp+TY51uBQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.5.0 h1:MxA59PGoCFb+vCwRQi3PhQEwHj4+r2dhuv9HG+vM7iM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.5.0/go.mod h1:uYt4CfhkJA9o0FN7jfE5minm/i4nUE4MjGUJkzB6Zs8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA=
|
||||
|
@ -62,8 +62,6 @@ github.com/KimMachineGun/automemlimit v0.5.0/go.mod h1:di3GCKiu9Y+1fs92erCbUvKzP
|
|||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
|
@ -87,14 +85,13 @@ github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+
|
|||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/aws/aws-sdk-go v1.50.0 h1:HBtrLeO+QyDKnc3t1+5DR1RxodOHCGr8ZcrHudpv7jI=
|
||||
github.com/aws/aws-sdk-go v1.50.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go v1.50.32 h1:POt81DvegnpQKM4DMDLlHz1CO6OBnEoQ1gRhYFd7QRY=
|
||||
github.com/aws/aws-sdk-go v1.50.32/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps=
|
||||
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0=
|
||||
|
@ -121,8 +118,8 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp
|
|||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY=
|
||||
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
|
||||
|
@ -136,7 +133,6 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
|
|||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/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.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -145,14 +141,14 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc
|
|||
github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE=
|
||||
github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/digitalocean/godo v1.108.0 h1:fWyMENvtxpCpva1UbKzOFnyAS04N1FNuBWWfPeTGquQ=
|
||||
github.com/digitalocean/godo v1.108.0/go.mod h1:R6EmmWI8CT1+fCtjWY9UCB+L5uufuZH13wk3YhxycCs=
|
||||
github.com/digitalocean/godo v1.109.0 h1:4W97RJLJSUQ3veRZDNbp1Ol3Rbn6Lmt9bKGvfqYI5SU=
|
||||
github.com/digitalocean/godo v1.109.0/go.mod h1:R6EmmWI8CT1+fCtjWY9UCB+L5uufuZH13wk3YhxycCs=
|
||||
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
||||
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/docker/docker v25.0.0+incompatible h1:g9b6wZTblhMgzOT2tspESstfw6ySZ9kdm94BLDKaZac=
|
||||
github.com/docker/docker v25.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v25.0.3+incompatible h1:D5fy/lYmY7bvZa0XTZ5/UJPljor41F+vdyJG5luQLfQ=
|
||||
github.com/docker/docker v25.0.3+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/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
|
@ -216,43 +212,24 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
|||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY=
|
||||
github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc=
|
||||
github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo=
|
||||
github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
||||
github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
||||
github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
||||
github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY=
|
||||
github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
|
||||
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
|
||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g=
|
||||
github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro=
|
||||
github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||
github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
|
||||
github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||
github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg=
|
||||
github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
|
||||
github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg=
|
||||
github.com/go-openapi/strfmt v0.22.0 h1:Ew9PnEYc246TwrEspvBdDHS4BVKXy/AOVsfqGDgAcaI=
|
||||
github.com/go-openapi/strfmt v0.22.0/go.mod h1:HzJ9kokGIju3/K6ap8jL+OlGAbjpSv27135Yr9OivU4=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU=
|
||||
github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
|
||||
github.com/go-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0=
|
||||
github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo=
|
||||
github.com/go-openapi/errors v0.21.1 h1:rVisxQPdETctjlYntm0Ek4dKf68nAQocCloCT50vWuI=
|
||||
github.com/go-openapi/errors v0.21.1/go.mod h1:LyiY9bgc7AVVh6wtVvMYEyoj3KJYNoRw92mmvnMWgj8=
|
||||
github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
|
||||
github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
|
||||
github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU=
|
||||
github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
|
||||
github.com/go-openapi/loads v0.21.5 h1:jDzF4dSoHw6ZFADCGltDb2lE4F6De7aWSpe+IcsRzT0=
|
||||
github.com/go-openapi/loads v0.21.5/go.mod h1:PxTsnFBoBe+z89riT+wYt3prmSBP6GDAQh2l9H1Flz8=
|
||||
github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do=
|
||||
github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw=
|
||||
github.com/go-openapi/strfmt v0.22.2 h1:DPYOrm6gexCfZZfXUaXFS4+Jw6HAaIIG0SZ5630f8yw=
|
||||
github.com/go-openapi/strfmt v0.22.2/go.mod h1:HB/b7TCm91rno75Dembc1dFW/0FPLk5CEXsoF9ReNc4=
|
||||
github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE=
|
||||
github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE=
|
||||
github.com/go-openapi/validate v0.23.0 h1:2l7PJLzCis4YUGEoW6eoQw3WhyM65WSIcjX6SQnlfDw=
|
||||
github.com/go-openapi/validate v0.23.0/go.mod h1:EeiAZ5bmpSIOJV1WLfyYF9qp/B1ZgSaEpHTJHtN5cbE=
|
||||
github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
|
||||
github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
|
@ -261,30 +238,6 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
|
|||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
|
||||
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
|
||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
||||
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
|
||||
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
|
||||
github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
|
||||
github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
|
||||
github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
|
||||
github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
|
||||
github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
|
||||
github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
|
||||
github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
|
||||
github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
|
||||
github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
|
||||
github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
|
||||
github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
|
||||
github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
|
||||
github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
|
||||
github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
|
||||
github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
|
||||
github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
|
||||
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
|
||||
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
|
||||
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
||||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
|
@ -296,8 +249,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
|
|||
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
|
||||
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
@ -327,10 +280,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
|||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
|
@ -367,22 +319,21 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
|
|||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 h1:WzfWbQz/Ze8v6l++GGbGNFZnUShVpP/0xffCPLL+ax8=
|
||||
github.com/google/pprof v0.0.0-20240117000934-35fc243c5815/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
|
||||
github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA=
|
||||
github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc=
|
||||
github.com/gophercloud/gophercloud v1.8.0 h1:TM3Jawprb2NrdOnvcHhWJalmKmAmOGgfZElM/3oBYCk=
|
||||
github.com/gophercloud/gophercloud v1.8.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
|
@ -399,14 +350,14 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
|
|||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/api v1.27.0 h1:gmJ6DPKQog1426xsdmgk5iqDyoRiNc+ipBdJOqKQFjc=
|
||||
github.com/hashicorp/consul/api v1.27.0/go.mod h1:JkekNRSou9lANFdt+4IKx3Za7XY0JzzpQjEb4Ivo1c8=
|
||||
github.com/hashicorp/consul/api v1.28.2 h1:mXfkRHrpHN4YY3RqL09nXU1eHKLNiuAN4kHvDQ16k/8=
|
||||
github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/consul/sdk v0.15.1 h1:kKIGxc7CZtflcF5DLfHeq7rOQmRq3vk7kwISN9bif8Q=
|
||||
github.com/hashicorp/consul/sdk v0.15.1/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A=
|
||||
github.com/hashicorp/consul/sdk v0.16.0 h1:SE9m0W6DEfgIVCJX7xU+iv/hUl4m/nxqMTnCdMxDpJ8=
|
||||
github.com/hashicorp/consul/sdk v0.16.0/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A=
|
||||
github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=
|
||||
github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
|
@ -436,8 +387,8 @@ github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa
|
|||
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
||||
github.com/hashicorp/go-sockaddr v1.0.6 h1:RSG8rKU28VTUTvEKghe5gIhIQpv8evvNpnDEyqO4u9I=
|
||||
github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
|
@ -457,8 +408,8 @@ github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/
|
|||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM=
|
||||
github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20230721134942-515895c7690c h1:Nc3Mt2BAnq0/VoLEntF/nipX+K1S7pG+RgwiitSv6v0=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20230721134942-515895c7690c/go.mod h1:O23qLAZuCx4htdY9zBaO4cJPXgleSFEdq6D/sezGgYE=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20240306004928-3e7191ccb702 h1:fI1LXuBaS1d9z1kmb++Og6YD8uMRwadXorCwE+xgOFA=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20240306004928-3e7191ccb702/go.mod h1:z71gkJdrkAt/Rl6C7Q79VE7AwJ5lUF+M+fzFTyIHYB0=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
|
||||
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
||||
|
@ -473,14 +424,13 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
|
|||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.1.11 h1:J/uRN4UWO3wCyGOeDdMKv8LWRzKu6UIkLEaes38Kzh8=
|
||||
github.com/ionos-cloud/sdk-go/v6 v6.1.11/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k=
|
||||
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
|
||||
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
|
||||
github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww=
|
||||
github.com/jarcoal/httpmock v1.3.1/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
|
@ -500,22 +450,17 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
|||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
|
@ -526,16 +471,11 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
|
|||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/linode/linodego v1.27.1 h1:KoQm5g2fppw8qIClJqUEL0yKH0+f+7te3Mewagb5QKE=
|
||||
github.com/linode/linodego v1.27.1/go.mod h1:5oAsx+uinHtVo6U77nXXXtox7MWzUW6aEkTOKXxA9uo=
|
||||
github.com/linode/linodego v1.30.0 h1:6HJli+LX7NGu+Sne2G+ux790EkVOWOV/SR4mK3jcs6k=
|
||||
github.com/linode/linodego v1.30.0/go.mod h1:/46h/XpmWi//oSA92GX2p3FIxb8HbX7grslPPQalR2o=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
|
@ -573,8 +513,6 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
|
|||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc=
|
||||
|
@ -586,7 +524,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
|||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
|
@ -601,7 +538,6 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
|
|||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM=
|
||||
github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
|
@ -614,11 +550,11 @@ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:v
|
|||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE=
|
||||
github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
|
||||
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
|
@ -643,7 +579,6 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T
|
|||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
|
@ -661,8 +596,8 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr
|
|||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/prometheus/alertmanager v0.26.0 h1:uOMJWfIwJguc3NaM3appWNbbrh6G/OjvaHMk22aBBYc=
|
||||
github.com/prometheus/alertmanager v0.26.0/go.mod h1:rVcnARltVjavgVaNnmevxK7kOn7IZavyf0KNgHkbEpU=
|
||||
github.com/prometheus/alertmanager v0.27.0 h1:V6nTa2J5V4s8TG4C4HtrBP/WNSebCCTYGGv4qecA/+I=
|
||||
github.com/prometheus/alertmanager v0.27.0/go.mod h1:8Ia/R3urPmbzJ8OsdvmZvIprDwvwmYCmUbwBL+jlPOE=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
|
@ -670,16 +605,16 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD
|
|||
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
||||
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
|
||||
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
|
@ -687,8 +622,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
|
|||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
|
||||
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
|
||||
github.com/prometheus/common v0.49.1-0.20240306132007-4199f18c3e92 h1:nuwTDY/15McImfuXcUD6AA3alpUNEXfWws8K/8SXr68=
|
||||
github.com/prometheus/common v0.49.1-0.20240306132007-4199f18c3e92/go.mod h1:Kxm+EULxRbUkjGU6WFsQqo3ORzB4tyKvlWFOE9mB2sE=
|
||||
github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/5AahrSrfM=
|
||||
github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI=
|
||||
github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4=
|
||||
|
@ -706,20 +641,18 @@ github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3c
|
|||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22 h1:wJrcTdddKOI8TFxs8cemnhKP2EmKy3yfUKHj3ZdfzYo=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.25 h1:/8rfZAdFfafRXOgz+ZpMZZWZ5pYggCY9t7e/BvjaBHM=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.25/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shoenig/test v0.6.6 h1:Oe8TPH9wAbv++YPNDKJWUnI8Q4PPWCx3UbOfH+FxiMU=
|
||||
github.com/shoenig/test v0.6.6/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/shoenig/test v1.7.1 h1:UJcjSAI3aUKx52kfcfhblgyhZceouhvvs3OYdWgn+PY=
|
||||
github.com/shoenig/test v1.7.1/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI=
|
||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs=
|
||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
|
@ -728,8 +661,6 @@ github.com/simonpasquier/klog-gokit v0.3.0/go.mod h1:+SUlDQNrhVtGt2FieaqNftzzk8P
|
|||
github.com/simonpasquier/klog-gokit/v3 v3.3.0 h1:HMzH999kO5gEgJTaWWO+xjncW5oycspcsBnjn9b853Q=
|
||||
github.com/simonpasquier/klog-gokit/v3 v3.3.0/go.mod h1:uSbnWC3T7kt1dQyY9sjv0Ao1SehMAJdVnUNSKhjaDsg=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
|
@ -749,37 +680,28 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
|
||||
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
|
@ -787,11 +709,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
|||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg=
|
||||
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
|
||||
go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
|
||||
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
|
||||
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
|
||||
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
||||
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
|
@ -801,30 +720,30 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/collector/featuregate v1.0.1 h1:ok//hLSXttBbyu4sSV1pTx1nKdr5udSmrWy5sFMIIbM=
|
||||
go.opentelemetry.io/collector/featuregate v1.0.1/go.mod h1:QQXjP4etmJQhkQ20j4P/rapWuItYxoFozg/iIwuKnYg=
|
||||
go.opentelemetry.io/collector/pdata v1.0.1 h1:dGX2h7maA6zHbl5D3AsMnF1c3Nn+3EUftbVCLzeyNvA=
|
||||
go.opentelemetry.io/collector/pdata v1.0.1/go.mod h1:jutXeu0QOXYY8wcZ/hege+YAnSBP3+jpTqYU1+JTI5Y=
|
||||
go.opentelemetry.io/collector/semconv v0.92.0 h1:3+OGPPuVu4rtrz8qGbpbiw7eKKULj4iJaSDTV52HM40=
|
||||
go.opentelemetry.io/collector/semconv v0.92.0/go.mod h1:gZ0uzkXsN+J5NpiRcdp9xOhNGQDDui8Y62p15sKrlzo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw=
|
||||
go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
|
||||
go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY=
|
||||
go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
|
||||
go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
|
||||
go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw=
|
||||
go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc=
|
||||
go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
|
||||
go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||
go.opentelemetry.io/collector/featuregate v1.3.0 h1:nrFSx+zfjdisjE9oCx25Aep3nJ9RaUjeE1qFL6eovoU=
|
||||
go.opentelemetry.io/collector/featuregate v1.3.0/go.mod h1:mm8+xyQfgDmqhyegZRNIQmoKsNnDTwWKFLsdMoXAb7A=
|
||||
go.opentelemetry.io/collector/pdata v1.3.0 h1:JRYN7tVHYFwmtQhIYbxWeiKSa2L1nCohyAs8sYqKFZo=
|
||||
go.opentelemetry.io/collector/pdata v1.3.0/go.mod h1:t7W0Undtes53HODPdSujPLTnfSR5fzT+WpL+RTaaayo=
|
||||
go.opentelemetry.io/collector/semconv v0.96.0 h1:DrZy8BpzJDnN2zFxXRj6BhfGYxNlqpFHBqyuS9fVHRY=
|
||||
go.opentelemetry.io/collector/semconv v0.96.0/go.mod h1:zOm/U3pgMIWcvrcnPbR9Xx2HinoXj46ERMK8PUV9wrs=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM=
|
||||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
|
||||
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI=
|
||||
go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
|
@ -843,20 +762,17 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
|||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -891,8 +807,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
||||
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -931,28 +847,26 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
|
||||
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -975,13 +889,10 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -1014,7 +925,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -1032,21 +942,20 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
|
@ -1071,13 +980,9 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
|
|||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
|
@ -1116,8 +1021,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
|
|||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -1137,8 +1042,8 @@ google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/
|
|||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.157.0 h1:ORAeqmbrrozeyw5NjnMxh7peHO0UzV4wWYSwZeCUb20=
|
||||
google.golang.org/api v0.157.0/go.mod h1:+z4v4ufbZ1WEpld6yMGHyggs+PmAHiaLNj5ytP3N01g=
|
||||
google.golang.org/api v0.168.0 h1:MBRe+Ki4mMN93jhDDbpuRLjRddooArz4FeSObvUMmjY=
|
||||
google.golang.org/api v0.168.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg=
|
||||
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.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
@ -1177,12 +1082,10 @@ google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1m
|
|||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg=
|
||||
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac h1:OZkkudMUu9LVQMCoRUbI/1p5VCo9BOrlvkqMvWtqa6s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 h1:8eadJkXbwDEMNwcB5O0s5Y5eCfyuCLdvaiOIaGTrWmQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78 h1:Xs9lu+tLXxLIfuci70nG4cpwaRC+mRQPUL7LoIeDJC4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
|
||||
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.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
|
@ -1201,8 +1104,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
|
|||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
|
||||
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
|
||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
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-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -1215,13 +1118,12 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
|||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
|
@ -1246,9 +1148,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
|
@ -1262,12 +1161,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY=
|
||||
k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0=
|
||||
k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8=
|
||||
k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg=
|
||||
k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY=
|
||||
k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4=
|
||||
k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
|
||||
k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
|
||||
k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
|
||||
k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
|
||||
k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
|
||||
k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
|
||||
|
|
|
@ -15,10 +15,10 @@ package histogram
|
|||
|
||||
import (
|
||||
"math"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
func TestGetBound(t *testing.T) {
|
||||
|
|
|
@ -16,9 +16,8 @@ package histogram
|
|||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// CounterResetHint contains the known information about a counter reset,
|
||||
|
|
|
@ -11,16 +11,16 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !stringlabels
|
||||
//go:build !stringlabels && !dedupelabels
|
||||
|
||||
package labels
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/cespare/xxhash/v2"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// Labels is a sorted set of labels. Order has to be guaranteed upon
|
||||
|
@ -342,6 +342,19 @@ func (ls Labels) Validate(f func(l Label) error) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// DropMetricName returns Labels with "__name__" removed.
|
||||
func (ls Labels) DropMetricName() Labels {
|
||||
for i, l := range ls {
|
||||
if l.Name == MetricName {
|
||||
if i == 0 { // Make common case fast with no allocations.
|
||||
return ls[1:]
|
||||
}
|
||||
return append(ls[:i], ls[i+1:]...)
|
||||
}
|
||||
}
|
||||
return ls
|
||||
}
|
||||
|
||||
// InternStrings calls intern on every string value inside ls, replacing them with what it returns.
|
||||
func (ls *Labels) InternStrings(intern func(string) string) {
|
||||
for i, l := range *ls {
|
||||
|
@ -358,6 +371,25 @@ func (ls Labels) ReleaseStrings(release func(string)) {
|
|||
}
|
||||
}
|
||||
|
||||
// Builder allows modifying Labels.
|
||||
type Builder struct {
|
||||
base Labels
|
||||
del []string
|
||||
add []Label
|
||||
}
|
||||
|
||||
// Reset clears all current state for the builder.
|
||||
func (b *Builder) Reset(base Labels) {
|
||||
b.base = base
|
||||
b.del = b.del[:0]
|
||||
b.add = b.add[:0]
|
||||
b.base.Range(func(l Label) {
|
||||
if l.Value == "" {
|
||||
b.del = append(b.del, l.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Labels returns the labels from the builder.
|
||||
// If no modifications were made, the original labels are returned.
|
||||
func (b *Builder) Labels() Labels {
|
||||
|
@ -388,11 +420,32 @@ type ScratchBuilder struct {
|
|||
add Labels
|
||||
}
|
||||
|
||||
// Symbol-table is no-op, just for api parity with dedupelabels.
|
||||
type SymbolTable struct{}
|
||||
|
||||
func NewSymbolTable() *SymbolTable { return nil }
|
||||
|
||||
func (t *SymbolTable) Len() int { return 0 }
|
||||
|
||||
// NewScratchBuilder creates a ScratchBuilder initialized for Labels with n entries.
|
||||
func NewScratchBuilder(n int) ScratchBuilder {
|
||||
return ScratchBuilder{add: make([]Label, 0, n)}
|
||||
}
|
||||
|
||||
// NewBuilderWithSymbolTable creates a Builder, for api parity with dedupelabels.
|
||||
func NewBuilderWithSymbolTable(_ *SymbolTable) *Builder {
|
||||
return NewBuilder(EmptyLabels())
|
||||
}
|
||||
|
||||
// NewScratchBuilderWithSymbolTable creates a ScratchBuilder, for api parity with dedupelabels.
|
||||
func NewScratchBuilderWithSymbolTable(_ *SymbolTable, n int) ScratchBuilder {
|
||||
return NewScratchBuilder(n)
|
||||
}
|
||||
|
||||
func (b *ScratchBuilder) SetSymbolTable(_ *SymbolTable) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
func (b *ScratchBuilder) Reset() {
|
||||
b.add = b.add[:0]
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@ package labels
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"slices"
|
||||
"strconv"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -39,7 +39,8 @@ type Label struct {
|
|||
}
|
||||
|
||||
func (ls Labels) String() string {
|
||||
var b bytes.Buffer
|
||||
var bytea [1024]byte // On stack to avoid memory allocation while building the output.
|
||||
b := bytes.NewBuffer(bytea[:0])
|
||||
|
||||
b.WriteByte('{')
|
||||
i := 0
|
||||
|
@ -50,7 +51,7 @@ func (ls Labels) String() string {
|
|||
}
|
||||
b.WriteString(l.Name)
|
||||
b.WriteByte('=')
|
||||
b.WriteString(strconv.Quote(l.Value))
|
||||
b.Write(strconv.AppendQuote(b.AvailableBuffer(), l.Value))
|
||||
i++
|
||||
})
|
||||
b.WriteByte('}')
|
||||
|
@ -123,13 +124,6 @@ func FromMap(m map[string]string) Labels {
|
|||
return New(l...)
|
||||
}
|
||||
|
||||
// Builder allows modifying Labels.
|
||||
type Builder struct {
|
||||
base Labels
|
||||
del []string
|
||||
add []Label
|
||||
}
|
||||
|
||||
// NewBuilder returns a new LabelsBuilder.
|
||||
func NewBuilder(base Labels) *Builder {
|
||||
b := &Builder{
|
||||
|
@ -140,18 +134,6 @@ func NewBuilder(base Labels) *Builder {
|
|||
return b
|
||||
}
|
||||
|
||||
// Reset clears all current state for the builder.
|
||||
func (b *Builder) Reset(base Labels) {
|
||||
b.base = base
|
||||
b.del = b.del[:0]
|
||||
b.add = b.add[:0]
|
||||
b.base.Range(func(l Label) {
|
||||
if l.Value == "" {
|
||||
b.del = append(b.del, l.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Del deletes the label of the given name.
|
||||
func (b *Builder) Del(ns ...string) *Builder {
|
||||
for _, n := range ns {
|
||||
|
|
807
model/labels/labels_dedupelabels.go
Normal file
807
model/labels/labels_dedupelabels.go
Normal file
|
@ -0,0 +1,807 @@
|
|||
// Copyright 2024 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build dedupelabels
|
||||
|
||||
package labels
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cespare/xxhash/v2"
|
||||
)
|
||||
|
||||
// Labels is implemented by a SymbolTable and string holding name/value
|
||||
// pairs encoded as indexes into the table in varint encoding.
|
||||
// Names are in alphabetical order.
|
||||
type Labels struct {
|
||||
syms *nameTable
|
||||
data string
|
||||
}
|
||||
|
||||
// Split SymbolTable into the part used by Labels and the part used by Builder. Only the latter needs the map.
|
||||
|
||||
// This part is used by Labels. All fields are immutable after construction.
|
||||
type nameTable struct {
|
||||
byNum []string // This slice header is never changed, even while we are building the symbol table.
|
||||
symbolTable *SymbolTable // If we need to use it in a Builder.
|
||||
}
|
||||
|
||||
// SymbolTable is used to map strings into numbers so they can be packed together.
|
||||
type SymbolTable struct {
|
||||
mx sync.Mutex
|
||||
*nameTable
|
||||
nextNum int
|
||||
byName map[string]int
|
||||
}
|
||||
|
||||
const defaultSymbolTableSize = 1024
|
||||
|
||||
func NewSymbolTable() *SymbolTable {
|
||||
t := &SymbolTable{
|
||||
nameTable: &nameTable{byNum: make([]string, defaultSymbolTableSize)},
|
||||
byName: make(map[string]int, defaultSymbolTableSize),
|
||||
}
|
||||
t.nameTable.symbolTable = t
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *SymbolTable) Len() int {
|
||||
t.mx.Lock()
|
||||
defer t.mx.Unlock()
|
||||
return len(t.byName)
|
||||
}
|
||||
|
||||
// ToNum maps a string to an integer, adding the string to the table if it is not already there.
|
||||
// Note: copies the string before adding, in case the caller passed part of
|
||||
// a buffer that should not be kept alive by this SymbolTable.
|
||||
func (t *SymbolTable) ToNum(name string) int {
|
||||
t.mx.Lock()
|
||||
defer t.mx.Unlock()
|
||||
return t.toNumUnlocked(name)
|
||||
}
|
||||
|
||||
func (t *SymbolTable) toNumUnlocked(name string) int {
|
||||
if i, found := t.byName[name]; found {
|
||||
return i
|
||||
}
|
||||
i := t.nextNum
|
||||
if t.nextNum == cap(t.byNum) {
|
||||
// Name table is full; copy to a new one. Don't touch the existing slice, as nameTable is immutable after construction.
|
||||
newSlice := make([]string, cap(t.byNum)*2)
|
||||
copy(newSlice, t.byNum)
|
||||
t.nameTable = &nameTable{byNum: newSlice, symbolTable: t}
|
||||
}
|
||||
name = strings.Clone(name)
|
||||
t.byNum[i] = name
|
||||
t.byName[name] = i
|
||||
t.nextNum++
|
||||
return i
|
||||
}
|
||||
|
||||
func (t *SymbolTable) checkNum(name string) (int, bool) {
|
||||
t.mx.Lock()
|
||||
defer t.mx.Unlock()
|
||||
i, bool := t.byName[name]
|
||||
return i, bool
|
||||
}
|
||||
|
||||
// ToName maps an integer to a string.
|
||||
func (t *nameTable) ToName(num int) string {
|
||||
return t.byNum[num]
|
||||
}
|
||||
|
||||
func decodeVarint(data string, index int) (int, int) {
|
||||
// Fast-path for common case of a single byte, value 0..127.
|
||||
b := data[index]
|
||||
index++
|
||||
if b < 0x80 {
|
||||
return int(b), index
|
||||
}
|
||||
value := int(b & 0x7F)
|
||||
for shift := uint(7); ; shift += 7 {
|
||||
// Just panic if we go of the end of data, since all Labels strings are constructed internally and
|
||||
// malformed data indicates a bug, or memory corruption.
|
||||
b := data[index]
|
||||
index++
|
||||
value |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return value, index
|
||||
}
|
||||
|
||||
func decodeString(t *nameTable, data string, index int) (string, int) {
|
||||
var num int
|
||||
num, index = decodeVarint(data, index)
|
||||
return t.ToName(num), index
|
||||
}
|
||||
|
||||
// Bytes returns ls as a byte slice.
|
||||
// It uses non-printing characters and so should not be used for printing.
|
||||
func (ls Labels) Bytes(buf []byte) []byte {
|
||||
b := bytes.NewBuffer(buf[:0])
|
||||
for i := 0; i < len(ls.data); {
|
||||
if i > 0 {
|
||||
b.WriteByte(seps[0])
|
||||
}
|
||||
var name, value string
|
||||
name, i = decodeString(ls.syms, ls.data, i)
|
||||
value, i = decodeString(ls.syms, ls.data, i)
|
||||
b.WriteString(name)
|
||||
b.WriteByte(seps[0])
|
||||
b.WriteString(value)
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// IsZero implements yaml.IsZeroer - if we don't have this then 'omitempty' fields are always omitted.
|
||||
func (ls Labels) IsZero() bool {
|
||||
return len(ls.data) == 0
|
||||
}
|
||||
|
||||
// MatchLabels returns a subset of Labels that matches/does not match with the provided label names based on the 'on' boolean.
|
||||
// If on is set to true, it returns the subset of labels that match with the provided label names and its inverse when 'on' is set to false.
|
||||
// TODO: This is only used in printing an error message
|
||||
func (ls Labels) MatchLabels(on bool, names ...string) Labels {
|
||||
b := NewBuilder(ls)
|
||||
if on {
|
||||
b.Keep(names...)
|
||||
} else {
|
||||
b.Del(MetricName)
|
||||
b.Del(names...)
|
||||
}
|
||||
return b.Labels()
|
||||
}
|
||||
|
||||
// Hash returns a hash value for the label set.
|
||||
// Note: the result is not guaranteed to be consistent across different runs of Prometheus.
|
||||
func (ls Labels) Hash() uint64 {
|
||||
// Use xxhash.Sum64(b) for fast path as it's faster.
|
||||
b := make([]byte, 0, 1024)
|
||||
for pos := 0; pos < len(ls.data); {
|
||||
name, newPos := decodeString(ls.syms, ls.data, pos)
|
||||
value, newPos := decodeString(ls.syms, ls.data, newPos)
|
||||
if len(b)+len(name)+len(value)+2 >= cap(b) {
|
||||
// If labels entry is 1KB+, hash the rest of them via Write().
|
||||
h := xxhash.New()
|
||||
_, _ = h.Write(b)
|
||||
for pos < len(ls.data) {
|
||||
name, pos = decodeString(ls.syms, ls.data, pos)
|
||||
value, pos = decodeString(ls.syms, ls.data, pos)
|
||||
_, _ = h.WriteString(name)
|
||||
_, _ = h.Write(seps)
|
||||
_, _ = h.WriteString(value)
|
||||
_, _ = h.Write(seps)
|
||||
}
|
||||
return h.Sum64()
|
||||
}
|
||||
|
||||
b = append(b, name...)
|
||||
b = append(b, seps[0])
|
||||
b = append(b, value...)
|
||||
b = append(b, seps[0])
|
||||
pos = newPos
|
||||
}
|
||||
return xxhash.Sum64(b)
|
||||
}
|
||||
|
||||
// HashForLabels returns a hash value for the labels matching the provided names.
|
||||
// 'names' have to be sorted in ascending order.
|
||||
func (ls Labels) HashForLabels(b []byte, names ...string) (uint64, []byte) {
|
||||
b = b[:0]
|
||||
j := 0
|
||||
for i := 0; i < len(ls.data); {
|
||||
var name, value string
|
||||
name, i = decodeString(ls.syms, ls.data, i)
|
||||
value, i = decodeString(ls.syms, ls.data, i)
|
||||
for j < len(names) && names[j] < name {
|
||||
j++
|
||||
}
|
||||
if j == len(names) {
|
||||
break
|
||||
}
|
||||
if name == names[j] {
|
||||
b = append(b, name...)
|
||||
b = append(b, seps[0])
|
||||
b = append(b, value...)
|
||||
b = append(b, seps[0])
|
||||
}
|
||||
}
|
||||
|
||||
return xxhash.Sum64(b), b
|
||||
}
|
||||
|
||||
// HashWithoutLabels returns a hash value for all labels except those matching
|
||||
// the provided names.
|
||||
// 'names' have to be sorted in ascending order.
|
||||
func (ls Labels) HashWithoutLabels(b []byte, names ...string) (uint64, []byte) {
|
||||
b = b[:0]
|
||||
j := 0
|
||||
for i := 0; i < len(ls.data); {
|
||||
var name, value string
|
||||
name, i = decodeString(ls.syms, ls.data, i)
|
||||
value, i = decodeString(ls.syms, ls.data, i)
|
||||
for j < len(names) && names[j] < name {
|
||||
j++
|
||||
}
|
||||
if name == MetricName || (j < len(names) && name == names[j]) {
|
||||
continue
|
||||
}
|
||||
b = append(b, name...)
|
||||
b = append(b, seps[0])
|
||||
b = append(b, value...)
|
||||
b = append(b, seps[0])
|
||||
}
|
||||
return xxhash.Sum64(b), b
|
||||
}
|
||||
|
||||
// BytesWithLabels is just as Bytes(), but only for labels matching names.
|
||||
// 'names' have to be sorted in ascending order.
|
||||
func (ls Labels) BytesWithLabels(buf []byte, names ...string) []byte {
|
||||
b := bytes.NewBuffer(buf[:0])
|
||||
j := 0
|
||||
for pos := 0; pos < len(ls.data); {
|
||||
lName, newPos := decodeString(ls.syms, ls.data, pos)
|
||||
lValue, newPos := decodeString(ls.syms, ls.data, newPos)
|
||||
for j < len(names) && names[j] < lName {
|
||||
j++
|
||||
}
|
||||
if j == len(names) {
|
||||
break
|
||||
}
|
||||
if lName == names[j] {
|
||||
if b.Len() > 1 {
|
||||
b.WriteByte(seps[0])
|
||||
}
|
||||
b.WriteString(lName)
|
||||
b.WriteByte(seps[0])
|
||||
b.WriteString(lValue)
|
||||
}
|
||||
pos = newPos
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// BytesWithoutLabels is just as Bytes(), but only for labels not matching names.
|
||||
// 'names' have to be sorted in ascending order.
|
||||
func (ls Labels) BytesWithoutLabels(buf []byte, names ...string) []byte {
|
||||
b := bytes.NewBuffer(buf[:0])
|
||||
j := 0
|
||||
for pos := 0; pos < len(ls.data); {
|
||||
lName, newPos := decodeString(ls.syms, ls.data, pos)
|
||||
lValue, newPos := decodeString(ls.syms, ls.data, newPos)
|
||||
for j < len(names) && names[j] < lName {
|
||||
j++
|
||||
}
|
||||
if j == len(names) || lName != names[j] {
|
||||
if b.Len() > 1 {
|
||||
b.WriteByte(seps[0])
|
||||
}
|
||||
b.WriteString(lName)
|
||||
b.WriteByte(seps[0])
|
||||
b.WriteString(lValue)
|
||||
}
|
||||
pos = newPos
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// Copy returns a copy of the labels.
|
||||
func (ls Labels) Copy() Labels {
|
||||
return Labels{syms: ls.syms, data: strings.Clone(ls.data)}
|
||||
}
|
||||
|
||||
// Get returns the value for the label with the given name.
|
||||
// Returns an empty string if the label doesn't exist.
|
||||
func (ls Labels) Get(name string) string {
|
||||
if name == "" { // Avoid crash in loop if someone asks for "".
|
||||
return "" // Prometheus does not store blank label names.
|
||||
}
|
||||
for i := 0; i < len(ls.data); {
|
||||
var lName, lValue string
|
||||
lName, i = decodeString(ls.syms, ls.data, i)
|
||||
if lName == name {
|
||||
lValue, _ = decodeString(ls.syms, ls.data, i)
|
||||
return lValue
|
||||
} else if lName[0] > name[0] { // Stop looking if we've gone past.
|
||||
break
|
||||
}
|
||||
_, i = decodeVarint(ls.data, i)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Has returns true if the label with the given name is present.
|
||||
func (ls Labels) Has(name string) bool {
|
||||
if name == "" { // Avoid crash in loop if someone asks for "".
|
||||
return false // Prometheus does not store blank label names.
|
||||
}
|
||||
for i := 0; i < len(ls.data); {
|
||||
var lName string
|
||||
lName, i = decodeString(ls.syms, ls.data, i)
|
||||
if lName == name {
|
||||
return true
|
||||
} else if lName[0] > name[0] { // Stop looking if we've gone past.
|
||||
break
|
||||
}
|
||||
_, i = decodeVarint(ls.data, i)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasDuplicateLabelNames returns whether ls has duplicate label names.
|
||||
// It assumes that the labelset is sorted.
|
||||
func (ls Labels) HasDuplicateLabelNames() (string, bool) {
|
||||
prevNum := -1
|
||||
for i := 0; i < len(ls.data); {
|
||||
var lNum int
|
||||
lNum, i = decodeVarint(ls.data, i)
|
||||
_, i = decodeVarint(ls.data, i)
|
||||
if lNum == prevNum {
|
||||
return ls.syms.ToName(lNum), true
|
||||
}
|
||||
prevNum = lNum
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// WithoutEmpty returns the labelset without empty labels.
|
||||
// May return the same labelset.
|
||||
func (ls Labels) WithoutEmpty() Labels {
|
||||
if ls.IsEmpty() {
|
||||
return ls
|
||||
}
|
||||
// Idea: have a constant symbol for blank, then we don't have to look it up.
|
||||
blank, ok := ls.syms.symbolTable.checkNum("")
|
||||
if !ok { // Symbol table has no entry for blank - none of the values can be blank.
|
||||
return ls
|
||||
}
|
||||
for pos := 0; pos < len(ls.data); {
|
||||
_, newPos := decodeVarint(ls.data, pos)
|
||||
lValue, newPos := decodeVarint(ls.data, newPos)
|
||||
if lValue != blank {
|
||||
pos = newPos
|
||||
continue
|
||||
}
|
||||
// Do not copy the slice until it's necessary.
|
||||
// TODO: could optimise the case where all blanks are at the end.
|
||||
// Note: we size the new buffer on the assumption there is exactly one blank value.
|
||||
buf := make([]byte, pos, pos+(len(ls.data)-newPos))
|
||||
copy(buf, ls.data[:pos]) // copy the initial non-blank labels
|
||||
pos = newPos // move past the first blank value
|
||||
for pos < len(ls.data) {
|
||||
var newPos int
|
||||
_, newPos = decodeVarint(ls.data, pos)
|
||||
lValue, newPos = decodeVarint(ls.data, newPos)
|
||||
if lValue != blank {
|
||||
buf = append(buf, ls.data[pos:newPos]...)
|
||||
}
|
||||
pos = newPos
|
||||
}
|
||||
return Labels{syms: ls.syms, data: yoloString(buf)}
|
||||
}
|
||||
return ls
|
||||
}
|
||||
|
||||
// Equal returns whether the two label sets are equal.
|
||||
func Equal(a, b Labels) bool {
|
||||
if a.syms == b.syms {
|
||||
return a.data == b.data
|
||||
}
|
||||
|
||||
la, lb := len(a.data), len(b.data)
|
||||
ia, ib := 0, 0
|
||||
for ia < la && ib < lb {
|
||||
var aValue, bValue string
|
||||
aValue, ia = decodeString(a.syms, a.data, ia)
|
||||
bValue, ib = decodeString(b.syms, b.data, ib)
|
||||
if aValue != bValue {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if ia != la || ib != lb {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// EmptyLabels returns an empty Labels value, for convenience.
|
||||
func EmptyLabels() Labels {
|
||||
return Labels{}
|
||||
}
|
||||
|
||||
func yoloString(b []byte) string {
|
||||
return *((*string)(unsafe.Pointer(&b)))
|
||||
}
|
||||
|
||||
// New returns a sorted Labels from the given labels.
|
||||
// The caller has to guarantee that all label names are unique.
|
||||
// Note this function is not efficient; should not be used in performance-critical places.
|
||||
func New(ls ...Label) Labels {
|
||||
slices.SortFunc(ls, func(a, b Label) int { return strings.Compare(a.Name, b.Name) })
|
||||
syms := NewSymbolTable()
|
||||
var stackSpace [16]int
|
||||
size, nums := mapLabelsToNumbers(syms, ls, stackSpace[:])
|
||||
buf := make([]byte, size)
|
||||
marshalNumbersToSizedBuffer(nums, buf)
|
||||
return Labels{syms: syms.nameTable, data: yoloString(buf)}
|
||||
}
|
||||
|
||||
// FromStrings creates new labels from pairs of strings.
|
||||
func FromStrings(ss ...string) Labels {
|
||||
if len(ss)%2 != 0 {
|
||||
panic("invalid number of strings")
|
||||
}
|
||||
ls := make([]Label, 0, len(ss)/2)
|
||||
for i := 0; i < len(ss); i += 2 {
|
||||
ls = append(ls, Label{Name: ss[i], Value: ss[i+1]})
|
||||
}
|
||||
|
||||
return New(ls...)
|
||||
}
|
||||
|
||||
// Compare compares the two label sets.
|
||||
// The result will be 0 if a==b, <0 if a < b, and >0 if a > b.
|
||||
func Compare(a, b Labels) int {
|
||||
la, lb := len(a.data), len(b.data)
|
||||
ia, ib := 0, 0
|
||||
for ia < la && ib < lb {
|
||||
var aName, bName string
|
||||
aName, ia = decodeString(a.syms, a.data, ia)
|
||||
bName, ib = decodeString(b.syms, b.data, ib)
|
||||
if aName != bName {
|
||||
if aName < bName {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
var aValue, bValue string
|
||||
aValue, ia = decodeString(a.syms, a.data, ia)
|
||||
bValue, ib = decodeString(b.syms, b.data, ib)
|
||||
if aValue != bValue {
|
||||
if aValue < bValue {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
}
|
||||
// If all labels so far were in common, the set with fewer labels comes first.
|
||||
return (la - ia) - (lb - ib)
|
||||
}
|
||||
|
||||
// Copy labels from b on top of whatever was in ls previously, reusing memory or expanding if needed.
|
||||
func (ls *Labels) CopyFrom(b Labels) {
|
||||
*ls = b // Straightforward memberwise copy is all we need.
|
||||
}
|
||||
|
||||
// IsEmpty returns true if ls represents an empty set of labels.
|
||||
func (ls Labels) IsEmpty() bool {
|
||||
return len(ls.data) == 0
|
||||
}
|
||||
|
||||
// Len returns the number of labels; it is relatively slow.
|
||||
func (ls Labels) Len() int {
|
||||
count := 0
|
||||
for i := 0; i < len(ls.data); {
|
||||
_, i = decodeVarint(ls.data, i)
|
||||
_, i = decodeVarint(ls.data, i)
|
||||
count++
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Range calls f on each label.
|
||||
func (ls Labels) Range(f func(l Label)) {
|
||||
for i := 0; i < len(ls.data); {
|
||||
var lName, lValue string
|
||||
lName, i = decodeString(ls.syms, ls.data, i)
|
||||
lValue, i = decodeString(ls.syms, ls.data, i)
|
||||
f(Label{Name: lName, Value: lValue})
|
||||
}
|
||||
}
|
||||
|
||||
// Validate calls f on each label. If f returns a non-nil error, then it returns that error cancelling the iteration.
|
||||
func (ls Labels) Validate(f func(l Label) error) error {
|
||||
for i := 0; i < len(ls.data); {
|
||||
var lName, lValue string
|
||||
lName, i = decodeString(ls.syms, ls.data, i)
|
||||
lValue, i = decodeString(ls.syms, ls.data, i)
|
||||
err := f(Label{Name: lName, Value: lValue})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InternStrings calls intern on every string value inside ls, replacing them with what it returns.
|
||||
func (ls *Labels) InternStrings(intern func(string) string) {
|
||||
// TODO: remove these calls as there is nothing to do.
|
||||
}
|
||||
|
||||
// ReleaseStrings calls release on every string value inside ls.
|
||||
func (ls Labels) ReleaseStrings(release func(string)) {
|
||||
// TODO: remove these calls as there is nothing to do.
|
||||
}
|
||||
|
||||
// DropMetricName returns Labels with "__name__" removed.
|
||||
func (ls Labels) DropMetricName() Labels {
|
||||
for i := 0; i < len(ls.data); {
|
||||
lName, i2 := decodeString(ls.syms, ls.data, i)
|
||||
_, i2 = decodeVarint(ls.data, i2)
|
||||
if lName == MetricName {
|
||||
if i == 0 { // Make common case fast with no allocations.
|
||||
ls.data = ls.data[i2:]
|
||||
} else {
|
||||
ls.data = ls.data[:i] + ls.data[i2:]
|
||||
}
|
||||
break
|
||||
} else if lName[0] > MetricName[0] { // Stop looking if we've gone past.
|
||||
break
|
||||
}
|
||||
i = i2
|
||||
}
|
||||
return ls
|
||||
}
|
||||
|
||||
// Builder allows modifying Labels.
|
||||
type Builder struct {
|
||||
syms *SymbolTable
|
||||
nums []int
|
||||
base Labels
|
||||
del []string
|
||||
add []Label
|
||||
}
|
||||
|
||||
// NewBuilderWithSymbolTable returns a new LabelsBuilder not based on any labels, but with the SymbolTable.
|
||||
func NewBuilderWithSymbolTable(s *SymbolTable) *Builder {
|
||||
return &Builder{
|
||||
syms: s,
|
||||
}
|
||||
}
|
||||
|
||||
// Reset clears all current state for the builder.
|
||||
func (b *Builder) Reset(base Labels) {
|
||||
if base.syms != nil { // If base has a symbol table, use that.
|
||||
b.syms = base.syms.symbolTable
|
||||
} else if b.syms == nil { // Or continue using previous symbol table in builder.
|
||||
b.syms = NewSymbolTable() // Don't do this in performance-sensitive code.
|
||||
}
|
||||
|
||||
b.base = base
|
||||
b.del = b.del[:0]
|
||||
b.add = b.add[:0]
|
||||
base.Range(func(l Label) {
|
||||
if l.Value == "" {
|
||||
b.del = append(b.del, l.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Labels returns the labels from the builder.
|
||||
// If no modifications were made, the original labels are returned.
|
||||
func (b *Builder) Labels() Labels {
|
||||
if len(b.del) == 0 && len(b.add) == 0 {
|
||||
return b.base
|
||||
}
|
||||
|
||||
slices.SortFunc(b.add, func(a, b Label) int { return strings.Compare(a.Name, b.Name) })
|
||||
slices.Sort(b.del)
|
||||
a, d, newSize := 0, 0, 0
|
||||
|
||||
newSize, b.nums = mapLabelsToNumbers(b.syms, b.add, b.nums)
|
||||
bufSize := len(b.base.data) + newSize
|
||||
buf := make([]byte, 0, bufSize)
|
||||
for pos := 0; pos < len(b.base.data); {
|
||||
oldPos := pos
|
||||
var lName string
|
||||
lName, pos = decodeString(b.base.syms, b.base.data, pos)
|
||||
_, pos = decodeVarint(b.base.data, pos)
|
||||
for d < len(b.del) && b.del[d] < lName {
|
||||
d++
|
||||
}
|
||||
if d < len(b.del) && b.del[d] == lName {
|
||||
continue // This label has been deleted.
|
||||
}
|
||||
for ; a < len(b.add) && b.add[a].Name < lName; a++ {
|
||||
buf = appendLabelTo(b.nums[a*2], b.nums[a*2+1], buf) // Insert label that was not in the base set.
|
||||
}
|
||||
if a < len(b.add) && b.add[a].Name == lName {
|
||||
buf = appendLabelTo(b.nums[a*2], b.nums[a*2+1], buf)
|
||||
a++
|
||||
continue // This label has been replaced.
|
||||
}
|
||||
buf = append(buf, b.base.data[oldPos:pos]...) // If base had a symbol-table we are using it, so we don't need to look up these symbols.
|
||||
}
|
||||
// We have come to the end of the base set; add any remaining labels.
|
||||
for ; a < len(b.add); a++ {
|
||||
buf = appendLabelTo(b.nums[a*2], b.nums[a*2+1], buf)
|
||||
}
|
||||
return Labels{syms: b.syms.nameTable, data: yoloString(buf)}
|
||||
}
|
||||
|
||||
func marshalNumbersToSizedBuffer(nums []int, data []byte) int {
|
||||
i := len(data)
|
||||
for index := len(nums) - 1; index >= 0; index-- {
|
||||
i = encodeVarint(data, i, nums[index])
|
||||
}
|
||||
return len(data) - i
|
||||
}
|
||||
|
||||
func sizeVarint(x uint64) (n int) {
|
||||
// Most common case first
|
||||
if x < 1<<7 {
|
||||
return 1
|
||||
}
|
||||
if x >= 1<<56 {
|
||||
return 9
|
||||
}
|
||||
if x >= 1<<28 {
|
||||
x >>= 28
|
||||
n = 4
|
||||
}
|
||||
if x >= 1<<14 {
|
||||
x >>= 14
|
||||
n += 2
|
||||
}
|
||||
if x >= 1<<7 {
|
||||
n++
|
||||
}
|
||||
return n + 1
|
||||
}
|
||||
|
||||
func encodeVarintSlow(data []byte, offset int, v uint64) int {
|
||||
offset -= sizeVarint(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
data[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
data[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
|
||||
// Special code for the common case that a value is less than 128
|
||||
func encodeVarint(data []byte, offset, v int) int {
|
||||
if v < 1<<7 {
|
||||
offset--
|
||||
data[offset] = uint8(v)
|
||||
return offset
|
||||
}
|
||||
return encodeVarintSlow(data, offset, uint64(v))
|
||||
}
|
||||
|
||||
// Map all the strings in lbls to the symbol table; return the total size required to hold them and all the individual mappings.
|
||||
func mapLabelsToNumbers(t *SymbolTable, lbls []Label, buf []int) (totalSize int, nums []int) {
|
||||
nums = buf[:0]
|
||||
t.mx.Lock()
|
||||
defer t.mx.Unlock()
|
||||
// we just encode name/value/name/value, without any extra tags or length bytes
|
||||
for _, m := range lbls {
|
||||
// strings are encoded as a single varint, the index into the symbol table.
|
||||
i := t.toNumUnlocked(m.Name)
|
||||
nums = append(nums, i)
|
||||
totalSize += sizeVarint(uint64(i))
|
||||
i = t.toNumUnlocked(m.Value)
|
||||
nums = append(nums, i)
|
||||
totalSize += sizeVarint(uint64(i))
|
||||
}
|
||||
return totalSize, nums
|
||||
}
|
||||
|
||||
func appendLabelTo(nameNum, valueNum int, buf []byte) []byte {
|
||||
size := sizeVarint(uint64(nameNum)) + sizeVarint(uint64(valueNum))
|
||||
sizeRequired := len(buf) + size
|
||||
if cap(buf) >= sizeRequired {
|
||||
buf = buf[:sizeRequired]
|
||||
} else {
|
||||
bufSize := cap(buf)
|
||||
// Double size of buffer each time it needs to grow, to amortise copying cost.
|
||||
for bufSize < sizeRequired {
|
||||
bufSize = bufSize*2 + 1
|
||||
}
|
||||
newBuf := make([]byte, sizeRequired, bufSize)
|
||||
copy(newBuf, buf)
|
||||
buf = newBuf
|
||||
}
|
||||
i := sizeRequired
|
||||
i = encodeVarint(buf, i, valueNum)
|
||||
i = encodeVarint(buf, i, nameNum)
|
||||
return buf
|
||||
}
|
||||
|
||||
// ScratchBuilder allows efficient construction of a Labels from scratch.
|
||||
type ScratchBuilder struct {
|
||||
syms *SymbolTable
|
||||
nums []int
|
||||
add []Label
|
||||
output Labels
|
||||
overwriteBuffer []byte
|
||||
}
|
||||
|
||||
// NewScratchBuilder creates a ScratchBuilder initialized for Labels with n entries.
|
||||
// Warning: expensive; don't call in tight loops.
|
||||
func NewScratchBuilder(n int) ScratchBuilder {
|
||||
return ScratchBuilder{syms: NewSymbolTable(), add: make([]Label, 0, n)}
|
||||
}
|
||||
|
||||
// NewScratchBuilderWithSymbolTable creates a ScratchBuilder initialized for Labels with n entries.
|
||||
func NewScratchBuilderWithSymbolTable(s *SymbolTable, n int) ScratchBuilder {
|
||||
return ScratchBuilder{syms: s, add: make([]Label, 0, n)}
|
||||
}
|
||||
|
||||
func (b *ScratchBuilder) SetSymbolTable(s *SymbolTable) {
|
||||
b.syms = s
|
||||
}
|
||||
|
||||
func (b *ScratchBuilder) Reset() {
|
||||
b.add = b.add[:0]
|
||||
b.output = EmptyLabels()
|
||||
}
|
||||
|
||||
// Add a name/value pair.
|
||||
// Note if you Add the same name twice you will get a duplicate label, which is invalid.
|
||||
func (b *ScratchBuilder) Add(name, value string) {
|
||||
b.add = append(b.add, Label{Name: name, Value: value})
|
||||
}
|
||||
|
||||
// Add a name/value pair, using []byte instead of string to reduce memory allocations.
|
||||
// The values must remain live until Labels() is called.
|
||||
func (b *ScratchBuilder) UnsafeAddBytes(name, value []byte) {
|
||||
b.add = append(b.add, Label{Name: yoloString(name), Value: yoloString(value)})
|
||||
}
|
||||
|
||||
// Sort the labels added so far by name.
|
||||
func (b *ScratchBuilder) Sort() {
|
||||
slices.SortFunc(b.add, func(a, b Label) int { return strings.Compare(a.Name, b.Name) })
|
||||
}
|
||||
|
||||
// Assign is for when you already have a Labels which you want this ScratchBuilder to return.
|
||||
func (b *ScratchBuilder) Assign(l Labels) {
|
||||
b.output = l
|
||||
}
|
||||
|
||||
// Labels returns the name/value pairs added as a Labels object. Calling Add() after Labels() has no effect.
|
||||
// Note: if you want them sorted, call Sort() first.
|
||||
func (b *ScratchBuilder) Labels() Labels {
|
||||
if b.output.IsEmpty() {
|
||||
var size int
|
||||
size, b.nums = mapLabelsToNumbers(b.syms, b.add, b.nums)
|
||||
buf := make([]byte, size)
|
||||
marshalNumbersToSizedBuffer(b.nums, buf)
|
||||
b.output = Labels{syms: b.syms.nameTable, data: yoloString(buf)}
|
||||
}
|
||||
return b.output
|
||||
}
|
||||
|
||||
// Write the newly-built Labels out to ls, reusing an internal buffer.
|
||||
// Callers must ensure that there are no other references to ls, or any strings fetched from it.
|
||||
func (b *ScratchBuilder) Overwrite(ls *Labels) {
|
||||
var size int
|
||||
size, b.nums = mapLabelsToNumbers(b.syms, b.add, b.nums)
|
||||
if size <= cap(b.overwriteBuffer) {
|
||||
b.overwriteBuffer = b.overwriteBuffer[:size]
|
||||
} else {
|
||||
b.overwriteBuffer = make([]byte, size)
|
||||
}
|
||||
marshalNumbersToSizedBuffer(b.nums, b.overwriteBuffer)
|
||||
ls.syms = b.syms.nameTable
|
||||
ls.data = yoloString(b.overwriteBuffer)
|
||||
}
|
|
@ -17,11 +17,11 @@ package labels
|
|||
|
||||
import (
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cespare/xxhash/v2"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// Labels is implemented by a single flat string holding name/value pairs.
|
||||
|
@ -188,8 +188,7 @@ func (ls Labels) BytesWithoutLabels(buf []byte, names ...string) []byte {
|
|||
|
||||
// Copy returns a copy of the labels.
|
||||
func (ls Labels) Copy() Labels {
|
||||
buf := append([]byte{}, ls.data...)
|
||||
return Labels{data: yoloString(buf)}
|
||||
return Labels{data: strings.Clone(ls.data)}
|
||||
}
|
||||
|
||||
// Get returns the value for the label with the given name.
|
||||
|
@ -364,13 +363,11 @@ func Compare(a, b Labels) int {
|
|||
|
||||
// Now we know that there is some difference before the end of a and b.
|
||||
// Go back through the fields and find which field that difference is in.
|
||||
firstCharDifferent := i
|
||||
for i = 0; ; {
|
||||
size, nextI := decodeSize(a.data, i)
|
||||
if nextI+size > firstCharDifferent {
|
||||
break
|
||||
}
|
||||
firstCharDifferent, i := i, 0
|
||||
size, nextI := decodeSize(a.data, i)
|
||||
for nextI+size <= firstCharDifferent {
|
||||
i = nextI + size
|
||||
size, nextI = decodeSize(a.data, i)
|
||||
}
|
||||
// Difference is inside this entry.
|
||||
aStr, _ := decodeString(a.data, i)
|
||||
|
@ -429,14 +426,52 @@ func (ls Labels) Validate(f func(l Label) error) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// InternStrings calls intern on every string value inside ls, replacing them with what it returns.
|
||||
func (ls *Labels) InternStrings(intern func(string) string) {
|
||||
ls.data = intern(ls.data)
|
||||
// DropMetricName returns Labels with "__name__" removed.
|
||||
func (ls Labels) DropMetricName() Labels {
|
||||
for i := 0; i < len(ls.data); {
|
||||
lName, i2 := decodeString(ls.data, i)
|
||||
size, i2 := decodeSize(ls.data, i2)
|
||||
i2 += size
|
||||
if lName == MetricName {
|
||||
if i == 0 { // Make common case fast with no allocations.
|
||||
ls.data = ls.data[i2:]
|
||||
} else {
|
||||
ls.data = ls.data[:i] + ls.data[i2:]
|
||||
}
|
||||
break
|
||||
} else if lName[0] > MetricName[0] { // Stop looking if we've gone past.
|
||||
break
|
||||
}
|
||||
i = i2
|
||||
}
|
||||
return ls
|
||||
}
|
||||
|
||||
// ReleaseStrings calls release on every string value inside ls.
|
||||
// InternStrings is a no-op because it would only save when the whole set of labels is identical.
|
||||
func (ls *Labels) InternStrings(intern func(string) string) {
|
||||
}
|
||||
|
||||
// ReleaseStrings is a no-op for the same reason as InternStrings.
|
||||
func (ls Labels) ReleaseStrings(release func(string)) {
|
||||
release(ls.data)
|
||||
}
|
||||
|
||||
// Builder allows modifying Labels.
|
||||
type Builder struct {
|
||||
base Labels
|
||||
del []string
|
||||
add []Label
|
||||
}
|
||||
|
||||
// Reset clears all current state for the builder.
|
||||
func (b *Builder) Reset(base Labels) {
|
||||
b.base = base
|
||||
b.del = b.del[:0]
|
||||
b.add = b.add[:0]
|
||||
b.base.Range(func(l Label) {
|
||||
if l.Value == "" {
|
||||
b.del = append(b.del, l.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Labels returns the labels from the builder.
|
||||
|
@ -643,3 +678,24 @@ func (b *ScratchBuilder) Overwrite(ls *Labels) {
|
|||
marshalLabelsToSizedBuffer(b.add, b.overwriteBuffer)
|
||||
ls.data = yoloString(b.overwriteBuffer)
|
||||
}
|
||||
|
||||
// Symbol-table is no-op, just for api parity with dedupelabels.
|
||||
type SymbolTable struct{}
|
||||
|
||||
func NewSymbolTable() *SymbolTable { return nil }
|
||||
|
||||
func (t *SymbolTable) Len() int { return 0 }
|
||||
|
||||
// NewBuilderWithSymbolTable creates a Builder, for api parity with dedupelabels.
|
||||
func NewBuilderWithSymbolTable(_ *SymbolTable) *Builder {
|
||||
return NewBuilder(EmptyLabels())
|
||||
}
|
||||
|
||||
// NewScratchBuilderWithSymbolTable creates a ScratchBuilder, for api parity with dedupelabels.
|
||||
func NewScratchBuilderWithSymbolTable(_ *SymbolTable, n int) ScratchBuilder {
|
||||
return NewScratchBuilder(n)
|
||||
}
|
||||
|
||||
func (b *ScratchBuilder) SetSymbolTable(_ *SymbolTable) {
|
||||
// no-op
|
||||
}
|
||||
|
|
|
@ -43,6 +43,13 @@ func TestLabels_String(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func BenchmarkString(b *testing.B) {
|
||||
ls := New(benchmarkLabels...)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = ls.String()
|
||||
}
|
||||
}
|
||||
|
||||
func TestLabels_MatchLabels(t *testing.T) {
|
||||
labels := FromStrings(
|
||||
"__name__", "ALERTS",
|
||||
|
@ -114,7 +121,7 @@ func TestLabels_MatchLabels(t *testing.T) {
|
|||
|
||||
for i, test := range tests {
|
||||
got := labels.MatchLabels(test.on, test.providedNames...)
|
||||
require.Equal(t, test.expected, got, "unexpected labelset for test case %d", i)
|
||||
require.True(t, Equal(test.expected, got), "unexpected labelset for test case %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,7 +214,7 @@ func TestLabels_WithoutEmpty(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run("", func(t *testing.T) {
|
||||
require.Equal(t, test.expected, test.input.WithoutEmpty())
|
||||
require.True(t, Equal(test.expected, test.input.WithoutEmpty()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -447,6 +454,12 @@ func TestLabels_Get(t *testing.T) {
|
|||
require.Equal(t, "222", FromStrings("aaaa", "111", "bbb", "222").Get("bbb"))
|
||||
}
|
||||
|
||||
func TestLabels_DropMetricName(t *testing.T) {
|
||||
require.True(t, Equal(FromStrings("aaa", "111", "bbb", "222"), FromStrings("aaa", "111", "bbb", "222").DropMetricName()))
|
||||
require.True(t, Equal(FromStrings("aaa", "111"), FromStrings(MetricName, "myname", "aaa", "111").DropMetricName()))
|
||||
require.True(t, Equal(FromStrings("__aaa__", "111", "bbb", "222"), FromStrings("__aaa__", "111", MetricName, "myname", "bbb", "222").DropMetricName()))
|
||||
}
|
||||
|
||||
// BenchmarkLabels_Get was written to check whether a binary search can improve the performance vs the linear search implementation
|
||||
// The results have shown that binary search would only be better when searching last labels in scenarios with more than 10 labels.
|
||||
// In the following list, `old` is the linear search while `new` is the binary search implementation (without calling sort.Search, which performs even worse here)
|
||||
|
@ -519,6 +532,16 @@ var comparisonBenchmarkScenarios = []struct {
|
|||
FromStrings("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo", "ppp", "qqq", "rrz"),
|
||||
FromStrings("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo", "ppp", "qqq", "rrr"),
|
||||
},
|
||||
{
|
||||
"real long equal",
|
||||
FromStrings("__name__", "kube_pod_container_status_last_terminated_exitcode", "cluster", "prod-af-north-0", " container", "prometheus", "instance", "kube-state-metrics-0:kube-state-metrics:ksm", "job", "kube-state-metrics/kube-state-metrics", " namespace", "observability-prometheus", "pod", "observability-prometheus-0", "uid", "d3ec90b2-4975-4607-b45d-b9ad64bb417e"),
|
||||
FromStrings("__name__", "kube_pod_container_status_last_terminated_exitcode", "cluster", "prod-af-north-0", " container", "prometheus", "instance", "kube-state-metrics-0:kube-state-metrics:ksm", "job", "kube-state-metrics/kube-state-metrics", " namespace", "observability-prometheus", "pod", "observability-prometheus-0", "uid", "d3ec90b2-4975-4607-b45d-b9ad64bb417e"),
|
||||
},
|
||||
{
|
||||
"real long different end",
|
||||
FromStrings("__name__", "kube_pod_container_status_last_terminated_exitcode", "cluster", "prod-af-north-0", " container", "prometheus", "instance", "kube-state-metrics-0:kube-state-metrics:ksm", "job", "kube-state-metrics/kube-state-metrics", " namespace", "observability-prometheus", "pod", "observability-prometheus-0", "uid", "d3ec90b2-4975-4607-b45d-b9ad64bb417e"),
|
||||
FromStrings("__name__", "kube_pod_container_status_last_terminated_exitcode", "cluster", "prod-af-north-0", " container", "prometheus", "instance", "kube-state-metrics-0:kube-state-metrics:ksm", "job", "kube-state-metrics/kube-state-metrics", " namespace", "observability-prometheus", "pod", "observability-prometheus-0", "uid", "deadbeef-0000-1111-2222-b9ad64bb417e"),
|
||||
},
|
||||
}
|
||||
|
||||
func BenchmarkLabels_Equals(b *testing.B) {
|
||||
|
@ -563,6 +586,7 @@ func TestLabels_BytesWithoutLabels(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBuilder(t *testing.T) {
|
||||
reuseBuilder := NewBuilderWithSymbolTable(NewSymbolTable())
|
||||
for i, tcase := range []struct {
|
||||
base Labels
|
||||
del []string
|
||||
|
@ -574,6 +598,11 @@ func TestBuilder(t *testing.T) {
|
|||
base: FromStrings("aaa", "111"),
|
||||
want: FromStrings("aaa", "111"),
|
||||
},
|
||||
{
|
||||
base: EmptyLabels(),
|
||||
set: []Label{{"aaa", "444"}, {"bbb", "555"}, {"ccc", "666"}},
|
||||
want: FromStrings("aaa", "444", "bbb", "555", "ccc", "666"),
|
||||
},
|
||||
{
|
||||
base: FromStrings("aaa", "111", "bbb", "222", "ccc", "333"),
|
||||
set: []Label{{"aaa", "444"}, {"bbb", "555"}, {"ccc", "666"}},
|
||||
|
@ -632,8 +661,7 @@ func TestBuilder(t *testing.T) {
|
|||
want: FromStrings("aaa", "111", "ddd", "444"),
|
||||
},
|
||||
} {
|
||||
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
||||
b := NewBuilder(tcase.base)
|
||||
test := func(t *testing.T, b *Builder) {
|
||||
for _, lbl := range tcase.set {
|
||||
b.Set(lbl.Name, lbl.Value)
|
||||
}
|
||||
|
@ -641,7 +669,7 @@ func TestBuilder(t *testing.T) {
|
|||
b.Keep(tcase.keep...)
|
||||
}
|
||||
b.Del(tcase.del...)
|
||||
require.Equal(t, tcase.want, b.Labels())
|
||||
require.True(t, Equal(tcase.want, b.Labels()))
|
||||
|
||||
// Check what happens when we call Range and mutate the builder.
|
||||
b.Range(func(l Label) {
|
||||
|
@ -650,6 +678,18 @@ func TestBuilder(t *testing.T) {
|
|||
}
|
||||
})
|
||||
require.Equal(t, tcase.want.BytesWithoutLabels(nil, "aaa", "bbb"), b.Labels().Bytes(nil))
|
||||
}
|
||||
t.Run(fmt.Sprintf("NewBuilder %d", i), func(t *testing.T) {
|
||||
test(t, NewBuilder(tcase.base))
|
||||
})
|
||||
t.Run(fmt.Sprintf("NewSymbolTable %d", i), func(t *testing.T) {
|
||||
b := NewBuilderWithSymbolTable(NewSymbolTable())
|
||||
b.Reset(tcase.base)
|
||||
test(t, b)
|
||||
})
|
||||
t.Run(fmt.Sprintf("reuseBuilder %d", i), func(t *testing.T) {
|
||||
reuseBuilder.Reset(tcase.base)
|
||||
test(t, reuseBuilder)
|
||||
})
|
||||
}
|
||||
t.Run("set_after_del", func(t *testing.T) {
|
||||
|
@ -688,21 +728,22 @@ func TestScratchBuilder(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
||||
b := ScratchBuilder{}
|
||||
b := NewScratchBuilder(len(tcase.add))
|
||||
for _, lbl := range tcase.add {
|
||||
b.Add(lbl.Name, lbl.Value)
|
||||
}
|
||||
b.Sort()
|
||||
require.Equal(t, tcase.want, b.Labels())
|
||||
require.True(t, Equal(tcase.want, b.Labels()))
|
||||
b.Assign(tcase.want)
|
||||
require.Equal(t, tcase.want, b.Labels())
|
||||
require.True(t, Equal(tcase.want, b.Labels()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLabels_Hash(t *testing.T) {
|
||||
lbls := FromStrings("foo", "bar", "baz", "qux")
|
||||
require.Equal(t, lbls.Hash(), lbls.Hash())
|
||||
hash1, hash2 := lbls.Hash(), lbls.Hash()
|
||||
require.Equal(t, hash1, hash2)
|
||||
require.NotEqual(t, lbls.Hash(), FromStrings("foo", "bar").Hash(), "different labels match.")
|
||||
}
|
||||
|
||||
|
@ -761,24 +802,24 @@ func BenchmarkLabels_Hash(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func BenchmarkBuilder(b *testing.B) {
|
||||
m := []Label{
|
||||
{"job", "node"},
|
||||
{"instance", "123.123.1.211:9090"},
|
||||
{"path", "/api/v1/namespaces/<namespace>/deployments/<name>"},
|
||||
{"method", "GET"},
|
||||
{"namespace", "system"},
|
||||
{"status", "500"},
|
||||
{"prometheus", "prometheus-core-1"},
|
||||
{"datacenter", "eu-west-1"},
|
||||
{"pod_name", "abcdef-99999-defee"},
|
||||
}
|
||||
var benchmarkLabels = []Label{
|
||||
{"job", "node"},
|
||||
{"instance", "123.123.1.211:9090"},
|
||||
{"path", "/api/v1/namespaces/<namespace>/deployments/<name>"},
|
||||
{"method", "GET"},
|
||||
{"namespace", "system"},
|
||||
{"status", "500"},
|
||||
{"prometheus", "prometheus-core-1"},
|
||||
{"datacenter", "eu-west-1"},
|
||||
{"pod_name", "abcdef-99999-defee"},
|
||||
}
|
||||
|
||||
func BenchmarkBuilder(b *testing.B) {
|
||||
var l Labels
|
||||
builder := NewBuilder(EmptyLabels())
|
||||
for i := 0; i < b.N; i++ {
|
||||
builder.Reset(EmptyLabels())
|
||||
for _, l := range m {
|
||||
for _, l := range benchmarkLabels {
|
||||
builder.Set(l.Name, l.Value)
|
||||
}
|
||||
l = builder.Labels()
|
||||
|
@ -787,18 +828,7 @@ func BenchmarkBuilder(b *testing.B) {
|
|||
}
|
||||
|
||||
func BenchmarkLabels_Copy(b *testing.B) {
|
||||
m := map[string]string{
|
||||
"job": "node",
|
||||
"instance": "123.123.1.211:9090",
|
||||
"path": "/api/v1/namespaces/<namespace>/deployments/<name>",
|
||||
"method": "GET",
|
||||
"namespace": "system",
|
||||
"status": "500",
|
||||
"prometheus": "prometheus-core-1",
|
||||
"datacenter": "eu-west-1",
|
||||
"pod_name": "abcdef-99999-defee",
|
||||
}
|
||||
l := FromMap(m)
|
||||
l := New(benchmarkLabels...)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
l = l.Copy()
|
||||
|
|
47
model/labels/sharding.go
Normal file
47
model/labels/sharding.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2020 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !stringlabels && !dedupelabels
|
||||
|
||||
package labels
|
||||
|
||||
import (
|
||||
"github.com/cespare/xxhash/v2"
|
||||
)
|
||||
|
||||
// StableHash is a labels hashing implementation which is guaranteed to not change over time.
|
||||
// This function should be used whenever labels hashing backward compatibility must be guaranteed.
|
||||
func StableHash(ls Labels) uint64 {
|
||||
// Use xxhash.Sum64(b) for fast path as it's faster.
|
||||
b := make([]byte, 0, 1024)
|
||||
for i, v := range ls {
|
||||
if len(b)+len(v.Name)+len(v.Value)+2 >= cap(b) {
|
||||
// If labels entry is 1KB+ do not allocate whole entry.
|
||||
h := xxhash.New()
|
||||
_, _ = h.Write(b)
|
||||
for _, v := range ls[i:] {
|
||||
_, _ = h.WriteString(v.Name)
|
||||
_, _ = h.Write(seps)
|
||||
_, _ = h.WriteString(v.Value)
|
||||
_, _ = h.Write(seps)
|
||||
}
|
||||
return h.Sum64()
|
||||
}
|
||||
|
||||
b = append(b, v.Name...)
|
||||
b = append(b, seps[0])
|
||||
b = append(b, v.Value...)
|
||||
b = append(b, seps[0])
|
||||
}
|
||||
return xxhash.Sum64(b)
|
||||
}
|
52
model/labels/sharding_dedupelabels.go
Normal file
52
model/labels/sharding_dedupelabels.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2024 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build dedupelabels
|
||||
|
||||
package labels
|
||||
|
||||
import (
|
||||
"github.com/cespare/xxhash/v2"
|
||||
)
|
||||
|
||||
// StableHash is a labels hashing implementation which is guaranteed to not change over time.
|
||||
// This function should be used whenever labels hashing backward compatibility must be guaranteed.
|
||||
func StableHash(ls Labels) uint64 {
|
||||
// Use xxhash.Sum64(b) for fast path as it's faster.
|
||||
b := make([]byte, 0, 1024)
|
||||
for pos := 0; pos < len(ls.data); {
|
||||
name, newPos := decodeString(ls.syms, ls.data, pos)
|
||||
value, newPos := decodeString(ls.syms, ls.data, newPos)
|
||||
if len(b)+len(name)+len(value)+2 >= cap(b) {
|
||||
// If labels entry is 1KB+, hash the rest of them via Write().
|
||||
h := xxhash.New()
|
||||
_, _ = h.Write(b)
|
||||
for pos < len(ls.data) {
|
||||
name, pos = decodeString(ls.syms, ls.data, pos)
|
||||
value, pos = decodeString(ls.syms, ls.data, pos)
|
||||
_, _ = h.WriteString(name)
|
||||
_, _ = h.Write(seps)
|
||||
_, _ = h.WriteString(value)
|
||||
_, _ = h.Write(seps)
|
||||
}
|
||||
return h.Sum64()
|
||||
}
|
||||
|
||||
b = append(b, name...)
|
||||
b = append(b, seps[0])
|
||||
b = append(b, value...)
|
||||
b = append(b, seps[0])
|
||||
pos = newPos
|
||||
}
|
||||
return xxhash.Sum64(b)
|
||||
}
|
54
model/labels/sharding_stringlabels.go
Normal file
54
model/labels/sharding_stringlabels.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2020 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build stringlabels
|
||||
|
||||
package labels
|
||||
|
||||
import (
|
||||
"github.com/cespare/xxhash/v2"
|
||||
)
|
||||
|
||||
// StableHash is a labels hashing implementation which is guaranteed to not change over time.
|
||||
// This function should be used whenever labels hashing backward compatibility must be guaranteed.
|
||||
func StableHash(ls Labels) uint64 {
|
||||
// Use xxhash.Sum64(b) for fast path as it's faster.
|
||||
b := make([]byte, 0, 1024)
|
||||
var h *xxhash.Digest
|
||||
for i := 0; i < len(ls.data); {
|
||||
var v Label
|
||||
v.Name, i = decodeString(ls.data, i)
|
||||
v.Value, i = decodeString(ls.data, i)
|
||||
if h == nil && len(b)+len(v.Name)+len(v.Value)+2 >= cap(b) {
|
||||
// If labels entry is 1KB+, switch to Write API. Copy in the values up to this point.
|
||||
h = xxhash.New()
|
||||
_, _ = h.Write(b)
|
||||
}
|
||||
if h != nil {
|
||||
_, _ = h.WriteString(v.Name)
|
||||
_, _ = h.Write(seps)
|
||||
_, _ = h.WriteString(v.Value)
|
||||
_, _ = h.Write(seps)
|
||||
continue
|
||||
}
|
||||
|
||||
b = append(b, v.Name...)
|
||||
b = append(b, seps[0])
|
||||
b = append(b, v.Value...)
|
||||
b = append(b, seps[0])
|
||||
}
|
||||
if h != nil {
|
||||
return h.Sum64()
|
||||
}
|
||||
return xxhash.Sum64(b)
|
||||
}
|
32
model/labels/sharding_test.go
Normal file
32
model/labels/sharding_test.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2020 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package labels
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestStableHash tests that StableHash is stable.
|
||||
// The hashes this test asserts should not be changed.
|
||||
func TestStableHash(t *testing.T) {
|
||||
for expectedHash, lbls := range map[uint64]Labels{
|
||||
0xef46db3751d8e999: EmptyLabels(),
|
||||
0x347c8ee7a9e29708: FromStrings("hello", "world"),
|
||||
0xcbab40540f26097d: FromStrings(MetricName, "metric", "label", "value"),
|
||||
} {
|
||||
require.Equal(t, expectedHash, StableHash(lbls))
|
||||
}
|
||||
}
|
|
@ -50,7 +50,7 @@ func ReadLabels(fn string, n int) ([]Labels, error) {
|
|||
defer f.Close()
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
b := ScratchBuilder{}
|
||||
b := NewScratchBuilder(0)
|
||||
|
||||
var mets []Labels
|
||||
hashes := map[uint64]struct{}{}
|
||||
|
|
|
@ -17,7 +17,7 @@ import "github.com/prometheus/common/model"
|
|||
|
||||
// Metadata stores a series' metadata information.
|
||||
type Metadata struct {
|
||||
Type model.MetricType
|
||||
Unit string
|
||||
Help string
|
||||
Type model.MetricType `json:"type"`
|
||||
Unit string `json:"unit"`
|
||||
Help string `json:"help"`
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
"github.com/prometheus/prometheus/util/testutil"
|
||||
)
|
||||
|
||||
func TestRelabel(t *testing.T) {
|
||||
|
@ -591,7 +592,7 @@ func TestRelabel(t *testing.T) {
|
|||
res, keep := Process(test.input, test.relabel...)
|
||||
require.Equal(t, !test.drop, keep)
|
||||
if keep {
|
||||
require.Equal(t, test.output, res)
|
||||
testutil.RequireEqual(t, test.output, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,8 +71,8 @@ type Parser interface {
|
|||
// if the scrape protocol or metric type does not support created timestamps.
|
||||
CreatedTimestamp() *int64
|
||||
|
||||
// Next advances the parser to the next sample. It returns false if no
|
||||
// more samples were read or an error occurred.
|
||||
// Next advances the parser to the next sample.
|
||||
// It returns (EntryInvalid, io.EOF) if no samples were read.
|
||||
Next() (Entry, error)
|
||||
}
|
||||
|
||||
|
@ -80,22 +80,22 @@ type Parser interface {
|
|||
//
|
||||
// This function always returns a valid parser, but might additionally
|
||||
// return an error if the content type cannot be parsed.
|
||||
func New(b []byte, contentType string, parseClassicHistograms bool) (Parser, error) {
|
||||
func New(b []byte, contentType string, parseClassicHistograms bool, st *labels.SymbolTable) (Parser, error) {
|
||||
if contentType == "" {
|
||||
return NewPromParser(b), nil
|
||||
return NewPromParser(b, st), nil
|
||||
}
|
||||
|
||||
mediaType, _, err := mime.ParseMediaType(contentType)
|
||||
if err != nil {
|
||||
return NewPromParser(b), err
|
||||
return NewPromParser(b, st), err
|
||||
}
|
||||
switch mediaType {
|
||||
case "application/openmetrics-text":
|
||||
return NewOpenMetricsParser(b), nil
|
||||
return NewOpenMetricsParser(b, st), nil
|
||||
case "application/vnd.google.protobuf":
|
||||
return NewProtobufParser(b, parseClassicHistograms), nil
|
||||
return NewProtobufParser(b, parseClassicHistograms, st), nil
|
||||
default:
|
||||
return NewPromParser(b), nil
|
||||
return NewPromParser(b, st), nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
)
|
||||
|
||||
func TestNewParser(t *testing.T) {
|
||||
|
@ -91,7 +93,7 @@ func TestNewParser(t *testing.T) {
|
|||
tt := tt // Copy to local variable before going parallel.
|
||||
t.Parallel()
|
||||
|
||||
p, err := New([]byte{}, tt.contentType, false)
|
||||
p, err := New([]byte{}, tt.contentType, false, labels.NewSymbolTable())
|
||||
tt.validateParser(t, p)
|
||||
if tt.err == "" {
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -50,12 +50,15 @@ S [ ]
|
|||
<sComment>TYPE{S} l.state = sMeta1; return tType
|
||||
<sComment>UNIT{S} l.state = sMeta1; return tUnit
|
||||
<sComment>"EOF"\n? l.state = sInit; return tEOFWord
|
||||
<sMeta1>\"(\\.|[^\\"])*\" l.state = sMeta2; return tMName
|
||||
<sMeta1>{M}({M}|{D})* l.state = sMeta2; return tMName
|
||||
<sMeta2>{S}{C}*\n l.state = sInit; return tText
|
||||
|
||||
{M}({M}|{D})* l.state = sValue; return tMName
|
||||
<sValue>\{ l.state = sLabels; return tBraceOpen
|
||||
\{ l.state = sLabels; return tBraceOpen
|
||||
<sLabels>{L}({L}|{D})* return tLName
|
||||
<sLabels>\"(\\.|[^\\"])*\" l.state = sLabels; return tQString
|
||||
<sLabels>\} l.state = sValue; return tBraceClose
|
||||
<sLabels>= l.state = sLValue; return tEqual
|
||||
<sLabels>, return tComma
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -81,6 +81,12 @@ type OpenMetricsParser struct {
|
|||
ts int64
|
||||
hasTS bool
|
||||
start int
|
||||
// offsets is a list of offsets into series that describe the positions
|
||||
// of the metric name and label names and values for this series.
|
||||
// p.offsets[0] is the start character of the metric name.
|
||||
// p.offsets[1] is the end of the metric name.
|
||||
// Subsequently, p.offsets is a pair of pair of offsets for the positions
|
||||
// of the label name and value start and end characters.
|
||||
offsets []int
|
||||
|
||||
eOffsets []int
|
||||
|
@ -91,8 +97,11 @@ type OpenMetricsParser struct {
|
|||
}
|
||||
|
||||
// NewOpenMetricsParser returns a new parser of the byte slice.
|
||||
func NewOpenMetricsParser(b []byte) Parser {
|
||||
return &OpenMetricsParser{l: &openMetricsLexer{b: b}}
|
||||
func NewOpenMetricsParser(b []byte, st *labels.SymbolTable) Parser {
|
||||
return &OpenMetricsParser{
|
||||
l: &openMetricsLexer{b: b},
|
||||
builder: labels.NewScratchBuilderWithSymbolTable(st, 16),
|
||||
}
|
||||
}
|
||||
|
||||
// Series returns the bytes of the series, the timestamp if set, and the value
|
||||
|
@ -153,20 +162,18 @@ func (p *OpenMetricsParser) Metric(l *labels.Labels) string {
|
|||
s := string(p.series)
|
||||
|
||||
p.builder.Reset()
|
||||
p.builder.Add(labels.MetricName, s[:p.offsets[0]-p.start])
|
||||
metricName := unreplace(s[p.offsets[0]-p.start : p.offsets[1]-p.start])
|
||||
p.builder.Add(labels.MetricName, metricName)
|
||||
|
||||
for i := 1; i < len(p.offsets); i += 4 {
|
||||
for i := 2; i < len(p.offsets); i += 4 {
|
||||
a := p.offsets[i] - p.start
|
||||
b := p.offsets[i+1] - p.start
|
||||
label := unreplace(s[a:b])
|
||||
c := p.offsets[i+2] - p.start
|
||||
d := p.offsets[i+3] - p.start
|
||||
value := unreplace(s[c:d])
|
||||
|
||||
value := s[c:d]
|
||||
// Replacer causes allocations. Replace only when necessary.
|
||||
if strings.IndexByte(s[c:d], byte('\\')) >= 0 {
|
||||
value = lvalReplacer.Replace(value)
|
||||
}
|
||||
p.builder.Add(s[a:b], value)
|
||||
p.builder.Add(label, value)
|
||||
}
|
||||
|
||||
p.builder.Sort()
|
||||
|
@ -232,8 +239,8 @@ func (p *OpenMetricsParser) parseError(exp string, got token) error {
|
|||
return fmt.Errorf("%s, got %q (%q) while parsing: %q", exp, p.l.b[p.l.start:e], got, p.l.b[p.start:e])
|
||||
}
|
||||
|
||||
// Next advances the parser to the next sample. It returns false if no
|
||||
// more samples were read or an error occurred.
|
||||
// Next advances the parser to the next sample.
|
||||
// It returns (EntryInvalid, io.EOF) if no samples were read.
|
||||
func (p *OpenMetricsParser) Next() (Entry, error) {
|
||||
var err error
|
||||
|
||||
|
@ -255,7 +262,13 @@ func (p *OpenMetricsParser) Next() (Entry, error) {
|
|||
case tHelp, tType, tUnit:
|
||||
switch t2 := p.nextToken(); t2 {
|
||||
case tMName:
|
||||
p.offsets = append(p.offsets, p.l.start, p.l.i)
|
||||
mStart := p.l.start
|
||||
mEnd := p.l.i
|
||||
if p.l.b[mStart] == '"' && p.l.b[mEnd-1] == '"' {
|
||||
mStart++
|
||||
mEnd--
|
||||
}
|
||||
p.offsets = append(p.offsets, mStart, mEnd)
|
||||
default:
|
||||
return EntryInvalid, p.parseError("expected metric name after "+t.String(), t2)
|
||||
}
|
||||
|
@ -312,58 +325,33 @@ func (p *OpenMetricsParser) Next() (Entry, error) {
|
|||
return EntryUnit, nil
|
||||
}
|
||||
|
||||
case tBraceOpen:
|
||||
// We found a brace, so make room for the eventual metric name. If these
|
||||
// values aren't updated, then the metric name was not set inside the
|
||||
// braces and we can return an error.
|
||||
if len(p.offsets) == 0 {
|
||||
p.offsets = []int{-1, -1}
|
||||
}
|
||||
if p.offsets, err = p.parseLVals(p.offsets, false); err != nil {
|
||||
return EntryInvalid, err
|
||||
}
|
||||
|
||||
p.series = p.l.b[p.start:p.l.i]
|
||||
return p.parseMetricSuffix(p.nextToken())
|
||||
case tMName:
|
||||
p.offsets = append(p.offsets, p.l.i)
|
||||
p.offsets = append(p.offsets, p.start, p.l.i)
|
||||
p.series = p.l.b[p.start:p.l.i]
|
||||
|
||||
t2 := p.nextToken()
|
||||
if t2 == tBraceOpen {
|
||||
p.offsets, err = p.parseLVals(p.offsets)
|
||||
p.offsets, err = p.parseLVals(p.offsets, false)
|
||||
if err != nil {
|
||||
return EntryInvalid, err
|
||||
}
|
||||
p.series = p.l.b[p.start:p.l.i]
|
||||
t2 = p.nextToken()
|
||||
}
|
||||
p.val, err = p.getFloatValue(t2, "metric")
|
||||
if err != nil {
|
||||
return EntryInvalid, err
|
||||
}
|
||||
|
||||
p.hasTS = false
|
||||
switch t2 := p.nextToken(); t2 {
|
||||
case tEOF:
|
||||
return EntryInvalid, errors.New("data does not end with # EOF")
|
||||
case tLinebreak:
|
||||
break
|
||||
case tComment:
|
||||
if err := p.parseComment(); err != nil {
|
||||
return EntryInvalid, err
|
||||
}
|
||||
case tTimestamp:
|
||||
p.hasTS = true
|
||||
var ts float64
|
||||
// A float is enough to hold what we need for millisecond resolution.
|
||||
if ts, err = parseFloat(yoloString(p.l.buf()[1:])); err != nil {
|
||||
return EntryInvalid, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i])
|
||||
}
|
||||
if math.IsNaN(ts) || math.IsInf(ts, 0) {
|
||||
return EntryInvalid, fmt.Errorf("invalid timestamp %f", ts)
|
||||
}
|
||||
p.ts = int64(ts * 1000)
|
||||
switch t3 := p.nextToken(); t3 {
|
||||
case tLinebreak:
|
||||
case tComment:
|
||||
if err := p.parseComment(); err != nil {
|
||||
return EntryInvalid, err
|
||||
}
|
||||
default:
|
||||
return EntryInvalid, p.parseError("expected next entry after timestamp", t3)
|
||||
}
|
||||
default:
|
||||
return EntryInvalid, p.parseError("expected timestamp or # symbol", t2)
|
||||
}
|
||||
return EntrySeries, nil
|
||||
return p.parseMetricSuffix(t2)
|
||||
|
||||
default:
|
||||
err = p.parseError("expected a valid start token", t)
|
||||
|
@ -374,7 +362,7 @@ func (p *OpenMetricsParser) Next() (Entry, error) {
|
|||
func (p *OpenMetricsParser) parseComment() error {
|
||||
var err error
|
||||
// Parse the labels.
|
||||
p.eOffsets, err = p.parseLVals(p.eOffsets)
|
||||
p.eOffsets, err = p.parseLVals(p.eOffsets, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -415,38 +403,47 @@ func (p *OpenMetricsParser) parseComment() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *OpenMetricsParser) parseLVals(offsets []int) ([]int, error) {
|
||||
first := true
|
||||
func (p *OpenMetricsParser) parseLVals(offsets []int, isExemplar bool) ([]int, error) {
|
||||
t := p.nextToken()
|
||||
for {
|
||||
t := p.nextToken()
|
||||
curTStart := p.l.start
|
||||
curTI := p.l.i
|
||||
switch t {
|
||||
case tBraceClose:
|
||||
return offsets, nil
|
||||
case tComma:
|
||||
if first {
|
||||
return nil, p.parseError("expected label name or left brace", t)
|
||||
}
|
||||
t = p.nextToken()
|
||||
if t != tLName {
|
||||
case tLName:
|
||||
case tQString:
|
||||
default:
|
||||
return nil, p.parseError("expected label name", t)
|
||||
}
|
||||
|
||||
t = p.nextToken()
|
||||
// A quoted string followed by a comma or brace is a metric name. Set the
|
||||
// offsets and continue processing. If this is an exemplar, this format
|
||||
// is not allowed.
|
||||
if t == tComma || t == tBraceClose {
|
||||
if isExemplar {
|
||||
return nil, p.parseError("expected label name", t)
|
||||
}
|
||||
case tLName:
|
||||
if !first {
|
||||
return nil, p.parseError("expected comma", t)
|
||||
if offsets[0] != -1 || offsets[1] != -1 {
|
||||
return nil, fmt.Errorf("metric name already set while parsing: %q", p.l.b[p.start:p.l.i])
|
||||
}
|
||||
default:
|
||||
if first {
|
||||
return nil, p.parseError("expected label name or left brace", t)
|
||||
offsets[0] = curTStart + 1
|
||||
offsets[1] = curTI - 1
|
||||
if t == tBraceClose {
|
||||
return offsets, nil
|
||||
}
|
||||
return nil, p.parseError("expected comma or left brace", t)
|
||||
|
||||
t = p.nextToken()
|
||||
continue
|
||||
}
|
||||
first = false
|
||||
// t is now a label name.
|
||||
// We have a label name, and it might be quoted.
|
||||
if p.l.b[curTStart] == '"' {
|
||||
curTStart++
|
||||
curTI--
|
||||
}
|
||||
offsets = append(offsets, curTStart, curTI)
|
||||
|
||||
offsets = append(offsets, p.l.start, p.l.i)
|
||||
|
||||
if t := p.nextToken(); t != tEqual {
|
||||
if t != tEqual {
|
||||
return nil, p.parseError("expected equal", t)
|
||||
}
|
||||
if t := p.nextToken(); t != tLValue {
|
||||
|
@ -459,9 +456,64 @@ func (p *OpenMetricsParser) parseLVals(offsets []int) ([]int, error) {
|
|||
// The openMetricsLexer ensures the value string is quoted. Strip first
|
||||
// and last character.
|
||||
offsets = append(offsets, p.l.start+1, p.l.i-1)
|
||||
|
||||
// Free trailing commas are allowed.
|
||||
t = p.nextToken()
|
||||
if t == tComma {
|
||||
t = p.nextToken()
|
||||
} else if t != tBraceClose {
|
||||
return nil, p.parseError("expected comma or brace close", t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parseMetricSuffix parses the end of the line after the metric name and
|
||||
// labels. It starts parsing with the provided token.
|
||||
func (p *OpenMetricsParser) parseMetricSuffix(t token) (Entry, error) {
|
||||
if p.offsets[0] == -1 {
|
||||
return EntryInvalid, fmt.Errorf("metric name not set while parsing: %q", p.l.b[p.start:p.l.i])
|
||||
}
|
||||
|
||||
var err error
|
||||
p.val, err = p.getFloatValue(t, "metric")
|
||||
if err != nil {
|
||||
return EntryInvalid, err
|
||||
}
|
||||
|
||||
p.hasTS = false
|
||||
switch t2 := p.nextToken(); t2 {
|
||||
case tEOF:
|
||||
return EntryInvalid, errors.New("data does not end with # EOF")
|
||||
case tLinebreak:
|
||||
break
|
||||
case tComment:
|
||||
if err := p.parseComment(); err != nil {
|
||||
return EntryInvalid, err
|
||||
}
|
||||
case tTimestamp:
|
||||
p.hasTS = true
|
||||
var ts float64
|
||||
// A float is enough to hold what we need for millisecond resolution.
|
||||
if ts, err = parseFloat(yoloString(p.l.buf()[1:])); err != nil {
|
||||
return EntryInvalid, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i])
|
||||
}
|
||||
if math.IsNaN(ts) || math.IsInf(ts, 0) {
|
||||
return EntryInvalid, fmt.Errorf("invalid timestamp %f", ts)
|
||||
}
|
||||
p.ts = int64(ts * 1000)
|
||||
switch t3 := p.nextToken(); t3 {
|
||||
case tLinebreak:
|
||||
case tComment:
|
||||
if err := p.parseComment(); err != nil {
|
||||
return EntryInvalid, err
|
||||
}
|
||||
default:
|
||||
return EntryInvalid, p.parseError("expected next entry after timestamp", t3)
|
||||
}
|
||||
}
|
||||
return EntrySeries, nil
|
||||
}
|
||||
|
||||
func (p *OpenMetricsParser) getFloatValue(t token, after string) (float64, error) {
|
||||
if t != tValue {
|
||||
return 0, p.parseError(fmt.Sprintf("expected value after %v", after), t)
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
package textparse
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
|
@ -73,17 +72,7 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
|
|||
|
||||
int64p := func(x int64) *int64 { return &x }
|
||||
|
||||
exp := []struct {
|
||||
lset labels.Labels
|
||||
m string
|
||||
t *int64
|
||||
v float64
|
||||
typ model.MetricType
|
||||
help string
|
||||
unit string
|
||||
comment string
|
||||
e *exemplar.Exemplar
|
||||
}{
|
||||
exp := []expectedParse{
|
||||
{
|
||||
m: "go_gc_duration_seconds",
|
||||
help: "A summary of the GC invocation durations.",
|
||||
|
@ -246,58 +235,79 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
|
|||
},
|
||||
}
|
||||
|
||||
p := NewOpenMetricsParser([]byte(input))
|
||||
i := 0
|
||||
p := NewOpenMetricsParser([]byte(input), labels.NewSymbolTable())
|
||||
checkParseResults(t, p, exp)
|
||||
}
|
||||
|
||||
var res labels.Labels
|
||||
func TestUTF8OpenMetricsParse(t *testing.T) {
|
||||
oldValidationScheme := model.NameValidationScheme
|
||||
model.NameValidationScheme = model.UTF8Validation
|
||||
defer func() {
|
||||
model.NameValidationScheme = oldValidationScheme
|
||||
}()
|
||||
|
||||
for {
|
||||
et, err := p.Next()
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
require.NoError(t, err)
|
||||
input := `# HELP "go.gc_duration_seconds" A summary of the GC invocation durations.
|
||||
# TYPE "go.gc_duration_seconds" summary
|
||||
# UNIT "go.gc_duration_seconds" seconds
|
||||
{"go.gc_duration_seconds",quantile="0"} 4.9351e-05
|
||||
{"go.gc_duration_seconds",quantile="0.25"} 7.424100000000001e-05
|
||||
{"go.gc_duration_seconds",quantile="0.5",a="b"} 8.3835e-05
|
||||
{"http.status",q="0.9",a="b"} 8.3835e-05
|
||||
{"http.status",q="0.9",a="b"} 8.3835e-05
|
||||
{q="0.9","http.status",a="b"} 8.3835e-05
|
||||
{"go.gc_duration_seconds_sum"} 0.004304266
|
||||
{"Heizölrückstoßabdämpfung 10€ metric with \"interesting\" {character\nchoices}","strange©™\n'quoted' \"name\""="6"} 10.0`
|
||||
|
||||
switch et {
|
||||
case EntrySeries:
|
||||
m, ts, v := p.Series()
|
||||
input += "\n# EOF\n"
|
||||
|
||||
var e exemplar.Exemplar
|
||||
p.Metric(&res)
|
||||
found := p.Exemplar(&e)
|
||||
require.Equal(t, exp[i].m, string(m))
|
||||
require.Equal(t, exp[i].t, ts)
|
||||
require.Equal(t, exp[i].v, v)
|
||||
require.Equal(t, exp[i].lset, res)
|
||||
if exp[i].e == nil {
|
||||
require.False(t, found)
|
||||
} else {
|
||||
require.True(t, found)
|
||||
require.Equal(t, *exp[i].e, e)
|
||||
}
|
||||
|
||||
case EntryType:
|
||||
m, typ := p.Type()
|
||||
require.Equal(t, exp[i].m, string(m))
|
||||
require.Equal(t, exp[i].typ, typ)
|
||||
|
||||
case EntryHelp:
|
||||
m, h := p.Help()
|
||||
require.Equal(t, exp[i].m, string(m))
|
||||
require.Equal(t, exp[i].help, string(h))
|
||||
|
||||
case EntryUnit:
|
||||
m, u := p.Unit()
|
||||
require.Equal(t, exp[i].m, string(m))
|
||||
require.Equal(t, exp[i].unit, string(u))
|
||||
|
||||
case EntryComment:
|
||||
require.Equal(t, exp[i].comment, string(p.Comment()))
|
||||
}
|
||||
|
||||
i++
|
||||
exp := []expectedParse{
|
||||
{
|
||||
m: "go.gc_duration_seconds",
|
||||
help: "A summary of the GC invocation durations.",
|
||||
}, {
|
||||
m: "go.gc_duration_seconds",
|
||||
typ: model.MetricTypeSummary,
|
||||
}, {
|
||||
m: "go.gc_duration_seconds",
|
||||
unit: "seconds",
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds",quantile="0"}`,
|
||||
v: 4.9351e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0"),
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds",quantile="0.25"}`,
|
||||
v: 7.424100000000001e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0.25"),
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds",quantile="0.5",a="b"}`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0.5", "a", "b"),
|
||||
}, {
|
||||
m: `{"http.status",q="0.9",a="b"}`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "http.status", "q", "0.9", "a", "b"),
|
||||
}, {
|
||||
m: `{"http.status",q="0.9",a="b"}`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "http.status", "q", "0.9", "a", "b"),
|
||||
}, {
|
||||
m: `{q="0.9","http.status",a="b"}`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "http.status", "q", "0.9", "a", "b"),
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds_sum"}`,
|
||||
v: 0.004304266,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds_sum"),
|
||||
}, {
|
||||
m: `{"Heizölrückstoßabdämpfung 10€ metric with \"interesting\" {character\nchoices}","strange©™\n'quoted' \"name\""="6"}`,
|
||||
v: 10.0,
|
||||
lset: labels.FromStrings("__name__", `Heizölrückstoßabdämpfung 10€ metric with "interesting" {character
|
||||
choices}`, "strange©™\n'quoted' \"name\"", "6"),
|
||||
},
|
||||
}
|
||||
require.Len(t, exp, i)
|
||||
|
||||
p := NewOpenMetricsParser([]byte(input), labels.NewSymbolTable())
|
||||
checkParseResults(t, p, exp)
|
||||
}
|
||||
|
||||
func TestOpenMetricsParseErrors(t *testing.T) {
|
||||
|
@ -456,17 +466,13 @@ func TestOpenMetricsParseErrors(t *testing.T) {
|
|||
input: "a{b='c'} 1\n# EOF\n",
|
||||
err: "expected label value, got \"'\" (\"INVALID\") while parsing: \"a{b='\"",
|
||||
},
|
||||
{
|
||||
input: "a{b=\"c\",} 1\n# EOF\n",
|
||||
err: "expected label name, got \"} \" (\"BCLOSE\") while parsing: \"a{b=\\\"c\\\",} \"",
|
||||
},
|
||||
{
|
||||
input: "a{,b=\"c\"} 1\n# EOF\n",
|
||||
err: "expected label name or left brace, got \",b\" (\"COMMA\") while parsing: \"a{,b\"",
|
||||
err: "expected label name, got \",b\" (\"COMMA\") while parsing: \"a{,b\"",
|
||||
},
|
||||
{
|
||||
input: "a{b=\"c\"d=\"e\"} 1\n# EOF\n",
|
||||
err: "expected comma, got \"d=\" (\"LNAME\") while parsing: \"a{b=\\\"c\\\"d=\"",
|
||||
err: "expected comma or brace close, got \"d=\" (\"LNAME\") while parsing: \"a{b=\\\"c\\\"d=\"",
|
||||
},
|
||||
{
|
||||
input: "a{b=\"c\",,d=\"e\"} 1\n# EOF\n",
|
||||
|
@ -478,12 +484,24 @@ func TestOpenMetricsParseErrors(t *testing.T) {
|
|||
},
|
||||
{
|
||||
input: "a{\xff=\"foo\"} 1\n# EOF\n",
|
||||
err: "expected label name or left brace, got \"\\xff\" (\"INVALID\") while parsing: \"a{\\xff\"",
|
||||
err: "expected label name, got \"\\xff\" (\"INVALID\") while parsing: \"a{\\xff\"",
|
||||
},
|
||||
{
|
||||
input: "a{b=\"\xff\"} 1\n# EOF\n",
|
||||
err: "invalid UTF-8 label value: \"\\\"\\xff\\\"\"",
|
||||
},
|
||||
{
|
||||
input: `{"a","b = "c"}
|
||||
# EOF
|
||||
`,
|
||||
err: "expected equal, got \"c\\\"\" (\"LNAME\") while parsing: \"{\\\"a\\\",\\\"b = \\\"c\\\"\"",
|
||||
},
|
||||
{
|
||||
input: `{"a",b\nc="d"} 1
|
||||
# EOF
|
||||
`,
|
||||
err: "expected equal, got \"\\\\\" (\"INVALID\") while parsing: \"{\\\"a\\\",b\\\\\"",
|
||||
},
|
||||
{
|
||||
input: "a true\n",
|
||||
err: "strconv.ParseFloat: parsing \"true\": invalid syntax while parsing: \"a true\"",
|
||||
|
@ -494,7 +512,7 @@ func TestOpenMetricsParseErrors(t *testing.T) {
|
|||
},
|
||||
{
|
||||
input: "empty_label_name{=\"\"} 0\n# EOF\n",
|
||||
err: "expected label name or left brace, got \"=\\\"\" (\"EQUAL\") while parsing: \"empty_label_name{=\\\"\"",
|
||||
err: "expected label name, got \"=\\\"\" (\"EQUAL\") while parsing: \"empty_label_name{=\\\"\"",
|
||||
},
|
||||
{
|
||||
input: "foo 1_2\n\n# EOF\n",
|
||||
|
@ -524,6 +542,14 @@ func TestOpenMetricsParseErrors(t *testing.T) {
|
|||
input: `custom_metric_total 1 # {aa="bb"}`,
|
||||
err: "expected value after exemplar labels, got \"}\" (\"EOF\") while parsing: \"custom_metric_total 1 # {aa=\\\"bb\\\"}\"",
|
||||
},
|
||||
{
|
||||
input: `custom_metric_total 1 # {bb}`,
|
||||
err: "expected label name, got \"}\" (\"BCLOSE\") while parsing: \"custom_metric_total 1 # {bb}\"",
|
||||
},
|
||||
{
|
||||
input: `custom_metric_total 1 # {bb, a="dd"}`,
|
||||
err: "expected label name, got \", \" (\"COMMA\") while parsing: \"custom_metric_total 1 # {bb, \"",
|
||||
},
|
||||
{
|
||||
input: `custom_metric_total 1 # {aa="bb",,cc="dd"} 1`,
|
||||
err: "expected label name, got \",c\" (\"COMMA\") while parsing: \"custom_metric_total 1 # {aa=\\\"bb\\\",,c\"",
|
||||
|
@ -550,7 +576,7 @@ func TestOpenMetricsParseErrors(t *testing.T) {
|
|||
},
|
||||
{
|
||||
input: `{b="c",} 1`,
|
||||
err: "expected a valid start token, got \"{\" (\"INVALID\") while parsing: \"{\"",
|
||||
err: "metric name not set while parsing: \"{b=\\\"c\\\",} 1\"",
|
||||
},
|
||||
{
|
||||
input: `a 1 NaN`,
|
||||
|
@ -579,7 +605,7 @@ func TestOpenMetricsParseErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, c := range cases {
|
||||
p := NewOpenMetricsParser([]byte(c.input))
|
||||
p := NewOpenMetricsParser([]byte(c.input), labels.NewSymbolTable())
|
||||
var err error
|
||||
for err == nil {
|
||||
_, err = p.Next()
|
||||
|
@ -644,7 +670,7 @@ func TestOMNullByteHandling(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, c := range cases {
|
||||
p := NewOpenMetricsParser([]byte(c.input))
|
||||
p := NewOpenMetricsParser([]byte(c.input), labels.NewSymbolTable())
|
||||
var err error
|
||||
for err == nil {
|
||||
_, err = p.Next()
|
||||
|
|
|
@ -66,12 +66,15 @@ C [^\n]
|
|||
# return l.consumeComment()
|
||||
<sComment>HELP[\t ]+ l.state = sMeta1; return tHelp
|
||||
<sComment>TYPE[\t ]+ l.state = sMeta1; return tType
|
||||
<sMeta1>\"(\\.|[^\\"])*\" l.state = sMeta2; return tMName
|
||||
<sMeta1>{M}({M}|{D})* l.state = sMeta2; return tMName
|
||||
<sMeta2>{C}* l.state = sInit; return tText
|
||||
|
||||
{M}({M}|{D})* l.state = sValue; return tMName
|
||||
<sValue>\{ l.state = sLabels; return tBraceOpen
|
||||
\{ l.state = sLabels; return tBraceOpen
|
||||
<sLabels>{L}({L}|{D})* return tLName
|
||||
<sLabels>\"(\\.|[^\\"])*\" l.state = sLabels; return tQString
|
||||
<sLabels>\} l.state = sValue; return tBraceClose
|
||||
<sLabels>= l.state = sLValue; return tEqual
|
||||
<sLabels>, return tComma
|
||||
|
|
|
@ -51,19 +51,19 @@ yystate0:
|
|||
case 0: // start condition: INITIAL
|
||||
goto yystart1
|
||||
case 1: // start condition: sComment
|
||||
goto yystart8
|
||||
goto yystart9
|
||||
case 2: // start condition: sMeta1
|
||||
goto yystart19
|
||||
goto yystart20
|
||||
case 3: // start condition: sMeta2
|
||||
goto yystart21
|
||||
goto yystart25
|
||||
case 4: // start condition: sLabels
|
||||
goto yystart24
|
||||
goto yystart28
|
||||
case 5: // start condition: sLValue
|
||||
goto yystart29
|
||||
case 6: // start condition: sValue
|
||||
goto yystart33
|
||||
case 7: // start condition: sTimestamp
|
||||
goto yystart36
|
||||
case 6: // start condition: sValue
|
||||
goto yystart40
|
||||
case 7: // start condition: sTimestamp
|
||||
goto yystart43
|
||||
}
|
||||
|
||||
yystate1:
|
||||
|
@ -82,6 +82,8 @@ yystart1:
|
|||
goto yystate3
|
||||
case c == '\x00':
|
||||
goto yystate2
|
||||
case c == '{':
|
||||
goto yystate8
|
||||
}
|
||||
|
||||
yystate2:
|
||||
|
@ -123,40 +125,35 @@ yystate7:
|
|||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyrule10
|
||||
goto yyrule11
|
||||
case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
|
||||
goto yystate7
|
||||
}
|
||||
|
||||
yystate8:
|
||||
c = l.next()
|
||||
yystart8:
|
||||
goto yyrule13
|
||||
|
||||
yystate9:
|
||||
c = l.next()
|
||||
yystart9:
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == 'H':
|
||||
goto yystate9
|
||||
goto yystate10
|
||||
case c == 'T':
|
||||
goto yystate14
|
||||
goto yystate15
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate3
|
||||
}
|
||||
|
||||
yystate9:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == 'E':
|
||||
goto yystate10
|
||||
}
|
||||
|
||||
yystate10:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == 'L':
|
||||
case c == 'E':
|
||||
goto yystate11
|
||||
}
|
||||
|
||||
|
@ -165,7 +162,7 @@ yystate11:
|
|||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == 'P':
|
||||
case c == 'L':
|
||||
goto yystate12
|
||||
}
|
||||
|
||||
|
@ -174,7 +171,7 @@ yystate12:
|
|||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == '\t' || c == ' ':
|
||||
case c == 'P':
|
||||
goto yystate13
|
||||
}
|
||||
|
||||
|
@ -182,18 +179,18 @@ yystate13:
|
|||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyrule6
|
||||
goto yyabort
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate13
|
||||
goto yystate14
|
||||
}
|
||||
|
||||
yystate14:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == 'Y':
|
||||
goto yystate15
|
||||
goto yyrule6
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate14
|
||||
}
|
||||
|
||||
yystate15:
|
||||
|
@ -201,7 +198,7 @@ yystate15:
|
|||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == 'P':
|
||||
case c == 'Y':
|
||||
goto yystate16
|
||||
}
|
||||
|
||||
|
@ -210,7 +207,7 @@ yystate16:
|
|||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == 'E':
|
||||
case c == 'P':
|
||||
goto yystate17
|
||||
}
|
||||
|
||||
|
@ -219,7 +216,7 @@ yystate17:
|
|||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == '\t' || c == ' ':
|
||||
case c == 'E':
|
||||
goto yystate18
|
||||
}
|
||||
|
||||
|
@ -227,167 +224,167 @@ yystate18:
|
|||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyrule7
|
||||
goto yyabort
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate18
|
||||
goto yystate19
|
||||
}
|
||||
|
||||
yystate19:
|
||||
c = l.next()
|
||||
yystart19:
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
|
||||
goto yystate20
|
||||
goto yyrule7
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate3
|
||||
goto yystate19
|
||||
}
|
||||
|
||||
yystate20:
|
||||
c = l.next()
|
||||
yystart20:
|
||||
switch {
|
||||
default:
|
||||
goto yyrule8
|
||||
case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
|
||||
goto yystate20
|
||||
goto yyabort
|
||||
case c == '"':
|
||||
goto yystate21
|
||||
case c == ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
|
||||
goto yystate24
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate3
|
||||
}
|
||||
|
||||
yystate21:
|
||||
c = l.next()
|
||||
yystart21:
|
||||
switch {
|
||||
default:
|
||||
goto yyrule9
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate23
|
||||
case c >= '\x01' && c <= '\b' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ':
|
||||
goto yyabort
|
||||
case c == '"':
|
||||
goto yystate22
|
||||
case c == '\\':
|
||||
goto yystate23
|
||||
case c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ':
|
||||
goto yystate21
|
||||
}
|
||||
|
||||
yystate22:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyrule9
|
||||
case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ':
|
||||
goto yystate22
|
||||
}
|
||||
goto yyrule8
|
||||
|
||||
yystate23:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyrule3
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate23
|
||||
case c >= '\x01' && c <= '\b' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ':
|
||||
goto yystate22
|
||||
goto yyabort
|
||||
case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ':
|
||||
goto yystate21
|
||||
}
|
||||
|
||||
yystate24:
|
||||
c = l.next()
|
||||
yystart24:
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == ',':
|
||||
goto yystate25
|
||||
case c == '=':
|
||||
goto yystate26
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate3
|
||||
case c == '}':
|
||||
goto yystate28
|
||||
case c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
|
||||
goto yystate27
|
||||
goto yyrule9
|
||||
case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
|
||||
goto yystate24
|
||||
}
|
||||
|
||||
yystate25:
|
||||
c = l.next()
|
||||
goto yyrule15
|
||||
yystart25:
|
||||
switch {
|
||||
default:
|
||||
goto yyrule10
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate27
|
||||
case c >= '\x01' && c <= '\b' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ':
|
||||
goto yystate26
|
||||
}
|
||||
|
||||
yystate26:
|
||||
c = l.next()
|
||||
goto yyrule14
|
||||
switch {
|
||||
default:
|
||||
goto yyrule10
|
||||
case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ':
|
||||
goto yystate26
|
||||
}
|
||||
|
||||
yystate27:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyrule12
|
||||
case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
|
||||
goto yyrule3
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate27
|
||||
case c >= '\x01' && c <= '\b' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'ÿ':
|
||||
goto yystate26
|
||||
}
|
||||
|
||||
yystate28:
|
||||
c = l.next()
|
||||
goto yyrule13
|
||||
yystart28:
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == '"':
|
||||
goto yystate29
|
||||
case c == ',':
|
||||
goto yystate32
|
||||
case c == '=':
|
||||
goto yystate33
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate3
|
||||
case c == '}':
|
||||
goto yystate35
|
||||
case c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
|
||||
goto yystate34
|
||||
}
|
||||
|
||||
yystate29:
|
||||
c = l.next()
|
||||
yystart29:
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == '"':
|
||||
goto yystate30
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate3
|
||||
case c == '\\':
|
||||
goto yystate31
|
||||
case c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ':
|
||||
goto yystate29
|
||||
}
|
||||
|
||||
yystate30:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == '"':
|
||||
goto yystate31
|
||||
case c == '\\':
|
||||
goto yystate32
|
||||
case c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ':
|
||||
goto yystate30
|
||||
}
|
||||
goto yyrule15
|
||||
|
||||
yystate31:
|
||||
c = l.next()
|
||||
goto yyrule16
|
||||
|
||||
yystate32:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ':
|
||||
goto yystate30
|
||||
goto yystate29
|
||||
}
|
||||
|
||||
yystate32:
|
||||
c = l.next()
|
||||
goto yyrule18
|
||||
|
||||
yystate33:
|
||||
c = l.next()
|
||||
yystart33:
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate3
|
||||
case c == '{':
|
||||
goto yystate35
|
||||
case c >= '\x01' && c <= '\b' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'z' || c >= '|' && c <= 'ÿ':
|
||||
goto yystate34
|
||||
}
|
||||
goto yyrule17
|
||||
|
||||
yystate34:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyrule17
|
||||
case c >= '\x01' && c <= '\b' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'z' || c >= '|' && c <= 'ÿ':
|
||||
goto yyrule14
|
||||
case c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z':
|
||||
goto yystate34
|
||||
}
|
||||
|
||||
yystate35:
|
||||
c = l.next()
|
||||
goto yyrule11
|
||||
goto yyrule16
|
||||
|
||||
yystate36:
|
||||
c = l.next()
|
||||
|
@ -395,25 +392,90 @@ yystart36:
|
|||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == '\n':
|
||||
case c == '"':
|
||||
goto yystate37
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate3
|
||||
case c >= '0' && c <= '9':
|
||||
goto yystate38
|
||||
}
|
||||
|
||||
yystate37:
|
||||
c = l.next()
|
||||
goto yyrule19
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == '"':
|
||||
goto yystate38
|
||||
case c == '\\':
|
||||
goto yystate39
|
||||
case c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ':
|
||||
goto yystate37
|
||||
}
|
||||
|
||||
yystate38:
|
||||
c = l.next()
|
||||
goto yyrule19
|
||||
|
||||
yystate39:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyrule18
|
||||
goto yyabort
|
||||
case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ':
|
||||
goto yystate37
|
||||
}
|
||||
|
||||
yystate40:
|
||||
c = l.next()
|
||||
yystart40:
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate3
|
||||
case c == '{':
|
||||
goto yystate42
|
||||
case c >= '\x01' && c <= '\b' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'z' || c >= '|' && c <= 'ÿ':
|
||||
goto yystate41
|
||||
}
|
||||
|
||||
yystate41:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyrule20
|
||||
case c >= '\x01' && c <= '\b' || c >= '\v' && c <= '\x1f' || c >= '!' && c <= 'z' || c >= '|' && c <= 'ÿ':
|
||||
goto yystate41
|
||||
}
|
||||
|
||||
yystate42:
|
||||
c = l.next()
|
||||
goto yyrule12
|
||||
|
||||
yystate43:
|
||||
c = l.next()
|
||||
yystart43:
|
||||
switch {
|
||||
default:
|
||||
goto yyabort
|
||||
case c == '\n':
|
||||
goto yystate44
|
||||
case c == '\t' || c == ' ':
|
||||
goto yystate3
|
||||
case c >= '0' && c <= '9':
|
||||
goto yystate38
|
||||
goto yystate45
|
||||
}
|
||||
|
||||
yystate44:
|
||||
c = l.next()
|
||||
goto yyrule22
|
||||
|
||||
yystate45:
|
||||
c = l.next()
|
||||
switch {
|
||||
default:
|
||||
goto yyrule21
|
||||
case c >= '0' && c <= '9':
|
||||
goto yystate45
|
||||
}
|
||||
|
||||
yyrule1: // \0
|
||||
|
@ -451,67 +513,85 @@ yyrule7: // TYPE[\t ]+
|
|||
return tType
|
||||
goto yystate0
|
||||
}
|
||||
yyrule8: // {M}({M}|{D})*
|
||||
yyrule8: // \"(\\.|[^\\"])*\"
|
||||
{
|
||||
l.state = sMeta2
|
||||
return tMName
|
||||
goto yystate0
|
||||
}
|
||||
yyrule9: // {C}*
|
||||
yyrule9: // {M}({M}|{D})*
|
||||
{
|
||||
l.state = sMeta2
|
||||
return tMName
|
||||
goto yystate0
|
||||
}
|
||||
yyrule10: // {C}*
|
||||
{
|
||||
l.state = sInit
|
||||
return tText
|
||||
goto yystate0
|
||||
}
|
||||
yyrule10: // {M}({M}|{D})*
|
||||
yyrule11: // {M}({M}|{D})*
|
||||
{
|
||||
l.state = sValue
|
||||
return tMName
|
||||
goto yystate0
|
||||
}
|
||||
yyrule11: // \{
|
||||
yyrule12: // \{
|
||||
{
|
||||
l.state = sLabels
|
||||
return tBraceOpen
|
||||
goto yystate0
|
||||
}
|
||||
yyrule12: // {L}({L}|{D})*
|
||||
yyrule13: // \{
|
||||
{
|
||||
l.state = sLabels
|
||||
return tBraceOpen
|
||||
goto yystate0
|
||||
}
|
||||
yyrule14: // {L}({L}|{D})*
|
||||
{
|
||||
return tLName
|
||||
}
|
||||
yyrule13: // \}
|
||||
yyrule15: // \"(\\.|[^\\"])*\"
|
||||
{
|
||||
l.state = sLabels
|
||||
return tQString
|
||||
goto yystate0
|
||||
}
|
||||
yyrule16: // \}
|
||||
{
|
||||
l.state = sValue
|
||||
return tBraceClose
|
||||
goto yystate0
|
||||
}
|
||||
yyrule14: // =
|
||||
yyrule17: // =
|
||||
{
|
||||
l.state = sLValue
|
||||
return tEqual
|
||||
goto yystate0
|
||||
}
|
||||
yyrule15: // ,
|
||||
yyrule18: // ,
|
||||
{
|
||||
return tComma
|
||||
}
|
||||
yyrule16: // \"(\\.|[^\\"])*\"
|
||||
yyrule19: // \"(\\.|[^\\"])*\"
|
||||
{
|
||||
l.state = sLabels
|
||||
return tLValue
|
||||
goto yystate0
|
||||
}
|
||||
yyrule17: // [^{ \t\n]+
|
||||
yyrule20: // [^{ \t\n]+
|
||||
{
|
||||
l.state = sTimestamp
|
||||
return tValue
|
||||
goto yystate0
|
||||
}
|
||||
yyrule18: // {D}+
|
||||
yyrule21: // {D}+
|
||||
{
|
||||
return tTimestamp
|
||||
}
|
||||
yyrule19: // \n
|
||||
yyrule22: // \n
|
||||
if true { // avoid go vet determining the below panic will not be reached
|
||||
l.state = sInit
|
||||
return tLinebreak
|
||||
|
@ -520,9 +600,7 @@ yyrule19: // \n
|
|||
panic("unreachable")
|
||||
|
||||
yyabort: // no lexem recognized
|
||||
//
|
||||
// silence unused label errors for build and satisfy go vet reachability analysis
|
||||
//
|
||||
{
|
||||
if false {
|
||||
goto yyabort
|
||||
|
@ -534,26 +612,26 @@ yyabort: // no lexem recognized
|
|||
goto yystate1
|
||||
}
|
||||
if false {
|
||||
goto yystate8
|
||||
goto yystate9
|
||||
}
|
||||
if false {
|
||||
goto yystate19
|
||||
goto yystate20
|
||||
}
|
||||
if false {
|
||||
goto yystate21
|
||||
goto yystate25
|
||||
}
|
||||
if false {
|
||||
goto yystate24
|
||||
}
|
||||
if false {
|
||||
goto yystate29
|
||||
}
|
||||
if false {
|
||||
goto yystate33
|
||||
goto yystate28
|
||||
}
|
||||
if false {
|
||||
goto yystate36
|
||||
}
|
||||
if false {
|
||||
goto yystate40
|
||||
}
|
||||
if false {
|
||||
goto yystate43
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround to gobble up comments that started with a HELP or TYPE
|
||||
|
|
|
@ -57,6 +57,7 @@ const (
|
|||
tComment
|
||||
tBlank
|
||||
tMName
|
||||
tQString
|
||||
tBraceOpen
|
||||
tBraceClose
|
||||
tLName
|
||||
|
@ -93,6 +94,8 @@ func (t token) String() string {
|
|||
return "BLANK"
|
||||
case tMName:
|
||||
return "MNAME"
|
||||
case tQString:
|
||||
return "QSTRING"
|
||||
case tBraceOpen:
|
||||
return "BOPEN"
|
||||
case tBraceClose:
|
||||
|
@ -153,12 +156,21 @@ type PromParser struct {
|
|||
ts int64
|
||||
hasTS bool
|
||||
start int
|
||||
// offsets is a list of offsets into series that describe the positions
|
||||
// of the metric name and label names and values for this series.
|
||||
// p.offsets[0] is the start character of the metric name.
|
||||
// p.offsets[1] is the end of the metric name.
|
||||
// Subsequently, p.offsets is a pair of pair of offsets for the positions
|
||||
// of the label name and value start and end characters.
|
||||
offsets []int
|
||||
}
|
||||
|
||||
// NewPromParser returns a new parser of the byte slice.
|
||||
func NewPromParser(b []byte) Parser {
|
||||
return &PromParser{l: &promlexer{b: append(b, '\n')}}
|
||||
func NewPromParser(b []byte, st *labels.SymbolTable) Parser {
|
||||
return &PromParser{
|
||||
l: &promlexer{b: append(b, '\n')},
|
||||
builder: labels.NewScratchBuilderWithSymbolTable(st, 16),
|
||||
}
|
||||
}
|
||||
|
||||
// Series returns the bytes of the series, the timestamp if set, and the value
|
||||
|
@ -218,20 +230,17 @@ func (p *PromParser) Metric(l *labels.Labels) string {
|
|||
s := string(p.series)
|
||||
|
||||
p.builder.Reset()
|
||||
p.builder.Add(labels.MetricName, s[:p.offsets[0]-p.start])
|
||||
metricName := unreplace(s[p.offsets[0]-p.start : p.offsets[1]-p.start])
|
||||
p.builder.Add(labels.MetricName, metricName)
|
||||
|
||||
for i := 1; i < len(p.offsets); i += 4 {
|
||||
for i := 2; i < len(p.offsets); i += 4 {
|
||||
a := p.offsets[i] - p.start
|
||||
b := p.offsets[i+1] - p.start
|
||||
label := unreplace(s[a:b])
|
||||
c := p.offsets[i+2] - p.start
|
||||
d := p.offsets[i+3] - p.start
|
||||
|
||||
value := s[c:d]
|
||||
// Replacer causes allocations. Replace only when necessary.
|
||||
if strings.IndexByte(s[c:d], byte('\\')) >= 0 {
|
||||
value = lvalReplacer.Replace(value)
|
||||
}
|
||||
p.builder.Add(s[a:b], value)
|
||||
value := unreplace(s[c:d])
|
||||
p.builder.Add(label, value)
|
||||
}
|
||||
|
||||
p.builder.Sort()
|
||||
|
@ -271,8 +280,8 @@ func (p *PromParser) parseError(exp string, got token) error {
|
|||
return fmt.Errorf("%s, got %q (%q) while parsing: %q", exp, p.l.b[p.l.start:e], got, p.l.b[p.start:e])
|
||||
}
|
||||
|
||||
// Next advances the parser to the next sample. It returns false if no
|
||||
// more samples were read or an error occurred.
|
||||
// Next advances the parser to the next sample.
|
||||
// It returns (EntryInvalid, io.EOF) if no samples were read.
|
||||
func (p *PromParser) Next() (Entry, error) {
|
||||
var err error
|
||||
|
||||
|
@ -289,7 +298,13 @@ func (p *PromParser) Next() (Entry, error) {
|
|||
case tHelp, tType:
|
||||
switch t2 := p.nextToken(); t2 {
|
||||
case tMName:
|
||||
p.offsets = append(p.offsets, p.l.start, p.l.i)
|
||||
mStart := p.l.start
|
||||
mEnd := p.l.i
|
||||
if p.l.b[mStart] == '"' && p.l.b[mEnd-1] == '"' {
|
||||
mStart++
|
||||
mEnd--
|
||||
}
|
||||
p.offsets = append(p.offsets, mStart, mEnd)
|
||||
default:
|
||||
return EntryInvalid, p.parseError("expected metric name after "+t.String(), t2)
|
||||
}
|
||||
|
@ -301,7 +316,7 @@ func (p *PromParser) Next() (Entry, error) {
|
|||
p.text = []byte{}
|
||||
}
|
||||
default:
|
||||
return EntryInvalid, fmt.Errorf("expected text in %s", t.String())
|
||||
return EntryInvalid, fmt.Errorf("expected text in %s, got %v", t.String(), t2.String())
|
||||
}
|
||||
switch t {
|
||||
case tType:
|
||||
|
@ -339,12 +354,24 @@ func (p *PromParser) Next() (Entry, error) {
|
|||
return EntryInvalid, p.parseError("linebreak expected after comment", t)
|
||||
}
|
||||
return EntryComment, nil
|
||||
case tBraceOpen:
|
||||
// We found a brace, so make room for the eventual metric name. If these
|
||||
// values aren't updated, then the metric name was not set inside the
|
||||
// braces and we can return an error.
|
||||
if len(p.offsets) == 0 {
|
||||
p.offsets = []int{-1, -1}
|
||||
}
|
||||
if err := p.parseLVals(); err != nil {
|
||||
return EntryInvalid, err
|
||||
}
|
||||
|
||||
case tMName:
|
||||
p.offsets = append(p.offsets, p.l.i)
|
||||
p.series = p.l.b[p.start:p.l.i]
|
||||
|
||||
return p.parseMetricSuffix(p.nextToken())
|
||||
case tMName:
|
||||
p.offsets = append(p.offsets, p.start, p.l.i)
|
||||
p.series = p.l.b[p.start:p.l.i]
|
||||
t2 := p.nextToken()
|
||||
// If there's a brace, consume and parse the label values.
|
||||
if t2 == tBraceOpen {
|
||||
if err := p.parseLVals(); err != nil {
|
||||
return EntryInvalid, err
|
||||
|
@ -352,32 +379,7 @@ func (p *PromParser) Next() (Entry, error) {
|
|||
p.series = p.l.b[p.start:p.l.i]
|
||||
t2 = p.nextToken()
|
||||
}
|
||||
if t2 != tValue {
|
||||
return EntryInvalid, p.parseError("expected value after metric", t2)
|
||||
}
|
||||
if p.val, err = parseFloat(yoloString(p.l.buf())); err != nil {
|
||||
return EntryInvalid, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i])
|
||||
}
|
||||
// Ensure canonical NaN value.
|
||||
if math.IsNaN(p.val) {
|
||||
p.val = math.Float64frombits(value.NormalNaN)
|
||||
}
|
||||
p.hasTS = false
|
||||
switch t := p.nextToken(); t {
|
||||
case tLinebreak:
|
||||
break
|
||||
case tTimestamp:
|
||||
p.hasTS = true
|
||||
if p.ts, err = strconv.ParseInt(yoloString(p.l.buf()), 10, 64); err != nil {
|
||||
return EntryInvalid, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i])
|
||||
}
|
||||
if t2 := p.nextToken(); t2 != tLinebreak {
|
||||
return EntryInvalid, p.parseError("expected next entry after timestamp", t2)
|
||||
}
|
||||
default:
|
||||
return EntryInvalid, p.parseError("expected timestamp or new record", t)
|
||||
}
|
||||
return EntrySeries, nil
|
||||
return p.parseMetricSuffix(t2)
|
||||
|
||||
default:
|
||||
err = p.parseError("expected a valid start token", t)
|
||||
|
@ -385,19 +387,43 @@ func (p *PromParser) Next() (Entry, error) {
|
|||
return EntryInvalid, err
|
||||
}
|
||||
|
||||
// parseLVals parses the contents inside the braces.
|
||||
func (p *PromParser) parseLVals() error {
|
||||
t := p.nextToken()
|
||||
for {
|
||||
curTStart := p.l.start
|
||||
curTI := p.l.i
|
||||
switch t {
|
||||
case tBraceClose:
|
||||
return nil
|
||||
case tLName:
|
||||
case tQString:
|
||||
default:
|
||||
return p.parseError("expected label name", t)
|
||||
}
|
||||
p.offsets = append(p.offsets, p.l.start, p.l.i)
|
||||
|
||||
if t := p.nextToken(); t != tEqual {
|
||||
t = p.nextToken()
|
||||
// A quoted string followed by a comma or brace is a metric name. Set the
|
||||
// offsets and continue processing.
|
||||
if t == tComma || t == tBraceClose {
|
||||
if p.offsets[0] != -1 || p.offsets[1] != -1 {
|
||||
return fmt.Errorf("metric name already set while parsing: %q", p.l.b[p.start:p.l.i])
|
||||
}
|
||||
p.offsets[0] = curTStart + 1
|
||||
p.offsets[1] = curTI - 1
|
||||
if t == tBraceClose {
|
||||
return nil
|
||||
}
|
||||
t = p.nextToken()
|
||||
continue
|
||||
}
|
||||
// We have a label name, and it might be quoted.
|
||||
if p.l.b[curTStart] == '"' {
|
||||
curTStart++
|
||||
curTI--
|
||||
}
|
||||
p.offsets = append(p.offsets, curTStart, curTI)
|
||||
if t != tEqual {
|
||||
return p.parseError("expected equal", t)
|
||||
}
|
||||
if t := p.nextToken(); t != tLValue {
|
||||
|
@ -411,13 +437,51 @@ func (p *PromParser) parseLVals() error {
|
|||
// and last character.
|
||||
p.offsets = append(p.offsets, p.l.start+1, p.l.i-1)
|
||||
|
||||
// Free trailing commas are allowed.
|
||||
// Free trailing commas are allowed. NOTE: this allows spaces between label
|
||||
// names, unlike in OpenMetrics. It is not clear if this is intended or an
|
||||
// accidental bug.
|
||||
if t = p.nextToken(); t == tComma {
|
||||
t = p.nextToken()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parseMetricSuffix parses the end of the line after the metric name and
|
||||
// labels. It starts parsing with the provided token.
|
||||
func (p *PromParser) parseMetricSuffix(t token) (Entry, error) {
|
||||
if p.offsets[0] == -1 {
|
||||
return EntryInvalid, fmt.Errorf("metric name not set while parsing: %q", p.l.b[p.start:p.l.i])
|
||||
}
|
||||
if t != tValue {
|
||||
return EntryInvalid, p.parseError("expected value after metric", t)
|
||||
}
|
||||
var err error
|
||||
if p.val, err = parseFloat(yoloString(p.l.buf())); err != nil {
|
||||
return EntryInvalid, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i])
|
||||
}
|
||||
// Ensure canonical NaN value.
|
||||
if math.IsNaN(p.val) {
|
||||
p.val = math.Float64frombits(value.NormalNaN)
|
||||
}
|
||||
p.hasTS = false
|
||||
switch t := p.nextToken(); t {
|
||||
case tLinebreak:
|
||||
break
|
||||
case tTimestamp:
|
||||
p.hasTS = true
|
||||
if p.ts, err = strconv.ParseInt(yoloString(p.l.buf()), 10, 64); err != nil {
|
||||
return EntryInvalid, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i])
|
||||
}
|
||||
if t2 := p.nextToken(); t2 != tLinebreak {
|
||||
return EntryInvalid, p.parseError("expected next entry after timestamp", t2)
|
||||
}
|
||||
default:
|
||||
return EntryInvalid, p.parseError("expected timestamp or new record", t)
|
||||
}
|
||||
|
||||
return EntrySeries, nil
|
||||
}
|
||||
|
||||
var lvalReplacer = strings.NewReplacer(
|
||||
`\"`, "\"",
|
||||
`\\`, "\\",
|
||||
|
@ -429,6 +493,14 @@ var helpReplacer = strings.NewReplacer(
|
|||
`\n`, "\n",
|
||||
)
|
||||
|
||||
func unreplace(s string) string {
|
||||
// Replacer causes allocations. Replace only when necessary.
|
||||
if strings.IndexByte(s, byte('\\')) >= 0 {
|
||||
return lvalReplacer.Replace(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func yoloString(b []byte) string {
|
||||
return *((*string)(unsafe.Pointer(&b)))
|
||||
}
|
||||
|
|
|
@ -15,19 +15,34 @@ package textparse
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/common/expfmt"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/klauspost/compress/gzip"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/prometheus/common/expfmt"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"github.com/prometheus/prometheus/model/exemplar"
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
"github.com/prometheus/prometheus/util/testutil"
|
||||
)
|
||||
|
||||
type expectedParse struct {
|
||||
lset labels.Labels
|
||||
m string
|
||||
t *int64
|
||||
v float64
|
||||
typ model.MetricType
|
||||
help string
|
||||
unit string
|
||||
comment string
|
||||
e *exemplar.Exemplar
|
||||
}
|
||||
|
||||
func TestPromParse(t *testing.T) {
|
||||
input := `# HELP go_gc_duration_seconds A summary of the GC invocation durations.
|
||||
# TYPE go_gc_duration_seconds summary
|
||||
|
@ -47,6 +62,7 @@ go_gc_duration_seconds{ quantile="1.0", a="b" } 8.3835e-05
|
|||
go_gc_duration_seconds { quantile="1.0", a="b" } 8.3835e-05
|
||||
go_gc_duration_seconds { quantile= "1.0", a= "b", } 8.3835e-05
|
||||
go_gc_duration_seconds { quantile = "1.0", a = "b" } 8.3835e-05
|
||||
go_gc_duration_seconds { quantile = "2.0" a = "b" } 8.3835e-05
|
||||
go_gc_duration_seconds_count 99
|
||||
some:aggregate:rate5m{a_b="c"} 1
|
||||
# HELP go_goroutines Number of goroutines that currently exist.
|
||||
|
@ -60,15 +76,7 @@ testmetric{label="\"bar\""} 1`
|
|||
|
||||
int64p := func(x int64) *int64 { return &x }
|
||||
|
||||
exp := []struct {
|
||||
lset labels.Labels
|
||||
m string
|
||||
t *int64
|
||||
v float64
|
||||
typ model.MetricType
|
||||
help string
|
||||
comment string
|
||||
}{
|
||||
exp := []expectedParse{
|
||||
{
|
||||
m: "go_gc_duration_seconds",
|
||||
help: "A summary of the GC invocation durations.",
|
||||
|
@ -129,6 +137,11 @@ testmetric{label="\"bar\""} 1`
|
|||
m: `go_gc_duration_seconds { quantile = "1.0", a = "b" }`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "1.0", "a", "b"),
|
||||
}, {
|
||||
// NOTE: Unlike OpenMetrics, Promparse allows spaces between label terms. This appears to be unintended and should probably be fixed.
|
||||
m: `go_gc_duration_seconds { quantile = "2.0" a = "b" }`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "go_gc_duration_seconds", "quantile", "2.0", "a", "b"),
|
||||
}, {
|
||||
m: `go_gc_duration_seconds_count`,
|
||||
v: 99,
|
||||
|
@ -170,7 +183,11 @@ testmetric{label="\"bar\""} 1`
|
|||
},
|
||||
}
|
||||
|
||||
p := NewPromParser([]byte(input))
|
||||
p := NewPromParser([]byte(input), labels.NewSymbolTable())
|
||||
checkParseResults(t, p, exp)
|
||||
}
|
||||
|
||||
func checkParseResults(t *testing.T, p Parser, exp []expectedParse) {
|
||||
i := 0
|
||||
|
||||
var res labels.Labels
|
||||
|
@ -191,7 +208,16 @@ testmetric{label="\"bar\""} 1`
|
|||
require.Equal(t, exp[i].m, string(m))
|
||||
require.Equal(t, exp[i].t, ts)
|
||||
require.Equal(t, exp[i].v, v)
|
||||
require.Equal(t, exp[i].lset, res)
|
||||
testutil.RequireEqual(t, exp[i].lset, res)
|
||||
|
||||
var e exemplar.Exemplar
|
||||
found := p.Exemplar(&e)
|
||||
if exp[i].e == nil {
|
||||
require.False(t, found)
|
||||
} else {
|
||||
require.True(t, found)
|
||||
testutil.RequireEqual(t, *exp[i].e, e)
|
||||
}
|
||||
|
||||
case EntryType:
|
||||
m, typ := p.Type()
|
||||
|
@ -203,6 +229,11 @@ testmetric{label="\"bar\""} 1`
|
|||
require.Equal(t, exp[i].m, string(m))
|
||||
require.Equal(t, exp[i].help, string(h))
|
||||
|
||||
case EntryUnit:
|
||||
m, u := p.Unit()
|
||||
require.Equal(t, exp[i].m, string(m))
|
||||
require.Equal(t, exp[i].unit, string(u))
|
||||
|
||||
case EntryComment:
|
||||
require.Equal(t, exp[i].comment, string(p.Comment()))
|
||||
}
|
||||
|
@ -212,6 +243,86 @@ testmetric{label="\"bar\""} 1`
|
|||
require.Len(t, exp, i)
|
||||
}
|
||||
|
||||
func TestUTF8PromParse(t *testing.T) {
|
||||
oldValidationScheme := model.NameValidationScheme
|
||||
model.NameValidationScheme = model.UTF8Validation
|
||||
defer func() {
|
||||
model.NameValidationScheme = oldValidationScheme
|
||||
}()
|
||||
|
||||
input := `# HELP "go.gc_duration_seconds" A summary of the GC invocation durations.
|
||||
# TYPE "go.gc_duration_seconds" summary
|
||||
{"go.gc_duration_seconds",quantile="0"} 4.9351e-05
|
||||
{"go.gc_duration_seconds",quantile="0.25",} 7.424100000000001e-05
|
||||
{"go.gc_duration_seconds",quantile="0.5",a="b"} 8.3835e-05
|
||||
{"go.gc_duration_seconds",quantile="0.8", a="b"} 8.3835e-05
|
||||
{"go.gc_duration_seconds", quantile="0.9", a="b"} 8.3835e-05
|
||||
{"go.gc_duration_seconds", quantile="1.0", a="b" } 8.3835e-05
|
||||
{ "go.gc_duration_seconds", quantile="1.0", a="b" } 8.3835e-05
|
||||
{ "go.gc_duration_seconds", quantile= "1.0", a= "b", } 8.3835e-05
|
||||
{ "go.gc_duration_seconds", quantile = "1.0", a = "b" } 8.3835e-05
|
||||
{"go.gc_duration_seconds_count"} 99
|
||||
{"Heizölrückstoßabdämpfung 10€ metric with \"interesting\" {character\nchoices}","strange©™\n'quoted' \"name\""="6"} 10.0`
|
||||
|
||||
exp := []expectedParse{
|
||||
{
|
||||
m: "go.gc_duration_seconds",
|
||||
help: "A summary of the GC invocation durations.",
|
||||
}, {
|
||||
m: "go.gc_duration_seconds",
|
||||
typ: model.MetricTypeSummary,
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds",quantile="0"}`,
|
||||
v: 4.9351e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0"),
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds",quantile="0.25",}`,
|
||||
v: 7.424100000000001e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0.25"),
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds",quantile="0.5",a="b"}`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0.5", "a", "b"),
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds",quantile="0.8", a="b"}`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0.8", "a", "b"),
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds", quantile="0.9", a="b"}`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0.9", "a", "b"),
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds", quantile="1.0", a="b" }`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "1.0", "a", "b"),
|
||||
}, {
|
||||
m: `{ "go.gc_duration_seconds", quantile="1.0", a="b" }`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "1.0", "a", "b"),
|
||||
}, {
|
||||
m: `{ "go.gc_duration_seconds", quantile= "1.0", a= "b", }`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "1.0", "a", "b"),
|
||||
}, {
|
||||
m: `{ "go.gc_duration_seconds", quantile = "1.0", a = "b" }`,
|
||||
v: 8.3835e-05,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "1.0", "a", "b"),
|
||||
}, {
|
||||
m: `{"go.gc_duration_seconds_count"}`,
|
||||
v: 99,
|
||||
lset: labels.FromStrings("__name__", "go.gc_duration_seconds_count"),
|
||||
}, {
|
||||
m: `{"Heizölrückstoßabdämpfung 10€ metric with \"interesting\" {character\nchoices}","strange©™\n'quoted' \"name\""="6"}`,
|
||||
v: 10.0,
|
||||
lset: labels.FromStrings("__name__", `Heizölrückstoßabdämpfung 10€ metric with "interesting" {character
|
||||
choices}`, "strange©™\n'quoted' \"name\"", "6"),
|
||||
},
|
||||
}
|
||||
|
||||
p := NewPromParser([]byte(input), labels.NewSymbolTable())
|
||||
checkParseResults(t, p, exp)
|
||||
}
|
||||
|
||||
func TestPromParseErrors(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
|
@ -237,6 +348,14 @@ func TestPromParseErrors(t *testing.T) {
|
|||
input: "a{b=\"\xff\"} 1\n",
|
||||
err: "invalid UTF-8 label value: \"\\\"\\xff\\\"\"",
|
||||
},
|
||||
{
|
||||
input: `{"a", "b = "c"}`,
|
||||
err: "expected equal, got \"c\\\"\" (\"LNAME\") while parsing: \"{\\\"a\\\", \\\"b = \\\"c\\\"\"",
|
||||
},
|
||||
{
|
||||
input: `{"a",b\nc="d"} 1`,
|
||||
err: "expected equal, got \"\\\\\" (\"INVALID\") while parsing: \"{\\\"a\\\",b\\\\\"",
|
||||
},
|
||||
{
|
||||
input: "a true\n",
|
||||
err: "strconv.ParseFloat: parsing \"true\": invalid syntax while parsing: \"a true\"",
|
||||
|
@ -267,7 +386,7 @@ func TestPromParseErrors(t *testing.T) {
|
|||
},
|
||||
{
|
||||
input: `{a="ok"} 1`,
|
||||
err: "expected a valid start token, got \"{\" (\"INVALID\") while parsing: \"{\"",
|
||||
err: "metric name not set while parsing: \"{a=\\\"ok\\\"} 1\"",
|
||||
},
|
||||
{
|
||||
input: "# TYPE #\n#EOF\n",
|
||||
|
@ -280,7 +399,7 @@ func TestPromParseErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, c := range cases {
|
||||
p := NewPromParser([]byte(c.input))
|
||||
p := NewPromParser([]byte(c.input), labels.NewSymbolTable())
|
||||
var err error
|
||||
for err == nil {
|
||||
_, err = p.Next()
|
||||
|
@ -334,7 +453,7 @@ func TestPromNullByteHandling(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, c := range cases {
|
||||
p := NewPromParser([]byte(c.input))
|
||||
p := NewPromParser([]byte(c.input), labels.NewSymbolTable())
|
||||
var err error
|
||||
for err == nil {
|
||||
_, err = p.Next()
|
||||
|
@ -355,7 +474,7 @@ const (
|
|||
)
|
||||
|
||||
func BenchmarkParse(b *testing.B) {
|
||||
for parserName, parser := range map[string]func([]byte) Parser{
|
||||
for parserName, parser := range map[string]func([]byte, *labels.SymbolTable) Parser{
|
||||
"prometheus": NewPromParser,
|
||||
"openmetrics": NewOpenMetricsParser,
|
||||
} {
|
||||
|
@ -374,8 +493,9 @@ func BenchmarkParse(b *testing.B) {
|
|||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
st := labels.NewSymbolTable()
|
||||
for i := 0; i < b.N; i += promtestdataSampleCount {
|
||||
p := parser(buf)
|
||||
p := parser(buf, st)
|
||||
|
||||
Outer:
|
||||
for i < b.N {
|
||||
|
@ -402,8 +522,9 @@ func BenchmarkParse(b *testing.B) {
|
|||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
st := labels.NewSymbolTable()
|
||||
for i := 0; i < b.N; i += promtestdataSampleCount {
|
||||
p := parser(buf)
|
||||
p := parser(buf, st)
|
||||
|
||||
Outer:
|
||||
for i < b.N {
|
||||
|
@ -435,8 +556,9 @@ func BenchmarkParse(b *testing.B) {
|
|||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
st := labels.NewSymbolTable()
|
||||
for i := 0; i < b.N; i += promtestdataSampleCount {
|
||||
p := parser(buf)
|
||||
p := parser(buf, st)
|
||||
|
||||
Outer:
|
||||
for i < b.N {
|
||||
|
@ -472,7 +594,7 @@ func BenchmarkParse(b *testing.B) {
|
|||
for i := 0; i < b.N; i += promtestdataSampleCount {
|
||||
decSamples := make(model.Vector, 0, 50)
|
||||
sdec := expfmt.SampleDecoder{
|
||||
Dec: expfmt.NewDecoder(bytes.NewReader(buf), expfmt.FmtText),
|
||||
Dec: expfmt.NewDecoder(bytes.NewReader(buf), expfmt.NewFormat(expfmt.TypeTextPlain)),
|
||||
Opts: &expfmt.DecodeOptions{
|
||||
Timestamp: model.TimeFromUnixNano(0),
|
||||
},
|
||||
|
|
|
@ -56,6 +56,8 @@ type ProtobufParser struct {
|
|||
fieldPos int
|
||||
fieldsDone bool // true if no more fields of a Summary or (legacy) Histogram to be processed.
|
||||
redoClassic bool // true after parsing a native histogram if we need to parse it again as a classic histogram.
|
||||
// exemplarPos is the position within the exemplars slice of a native histogram.
|
||||
exemplarPos int
|
||||
|
||||
// exemplarReturned is set to true each time an exemplar has been
|
||||
// returned, and set back to false upon each Next() call.
|
||||
|
@ -78,13 +80,14 @@ type ProtobufParser struct {
|
|||
}
|
||||
|
||||
// NewProtobufParser returns a parser for the payload in the byte slice.
|
||||
func NewProtobufParser(b []byte, parseClassicHistograms bool) Parser {
|
||||
func NewProtobufParser(b []byte, parseClassicHistograms bool, st *labels.SymbolTable) Parser {
|
||||
return &ProtobufParser{
|
||||
in: b,
|
||||
state: EntryInvalid,
|
||||
mf: &dto.MetricFamily{},
|
||||
metricBytes: &bytes.Buffer{},
|
||||
parseClassicHistograms: parseClassicHistograms,
|
||||
builder: labels.NewScratchBuilderWithSymbolTable(st, 16),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,8 +307,9 @@ func (p *ProtobufParser) Metric(l *labels.Labels) string {
|
|||
|
||||
// Exemplar writes the exemplar of the current sample into the passed
|
||||
// exemplar. It returns if an exemplar exists or not. In case of a native
|
||||
// histogram, the legacy bucket section is still used for exemplars. To ingest
|
||||
// all exemplars, call the Exemplar method repeatedly until it returns false.
|
||||
// histogram, the exemplars in the native histogram will be returned.
|
||||
// If this field is empty, the classic bucket section is still used for exemplars.
|
||||
// To ingest all exemplars, call the Exemplar method repeatedly until it returns false.
|
||||
func (p *ProtobufParser) Exemplar(ex *exemplar.Exemplar) bool {
|
||||
if p.exemplarReturned && p.state == EntrySeries {
|
||||
// We only ever return one exemplar per (non-native-histogram) series.
|
||||
|
@ -317,28 +321,42 @@ func (p *ProtobufParser) Exemplar(ex *exemplar.Exemplar) bool {
|
|||
case dto.MetricType_COUNTER:
|
||||
exProto = m.GetCounter().GetExemplar()
|
||||
case dto.MetricType_HISTOGRAM, dto.MetricType_GAUGE_HISTOGRAM:
|
||||
bb := m.GetHistogram().GetBucket()
|
||||
isClassic := p.state == EntrySeries
|
||||
if p.fieldPos < 0 {
|
||||
if isClassic {
|
||||
return false // At _count or _sum.
|
||||
if !isClassic && len(m.GetHistogram().GetExemplars()) > 0 {
|
||||
exs := m.GetHistogram().GetExemplars()
|
||||
for p.exemplarPos < len(exs) {
|
||||
exProto = exs[p.exemplarPos]
|
||||
p.exemplarPos++
|
||||
if exProto != nil && exProto.GetTimestamp() != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
p.fieldPos = 0 // Start at 1st bucket for native histograms.
|
||||
}
|
||||
for p.fieldPos < len(bb) {
|
||||
exProto = bb[p.fieldPos].GetExemplar()
|
||||
if isClassic {
|
||||
break
|
||||
if exProto != nil && exProto.GetTimestamp() == nil {
|
||||
return false
|
||||
}
|
||||
p.fieldPos++
|
||||
// We deliberately drop exemplars with no timestamp only for native histograms.
|
||||
if exProto != nil && (isClassic || exProto.GetTimestamp() != nil) {
|
||||
break // Found a classic histogram exemplar or a native histogram exemplar with a timestamp.
|
||||
} else {
|
||||
bb := m.GetHistogram().GetBucket()
|
||||
if p.fieldPos < 0 {
|
||||
if isClassic {
|
||||
return false // At _count or _sum.
|
||||
}
|
||||
p.fieldPos = 0 // Start at 1st bucket for native histograms.
|
||||
}
|
||||
for p.fieldPos < len(bb) {
|
||||
exProto = bb[p.fieldPos].GetExemplar()
|
||||
if isClassic {
|
||||
break
|
||||
}
|
||||
p.fieldPos++
|
||||
// We deliberately drop exemplars with no timestamp only for native histograms.
|
||||
if exProto != nil && (isClassic || exProto.GetTimestamp() != nil) {
|
||||
break // Found a classic histogram exemplar or a native histogram exemplar with a timestamp.
|
||||
}
|
||||
}
|
||||
// If the last exemplar for native histograms has no timestamp, ignore it.
|
||||
if !isClassic && exProto.GetTimestamp() == nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// If the last exemplar for native histograms has no timestamp, ignore it.
|
||||
if !isClassic && exProto.GetTimestamp() == nil {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/prometheus/prometheus/model/exemplar"
|
||||
"github.com/prometheus/prometheus/model/histogram"
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
"github.com/prometheus/prometheus/util/testutil"
|
||||
|
||||
dto "github.com/prometheus/prometheus/prompb/io/prometheus/client"
|
||||
)
|
||||
|
@ -595,6 +596,105 @@ metric: <
|
|||
>
|
||||
>
|
||||
|
||||
`,
|
||||
`name: "test_histogram_with_native_histogram_exemplars"
|
||||
help: "A histogram with native histogram exemplars."
|
||||
type: HISTOGRAM
|
||||
metric: <
|
||||
histogram: <
|
||||
sample_count: 175
|
||||
sample_sum: 0.0008280461746287094
|
||||
bucket: <
|
||||
cumulative_count: 2
|
||||
upper_bound: -0.0004899999999999998
|
||||
>
|
||||
bucket: <
|
||||
cumulative_count: 4
|
||||
upper_bound: -0.0003899999999999998
|
||||
exemplar: <
|
||||
label: <
|
||||
name: "dummyID"
|
||||
value: "59727"
|
||||
>
|
||||
value: -0.00039
|
||||
timestamp: <
|
||||
seconds: 1625851155
|
||||
nanos: 146848499
|
||||
>
|
||||
>
|
||||
>
|
||||
bucket: <
|
||||
cumulative_count: 16
|
||||
upper_bound: -0.0002899999999999998
|
||||
exemplar: <
|
||||
label: <
|
||||
name: "dummyID"
|
||||
value: "5617"
|
||||
>
|
||||
value: -0.00029
|
||||
>
|
||||
>
|
||||
schema: 3
|
||||
zero_threshold: 2.938735877055719e-39
|
||||
zero_count: 2
|
||||
negative_span: <
|
||||
offset: -162
|
||||
length: 1
|
||||
>
|
||||
negative_span: <
|
||||
offset: 23
|
||||
length: 4
|
||||
>
|
||||
negative_delta: 1
|
||||
negative_delta: 3
|
||||
negative_delta: -2
|
||||
negative_delta: -1
|
||||
negative_delta: 1
|
||||
positive_span: <
|
||||
offset: -161
|
||||
length: 1
|
||||
>
|
||||
positive_span: <
|
||||
offset: 8
|
||||
length: 3
|
||||
>
|
||||
positive_delta: 1
|
||||
positive_delta: 2
|
||||
positive_delta: -1
|
||||
positive_delta: -1
|
||||
exemplars: <
|
||||
label: <
|
||||
name: "dummyID"
|
||||
value: "59780"
|
||||
>
|
||||
value: -0.00039
|
||||
timestamp: <
|
||||
seconds: 1625851155
|
||||
nanos: 146848499
|
||||
>
|
||||
>
|
||||
exemplars: <
|
||||
label: <
|
||||
name: "dummyID"
|
||||
value: "5617"
|
||||
>
|
||||
value: -0.00029
|
||||
>
|
||||
exemplars: <
|
||||
label: <
|
||||
name: "dummyID"
|
||||
value: "59772"
|
||||
>
|
||||
value: -0.00052
|
||||
timestamp: <
|
||||
seconds: 1625851160
|
||||
nanos: 156848499
|
||||
>
|
||||
>
|
||||
>
|
||||
timestamp_ms: 1234568
|
||||
>
|
||||
|
||||
`,
|
||||
}
|
||||
|
||||
|
@ -643,7 +743,7 @@ func TestProtobufParse(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "ignore classic buckets of native histograms",
|
||||
parser: NewProtobufParser(inputBuf.Bytes(), false),
|
||||
parser: NewProtobufParser(inputBuf.Bytes(), false, labels.NewSymbolTable()),
|
||||
expected: []parseResult{
|
||||
{
|
||||
m: "go_build_info",
|
||||
|
@ -1140,11 +1240,47 @@ func TestProtobufParse(t *testing.T) {
|
|||
"__name__", "test_gaugehistogram_with_createdtimestamp",
|
||||
),
|
||||
},
|
||||
{
|
||||
m: "test_histogram_with_native_histogram_exemplars",
|
||||
help: "A histogram with native histogram exemplars.",
|
||||
},
|
||||
{
|
||||
m: "test_histogram_with_native_histogram_exemplars",
|
||||
typ: model.MetricTypeHistogram,
|
||||
},
|
||||
{
|
||||
m: "test_histogram_with_native_histogram_exemplars",
|
||||
t: 1234568,
|
||||
shs: &histogram.Histogram{
|
||||
Count: 175,
|
||||
ZeroCount: 2,
|
||||
Sum: 0.0008280461746287094,
|
||||
ZeroThreshold: 2.938735877055719e-39,
|
||||
Schema: 3,
|
||||
PositiveSpans: []histogram.Span{
|
||||
{Offset: -161, Length: 1},
|
||||
{Offset: 8, Length: 3},
|
||||
},
|
||||
NegativeSpans: []histogram.Span{
|
||||
{Offset: -162, Length: 1},
|
||||
{Offset: 23, Length: 4},
|
||||
},
|
||||
PositiveBuckets: []int64{1, 2, -1, -1},
|
||||
NegativeBuckets: []int64{1, 3, -2, -1, 1},
|
||||
},
|
||||
lset: labels.FromStrings(
|
||||
"__name__", "test_histogram_with_native_histogram_exemplars",
|
||||
),
|
||||
e: []exemplar.Exemplar{
|
||||
{Labels: labels.FromStrings("dummyID", "59780"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
|
||||
{Labels: labels.FromStrings("dummyID", "59772"), Value: -0.00052, HasTs: true, Ts: 1625851160156},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "parse classic and native buckets",
|
||||
parser: NewProtobufParser(inputBuf.Bytes(), true),
|
||||
parser: NewProtobufParser(inputBuf.Bytes(), true, labels.NewSymbolTable()),
|
||||
expected: []parseResult{
|
||||
{ // 0
|
||||
m: "go_build_info",
|
||||
|
@ -1958,6 +2094,100 @@ func TestProtobufParse(t *testing.T) {
|
|||
"__name__", "test_gaugehistogram_with_createdtimestamp",
|
||||
),
|
||||
},
|
||||
{ // 94
|
||||
m: "test_histogram_with_native_histogram_exemplars",
|
||||
help: "A histogram with native histogram exemplars.",
|
||||
},
|
||||
{ // 95
|
||||
m: "test_histogram_with_native_histogram_exemplars",
|
||||
typ: model.MetricTypeHistogram,
|
||||
},
|
||||
{ // 96
|
||||
m: "test_histogram_with_native_histogram_exemplars",
|
||||
t: 1234568,
|
||||
shs: &histogram.Histogram{
|
||||
Count: 175,
|
||||
ZeroCount: 2,
|
||||
Sum: 0.0008280461746287094,
|
||||
ZeroThreshold: 2.938735877055719e-39,
|
||||
Schema: 3,
|
||||
PositiveSpans: []histogram.Span{
|
||||
{Offset: -161, Length: 1},
|
||||
{Offset: 8, Length: 3},
|
||||
},
|
||||
NegativeSpans: []histogram.Span{
|
||||
{Offset: -162, Length: 1},
|
||||
{Offset: 23, Length: 4},
|
||||
},
|
||||
PositiveBuckets: []int64{1, 2, -1, -1},
|
||||
NegativeBuckets: []int64{1, 3, -2, -1, 1},
|
||||
},
|
||||
lset: labels.FromStrings(
|
||||
"__name__", "test_histogram_with_native_histogram_exemplars",
|
||||
),
|
||||
e: []exemplar.Exemplar{
|
||||
{Labels: labels.FromStrings("dummyID", "59780"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
|
||||
{Labels: labels.FromStrings("dummyID", "59772"), Value: -0.00052, HasTs: true, Ts: 1625851160156},
|
||||
},
|
||||
},
|
||||
{ // 97
|
||||
m: "test_histogram_with_native_histogram_exemplars_count",
|
||||
t: 1234568,
|
||||
v: 175,
|
||||
lset: labels.FromStrings(
|
||||
"__name__", "test_histogram_with_native_histogram_exemplars_count",
|
||||
),
|
||||
},
|
||||
{ // 98
|
||||
m: "test_histogram_with_native_histogram_exemplars_sum",
|
||||
t: 1234568,
|
||||
v: 0.0008280461746287094,
|
||||
lset: labels.FromStrings(
|
||||
"__name__", "test_histogram_with_native_histogram_exemplars_sum",
|
||||
),
|
||||
},
|
||||
{ // 99
|
||||
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff-0.0004899999999999998",
|
||||
t: 1234568,
|
||||
v: 2,
|
||||
lset: labels.FromStrings(
|
||||
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
|
||||
"le", "-0.0004899999999999998",
|
||||
),
|
||||
},
|
||||
{ // 100
|
||||
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff-0.0003899999999999998",
|
||||
t: 1234568,
|
||||
v: 4,
|
||||
lset: labels.FromStrings(
|
||||
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
|
||||
"le", "-0.0003899999999999998",
|
||||
),
|
||||
e: []exemplar.Exemplar{
|
||||
{Labels: labels.FromStrings("dummyID", "59727"), Value: -0.00039, HasTs: true, Ts: 1625851155146},
|
||||
},
|
||||
},
|
||||
{ // 101
|
||||
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff-0.0002899999999999998",
|
||||
t: 1234568,
|
||||
v: 16,
|
||||
lset: labels.FromStrings(
|
||||
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
|
||||
"le", "-0.0002899999999999998",
|
||||
),
|
||||
e: []exemplar.Exemplar{
|
||||
{Labels: labels.FromStrings("dummyID", "5617"), Value: -0.00029, HasTs: false},
|
||||
},
|
||||
},
|
||||
{ // 102
|
||||
m: "test_histogram_with_native_histogram_exemplars_bucket\xffle\xff+Inf",
|
||||
t: 1234568,
|
||||
v: 175,
|
||||
lset: labels.FromStrings(
|
||||
"__name__", "test_histogram_with_native_histogram_exemplars_bucket",
|
||||
"le", "+Inf",
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -1993,12 +2223,12 @@ func TestProtobufParse(t *testing.T) {
|
|||
require.Equal(t, int64(0), exp[i].t, "i: %d", i)
|
||||
}
|
||||
require.Equal(t, exp[i].v, v, "i: %d", i)
|
||||
require.Equal(t, exp[i].lset, res, "i: %d", i)
|
||||
testutil.RequireEqual(t, exp[i].lset, res, "i: %d", i)
|
||||
if len(exp[i].e) == 0 {
|
||||
require.False(t, eFound, "i: %d", i)
|
||||
} else {
|
||||
require.True(t, eFound, "i: %d", i)
|
||||
require.Equal(t, exp[i].e[0], e, "i: %d", i)
|
||||
testutil.RequireEqual(t, exp[i].e[0], e, "i: %d", i)
|
||||
require.False(t, p.Exemplar(&e), "too many exemplars returned, i: %d", i)
|
||||
}
|
||||
if exp[i].ct != 0 {
|
||||
|
@ -2017,7 +2247,7 @@ func TestProtobufParse(t *testing.T) {
|
|||
} else {
|
||||
require.Equal(t, int64(0), exp[i].t, "i: %d", i)
|
||||
}
|
||||
require.Equal(t, exp[i].lset, res, "i: %d", i)
|
||||
testutil.RequireEqual(t, exp[i].lset, res, "i: %d", i)
|
||||
require.Equal(t, exp[i].m, string(m), "i: %d", i)
|
||||
if shs != nil {
|
||||
require.Equal(t, exp[i].shs, shs, "i: %d", i)
|
||||
|
@ -2026,7 +2256,7 @@ func TestProtobufParse(t *testing.T) {
|
|||
}
|
||||
j := 0
|
||||
for e := (exemplar.Exemplar{}); p.Exemplar(&e); j++ {
|
||||
require.Equal(t, exp[i].e[j], e, "i: %d", i)
|
||||
testutil.RequireEqual(t, exp[i].e[j], e, "i: %d", i)
|
||||
e = exemplar.Exemplar{}
|
||||
}
|
||||
require.Len(t, exp[i].e, j, "not enough exemplars found, i: %d", i)
|
||||
|
|
|
@ -350,7 +350,7 @@ func (n *Manager) Send(alerts ...*Alert) {
|
|||
n.mtx.Lock()
|
||||
defer n.mtx.Unlock()
|
||||
|
||||
alerts = n.relabelAlerts(alerts)
|
||||
alerts = relabelAlerts(n.opts.RelabelConfigs, n.opts.ExternalLabels, alerts)
|
||||
if len(alerts) == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -378,20 +378,19 @@ func (n *Manager) Send(alerts ...*Alert) {
|
|||
n.setMore()
|
||||
}
|
||||
|
||||
// Attach external labels and process relabelling rules.
|
||||
func (n *Manager) relabelAlerts(alerts []*Alert) []*Alert {
|
||||
func relabelAlerts(relabelConfigs []*relabel.Config, externalLabels labels.Labels, alerts []*Alert) []*Alert {
|
||||
lb := labels.NewBuilder(labels.EmptyLabels())
|
||||
var relabeledAlerts []*Alert
|
||||
|
||||
for _, a := range alerts {
|
||||
lb.Reset(a.Labels)
|
||||
n.opts.ExternalLabels.Range(func(l labels.Label) {
|
||||
externalLabels.Range(func(l labels.Label) {
|
||||
if a.Labels.Get(l.Name) == "" {
|
||||
lb.Set(l.Name, l.Value)
|
||||
}
|
||||
})
|
||||
|
||||
keep := relabel.ProcessBuilder(lb, n.opts.RelabelConfigs...)
|
||||
keep := relabel.ProcessBuilder(lb, relabelConfigs...)
|
||||
if !keep {
|
||||
continue
|
||||
}
|
||||
|
@ -473,17 +472,27 @@ func (n *Manager) sendAll(alerts ...*Alert) bool {
|
|||
)
|
||||
for _, ams := range amSets {
|
||||
var (
|
||||
payload []byte
|
||||
err error
|
||||
payload []byte
|
||||
err error
|
||||
amAlerts = alerts
|
||||
)
|
||||
|
||||
ams.mtx.RLock()
|
||||
|
||||
if len(ams.cfg.AlertRelabelConfigs) > 0 {
|
||||
amAlerts = relabelAlerts(ams.cfg.AlertRelabelConfigs, labels.Labels{}, alerts)
|
||||
if len(amAlerts) == 0 {
|
||||
continue
|
||||
}
|
||||
// We can't use the cached values from previous iteration.
|
||||
v1Payload, v2Payload = nil, nil
|
||||
}
|
||||
|
||||
switch ams.cfg.APIVersion {
|
||||
case config.AlertmanagerAPIVersionV1:
|
||||
{
|
||||
if v1Payload == nil {
|
||||
v1Payload, err = json.Marshal(alerts)
|
||||
v1Payload, err = json.Marshal(amAlerts)
|
||||
if err != nil {
|
||||
level.Error(n.logger).Log("msg", "Encoding alerts for Alertmanager API v1 failed", "err", err)
|
||||
ams.mtx.RUnlock()
|
||||
|
@ -496,7 +505,7 @@ func (n *Manager) sendAll(alerts ...*Alert) bool {
|
|||
case config.AlertmanagerAPIVersionV2:
|
||||
{
|
||||
if v2Payload == nil {
|
||||
openAPIAlerts := alertsToOpenAPIAlerts(alerts)
|
||||
openAPIAlerts := alertsToOpenAPIAlerts(amAlerts)
|
||||
|
||||
v2Payload, err = json.Marshal(openAPIAlerts)
|
||||
if err != nil {
|
||||
|
@ -519,24 +528,29 @@ func (n *Manager) sendAll(alerts ...*Alert) bool {
|
|||
}
|
||||
}
|
||||
|
||||
if len(ams.cfg.AlertRelabelConfigs) > 0 {
|
||||
// We can't use the cached values on the next iteration.
|
||||
v1Payload, v2Payload = nil, nil
|
||||
}
|
||||
|
||||
for _, am := range ams.ams {
|
||||
wg.Add(1)
|
||||
|
||||
ctx, cancel := context.WithTimeout(n.ctx, time.Duration(ams.cfg.Timeout))
|
||||
defer cancel()
|
||||
|
||||
go func(client *http.Client, url string) {
|
||||
go func(ctx context.Context, client *http.Client, url string, payload []byte, count int) {
|
||||
if err := n.sendOne(ctx, client, url, payload); err != nil {
|
||||
level.Error(n.logger).Log("alertmanager", url, "count", len(alerts), "msg", "Error sending alert", "err", err)
|
||||
level.Error(n.logger).Log("alertmanager", url, "count", count, "msg", "Error sending alert", "err", err)
|
||||
n.metrics.errors.WithLabelValues(url).Inc()
|
||||
} else {
|
||||
numSuccess.Inc()
|
||||
}
|
||||
n.metrics.latency.WithLabelValues(url).Observe(time.Since(begin).Seconds())
|
||||
n.metrics.sent.WithLabelValues(url).Add(float64(len(alerts)))
|
||||
n.metrics.sent.WithLabelValues(url).Add(float64(len(amAlerts)))
|
||||
|
||||
wg.Done()
|
||||
}(ams.client, am.url().String())
|
||||
}(ctx, ams.client, am.url().String(), payload, len(amAlerts))
|
||||
}
|
||||
|
||||
ams.mtx.RUnlock()
|
||||
|
|
|
@ -98,6 +98,41 @@ func alertsEqual(a, b []*Alert) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func newTestHTTPServerBuilder(expected *[]*Alert, errc chan<- error, u, p string, status *atomic.Int32) *httptest.Server {
|
||||
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
select {
|
||||
case errc <- err:
|
||||
default:
|
||||
}
|
||||
}()
|
||||
user, pass, _ := r.BasicAuth()
|
||||
if user != u || pass != p {
|
||||
err = fmt.Errorf("unexpected user/password: %s/%s != %s/%s", user, pass, u, p)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error reading body: %w", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var alerts []*Alert
|
||||
err = json.Unmarshal(b, &alerts)
|
||||
if err == nil {
|
||||
err = alertsEqual(*expected, alerts)
|
||||
}
|
||||
w.WriteHeader(int(status.Load()))
|
||||
}))
|
||||
}
|
||||
|
||||
func TestHandlerSendAll(t *testing.T) {
|
||||
var (
|
||||
errc = make(chan error, 1)
|
||||
|
@ -107,42 +142,8 @@ func TestHandlerSendAll(t *testing.T) {
|
|||
status1.Store(int32(http.StatusOK))
|
||||
status2.Store(int32(http.StatusOK))
|
||||
|
||||
newHTTPServer := func(u, p string, status *atomic.Int32) *httptest.Server {
|
||||
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
select {
|
||||
case errc <- err:
|
||||
default:
|
||||
}
|
||||
}()
|
||||
user, pass, _ := r.BasicAuth()
|
||||
if user != u || pass != p {
|
||||
err = fmt.Errorf("unexpected user/password: %s/%s != %s/%s", user, pass, u, p)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error reading body: %w", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var alerts []*Alert
|
||||
err = json.Unmarshal(b, &alerts)
|
||||
if err == nil {
|
||||
err = alertsEqual(expected, alerts)
|
||||
}
|
||||
w.WriteHeader(int(status.Load()))
|
||||
}))
|
||||
}
|
||||
server1 := newHTTPServer("prometheus", "testing_password", &status1)
|
||||
server2 := newHTTPServer("", "", &status2)
|
||||
server1 := newTestHTTPServerBuilder(&expected, errc, "prometheus", "testing_password", &status1)
|
||||
server2 := newTestHTTPServerBuilder(&expected, errc, "", "", &status2)
|
||||
defer server1.Close()
|
||||
defer server2.Close()
|
||||
|
||||
|
@ -213,6 +214,90 @@ func TestHandlerSendAll(t *testing.T) {
|
|||
checkNoErr()
|
||||
}
|
||||
|
||||
func TestHandlerSendAllRemapPerAm(t *testing.T) {
|
||||
var (
|
||||
errc = make(chan error, 1)
|
||||
expected1 = make([]*Alert, 0, maxBatchSize)
|
||||
expected2 = make([]*Alert, 0, maxBatchSize)
|
||||
|
||||
status1, status2 atomic.Int32
|
||||
)
|
||||
status1.Store(int32(http.StatusOK))
|
||||
status2.Store(int32(http.StatusOK))
|
||||
|
||||
server1 := newTestHTTPServerBuilder(&expected1, errc, "", "", &status1)
|
||||
server2 := newTestHTTPServerBuilder(&expected2, errc, "", "", &status2)
|
||||
|
||||
defer server1.Close()
|
||||
defer server2.Close()
|
||||
|
||||
h := NewManager(&Options{}, nil)
|
||||
h.alertmanagers = make(map[string]*alertmanagerSet)
|
||||
|
||||
am1Cfg := config.DefaultAlertmanagerConfig
|
||||
am1Cfg.Timeout = model.Duration(time.Second)
|
||||
|
||||
am2Cfg := config.DefaultAlertmanagerConfig
|
||||
am2Cfg.Timeout = model.Duration(time.Second)
|
||||
am2Cfg.AlertRelabelConfigs = []*relabel.Config{
|
||||
{
|
||||
SourceLabels: model.LabelNames{"alertnamedrop"},
|
||||
Action: "drop",
|
||||
Regex: relabel.MustNewRegexp(".+"),
|
||||
},
|
||||
}
|
||||
|
||||
h.alertmanagers["1"] = &alertmanagerSet{
|
||||
ams: []alertmanager{
|
||||
alertmanagerMock{
|
||||
urlf: func() string { return server1.URL },
|
||||
},
|
||||
},
|
||||
cfg: &am1Cfg,
|
||||
}
|
||||
|
||||
h.alertmanagers["2"] = &alertmanagerSet{
|
||||
ams: []alertmanager{
|
||||
alertmanagerMock{
|
||||
urlf: func() string { return server2.URL },
|
||||
},
|
||||
},
|
||||
cfg: &am2Cfg,
|
||||
}
|
||||
|
||||
for i := range make([]struct{}, maxBatchSize/2) {
|
||||
h.queue = append(h.queue, &Alert{
|
||||
Labels: labels.FromStrings("alertname", fmt.Sprintf("%d", i)),
|
||||
})
|
||||
h.queue = append(h.queue, &Alert{
|
||||
Labels: labels.FromStrings("alertnamedrop", fmt.Sprintf("%d", i)),
|
||||
})
|
||||
|
||||
expected1 = append(expected1, &Alert{
|
||||
Labels: labels.FromStrings("alertname", fmt.Sprintf("%d", i)),
|
||||
})
|
||||
expected1 = append(expected1, &Alert{
|
||||
Labels: labels.FromStrings("alertnamedrop", fmt.Sprintf("%d", i)),
|
||||
})
|
||||
|
||||
expected2 = append(expected2, &Alert{
|
||||
Labels: labels.FromStrings("alertname", fmt.Sprintf("%d", i)),
|
||||
})
|
||||
}
|
||||
|
||||
checkNoErr := func() {
|
||||
t.Helper()
|
||||
select {
|
||||
case err := <-errc:
|
||||
require.NoError(t, err)
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
require.True(t, h.sendAll(h.queue...), "all sends failed unexpectedly")
|
||||
checkNoErr()
|
||||
}
|
||||
|
||||
func TestCustomDo(t *testing.T) {
|
||||
const testURL = "http://testurl.com/"
|
||||
const testBody = "testbody"
|
||||
|
|
|
@ -438,11 +438,13 @@ type Histogram struct {
|
|||
// Use either "positive_delta" or "positive_count", the former for
|
||||
// regular histograms with integer counts, the latter for float
|
||||
// histograms.
|
||||
PositiveDelta []int64 `protobuf:"zigzag64,13,rep,packed,name=positive_delta,json=positiveDelta,proto3" json:"positive_delta,omitempty"`
|
||||
PositiveCount []float64 `protobuf:"fixed64,14,rep,packed,name=positive_count,json=positiveCount,proto3" json:"positive_count,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
PositiveDelta []int64 `protobuf:"zigzag64,13,rep,packed,name=positive_delta,json=positiveDelta,proto3" json:"positive_delta,omitempty"`
|
||||
PositiveCount []float64 `protobuf:"fixed64,14,rep,packed,name=positive_count,json=positiveCount,proto3" json:"positive_count,omitempty"`
|
||||
// Only used for native histograms. These exemplars MUST have a timestamp.
|
||||
Exemplars []*Exemplar `protobuf:"bytes,16,rep,name=exemplars,proto3" json:"exemplars,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Histogram) Reset() { *m = Histogram{} }
|
||||
|
@ -583,6 +585,13 @@ func (m *Histogram) GetPositiveCount() []float64 {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *Histogram) GetExemplars() []*Exemplar {
|
||||
if m != nil {
|
||||
return m.Exemplars
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Bucket struct {
|
||||
CumulativeCount uint64 `protobuf:"varint,1,opt,name=cumulative_count,json=cumulativeCount,proto3" json:"cumulative_count,omitempty"`
|
||||
CumulativeCountFloat float64 `protobuf:"fixed64,4,opt,name=cumulative_count_float,json=cumulativeCountFloat,proto3" json:"cumulative_count_float,omitempty"`
|
||||
|
@ -973,68 +982,69 @@ func init() {
|
|||
}
|
||||
|
||||
var fileDescriptor_d1e5ddb18987a258 = []byte{
|
||||
// 969 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdd, 0x8e, 0xdb, 0x44,
|
||||
0x14, 0xae, 0x9b, 0x5f, 0x9f, 0x6c, 0x76, 0xbd, 0x43, 0x54, 0x59, 0x0b, 0xbb, 0x09, 0x96, 0x90,
|
||||
0x16, 0x84, 0x12, 0x01, 0x45, 0xa0, 0x52, 0x24, 0x76, 0xdb, 0x6d, 0x8a, 0x4a, 0xda, 0x32, 0x49,
|
||||
0x2e, 0xca, 0x8d, 0x35, 0x49, 0x66, 0x1d, 0x0b, 0xdb, 0x63, 0xec, 0x71, 0xc5, 0x72, 0xcf, 0x33,
|
||||
0xf0, 0x02, 0x3c, 0x06, 0xe2, 0x12, 0xf5, 0x92, 0x2b, 0x2e, 0x11, 0xda, 0x27, 0x41, 0xf3, 0x63,
|
||||
0x3b, 0x5b, 0x39, 0x0b, 0x0b, 0x77, 0x33, 0x5f, 0xbe, 0x73, 0xe6, 0x3b, 0xdf, 0x4c, 0xce, 0x31,
|
||||
0x38, 0x3e, 0x1b, 0xc5, 0x09, 0x0b, 0x29, 0x5f, 0xd3, 0x2c, 0x1d, 0x2d, 0x03, 0x9f, 0x46, 0x7c,
|
||||
0x14, 0x52, 0x9e, 0xf8, 0xcb, 0x74, 0x18, 0x27, 0x8c, 0x33, 0xd4, 0xf3, 0xd9, 0xb0, 0xe4, 0x0c,
|
||||
0x15, 0xe7, 0xa0, 0xe7, 0x31, 0x8f, 0x49, 0xc2, 0x48, 0xac, 0x14, 0xf7, 0xa0, 0xef, 0x31, 0xe6,
|
||||
0x05, 0x74, 0x24, 0x77, 0x8b, 0xec, 0x7c, 0xc4, 0xfd, 0x90, 0xa6, 0x9c, 0x84, 0xb1, 0x22, 0x38,
|
||||
0x1f, 0x83, 0xf9, 0x15, 0x59, 0xd0, 0xe0, 0x39, 0xf1, 0x13, 0x84, 0xa0, 0x1e, 0x91, 0x90, 0xda,
|
||||
0xc6, 0xc0, 0x38, 0x36, 0xb1, 0x5c, 0xa3, 0x1e, 0x34, 0x5e, 0x92, 0x20, 0xa3, 0xf6, 0x6d, 0x09,
|
||||
0xaa, 0x8d, 0x73, 0x08, 0x8d, 0x31, 0xc9, 0xbc, 0x8d, 0x9f, 0x45, 0x8c, 0x91, 0xff, 0xfc, 0xb3,
|
||||
0x01, 0xad, 0x07, 0x2c, 0x8b, 0x38, 0x4d, 0xaa, 0x19, 0xe8, 0x1e, 0xb4, 0xe9, 0xf7, 0x34, 0x8c,
|
||||
0x03, 0x92, 0xc8, 0xcc, 0x9d, 0x0f, 0x8f, 0x86, 0x55, 0x75, 0x0d, 0xcf, 0x34, 0x0b, 0x17, 0x7c,
|
||||
0x34, 0x86, 0xfd, 0x65, 0x42, 0x09, 0xa7, 0x2b, 0xb7, 0x28, 0xc7, 0xae, 0xc9, 0x24, 0x07, 0x43,
|
||||
0x55, 0xf0, 0x30, 0x2f, 0x78, 0x38, 0xcb, 0x19, 0xd8, 0xd2, 0x41, 0x05, 0xe2, 0xdc, 0x87, 0xf6,
|
||||
0xd7, 0x19, 0x89, 0xb8, 0x1f, 0x50, 0x74, 0x00, 0xed, 0xef, 0xf4, 0x5a, 0x2b, 0x2d, 0xf6, 0x57,
|
||||
0x3d, 0x28, 0x8a, 0xfc, 0xc3, 0x80, 0xd6, 0x34, 0x0b, 0x43, 0x92, 0x5c, 0xa0, 0xb7, 0x61, 0x27,
|
||||
0x25, 0x61, 0x1c, 0x50, 0x77, 0x29, 0xca, 0x96, 0x19, 0xea, 0xb8, 0xa3, 0x30, 0xe9, 0x04, 0x3a,
|
||||
0x04, 0xd0, 0x94, 0x34, 0x0b, 0x75, 0x26, 0x53, 0x21, 0xd3, 0x2c, 0x44, 0x5f, 0x6c, 0x9c, 0x5f,
|
||||
0x1b, 0xd4, 0xb6, 0x1b, 0x92, 0x2b, 0x3e, 0xad, 0xbf, 0xfa, 0xb3, 0x7f, 0x6b, 0x43, 0x65, 0xa5,
|
||||
0x2d, 0xf5, 0xff, 0x60, 0x4b, 0x1f, 0x5a, 0xf3, 0x88, 0x5f, 0xc4, 0x74, 0xb5, 0xe5, 0x7a, 0x7f,
|
||||
0x6d, 0x80, 0xf9, 0xd8, 0x4f, 0x39, 0xf3, 0x12, 0x12, 0xfe, 0x9b, 0xda, 0xdf, 0x07, 0xb4, 0x49,
|
||||
0x71, 0xcf, 0x03, 0x46, 0xb8, 0xd4, 0x66, 0x60, 0x6b, 0x83, 0xf8, 0x48, 0xe0, 0xff, 0xe4, 0xd4,
|
||||
0x3d, 0x68, 0x2e, 0xb2, 0xe5, 0xb7, 0x94, 0x6b, 0x9f, 0xde, 0xaa, 0xf6, 0xe9, 0x54, 0x72, 0xb4,
|
||||
0x4b, 0x3a, 0xa2, 0xda, 0xa3, 0xbd, 0x9b, 0x7b, 0x84, 0xee, 0x40, 0x33, 0x5d, 0xae, 0x69, 0x48,
|
||||
0xec, 0xc6, 0xc0, 0x38, 0xde, 0xc7, 0x7a, 0x87, 0xde, 0x81, 0xdd, 0x1f, 0x68, 0xc2, 0x5c, 0xbe,
|
||||
0x4e, 0x68, 0xba, 0x66, 0xc1, 0xca, 0x6e, 0x4a, 0xfd, 0x5d, 0x81, 0xce, 0x72, 0x50, 0x94, 0x28,
|
||||
0x69, 0xca, 0xb1, 0x96, 0x74, 0xcc, 0x14, 0x88, 0xf2, 0xeb, 0x18, 0xac, 0xf2, 0x67, 0xed, 0x56,
|
||||
0x5b, 0xe6, 0xd9, 0x2d, 0x48, 0xca, 0xab, 0x27, 0xd0, 0x8d, 0xa8, 0x47, 0xb8, 0xff, 0x92, 0xba,
|
||||
0x69, 0x4c, 0x22, 0xdb, 0x94, 0x9e, 0x0c, 0xae, 0xf3, 0x64, 0x1a, 0x93, 0x48, 0xfb, 0xb2, 0x93,
|
||||
0x07, 0x0b, 0x4c, 0x88, 0x2f, 0x92, 0xad, 0x68, 0xc0, 0x89, 0x0d, 0x83, 0xda, 0x31, 0xc2, 0xc5,
|
||||
0x11, 0x0f, 0x05, 0x78, 0x85, 0xa6, 0x0a, 0xe8, 0x0c, 0x6a, 0xa2, 0xc6, 0x1c, 0x55, 0x45, 0x3c,
|
||||
0x81, 0x6e, 0xcc, 0x52, 0xbf, 0x94, 0xb6, 0x73, 0x33, 0x69, 0x79, 0x70, 0x2e, 0xad, 0x48, 0xa6,
|
||||
0xa4, 0x75, 0x95, 0xb4, 0x1c, 0x2d, 0xa4, 0x15, 0x34, 0x25, 0x6d, 0x57, 0x49, 0xcb, 0x51, 0x29,
|
||||
0xcd, 0xf9, 0xcd, 0x80, 0xa6, 0x3a, 0x10, 0xbd, 0x0b, 0xd6, 0x32, 0x0b, 0xb3, 0x60, 0xb3, 0x1c,
|
||||
0xf5, 0x82, 0xf7, 0x4a, 0x5c, 0x15, 0x74, 0x17, 0xee, 0xbc, 0x4e, 0xbd, 0xf2, 0x92, 0x7b, 0xaf,
|
||||
0x05, 0xa8, 0x1b, 0xea, 0x43, 0x27, 0x8b, 0x63, 0x9a, 0xb8, 0x0b, 0x96, 0x45, 0x2b, 0xfd, 0x9c,
|
||||
0x41, 0x42, 0xa7, 0x02, 0xb9, 0xd2, 0x0a, 0x6b, 0x37, 0x6b, 0x85, 0xce, 0x7d, 0x80, 0xd2, 0x38,
|
||||
0xf1, 0x28, 0xd9, 0xf9, 0x79, 0x4a, 0x55, 0x05, 0xfb, 0x58, 0xef, 0x04, 0x1e, 0xd0, 0xc8, 0xe3,
|
||||
0x6b, 0x79, 0x7a, 0x17, 0xeb, 0x9d, 0xf3, 0x93, 0x01, 0xed, 0x3c, 0x29, 0xfa, 0x0c, 0x1a, 0x81,
|
||||
0x98, 0x04, 0xb6, 0x21, 0xaf, 0xa9, 0x5f, 0xad, 0xa1, 0x18, 0x16, 0xfa, 0x96, 0x54, 0x4c, 0x75,
|
||||
0x87, 0x44, 0x9f, 0x82, 0x79, 0x93, 0x06, 0x5d, 0x92, 0x9d, 0x1f, 0x6b, 0xd0, 0x9c, 0xc8, 0xa9,
|
||||
0xf7, 0xff, 0x74, 0x7d, 0x00, 0x0d, 0x4f, 0xcc, 0x29, 0x3d, 0x63, 0xde, 0xac, 0x0e, 0x96, 0xa3,
|
||||
0x0c, 0x2b, 0x26, 0xfa, 0x04, 0x5a, 0x4b, 0x35, 0xba, 0xb4, 0xe4, 0xc3, 0xea, 0x20, 0x3d, 0xdf,
|
||||
0x70, 0xce, 0x16, 0x81, 0xa9, 0x1a, 0x07, 0xba, 0xeb, 0x6e, 0x09, 0xd4, 0x33, 0x03, 0xe7, 0x6c,
|
||||
0x11, 0x98, 0xa9, 0x7e, 0x2b, 0x9b, 0xc9, 0xd6, 0x40, 0xdd, 0x94, 0x71, 0xce, 0x46, 0x9f, 0x83,
|
||||
0xb9, 0xce, 0xdb, 0xb0, 0x6c, 0x22, 0x5b, 0xed, 0x29, 0xba, 0x35, 0x2e, 0x23, 0x44, 0xe3, 0x2e,
|
||||
0x1c, 0x77, 0xc3, 0x54, 0x76, 0xaa, 0x1a, 0xee, 0x14, 0xd8, 0x24, 0x75, 0x7e, 0x31, 0x60, 0x47,
|
||||
0xdd, 0xc3, 0x23, 0x12, 0xfa, 0xc1, 0x45, 0xe5, 0x27, 0x02, 0x82, 0xfa, 0x9a, 0x06, 0xb1, 0xfe,
|
||||
0x42, 0x90, 0x6b, 0x74, 0x17, 0xea, 0x42, 0xa3, 0xb4, 0x70, 0x77, 0xdb, 0x7f, 0x5e, 0x65, 0x9e,
|
||||
0x5d, 0xc4, 0x14, 0x4b, 0xb6, 0x68, 0xed, 0xea, 0x5b, 0xc7, 0xae, 0x5f, 0xd7, 0xda, 0x55, 0x5c,
|
||||
0xde, 0xda, 0x55, 0x84, 0x50, 0x91, 0x45, 0x3e, 0x97, 0x16, 0x9a, 0x58, 0xae, 0xdf, 0x5b, 0x00,
|
||||
0x94, 0x67, 0xa0, 0x0e, 0xb4, 0x1e, 0x3c, 0x9b, 0x3f, 0x9d, 0x9d, 0x61, 0xeb, 0x16, 0x32, 0xa1,
|
||||
0x31, 0x3e, 0x99, 0x8f, 0xcf, 0x2c, 0x43, 0xe0, 0xd3, 0xf9, 0x64, 0x72, 0x82, 0x5f, 0x58, 0xb7,
|
||||
0xc5, 0x66, 0xfe, 0x74, 0xf6, 0xe2, 0xf9, 0xd9, 0x43, 0xab, 0x86, 0xba, 0x60, 0x3e, 0xfe, 0x72,
|
||||
0x3a, 0x7b, 0x36, 0xc6, 0x27, 0x13, 0xab, 0x8e, 0xde, 0x80, 0x3d, 0x19, 0xe3, 0x96, 0x60, 0xe3,
|
||||
0xd4, 0x79, 0x75, 0x79, 0x64, 0xfc, 0x7e, 0x79, 0x64, 0xfc, 0x75, 0x79, 0x64, 0x7c, 0xd3, 0xf3,
|
||||
0x99, 0x5b, 0x0a, 0x76, 0x95, 0xe0, 0x45, 0x53, 0xbe, 0xf6, 0x8f, 0xfe, 0x0e, 0x00, 0x00, 0xff,
|
||||
0xff, 0x6d, 0x53, 0xc5, 0x1e, 0xdf, 0x09, 0x00, 0x00,
|
||||
// 982 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x4d, 0x8f, 0xdb, 0x44,
|
||||
0x18, 0xae, 0x9b, 0x4f, 0xbf, 0xd9, 0x6c, 0xbd, 0x43, 0x54, 0x59, 0x0b, 0xbb, 0x09, 0x96, 0x90,
|
||||
0x16, 0x84, 0x12, 0x01, 0x45, 0xa0, 0xb2, 0x48, 0xec, 0xb6, 0xdb, 0x14, 0x95, 0xb4, 0x65, 0x92,
|
||||
0x1c, 0xca, 0xc5, 0x9a, 0x24, 0xb3, 0x8e, 0x85, 0xbf, 0xb0, 0xc7, 0x15, 0xcb, 0x9d, 0xdf, 0xc0,
|
||||
0x1f, 0xe0, 0x67, 0x70, 0x46, 0x3d, 0x72, 0xe2, 0x88, 0xd0, 0xfe, 0x0e, 0x0e, 0x68, 0xbe, 0xec,
|
||||
0x6c, 0xe5, 0x2c, 0x2c, 0xdc, 0x3c, 0x8f, 0x9f, 0x67, 0xe6, 0x79, 0x1f, 0xdb, 0xef, 0x6b, 0x70,
|
||||
0xfc, 0x78, 0x94, 0xa4, 0x71, 0x48, 0xd9, 0x9a, 0xe6, 0xd9, 0x68, 0x19, 0xf8, 0x34, 0x62, 0xa3,
|
||||
0x90, 0xb2, 0xd4, 0x5f, 0x66, 0xc3, 0x24, 0x8d, 0x59, 0x8c, 0x7a, 0x7e, 0x3c, 0x2c, 0x39, 0x43,
|
||||
0xc9, 0xd9, 0xef, 0x79, 0xb1, 0x17, 0x0b, 0xc2, 0x88, 0x5f, 0x49, 0xee, 0x7e, 0xdf, 0x8b, 0x63,
|
||||
0x2f, 0xa0, 0x23, 0xb1, 0x5a, 0xe4, 0xe7, 0x23, 0xe6, 0x87, 0x34, 0x63, 0x24, 0x4c, 0x24, 0xc1,
|
||||
0xf9, 0x18, 0xcc, 0xaf, 0xc8, 0x82, 0x06, 0xcf, 0x89, 0x9f, 0x22, 0x04, 0xf5, 0x88, 0x84, 0xd4,
|
||||
0x36, 0x06, 0xc6, 0x91, 0x89, 0xc5, 0x35, 0xea, 0x41, 0xe3, 0x25, 0x09, 0x72, 0x6a, 0xdf, 0x16,
|
||||
0xa0, 0x5c, 0x38, 0x07, 0xd0, 0x18, 0x93, 0xdc, 0xdb, 0xb8, 0xcd, 0x35, 0x86, 0xbe, 0xfd, 0xb3,
|
||||
0x01, 0xad, 0x07, 0x71, 0x1e, 0x31, 0x9a, 0x56, 0x33, 0xd0, 0x7d, 0x68, 0xd3, 0xef, 0x69, 0x98,
|
||||
0x04, 0x24, 0x15, 0x3b, 0x77, 0x3e, 0x3c, 0x1c, 0x56, 0xd5, 0x35, 0x3c, 0x53, 0x2c, 0x5c, 0xf0,
|
||||
0xd1, 0x18, 0xf6, 0x96, 0x29, 0x25, 0x8c, 0xae, 0xdc, 0xa2, 0x1c, 0xbb, 0x26, 0x36, 0xd9, 0x1f,
|
||||
0xca, 0x82, 0x87, 0xba, 0xe0, 0xe1, 0x4c, 0x33, 0xb0, 0xa5, 0x44, 0x05, 0xe2, 0x1c, 0x43, 0xfb,
|
||||
0xeb, 0x9c, 0x44, 0xcc, 0x0f, 0x28, 0xda, 0x87, 0xf6, 0x77, 0xea, 0x5a, 0x39, 0x2d, 0xd6, 0x57,
|
||||
0x33, 0x28, 0x8a, 0xfc, 0xdd, 0x80, 0xd6, 0x34, 0x0f, 0x43, 0x92, 0x5e, 0xa0, 0xb7, 0x61, 0x27,
|
||||
0x23, 0x61, 0x12, 0x50, 0x77, 0xc9, 0xcb, 0x16, 0x3b, 0xd4, 0x71, 0x47, 0x62, 0x22, 0x09, 0x74,
|
||||
0x00, 0xa0, 0x28, 0x59, 0x1e, 0xaa, 0x9d, 0x4c, 0x89, 0x4c, 0xf3, 0x10, 0x7d, 0xb1, 0x71, 0x7e,
|
||||
0x6d, 0x50, 0xdb, 0x1e, 0x88, 0x76, 0x7c, 0x5a, 0x7f, 0xf5, 0x47, 0xff, 0xd6, 0x86, 0xcb, 0xca,
|
||||
0x58, 0xea, 0xff, 0x21, 0x96, 0x3e, 0xb4, 0xe6, 0x11, 0xbb, 0x48, 0xe8, 0x6a, 0xcb, 0xe3, 0xfd,
|
||||
0xab, 0x01, 0xe6, 0x63, 0x3f, 0x63, 0xb1, 0x97, 0x92, 0xf0, 0xdf, 0xd4, 0xfe, 0x3e, 0xa0, 0x4d,
|
||||
0x8a, 0x7b, 0x1e, 0xc4, 0x84, 0x09, 0x6f, 0x06, 0xb6, 0x36, 0x88, 0x8f, 0x38, 0xfe, 0x4f, 0x49,
|
||||
0xdd, 0x87, 0xe6, 0x22, 0x5f, 0x7e, 0x4b, 0x99, 0xca, 0xe9, 0xad, 0xea, 0x9c, 0x4e, 0x05, 0x47,
|
||||
0xa5, 0xa4, 0x14, 0xd5, 0x19, 0xdd, 0xb9, 0x79, 0x46, 0xe8, 0x2e, 0x34, 0xb3, 0xe5, 0x9a, 0x86,
|
||||
0xc4, 0x6e, 0x0c, 0x8c, 0xa3, 0x3d, 0xac, 0x56, 0xe8, 0x1d, 0xd8, 0xfd, 0x81, 0xa6, 0xb1, 0xcb,
|
||||
0xd6, 0x29, 0xcd, 0xd6, 0x71, 0xb0, 0xb2, 0x9b, 0xc2, 0x7f, 0x97, 0xa3, 0x33, 0x0d, 0xf2, 0x12,
|
||||
0x05, 0x4d, 0x26, 0xd6, 0x12, 0x89, 0x99, 0x1c, 0x91, 0x79, 0x1d, 0x81, 0x55, 0xde, 0x56, 0x69,
|
||||
0xb5, 0xc5, 0x3e, 0xbb, 0x05, 0x49, 0x66, 0xf5, 0x04, 0xba, 0x11, 0xf5, 0x08, 0xf3, 0x5f, 0x52,
|
||||
0x37, 0x4b, 0x48, 0x64, 0x9b, 0x22, 0x93, 0xc1, 0x75, 0x99, 0x4c, 0x13, 0x12, 0xa9, 0x5c, 0x76,
|
||||
0xb4, 0x98, 0x63, 0xdc, 0x7c, 0xb1, 0xd9, 0x8a, 0x06, 0x8c, 0xd8, 0x30, 0xa8, 0x1d, 0x21, 0x5c,
|
||||
0x1c, 0xf1, 0x90, 0x83, 0x57, 0x68, 0xb2, 0x80, 0xce, 0xa0, 0xc6, 0x6b, 0xd4, 0xa8, 0x2c, 0xe2,
|
||||
0x09, 0x74, 0x93, 0x38, 0xf3, 0x4b, 0x6b, 0x3b, 0x37, 0xb3, 0xa6, 0xc5, 0xda, 0x5a, 0xb1, 0x99,
|
||||
0xb4, 0xd6, 0x95, 0xd6, 0x34, 0x5a, 0x58, 0x2b, 0x68, 0xd2, 0xda, 0xae, 0xb4, 0xa6, 0x51, 0x69,
|
||||
0xed, 0x18, 0x4c, 0xdd, 0x4d, 0x32, 0xdb, 0xba, 0xee, 0x6b, 0x2b, 0xda, 0x4f, 0x29, 0x70, 0x7e,
|
||||
0x35, 0xa0, 0x29, 0xed, 0xa2, 0x77, 0xc1, 0x5a, 0xe6, 0x61, 0x1e, 0x6c, 0x86, 0x21, 0xdf, 0xff,
|
||||
0x3b, 0x25, 0x2e, 0xcf, 0xbc, 0x07, 0x77, 0x5f, 0xa7, 0x5e, 0xf9, 0x0e, 0x7a, 0xaf, 0x09, 0xe4,
|
||||
0xf3, 0xed, 0x43, 0x27, 0x4f, 0x12, 0x9a, 0xba, 0x8b, 0x38, 0x8f, 0x56, 0xea, 0x63, 0x00, 0x01,
|
||||
0x9d, 0x72, 0xe4, 0x4a, 0x23, 0xad, 0xdd, 0xac, 0x91, 0x3a, 0xc7, 0x00, 0x65, 0xec, 0xfc, 0x95,
|
||||
0x8e, 0xcf, 0xcf, 0x33, 0x2a, 0x2b, 0xd8, 0xc3, 0x6a, 0xc5, 0xf1, 0x80, 0x46, 0x1e, 0x5b, 0x8b,
|
||||
0xd3, 0xbb, 0x58, 0xad, 0x9c, 0x9f, 0x0c, 0x68, 0xeb, 0x4d, 0xd1, 0x67, 0xd0, 0x08, 0xf8, 0x1c,
|
||||
0xb1, 0x0d, 0x91, 0x66, 0xbf, 0xda, 0x43, 0x31, 0x6a, 0xd4, 0x33, 0x96, 0x9a, 0xea, 0xfe, 0x8a,
|
||||
0x3e, 0x05, 0xf3, 0x26, 0xed, 0xbd, 0x24, 0x3b, 0x3f, 0xd6, 0xa0, 0x39, 0x11, 0x33, 0xf3, 0xff,
|
||||
0xf9, 0xfa, 0x00, 0x1a, 0x1e, 0x9f, 0x72, 0x6a, 0x42, 0xbd, 0x59, 0x2d, 0x16, 0x83, 0x10, 0x4b,
|
||||
0x26, 0xfa, 0x04, 0x5a, 0x4b, 0x39, 0xf8, 0x94, 0xe5, 0x83, 0x6a, 0x91, 0x9a, 0x8e, 0x58, 0xb3,
|
||||
0xb9, 0x30, 0x93, 0xc3, 0x44, 0xf5, 0xec, 0x2d, 0x42, 0x35, 0x71, 0xb0, 0x66, 0x73, 0x61, 0x2e,
|
||||
0xbb, 0xb5, 0x68, 0x45, 0x5b, 0x85, 0xaa, 0xa5, 0x63, 0xcd, 0x46, 0x9f, 0x83, 0xb9, 0xd6, 0x4d,
|
||||
0x5c, 0xb4, 0xa0, 0xad, 0xf1, 0x14, 0xbd, 0x1e, 0x97, 0x0a, 0xde, 0xf6, 0x8b, 0xc4, 0xdd, 0x30,
|
||||
0x13, 0x7d, 0xae, 0x86, 0x3b, 0x05, 0x36, 0xc9, 0x9c, 0x5f, 0x0c, 0xd8, 0x91, 0xcf, 0xe1, 0x11,
|
||||
0x09, 0xfd, 0xe0, 0xa2, 0xf2, 0x07, 0x03, 0x41, 0x7d, 0x4d, 0x83, 0x44, 0xfd, 0x5f, 0x88, 0x6b,
|
||||
0x74, 0x0f, 0xea, 0xdc, 0xa3, 0x88, 0x70, 0x77, 0x5b, 0xc7, 0x90, 0x3b, 0xcf, 0x2e, 0x12, 0x8a,
|
||||
0x05, 0x9b, 0x0f, 0x06, 0xf9, 0xa7, 0x64, 0xd7, 0xaf, 0x1b, 0x0c, 0x52, 0xa7, 0x07, 0x83, 0x54,
|
||||
0x70, 0x17, 0x79, 0xe4, 0x33, 0x11, 0xa1, 0x89, 0xc5, 0xf5, 0x7b, 0x0b, 0x80, 0xf2, 0x0c, 0xd4,
|
||||
0x81, 0xd6, 0x83, 0x67, 0xf3, 0xa7, 0xb3, 0x33, 0x6c, 0xdd, 0x42, 0x26, 0x34, 0xc6, 0x27, 0xf3,
|
||||
0xf1, 0x99, 0x65, 0x70, 0x7c, 0x3a, 0x9f, 0x4c, 0x4e, 0xf0, 0x0b, 0xeb, 0x36, 0x5f, 0xcc, 0x9f,
|
||||
0xce, 0x5e, 0x3c, 0x3f, 0x7b, 0x68, 0xd5, 0x50, 0x17, 0xcc, 0xc7, 0x5f, 0x4e, 0x67, 0xcf, 0xc6,
|
||||
0xf8, 0x64, 0x62, 0xd5, 0xd1, 0x1b, 0x70, 0x47, 0x68, 0xdc, 0x12, 0x6c, 0x9c, 0x3a, 0xaf, 0x2e,
|
||||
0x0f, 0x8d, 0xdf, 0x2e, 0x0f, 0x8d, 0x3f, 0x2f, 0x0f, 0x8d, 0x6f, 0x7a, 0x7e, 0xec, 0x96, 0x86,
|
||||
0x5d, 0x69, 0x78, 0xd1, 0x14, 0x6f, 0xfb, 0x47, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0x1c, 0xe1,
|
||||
0xcf, 0xb8, 0x1d, 0x0a, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *LabelPair) Marshal() (dAtA []byte, err error) {
|
||||
|
@ -1328,6 +1338,22 @@ func (m *Histogram) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if len(m.Exemplars) > 0 {
|
||||
for iNdEx := len(m.Exemplars) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.Exemplars[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintMetrics(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0x82
|
||||
}
|
||||
}
|
||||
if m.CreatedTimestamp != nil {
|
||||
{
|
||||
size, err := m.CreatedTimestamp.MarshalToSizedBuffer(dAtA[:i])
|
||||
|
@ -2006,6 +2032,12 @@ func (m *Histogram) Size() (n int) {
|
|||
l = m.CreatedTimestamp.Size()
|
||||
n += 1 + l + sovMetrics(uint64(l))
|
||||
}
|
||||
if len(m.Exemplars) > 0 {
|
||||
for _, e := range m.Exemplars {
|
||||
l = e.Size()
|
||||
n += 2 + l + sovMetrics(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
|
@ -3291,6 +3323,40 @@ func (m *Histogram) Unmarshal(dAtA []byte) error {
|
|||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 16:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Exemplars", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowMetrics
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthMetrics
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthMetrics
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Exemplars = append(m.Exemplars, &Exemplar{})
|
||||
if err := m.Exemplars[len(m.Exemplars)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipMetrics(dAtA[iNdEx:])
|
||||
|
|
|
@ -112,6 +112,9 @@ message Histogram {
|
|||
// histograms.
|
||||
repeated sint64 positive_delta = 13; // Count delta of each bucket compared to previous one (or to zero for 1st bucket).
|
||||
repeated double positive_count = 14; // Absolute count of each bucket.
|
||||
|
||||
// Only used for native histograms. These exemplars MUST have a timestamp.
|
||||
repeated Exemplar exemplars = 16;
|
||||
}
|
||||
|
||||
message Bucket {
|
||||
|
|
|
@ -33,6 +33,10 @@ func setupRangeQueryTestData(stor *teststorage.TestStorage, _ *Engine, interval,
|
|||
ctx := context.Background()
|
||||
|
||||
metrics := []labels.Labels{}
|
||||
// Generating test series: a_X, b_X, and h_X, where X can take values of one, ten, or hundred,
|
||||
// representing the number of series each metric name contains.
|
||||
// Metric a_X and b_X are simple metrics where h_X is a histogram.
|
||||
// These metrics will have data for all test time range
|
||||
metrics = append(metrics, labels.FromStrings("__name__", "a_one"))
|
||||
metrics = append(metrics, labels.FromStrings("__name__", "b_one"))
|
||||
for j := 0; j < 10; j++ {
|
||||
|
@ -59,6 +63,9 @@ func setupRangeQueryTestData(stor *teststorage.TestStorage, _ *Engine, interval,
|
|||
}
|
||||
refs := make([]storage.SeriesRef, len(metrics))
|
||||
|
||||
// Number points for each different label value of "l" for the sparse series
|
||||
pointsPerSparseSeries := numIntervals / 50
|
||||
|
||||
for s := 0; s < numIntervals; s++ {
|
||||
a := stor.Appender(context.Background())
|
||||
ts := int64(s * interval)
|
||||
|
@ -66,10 +73,18 @@ func setupRangeQueryTestData(stor *teststorage.TestStorage, _ *Engine, interval,
|
|||
ref, _ := a.Append(refs[i], metric, ts, float64(s)+float64(i)/float64(len(metrics)))
|
||||
refs[i] = ref
|
||||
}
|
||||
// Generating a sparse time series: each label value of "l" will contain data only for
|
||||
// pointsPerSparseSeries points
|
||||
metric := labels.FromStrings("__name__", "sparse", "l", strconv.Itoa(s/pointsPerSparseSeries))
|
||||
_, err := a.Append(0, metric, ts, float64(s)/float64(len(metrics)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := a.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
stor.DB.ForceHeadMMap() // Ensure we have at most one head chunk for every series.
|
||||
stor.DB.Compact(ctx)
|
||||
return nil
|
||||
|
@ -94,6 +109,10 @@ func rangeQueryCases() []benchCase {
|
|||
expr: "rate(a_X[1m])",
|
||||
steps: 10000,
|
||||
},
|
||||
{
|
||||
expr: "rate(sparse[1m])",
|
||||
steps: 10000,
|
||||
},
|
||||
// Holt-Winters and long ranges.
|
||||
{
|
||||
expr: "holt_winters(a_X[1d], 0.3, 0.3)",
|
||||
|
|
166
promql/engine.go
166
promql/engine.go
|
@ -22,6 +22,7 @@ import (
|
|||
"math"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -30,13 +31,11 @@ import (
|
|||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/grafana/regexp"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/model"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/prometheus/prometheus/model/histogram"
|
||||
"github.com/prometheus/prometheus/model/labels"
|
||||
|
@ -116,6 +115,12 @@ func (e ErrStorage) Error() string {
|
|||
return e.Err.Error()
|
||||
}
|
||||
|
||||
// QueryEngine defines the interface for the *promql.Engine, so it can be replaced, wrapped or mocked.
|
||||
type QueryEngine interface {
|
||||
NewInstantQuery(ctx context.Context, q storage.Queryable, opts QueryOpts, qs string, ts time.Time) (Query, error)
|
||||
NewRangeQuery(ctx context.Context, q storage.Queryable, opts QueryOpts, qs string, start, end time.Time, interval time.Duration) (Query, error)
|
||||
}
|
||||
|
||||
// QueryLogger is an interface that can be used to log all the queries logged
|
||||
// by the engine.
|
||||
type QueryLogger interface {
|
||||
|
@ -1076,12 +1081,10 @@ type EvalNodeHelper struct {
|
|||
Out Vector
|
||||
|
||||
// Caches.
|
||||
// DropMetricName and label_*.
|
||||
// label_*.
|
||||
Dmn map[uint64]labels.Labels
|
||||
// funcHistogramQuantile for classic histograms.
|
||||
signatureToMetricWithBuckets map[string]*metricWithBuckets
|
||||
// label_replace.
|
||||
regex *regexp.Regexp
|
||||
|
||||
lb *labels.Builder
|
||||
lblBuf []byte
|
||||
|
@ -1101,21 +1104,6 @@ func (enh *EvalNodeHelper) resetBuilder(lbls labels.Labels) {
|
|||
}
|
||||
}
|
||||
|
||||
// DropMetricName is a cached version of DropMetricName.
|
||||
func (enh *EvalNodeHelper) DropMetricName(l labels.Labels) labels.Labels {
|
||||
if enh.Dmn == nil {
|
||||
enh.Dmn = make(map[uint64]labels.Labels, len(enh.Out))
|
||||
}
|
||||
h := l.Hash()
|
||||
ret, ok := enh.Dmn[h]
|
||||
if ok {
|
||||
return ret
|
||||
}
|
||||
ret = dropMetricName(l)
|
||||
enh.Dmn[h] = ret
|
||||
return ret
|
||||
}
|
||||
|
||||
// rangeEval evaluates the given expressions, and then for each step calls
|
||||
// the given funcCall with the values computed for each expression at that
|
||||
// step. The return value is the combination into time series of all the
|
||||
|
@ -1214,6 +1202,9 @@ func (ev *evaluator) rangeEval(prepSeries func(labels.Labels, *EvalSeriesHelper)
|
|||
if prepSeries != nil {
|
||||
bufHelpers[i] = append(bufHelpers[i], seriesHelpers[i][si])
|
||||
}
|
||||
// Don't add histogram size here because we only
|
||||
// copy the pointer above, not the whole
|
||||
// histogram.
|
||||
ev.currentSamples++
|
||||
if ev.currentSamples > ev.maxSamples {
|
||||
ev.error(ErrTooManySamples(env))
|
||||
|
@ -1239,7 +1230,6 @@ func (ev *evaluator) rangeEval(prepSeries func(labels.Labels, *EvalSeriesHelper)
|
|||
if ev.currentSamples > ev.maxSamples {
|
||||
ev.error(ErrTooManySamples(env))
|
||||
}
|
||||
ev.samplesStats.UpdatePeak(ev.currentSamples)
|
||||
|
||||
// If this could be an instant query, shortcut so as not to change sort order.
|
||||
if ev.endTimestamp == ev.startTimestamp {
|
||||
|
@ -1424,6 +1414,15 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
|||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Special handling for functions that work on series not samples.
|
||||
switch e.Func.Name {
|
||||
case "label_replace":
|
||||
return ev.evalLabelReplace(e.Args)
|
||||
case "label_join":
|
||||
return ev.evalLabelJoin(e.Args)
|
||||
}
|
||||
|
||||
if !matrixArg {
|
||||
// Does not have a matrix argument.
|
||||
return ev.rangeEval(nil, func(v []parser.Value, _ [][]EvalSeriesHelper, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
|
||||
|
@ -1467,6 +1466,7 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
|||
// Reuse objects across steps to save memory allocations.
|
||||
var floats []FPoint
|
||||
var histograms []HPoint
|
||||
var prevSS *Series
|
||||
inMatrix := make(Matrix, 1)
|
||||
inArgs[matrixArgIndex] = inMatrix
|
||||
enh := &EvalNodeHelper{Out: make(Vector, 0, 1)}
|
||||
|
@ -1492,7 +1492,7 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
|||
// vector functions, the only change needed is to drop the
|
||||
// metric name in the output.
|
||||
if e.Func.Name != "last_over_time" {
|
||||
metric = dropMetricName(metric)
|
||||
metric = metric.DropMetricName()
|
||||
}
|
||||
ss := Series{
|
||||
Metric: metric,
|
||||
|
@ -1508,10 +1508,14 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
|||
otherInArgs[j][0].F = otherArgs[j][0].Floats[step].F
|
||||
}
|
||||
}
|
||||
maxt := ts - offset
|
||||
mint := maxt - selRange
|
||||
// Evaluate the matrix selector for this series for this step.
|
||||
floats, histograms = ev.matrixIterSlice(it, mint, maxt, floats, histograms)
|
||||
// Evaluate the matrix selector for this series
|
||||
// for this step, but only if this is the 1st
|
||||
// iteration or no @ modifier has been used.
|
||||
if ts == ev.startTimestamp || selVS.Timestamp == nil {
|
||||
maxt := ts - offset
|
||||
mint := maxt - selRange
|
||||
floats, histograms = ev.matrixIterSlice(it, mint, maxt, floats, histograms)
|
||||
}
|
||||
if len(floats)+len(histograms) == 0 {
|
||||
continue
|
||||
}
|
||||
|
@ -1527,12 +1531,13 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
|||
if len(outVec) > 0 {
|
||||
if outVec[0].H == nil {
|
||||
if ss.Floats == nil {
|
||||
ss.Floats = getFPointSlice(numSteps)
|
||||
ss.Floats = reuseOrGetFPointSlices(prevSS, numSteps)
|
||||
}
|
||||
|
||||
ss.Floats = append(ss.Floats, FPoint{F: outVec[0].F, T: ts})
|
||||
} else {
|
||||
if ss.Histograms == nil {
|
||||
ss.Histograms = getHPointSlice(numSteps)
|
||||
ss.Histograms = reuseOrGetHPointSlices(prevSS, numSteps)
|
||||
}
|
||||
ss.Histograms = append(ss.Histograms, HPoint{H: outVec[0].H, T: ts})
|
||||
}
|
||||
|
@ -1541,13 +1546,14 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
|||
it.ReduceDelta(stepRange)
|
||||
}
|
||||
histSamples := totalHPointSize(ss.Histograms)
|
||||
|
||||
if len(ss.Floats)+histSamples > 0 {
|
||||
if ev.currentSamples+len(ss.Floats)+histSamples <= ev.maxSamples {
|
||||
mat = append(mat, ss)
|
||||
ev.currentSamples += len(ss.Floats) + histSamples
|
||||
} else {
|
||||
if ev.currentSamples+len(ss.Floats)+histSamples > ev.maxSamples {
|
||||
ev.error(ErrTooManySamples(env))
|
||||
}
|
||||
mat = append(mat, ss)
|
||||
prevSS = &mat[len(mat)-1]
|
||||
ev.currentSamples += len(ss.Floats) + histSamples
|
||||
}
|
||||
ev.samplesStats.UpdatePeak(ev.currentSamples)
|
||||
|
||||
|
@ -1624,7 +1630,7 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
|||
mat := val.(Matrix)
|
||||
if e.Op == parser.SUB {
|
||||
for i := range mat {
|
||||
mat[i].Metric = dropMetricName(mat[i].Metric)
|
||||
mat[i].Metric = mat[i].Metric.DropMetricName()
|
||||
for j := range mat[i].Floats {
|
||||
mat[i].Floats[j].F = -mat[i].Floats[j].F
|
||||
}
|
||||
|
@ -1693,6 +1699,7 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
|||
ev.error(errWithWarnings{fmt.Errorf("expanding series: %w", err), ws})
|
||||
}
|
||||
mat := make(Matrix, 0, len(e.Series))
|
||||
var prevSS *Series
|
||||
it := storage.NewMemoizedEmptyIterator(durationMilliseconds(ev.lookbackDelta))
|
||||
var chkIter chunkenc.Iterator
|
||||
for i, s := range e.Series {
|
||||
|
@ -1709,32 +1716,35 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
|||
step++
|
||||
_, f, h, ok := ev.vectorSelectorSingle(it, e, ts)
|
||||
if ok {
|
||||
if ev.currentSamples < ev.maxSamples {
|
||||
if h == nil {
|
||||
if ss.Floats == nil {
|
||||
ss.Floats = getFPointSlice(numSteps)
|
||||
}
|
||||
ss.Floats = append(ss.Floats, FPoint{F: f, T: ts})
|
||||
ev.currentSamples++
|
||||
ev.samplesStats.IncrementSamplesAtStep(step, 1)
|
||||
} else {
|
||||
if ss.Histograms == nil {
|
||||
ss.Histograms = getHPointSlice(numSteps)
|
||||
}
|
||||
point := HPoint{H: h, T: ts}
|
||||
ss.Histograms = append(ss.Histograms, point)
|
||||
histSize := point.size()
|
||||
ev.currentSamples += histSize
|
||||
ev.samplesStats.IncrementSamplesAtStep(step, int64(histSize))
|
||||
if h == nil {
|
||||
ev.currentSamples++
|
||||
ev.samplesStats.IncrementSamplesAtStep(step, 1)
|
||||
if ev.currentSamples > ev.maxSamples {
|
||||
ev.error(ErrTooManySamples(env))
|
||||
}
|
||||
if ss.Floats == nil {
|
||||
ss.Floats = reuseOrGetFPointSlices(prevSS, numSteps)
|
||||
}
|
||||
ss.Floats = append(ss.Floats, FPoint{F: f, T: ts})
|
||||
} else {
|
||||
ev.error(ErrTooManySamples(env))
|
||||
point := HPoint{H: h, T: ts}
|
||||
histSize := point.size()
|
||||
ev.currentSamples += histSize
|
||||
ev.samplesStats.IncrementSamplesAtStep(step, int64(histSize))
|
||||
if ev.currentSamples > ev.maxSamples {
|
||||
ev.error(ErrTooManySamples(env))
|
||||
}
|
||||
if ss.Histograms == nil {
|
||||
ss.Histograms = reuseOrGetHPointSlices(prevSS, numSteps)
|
||||
}
|
||||
ss.Histograms = append(ss.Histograms, point)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(ss.Floats)+len(ss.Histograms) > 0 {
|
||||
mat = append(mat, ss)
|
||||
prevSS = &mat[len(mat)-1]
|
||||
}
|
||||
}
|
||||
ev.samplesStats.UpdatePeak(ev.currentSamples)
|
||||
|
@ -1855,6 +1865,30 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio
|
|||
panic(fmt.Errorf("unhandled expression of type: %T", expr))
|
||||
}
|
||||
|
||||
// reuseOrGetHPointSlices reuses the space from previous slice to create new slice if the former has lots of room.
|
||||
// The previous slices capacity is adjusted so when it is re-used from the pool it doesn't overflow into the new one.
|
||||
func reuseOrGetHPointSlices(prevSS *Series, numSteps int) (r []HPoint) {
|
||||
if prevSS != nil && cap(prevSS.Histograms)-2*len(prevSS.Histograms) > 0 {
|
||||
r = prevSS.Histograms[len(prevSS.Histograms):]
|
||||
prevSS.Histograms = prevSS.Histograms[0:len(prevSS.Histograms):len(prevSS.Histograms)]
|
||||
return
|
||||
}
|
||||
|
||||
return getHPointSlice(numSteps)
|
||||
}
|
||||
|
||||
// reuseOrGetFPointSlices reuses the space from previous slice to create new slice if the former has lots of room.
|
||||
// The previous slices capacity is adjusted so when it is re-used from the pool it doesn't overflow into the new one.
|
||||
func reuseOrGetFPointSlices(prevSS *Series, numSteps int) (r []FPoint) {
|
||||
if prevSS != nil && cap(prevSS.Floats)-2*len(prevSS.Floats) > 0 {
|
||||
r = prevSS.Floats[len(prevSS.Floats):]
|
||||
prevSS.Floats = prevSS.Floats[0:len(prevSS.Floats):len(prevSS.Floats)]
|
||||
return
|
||||
}
|
||||
|
||||
return getFPointSlice(numSteps)
|
||||
}
|
||||
|
||||
func (ev *evaluator) rangeEvalTimestampFunctionOverVectorSelector(vs *parser.VectorSelector, call FunctionCall, e *parser.Call) (parser.Value, annotations.Annotations) {
|
||||
ws, err := checkAndExpandSeriesSet(ev.ctx, vs)
|
||||
if err != nil {
|
||||
|
@ -2143,10 +2177,10 @@ loop:
|
|||
histograms = histograms[:n]
|
||||
continue loop
|
||||
}
|
||||
if ev.currentSamples >= ev.maxSamples {
|
||||
ev.currentSamples += histograms[n].size()
|
||||
if ev.currentSamples > ev.maxSamples {
|
||||
ev.error(ErrTooManySamples(env))
|
||||
}
|
||||
ev.currentSamples += histograms[n].size()
|
||||
}
|
||||
case chunkenc.ValFloat:
|
||||
t, f := buf.At()
|
||||
|
@ -2155,10 +2189,10 @@ loop:
|
|||
}
|
||||
// Values in the buffer are guaranteed to be smaller than maxt.
|
||||
if t >= mintFloats {
|
||||
if ev.currentSamples >= ev.maxSamples {
|
||||
ev.currentSamples++
|
||||
if ev.currentSamples > ev.maxSamples {
|
||||
ev.error(ErrTooManySamples(env))
|
||||
}
|
||||
ev.currentSamples++
|
||||
if floats == nil {
|
||||
floats = getFPointSlice(16)
|
||||
}
|
||||
|
@ -2186,22 +2220,22 @@ loop:
|
|||
histograms = histograms[:n]
|
||||
break
|
||||
}
|
||||
if ev.currentSamples >= ev.maxSamples {
|
||||
ev.currentSamples += histograms[n].size()
|
||||
if ev.currentSamples > ev.maxSamples {
|
||||
ev.error(ErrTooManySamples(env))
|
||||
}
|
||||
ev.currentSamples += histograms[n].size()
|
||||
|
||||
case chunkenc.ValFloat:
|
||||
t, f := it.At()
|
||||
if t == maxt && !value.IsStaleNaN(f) {
|
||||
if ev.currentSamples >= ev.maxSamples {
|
||||
ev.currentSamples++
|
||||
if ev.currentSamples > ev.maxSamples {
|
||||
ev.error(ErrTooManySamples(env))
|
||||
}
|
||||
if floats == nil {
|
||||
floats = getFPointSlice(16)
|
||||
}
|
||||
floats = append(floats, FPoint{T: t, F: f})
|
||||
ev.currentSamples++
|
||||
}
|
||||
}
|
||||
ev.samplesStats.UpdatePeak(ev.currentSamples)
|
||||
|
@ -2370,7 +2404,7 @@ func (ev *evaluator) VectorBinop(op parser.ItemType, lhs, rhs Vector, matching *
|
|||
}
|
||||
metric := resultMetric(ls.Metric, rs.Metric, op, matching, enh)
|
||||
if returnBool {
|
||||
metric = enh.DropMetricName(metric)
|
||||
metric = metric.DropMetricName()
|
||||
}
|
||||
insertedSigs, exists := matchedSigs[sig]
|
||||
if matching.Card == parser.CardOneToOne {
|
||||
|
@ -2492,7 +2526,7 @@ func (ev *evaluator) VectorscalarBinop(op parser.ItemType, lhs Vector, rhs Scala
|
|||
lhsSample.F = float
|
||||
lhsSample.H = histogram
|
||||
if shouldDropMetricName(op) || returnBool {
|
||||
lhsSample.Metric = enh.DropMetricName(lhsSample.Metric)
|
||||
lhsSample.Metric = lhsSample.Metric.DropMetricName()
|
||||
}
|
||||
enh.Out = append(enh.Out, lhsSample)
|
||||
}
|
||||
|
@ -2500,10 +2534,6 @@ func (ev *evaluator) VectorscalarBinop(op parser.ItemType, lhs Vector, rhs Scala
|
|||
return enh.Out
|
||||
}
|
||||
|
||||
func dropMetricName(l labels.Labels) labels.Labels {
|
||||
return labels.NewBuilder(l).Del(labels.MetricName).Labels()
|
||||
}
|
||||
|
||||
// scalarBinop evaluates a binary operation between two Scalars.
|
||||
func scalarBinop(op parser.ItemType, lhs, rhs float64) float64 {
|
||||
switch op {
|
||||
|
@ -2854,8 +2884,7 @@ func (ev *evaluator) aggregation(e *parser.AggregateExpr, grouping []string, par
|
|||
case parser.AVG:
|
||||
if aggr.hasFloat && aggr.hasHistogram {
|
||||
// We cannot aggregate histogram sample with a float64 sample.
|
||||
metricName := aggr.labels.Get(labels.MetricName)
|
||||
annos.Add(annotations.NewMixedFloatsHistogramsWarning(metricName, e.Expr.PositionRange()))
|
||||
annos.Add(annotations.NewMixedFloatsHistogramsAggWarning(e.Expr.PositionRange()))
|
||||
continue
|
||||
}
|
||||
if aggr.hasHistogram {
|
||||
|
@ -2908,8 +2937,7 @@ func (ev *evaluator) aggregation(e *parser.AggregateExpr, grouping []string, par
|
|||
case parser.SUM:
|
||||
if aggr.hasFloat && aggr.hasHistogram {
|
||||
// We cannot aggregate histogram sample with a float64 sample.
|
||||
metricName := aggr.labels.Get(labels.MetricName)
|
||||
annos.Add(annotations.NewMixedFloatsHistogramsWarning(metricName, e.Expr.PositionRange()))
|
||||
annos.Add(annotations.NewMixedFloatsHistogramsAggWarning(e.Expr.PositionRange()))
|
||||
continue
|
||||
}
|
||||
if aggr.hasHistogram {
|
||||
|
|
|
@ -38,6 +38,7 @@ import (
|
|||
"github.com/prometheus/prometheus/util/annotations"
|
||||
"github.com/prometheus/prometheus/util/stats"
|
||||
"github.com/prometheus/prometheus/util/teststorage"
|
||||
"github.com/prometheus/prometheus/util/testutil"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
@ -754,6 +755,7 @@ load 10s
|
|||
metricWith3SampleEvery10Seconds{a="1",b="1"} 1+1x100
|
||||
metricWith3SampleEvery10Seconds{a="2",b="2"} 1+1x100
|
||||
metricWith3SampleEvery10Seconds{a="3",b="2"} 1+1x100
|
||||
metricWith1HistogramEvery10Seconds {{schema:1 count:5 sum:20 buckets:[1 2 1 1]}}+{{schema:1 count:10 sum:5 buckets:[1 2 3 4]}}x100
|
||||
`)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
|
@ -794,6 +796,15 @@ load 10s
|
|||
21000: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "metricWith1HistogramEvery10Seconds",
|
||||
Start: time.Unix(21, 0),
|
||||
PeakSamples: 12,
|
||||
TotalSamples: 12, // 1 histogram sample of size 12 / 10 seconds
|
||||
TotalSamplesPerStep: stats.TotalSamplesPerStep{
|
||||
21000: 12,
|
||||
},
|
||||
},
|
||||
{
|
||||
// timestamp function has a special handling.
|
||||
Query: "timestamp(metricWith1SampleEvery10Seconds)",
|
||||
|
@ -804,6 +815,15 @@ load 10s
|
|||
21000: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "timestamp(metricWith1HistogramEvery10Seconds)",
|
||||
Start: time.Unix(21, 0),
|
||||
PeakSamples: 13, // histogram size 12 + 1 extra because of timestamp
|
||||
TotalSamples: 1, // 1 float sample (because of timestamp) / 10 seconds
|
||||
TotalSamplesPerStep: stats.TotalSamplesPerStep{
|
||||
21000: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "metricWith1SampleEvery10Seconds",
|
||||
Start: time.Unix(22, 0),
|
||||
|
@ -876,11 +896,20 @@ load 10s
|
|||
201000: 6,
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "metricWith1HistogramEvery10Seconds[60s]",
|
||||
Start: time.Unix(201, 0),
|
||||
PeakSamples: 72,
|
||||
TotalSamples: 72, // 1 histogram (size 12) / 10 seconds * 60 seconds
|
||||
TotalSamplesPerStep: stats.TotalSamplesPerStep{
|
||||
201000: 72,
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "max_over_time(metricWith1SampleEvery10Seconds[59s])[20s:5s]",
|
||||
Start: time.Unix(201, 0),
|
||||
PeakSamples: 10,
|
||||
TotalSamples: 24, // (1 sample / 10 seconds * 60 seconds) * 60/5 (using 59s so we always return 6 samples
|
||||
TotalSamples: 24, // (1 sample / 10 seconds * 60 seconds) * 20/5 (using 59s so we always return 6 samples
|
||||
// as if we run a query on 00 looking back 60 seconds we will return 7 samples;
|
||||
// see next test).
|
||||
TotalSamplesPerStep: stats.TotalSamplesPerStep{
|
||||
|
@ -891,12 +920,22 @@ load 10s
|
|||
Query: "max_over_time(metricWith1SampleEvery10Seconds[60s])[20s:5s]",
|
||||
Start: time.Unix(201, 0),
|
||||
PeakSamples: 11,
|
||||
TotalSamples: 26, // (1 sample / 10 seconds * 60 seconds) + 2 as
|
||||
TotalSamples: 26, // (1 sample / 10 seconds * 60 seconds) * 4 + 2 as
|
||||
// max_over_time(metricWith1SampleEvery10Seconds[60s]) @ 190 and 200 will return 7 samples.
|
||||
TotalSamplesPerStep: stats.TotalSamplesPerStep{
|
||||
201000: 26,
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "max_over_time(metricWith1HistogramEvery10Seconds[60s])[20s:5s]",
|
||||
Start: time.Unix(201, 0),
|
||||
PeakSamples: 72,
|
||||
TotalSamples: 312, // (1 histogram (size 12) / 10 seconds * 60 seconds) * 4 + 2 * 12 as
|
||||
// max_over_time(metricWith1SampleEvery10Seconds[60s]) @ 190 and 200 will return 7 samples.
|
||||
TotalSamplesPerStep: stats.TotalSamplesPerStep{
|
||||
201000: 312,
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "metricWith1SampleEvery10Seconds[60s] @ 30",
|
||||
Start: time.Unix(201, 0),
|
||||
|
@ -906,6 +945,15 @@ load 10s
|
|||
201000: 4,
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "metricWith1HistogramEvery10Seconds[60s] @ 30",
|
||||
Start: time.Unix(201, 0),
|
||||
PeakSamples: 48,
|
||||
TotalSamples: 48, // @ modifier force the evaluation to at 30 seconds - So it brings 4 datapoints (0, 10, 20, 30 seconds) * 1 series
|
||||
TotalSamplesPerStep: stats.TotalSamplesPerStep{
|
||||
201000: 48,
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: "sum(max_over_time(metricWith3SampleEvery10Seconds[60s] @ 30))",
|
||||
Start: time.Unix(201, 0),
|
||||
|
@ -1034,13 +1082,42 @@ load 10s
|
|||
},
|
||||
},
|
||||
{
|
||||
// timestamp function as a special handling
|
||||
Query: `metricWith1HistogramEvery10Seconds`,
|
||||
Start: time.Unix(204, 0),
|
||||
End: time.Unix(223, 0),
|
||||
Interval: 5 * time.Second,
|
||||
PeakSamples: 48,
|
||||
TotalSamples: 48, // 1 histogram (size 12) per query * 4 steps
|
||||
TotalSamplesPerStep: stats.TotalSamplesPerStep{
|
||||
204000: 12, // aligned to the step time, not the sample time
|
||||
209000: 12,
|
||||
214000: 12,
|
||||
219000: 12,
|
||||
},
|
||||
},
|
||||
{
|
||||
// timestamp function has a special handling
|
||||
Query: "timestamp(metricWith1SampleEvery10Seconds)",
|
||||
Start: time.Unix(201, 0),
|
||||
End: time.Unix(220, 0),
|
||||
Interval: 5 * time.Second,
|
||||
PeakSamples: 5,
|
||||
TotalSamples: 4, // (1 sample / 10 seconds) * 4 steps
|
||||
TotalSamples: 4, // 1 sample per query * 4 steps
|
||||
TotalSamplesPerStep: stats.TotalSamplesPerStep{
|
||||
201000: 1,
|
||||
206000: 1,
|
||||
211000: 1,
|
||||
216000: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
// timestamp function has a special handling
|
||||
Query: "timestamp(metricWith1HistogramEvery10Seconds)",
|
||||
Start: time.Unix(201, 0),
|
||||
End: time.Unix(220, 0),
|
||||
Interval: 5 * time.Second,
|
||||
PeakSamples: 16,
|
||||
TotalSamples: 4, // 1 sample per query * 4 steps
|
||||
TotalSamplesPerStep: stats.TotalSamplesPerStep{
|
||||
201000: 1,
|
||||
206000: 1,
|
||||
|
@ -1631,7 +1708,7 @@ load 1ms
|
|||
sort.Sort(expMat)
|
||||
sort.Sort(res.Value.(Matrix))
|
||||
}
|
||||
require.Equal(t, c.result, res.Value, "query %q failed", c.query)
|
||||
testutil.RequireEqual(t, c.result, res.Value, "query %q failed", c.query)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1956,7 +2033,7 @@ func TestSubquerySelector(t *testing.T) {
|
|||
require.Equal(t, c.Result.Err, res.Err)
|
||||
mat := res.Value.(Matrix)
|
||||
sort.Sort(mat)
|
||||
require.Equal(t, c.Result.Value, mat)
|
||||
testutil.RequireEqual(t, c.Result.Value, mat)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -2001,7 +2078,7 @@ load 1m
|
|||
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
require.Equal(t, expectedResult, res.Value)
|
||||
testutil.RequireEqual(t, expectedResult, res.Value)
|
||||
}
|
||||
|
||||
type FakeQueryLogger struct {
|
||||
|
@ -3147,7 +3224,7 @@ func TestRangeQuery(t *testing.T) {
|
|||
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
require.Equal(t, c.Result, res.Value)
|
||||
testutil.RequireEqual(t, c.Result, res.Value)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -4314,6 +4391,8 @@ func TestNativeHistogram_Sum_Count_Add_AvgOperator(t *testing.T) {
|
|||
|
||||
ts := idx0 * int64(10*time.Minute/time.Millisecond)
|
||||
app := storage.Appender(context.Background())
|
||||
_, err := app.Append(0, labels.FromStrings("__name__", "float_series", "idx", "0"), ts, 42)
|
||||
require.NoError(t, err)
|
||||
for idx1, h := range c.histograms {
|
||||
lbls := labels.FromStrings("__name__", seriesName, "idx", fmt.Sprintf("%d", idx1))
|
||||
// Since we mutate h later, we need to create a copy here.
|
||||
|
@ -4343,17 +4422,31 @@ func TestNativeHistogram_Sum_Count_Add_AvgOperator(t *testing.T) {
|
|||
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
require.Empty(t, res.Warnings)
|
||||
|
||||
vector, err := res.Vector()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, exp, vector)
|
||||
testutil.RequireEqual(t, exp, vector)
|
||||
}
|
||||
queryAndCheckAnnotations := func(queryString string, ts int64, expWarnings annotations.Annotations) {
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(ts))
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
require.Equal(t, expWarnings, res.Warnings)
|
||||
}
|
||||
|
||||
// sum().
|
||||
queryString := fmt.Sprintf("sum(%s)", seriesName)
|
||||
queryAndCheck(queryString, ts, []Sample{{T: ts, H: &c.expected, Metric: labels.EmptyLabels()}})
|
||||
|
||||
queryString = `sum({idx="0"})`
|
||||
var annos annotations.Annotations
|
||||
annos.Add(annotations.NewMixedFloatsHistogramsAggWarning(posrange.PositionRange{Start: 4, End: 13}))
|
||||
queryAndCheckAnnotations(queryString, ts, annos)
|
||||
|
||||
// + operator.
|
||||
queryString = fmt.Sprintf(`%s{idx="0"}`, seriesName)
|
||||
for idx := 1; idx < len(c.histograms); idx++ {
|
||||
|
@ -4605,7 +4698,7 @@ func TestNativeHistogram_SubOperator(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
require.Equal(t, exp, vector)
|
||||
testutil.RequireEqual(t, exp, vector)
|
||||
}
|
||||
|
||||
// - operator.
|
||||
|
@ -4753,7 +4846,7 @@ func TestNativeHistogram_MulDivOperator(t *testing.T) {
|
|||
vector, err := res.Vector()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, exp, vector)
|
||||
testutil.RequireEqual(t, exp, vector)
|
||||
}
|
||||
|
||||
// histogram * scalar.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue