Merge branch 'main' of github.com:grafana/grafana into task/45304-integrate-alerts-with-folders

This commit is contained in:
Konrad Lalik
2022-03-03 08:55:11 +01:00
411 changed files with 11853 additions and 3909 deletions

View File

@@ -44,7 +44,7 @@ exports[`no enzyme tests`] = {
"packages/grafana-ui/src/components/Logs/LogRows.test.tsx:2288254498": [
[3, 17, 13, "RegExp match", "2409514259"]
],
"packages/grafana-ui/src/components/QueryField/QueryField.test.tsx:1906163280": [
"packages/grafana-ui/src/components/QueryField/QueryField.test.tsx:1297745712": [
[1, 19, 13, "RegExp match", "2409514259"]
],
"packages/grafana-ui/src/components/Slider/Slider.test.tsx:2110443485": [
@@ -104,7 +104,7 @@ exports[`no enzyme tests`] = {
"packages/jaeger-ui-components/src/TraceTimelineViewer/SpanBar.test.js:2127169675": [
[15, 17, 13, "RegExp match", "2409514259"]
],
"packages/jaeger-ui-components/src/TraceTimelineViewer/SpanBarRow.test.js:2454947085": [
"packages/jaeger-ui-components/src/TraceTimelineViewer/SpanBarRow.test.js:814916029": [
[15, 26, 13, "RegExp match", "2409514259"]
],
"packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetail/AccordianKeyValues.test.js:2200354834": [
@@ -113,7 +113,7 @@ exports[`no enzyme tests`] = {
"packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetail/AccordianLogs.test.js:3242453659": [
[15, 19, 13, "RegExp match", "2409514259"]
],
"packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetail/AccordianReferences.test.js:3043344541": [
"packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetail/AccordianReferences.test.js:1301875390": [
[15, 19, 13, "RegExp match", "2409514259"]
],
"packages/jaeger-ui-components/src/TraceTimelineViewer/SpanDetail/AccordianText.test.js:2881451220": [
@@ -326,7 +326,7 @@ exports[`no enzyme tests`] = {
"public/app/plugins/datasource/elasticsearch/configuration/DataLinks.test.tsx:2916632804": [
[1, 17, 13, "RegExp match", "2409514259"]
],
"public/app/plugins/datasource/grafana-azure-monitor-datasource/components/InsightsConfig.test.tsx:866257119": [
"public/app/plugins/datasource/grafana-azure-monitor-datasource/components/deprecated/components/InsightsConfig.test.tsx:1635510338": [
[1, 19, 13, "RegExp match", "2409514259"]
],
"public/app/plugins/datasource/influxdb/components/ConfigEditor.test.tsx:767000341": [

View File

@@ -11,7 +11,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -114,7 +114,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -145,6 +145,15 @@ steps:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend
- commands:
- ./bin/grabpl build-frontend-packages --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER}
--no-pull-enterprise
depends_on:
- initialize
environment:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend-packages
- commands:
- ./bin/grabpl build-plugins --jobs 8 --edition oss
depends_on:
@@ -159,22 +168,14 @@ steps:
image: grafana/build-container:1.5.1
name: validate-scuemata
- commands:
- '# Make sure the git tree is clean.'
- '# Stashing changes, since packages that were produced in build-backend step are
needed.'
- git stash
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root .
- '# The above command generates Typescript files (*.gen.ts) from all appropriate
.cue files.'
- '# It is required that the generated Typescript be in sync with the input CUE
files.'
- '# ...Modulo eslint auto-fixes...:'
- yarn run eslint . --ext .gen.ts --fix
- '# If any filenames are emitted by the below script, run the generator command
`grafana-cli cue gen-ts` locally and commit the result.'
- ./scripts/clean-git-or-error.sh
- '# Un-stash changes.'
- git stash pop
- '# To enforce this, the following command will attempt to generate Typescript
from all'
- '# appropriate .cue files, then compare with the corresponding (*.gen.ts) file
the generated'
- '# code would have been written to. It exits 1 if any diffs are found.'
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root . --diff
depends_on:
- validate-scuemata
image: grafana/build-container:1.5.1
@@ -186,6 +187,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
environment: null
image: grafana/build-container:1.5.1
name: package
@@ -195,6 +197,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
detach: true
environment:
ARCH: linux-amd64
@@ -208,7 +211,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-dashboards-suite
- commands:
- apt-get install -y netcat
@@ -217,7 +220,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-smoke-tests-suite
- commands:
- apt-get install -y netcat
@@ -226,7 +229,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-panels-suite
- commands:
- apt-get install -y netcat
@@ -235,7 +238,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-various-suite
- commands:
- apt-get update
@@ -274,6 +277,7 @@ steps:
- ./bin/grabpl verify-storybook
depends_on:
- build-frontend
- build-frontend-packages
environment:
NODE_OPTIONS: --max_old_space_size=4096
image: grafana/build-container:1.5.1
@@ -354,7 +358,7 @@ services:
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -418,7 +422,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -474,7 +478,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -527,7 +531,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -628,7 +632,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -670,6 +674,15 @@ steps:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend
- commands:
- ./bin/grabpl build-frontend-packages --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER}
--no-pull-enterprise
depends_on:
- initialize
environment:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend-packages
- commands:
- ./bin/grabpl build-plugins --jobs 8 --edition oss --sign --signing-admin
depends_on:
@@ -686,22 +699,14 @@ steps:
image: grafana/build-container:1.5.1
name: validate-scuemata
- commands:
- '# Make sure the git tree is clean.'
- '# Stashing changes, since packages that were produced in build-backend step are
needed.'
- git stash
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root .
- '# The above command generates Typescript files (*.gen.ts) from all appropriate
.cue files.'
- '# It is required that the generated Typescript be in sync with the input CUE
files.'
- '# ...Modulo eslint auto-fixes...:'
- yarn run eslint . --ext .gen.ts --fix
- '# If any filenames are emitted by the below script, run the generator command
`grafana-cli cue gen-ts` locally and commit the result.'
- ./scripts/clean-git-or-error.sh
- '# Un-stash changes.'
- git stash pop
- '# To enforce this, the following command will attempt to generate Typescript
from all'
- '# appropriate .cue files, then compare with the corresponding (*.gen.ts) file
the generated'
- '# code would have been written to. It exits 1 if any diffs are found.'
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root . --diff
depends_on:
- validate-scuemata
image: grafana/build-container:1.5.1
@@ -713,6 +718,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
environment:
GITHUB_TOKEN:
from_secret: github_token
@@ -732,6 +738,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
detach: true
environment:
ARCH: linux-amd64
@@ -745,7 +752,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-dashboards-suite
- commands:
- apt-get install -y netcat
@@ -754,7 +761,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-smoke-tests-suite
- commands:
- apt-get install -y netcat
@@ -763,7 +770,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-panels-suite
- commands:
- apt-get install -y netcat
@@ -772,7 +779,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-various-suite
- commands:
- apt-get update
@@ -811,6 +818,7 @@ steps:
- ./bin/grabpl verify-storybook
depends_on:
- build-frontend
- build-frontend-packages
environment:
NODE_OPTIONS: --max_old_space_size=4096
image: grafana/build-container:1.5.1
@@ -1007,7 +1015,7 @@ services:
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -1075,7 +1083,7 @@ steps:
name: identify-runner
- commands:
- $$ProgressPreference = "SilentlyContinue"
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/windows/grabpl.exe
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/windows/grabpl.exe
-OutFile grabpl.exe
image: grafana/ci-wix:0.1.1
name: initialize
@@ -1158,7 +1166,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -1240,7 +1248,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -1274,6 +1282,15 @@ steps:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend
- commands:
- ./bin/grabpl build-frontend-packages --jobs 8 --github-token $${GITHUB_TOKEN}
--edition oss --no-pull-enterprise ${DRONE_TAG}
depends_on:
- initialize
environment:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend-packages
- commands:
- ./bin/grabpl build-plugins --jobs 8 --edition oss --sign --signing-admin
depends_on:
@@ -1290,22 +1307,14 @@ steps:
image: grafana/build-container:1.5.1
name: validate-scuemata
- commands:
- '# Make sure the git tree is clean.'
- '# Stashing changes, since packages that were produced in build-backend step are
needed.'
- git stash
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root .
- '# The above command generates Typescript files (*.gen.ts) from all appropriate
.cue files.'
- '# It is required that the generated Typescript be in sync with the input CUE
files.'
- '# ...Modulo eslint auto-fixes...:'
- yarn run eslint . --ext .gen.ts --fix
- '# If any filenames are emitted by the below script, run the generator command
`grafana-cli cue gen-ts` locally and commit the result.'
- ./scripts/clean-git-or-error.sh
- '# Un-stash changes.'
- git stash pop
- '# To enforce this, the following command will attempt to generate Typescript
from all'
- '# appropriate .cue files, then compare with the corresponding (*.gen.ts) file
the generated'
- '# code would have been written to. It exits 1 if any diffs are found.'
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root . --diff
depends_on:
- validate-scuemata
image: grafana/build-container:1.5.1
@@ -1317,6 +1326,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
environment:
GITHUB_TOKEN:
from_secret: github_token
@@ -1367,6 +1377,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
detach: true
environment:
ARCH: linux-amd64
@@ -1380,7 +1391,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-dashboards-suite
- commands:
- apt-get install -y netcat
@@ -1389,7 +1400,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-smoke-tests-suite
- commands:
- apt-get install -y netcat
@@ -1398,7 +1409,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-panels-suite
- commands:
- apt-get install -y netcat
@@ -1407,7 +1418,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-various-suite
- commands:
- apt-get update
@@ -1446,6 +1457,7 @@ steps:
- ./bin/grabpl verify-storybook
depends_on:
- build-frontend
- build-frontend-packages
environment:
NODE_OPTIONS: --max_old_space_size=4096
image: grafana/build-container:1.5.1
@@ -1544,7 +1556,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -1665,7 +1677,7 @@ services:
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -1749,7 +1761,7 @@ steps:
name: identify-runner
- commands:
- $$ProgressPreference = "SilentlyContinue"
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/windows/grabpl.exe
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/windows/grabpl.exe
-OutFile grabpl.exe
image: grafana/ci-wix:0.1.1
name: initialize
@@ -1808,7 +1820,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -1864,6 +1876,15 @@ steps:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend
- commands:
- ./bin/grabpl build-frontend-packages --jobs 8 --github-token $${GITHUB_TOKEN}
--edition enterprise --no-pull-enterprise ${DRONE_TAG}
depends_on:
- initialize
environment:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend-packages
- commands:
- ./bin/grabpl build-plugins --jobs 8 --edition enterprise --sign --signing-admin
depends_on:
@@ -1880,22 +1901,14 @@ steps:
image: grafana/build-container:1.5.1
name: validate-scuemata
- commands:
- '# Make sure the git tree is clean.'
- '# Stashing changes, since packages that were produced in build-backend step are
needed.'
- git stash
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root .
- '# The above command generates Typescript files (*.gen.ts) from all appropriate
.cue files.'
- '# It is required that the generated Typescript be in sync with the input CUE
files.'
- '# ...Modulo eslint auto-fixes...:'
- yarn run eslint . --ext .gen.ts --fix
- '# If any filenames are emitted by the below script, run the generator command
`grafana-cli cue gen-ts` locally and commit the result.'
- ./scripts/clean-git-or-error.sh
- '# Un-stash changes.'
- git stash pop
- '# To enforce this, the following command will attempt to generate Typescript
from all'
- '# appropriate .cue files, then compare with the corresponding (*.gen.ts) file
the generated'
- '# code would have been written to. It exits 1 if any diffs are found.'
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root . --diff
depends_on:
- validate-scuemata
image: grafana/build-container:1.5.1
@@ -1917,6 +1930,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
- build-backend-enterprise2
environment:
GITHUB_TOKEN:
@@ -1968,6 +1982,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
detach: true
environment:
ARCH: linux-amd64
@@ -1982,7 +1997,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-dashboards-suite
- commands:
- apt-get install -y netcat
@@ -1991,7 +2006,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-smoke-tests-suite
- commands:
- apt-get install -y netcat
@@ -2000,7 +2015,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-panels-suite
- commands:
- apt-get install -y netcat
@@ -2009,7 +2024,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-various-suite
- commands:
- apt-get update
@@ -2073,6 +2088,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
- build-backend-enterprise2
environment:
GITHUB_TOKEN:
@@ -2147,7 +2163,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2320,7 +2336,7 @@ services:
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2448,7 +2464,7 @@ steps:
name: identify-runner
- commands:
- $$ProgressPreference = "SilentlyContinue"
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/windows/grabpl.exe
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/windows/grabpl.exe
-OutFile grabpl.exe
- git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"
- cd grafana-enterprise
@@ -2523,7 +2539,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2601,7 +2617,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2662,7 +2678,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2741,7 +2757,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2803,7 +2819,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2839,7 +2855,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2886,7 +2902,7 @@ steps:
name: initialize
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2934,7 +2950,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2997,7 +3013,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -3028,6 +3044,15 @@ steps:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend
- commands:
- ./bin/grabpl build-frontend-packages --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER}
--no-pull-enterprise
depends_on:
- initialize
environment:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend-packages
- commands:
- ./bin/grabpl build-plugins --jobs 8 --edition oss --sign --signing-admin
depends_on:
@@ -3044,22 +3069,14 @@ steps:
image: grafana/build-container:1.5.1
name: validate-scuemata
- commands:
- '# Make sure the git tree is clean.'
- '# Stashing changes, since packages that were produced in build-backend step are
needed.'
- git stash
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root .
- '# The above command generates Typescript files (*.gen.ts) from all appropriate
.cue files.'
- '# It is required that the generated Typescript be in sync with the input CUE
files.'
- '# ...Modulo eslint auto-fixes...:'
- yarn run eslint . --ext .gen.ts --fix
- '# If any filenames are emitted by the below script, run the generator command
`grafana-cli cue gen-ts` locally and commit the result.'
- ./scripts/clean-git-or-error.sh
- '# Un-stash changes.'
- git stash pop
- '# To enforce this, the following command will attempt to generate Typescript
from all'
- '# appropriate .cue files, then compare with the corresponding (*.gen.ts) file
the generated'
- '# code would have been written to. It exits 1 if any diffs are found.'
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root . --diff
depends_on:
- validate-scuemata
image: grafana/build-container:1.5.1
@@ -3071,6 +3088,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
environment:
GITHUB_TOKEN:
from_secret: github_token
@@ -3121,6 +3139,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
detach: true
environment:
ARCH: linux-amd64
@@ -3134,7 +3153,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-dashboards-suite
- commands:
- apt-get install -y netcat
@@ -3143,7 +3162,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-smoke-tests-suite
- commands:
- apt-get install -y netcat
@@ -3152,7 +3171,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-panels-suite
- commands:
- apt-get install -y netcat
@@ -3161,7 +3180,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-various-suite
- commands:
- apt-get update
@@ -3200,6 +3219,7 @@ steps:
- ./bin/grabpl verify-storybook
depends_on:
- build-frontend
- build-frontend-packages
environment:
NODE_OPTIONS: --max_old_space_size=4096
image: grafana/build-container:1.5.1
@@ -3256,7 +3276,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -3370,7 +3390,7 @@ services:
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -3447,7 +3467,7 @@ steps:
name: identify-runner
- commands:
- $$ProgressPreference = "SilentlyContinue"
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/windows/grabpl.exe
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/windows/grabpl.exe
-OutFile grabpl.exe
image: grafana/ci-wix:0.1.1
name: initialize
@@ -3495,7 +3515,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -3545,6 +3565,15 @@ steps:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend
- commands:
- ./bin/grabpl build-frontend-packages --jobs 8 --edition enterprise --build-id
${DRONE_BUILD_NUMBER} --no-pull-enterprise
depends_on:
- initialize
environment:
NODE_OPTIONS: --max_old_space_size=8192
image: grafana/build-container:1.5.1
name: build-frontend-packages
- commands:
- ./bin/grabpl build-plugins --jobs 8 --edition enterprise --sign --signing-admin
depends_on:
@@ -3561,22 +3590,14 @@ steps:
image: grafana/build-container:1.5.1
name: validate-scuemata
- commands:
- '# Make sure the git tree is clean.'
- '# Stashing changes, since packages that were produced in build-backend step are
needed.'
- git stash
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root .
- '# The above command generates Typescript files (*.gen.ts) from all appropriate
.cue files.'
- '# It is required that the generated Typescript be in sync with the input CUE
files.'
- '# ...Modulo eslint auto-fixes...:'
- yarn run eslint . --ext .gen.ts --fix
- '# If any filenames are emitted by the below script, run the generator command
`grafana-cli cue gen-ts` locally and commit the result.'
- ./scripts/clean-git-or-error.sh
- '# Un-stash changes.'
- git stash pop
- '# To enforce this, the following command will attempt to generate Typescript
from all'
- '# appropriate .cue files, then compare with the corresponding (*.gen.ts) file
the generated'
- '# code would have been written to. It exits 1 if any diffs are found.'
- ./bin/linux-amd64/grafana-cli cue gen-ts --grafana-root . --diff
depends_on:
- validate-scuemata
image: grafana/build-container:1.5.1
@@ -3596,6 +3617,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
- build-backend-enterprise2
environment:
GITHUB_TOKEN:
@@ -3647,6 +3669,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
detach: true
environment:
ARCH: linux-amd64
@@ -3661,7 +3684,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-dashboards-suite
- commands:
- apt-get install -y netcat
@@ -3670,7 +3693,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-smoke-tests-suite
- commands:
- apt-get install -y netcat
@@ -3679,7 +3702,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-panels-suite
- commands:
- apt-get install -y netcat
@@ -3688,7 +3711,7 @@ steps:
- grafana-server
environment:
HOST: grafana-server
image: cypress/included:9.3.1
image: cypress/included:9.5.0
name: end-to-end-tests-various-suite
- commands:
- apt-get update
@@ -3727,6 +3750,7 @@ steps:
- ./bin/grabpl verify-storybook
depends_on:
- build-frontend
- build-frontend-packages
environment:
NODE_OPTIONS: --max_old_space_size=4096
image: grafana/build-container:1.5.1
@@ -3760,6 +3784,7 @@ steps:
- build-plugins
- build-backend
- build-frontend
- build-frontend-packages
- build-backend-enterprise2
environment:
GITHUB_TOKEN:
@@ -3827,7 +3852,7 @@ services: []
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -3990,7 +4015,7 @@ services:
steps:
- commands:
- mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/grabpl
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -4108,7 +4133,7 @@ steps:
name: identify-runner
- commands:
- $$ProgressPreference = "SilentlyContinue"
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.5/windows/grabpl.exe
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.7/windows/grabpl.exe
-OutFile grabpl.exe
- git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"
- cd grafana-enterprise
@@ -4305,6 +4330,6 @@ kind: secret
name: gcp_upload_artifacts_key
---
kind: signature
hmac: d9de3f45c31338ed1936f253e8a1f3390822468daeb3395bc368dced68068519
hmac: c2da781acf9dc4a0178c13a5d9029d9ef3af96a6171ceaafc3c35c59dcfd1ac3
...

View File

@@ -10,6 +10,9 @@ scripts/grafana-server/tmp
public/lib/monaco
deployment_tools_config.json
# TS generate from cue by cuetsy
**/*.gen.ts
# Auto-generated localisation files
public/locales/_build/
public/locales/**/*.js

3
.github/CODEOWNERS vendored
View File

@@ -53,9 +53,10 @@ go.sum @grafana/backend-platform
/pkg/services/sqlstore/migrations @grafana/backend-platform @grafana/hosted-grafana-team
*_mig.go @grafana/backend-platform @grafana/hosted-grafana-team
# Grafana live
# Grafana edge
/pkg/services/live/ @grafana/grafana-edge-squad
/pkg/services/searchV2/ @grafana/grafana-edge-squad
/pkg/infra/filestore/ @grafana/grafana-edge-squad
# Alerting
/pkg/services/ngalert @grafana/alerting-squad-backend

View File

@@ -209,5 +209,13 @@
"removeFromProject":{
"url":"https://github.com/grafana/grafana/projects/33"
}
},
{
"type": "label",
"name": "team/grafana-partners",
"action": "addToProject",
"addToProject": {
"url": "https://github.com/orgs/grafana/projects/87"
}
}
]

View File

@@ -11,12 +11,15 @@
"@types/d3-scale-chromatic", // we should bump this once we move to esm modules
"@types/grafana__slate-react", // should be updated when the `slate` package is updated
"@types/react-icons", // jaeger-ui-components is being refactored to use @grafana/ui icons instead
"commander", // we are planning to remove this, so no need to update it
"d3",
"d3-force", // we should bump this once we move to esm modules
"d3-interpolate", // we should bump this once we move to esm modules
"d3-scale-chromatic", // we should bump this once we move to esm modules
"execa", // we should bump this once we move to esm modules
"history", // we should bump this together with react-router-dom
"@mdx-js/react", // storybook peer-depends on it's 1.x version, we should upgrade this when we upgrade storybook
"monaco-editor", // due to us exposing this via @grafana/ui/CodeEditor's props bumping can break plugins
"react-hook-form", // due to us exposing these hooks via @grafana/ui form components bumping can break plugins
"react-icons", // jaeger-ui-components is being refactored to use @grafana/ui icons instead
"react-router-dom", // we should bump this together with history

47
.github/stale.yml vendored
View File

@@ -1,47 +0,0 @@
# Configuration for probot-stale - https://github.com/probot/stale
# General configuration
# Label to use when marking as stale
staleLabel: stale
# Pull request specific configuration
pulls:
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 14
# Number of days of inactivity before a stale Issue or Pull Request is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 30
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This pull request has been automatically marked as stale because it has not had
activity in the last 2 weeks. It will be closed in 30 days if no further activity occurs. Please
feel free to give a status update now, ping for review, or re-open when it's ready.
Thank you for your contributions!
# Comment to post when closing a stale Issue or Pull Request.
closeComment: >
This pull request has been automatically closed because it has not had
activity in the last 30 days. Please feel free to give a status update now, ping for review, or re-open when it's ready.
Thank you for your contributions!
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 1
exemptLabels:
- help wanted
- type/bug
- type/feature-request
- Epic
- no stalebot
# Issue specific configuration
issues:
limitPerRun: 1
daysUntilStale: 100000
daysUntilClose: 100000
markComment: >
This issue has been automatically marked as stale because it has not had activity in the
last 100 days. It will be closed in the next 100 days if no activity occurs.
Thank you for your contributions.
closeComment: >
This issue has been automatically closed because it has not had activity in the
last month and a half. If this issue is still valid, please ping a maintainer and ask them to check this again.
Thank you for your contributions.

View File

@@ -16,6 +16,8 @@ on:
required: true
metricsWriteAPIKey:
required: true
env:
YARN_ENABLE_IMMUTABLE_INSTALLS: false
jobs:
main:
runs-on: ubuntu-latest
@@ -80,7 +82,7 @@ jobs:
ref: main
- uses: actions/setup-node@v2.5.1
with:
node-version: '14'
node-version: '16'
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Run bump version (manually invoked)

View File

@@ -13,7 +13,7 @@ on:
- milestoned
- demilestoned
concurrency:
group: pr-checks-${{ github.event.issue.number }}
group: pr-checks-${{ github.event.number }}
jobs:
main:
runs-on: ubuntu-latest

View File

@@ -4,7 +4,7 @@ on:
types:
- closed
concurrency:
group: pr-commands-closed-${{ github.event.issue.number }}
group: pr-commands-closed-${{ github.event.number }}
jobs:
close_job:
# this job will only run if the PR has been closed without being merged

View File

@@ -5,7 +5,7 @@ on:
- opened
- synchronize
concurrency:
group: pr-commands-${{ github.event.issue.number }}
group: pr-commands-${{ github.event.number }}
jobs:
main:
runs-on: ubuntu-latest

33
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '30 1 * * *'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4
with:
repo-token: ${{ secrets.GH_BOT_ACCESS_TOKEN }}
# Number of days of inactivity before a stale Issue or Pull Request is closed.
# Set to -1 to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
days-before-close: 14
# Number of days of inactivity before an Issue or Pull Request becomes stale
days-before-stale: 30
# We don't want any Issues to be marked as stale for now.
days-before-issue-stale: -1
exempt-issue-labels: no stalebot
exempt-pr-labels: no stalebot
operations-per-run: 100
stale-issue-label: stale
stale-pr-label: stale
stale-pr-message: >
This pull request has been automatically marked as stale because it has not had
activity in the last 30 days. It will be closed in 2 weeks if no further activity occurs. Please
feel free to give a status update now, ping for review, or re-open when it's ready.
Thank you for your contributions!
close-pr-message: >
This pull request has been automatically closed because it has not had
activity in the last 2 weeks. Please feel free to give a status update now, ping for review, or re-open when it's ready.
Thank you for your contributions!

View File

@@ -1,3 +1,39 @@
<!-- 8.4.3 START -->
# 8.4.3 (2022-03-02)
### Features and enhancements
- **Alerting:** Grafana uses > instead of >= when checking the For duration. [#46010](https://github.com/grafana/grafana/issues/46010)
- **Alerting:** Use expanded labels in dashboard annotations. [#45726](https://github.com/grafana/grafana/pull/45726), [@grobinson-grafana](https://github.com/grobinson-grafana)
- **Logs:** Escape windows newline into single newline. [#45771](https://github.com/grafana/grafana/pull/45771), [@perosb](https://github.com/perosb)
### Bug fixes
- **Alerting:** Fix use of > instead of >= when checking the For duration. [#46011](https://github.com/grafana/grafana/pull/46011), [@grobinson-grafana](https://github.com/grobinson-grafana)
- **Azure Monitor:** Fixes broken log queries that use workspace. [#45820](https://github.com/grafana/grafana/pull/45820), [@sunker](https://github.com/sunker)
- **CloudWatch:** Remove error message when using multi-valued template vars in region field. [#45886](https://github.com/grafana/grafana/pull/45886), [@sunker](https://github.com/sunker)
- **Middleware:** Fix IPv6 host parsing in CSRF check. [#45911](https://github.com/grafana/grafana/pull/45911), [@ying-jeanne](https://github.com/ying-jeanne)
### Plugin development fixes & changes
- **ClipboardButton:** Use a fallback when the Clipboard API is unavailable. [#45831](https://github.com/grafana/grafana/pull/45831), [@ashharrison90](https://github.com/ashharrison90)
<!-- 8.4.3 END -->
<!-- 8.4.2 START -->
# 8.4.2 (2022-02-23)
### Features and enhancements
- **OAuth:** Add setting to skip org assignment for external users. [#34834](https://github.com/grafana/grafana/pull/34834), [@baez90](https://github.com/baez90)
- **Tracing:** Add option to map tag names to log label names in trace to logs settings. [#45178](https://github.com/grafana/grafana/pull/45178), [@connorlindsey](https://github.com/connorlindsey)
### Bug fixes
- **Explore:** Fix closing split pane when logs panel is used. [#45602](https://github.com/grafana/grafana/pull/45602), [@ifrost](https://github.com/ifrost)
<!-- 8.4.2 END -->
<!-- 8.4.1 START -->
# 8.4.1 (2022-02-18)
@@ -87,6 +123,16 @@ AngularJS plugin support is now in a deprecated state, meaning it will be remove
- **News:** Reload feed when changing the time range or refreshing. [#42217](https://github.com/grafana/grafana/pull/42217), [@ashharrison90](https://github.com/ashharrison90)
- **UI/Plot:** Implement keyboard controls for plot cursor. [#42244](https://github.com/grafana/grafana/pull/42244), [@kaydelaney](https://github.com/kaydelaney)
<!-- 8.3.7 START -->
# 8.3.7 (2022-03-01)
### Bug fixes
- **Provisioning:** Ensure that the default value for orgID is set when provisioning datasources to be deleted. [#44244](https://github.com/grafana/grafana/pull/44244), [@filewalkwithme](https://github.com/filewalkwithme)
<!-- 8.3.7 END -->
<!-- 8.3.6 START -->
# 8.3.6 (2022-02-09)

View File

@@ -1,14 +1,14 @@
![Grafana](docs/logo-horizontal.png)
The open-source platform for monitoring and observability.
The open-source platform for monitoring and observability
[![License](https://img.shields.io/github/license/grafana/grafana)](LICENSE)
[![Drone](https://drone.grafana.net/api/badges/grafana/grafana/status.svg)](https://drone.grafana.net/grafana/grafana)
[![Go Report Card](https://goreportcard.com/badge/github.com/grafana/grafana)](https://goreportcard.com/report/github.com/grafana/grafana)
Grafana allows you to query, visualize, alert on and understand your metrics no matter where they are stored. Create, explore, and share dashboards with your team and foster a data driven culture:
Grafana allows you to query, visualize, alert on and understand your metrics no matter where they are stored. Create, explore, and share dashboards with your team and foster a data-driven culture:
- **Visualize:** Fast and flexible client side graphs with a multitude of options. Panel plugins offer many different ways to visualize metrics and logs.
- **Visualizations:** Fast and flexible client side graphs with a multitude of options. Panel plugins offer many different ways to visualize metrics and logs.
- **Dynamic Dashboards:** Create dynamic & reusable dashboards with template variables that appear as dropdowns at the top of the dashboard.
- **Explore Metrics:** Explore your data through ad-hoc queries and dynamic drilldown. Split view and compare different time ranges, queries and data sources side by side.
- **Explore Logs:** Experience the magic of switching from metrics to logs with preserved label filters. Quickly search through all your logs or streaming them live.

View File

@@ -136,6 +136,20 @@ Running the backend tests on Windows currently needs some tweaking, so use the b
go run build.go test
```
### Run PostgreSQL and MySQL integration tests
To run PostgreSQL and MySQL integration tests locally, you need to start the docker blocks for MySQL and/or PostgreSQL test data sources by running `make devenv sources=mysql_tests,postgres_tests`. When your test data sources are running, you can execute integration tests by running:
```
GRAFANA_TEST_DB=mysql go test -covermode=atomic -tags=integration ./pkg/...
```
and/or
```
GRAFANA_TEST_DB=postgres go test -covermode=atomic -tags=integration ./pkg/...
```
### Run end-to-end tests
The end to end tests in Grafana use [Cypress](https://www.cypress.io/) to run automated scripts in a headless Chromium browser. Read more about our [e2e framework](/contribute/style-guides/e2e.md).

View File

@@ -195,7 +195,7 @@ datasources:
timeInterval: 10s
interval: Daily
timeField: "@timestamp"
esVersion: 70
esVersion: 7.10.0
- name: gdev-elasticsearch-v7-logs
type: elasticsearch
@@ -205,7 +205,7 @@ datasources:
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 70
esVersion: 7.10.0
- name: gdev-elasticsearch-v7-filebeat
type: elasticsearch
@@ -215,7 +215,7 @@ datasources:
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 70
esVersion: 7.10.0
timeInterval: "10s"
logMessageField: message
logLevelField: fields.level
@@ -228,7 +228,7 @@ datasources:
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 70
esVersion: 7.10.0
timeInterval: "10s"
- name: gdev-mysql

View File

@@ -1,7 +1,7 @@
# You need to run 'sysctl -w vm.max_map_count=262144' on the host machine
elasticsearch7:
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.0.0
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
command: elasticsearch -E "discovery.type=single-node"
ports:
- "12200:9200"
@@ -17,7 +17,7 @@
FD_PORT: 9200
filebeat7:
image: docker.elastic.co/beats/filebeat-oss:7.0.0
image: docker.elastic.co/beats/filebeat-oss:7.17.0
command: filebeat -e -strict.perms=false
volumes:
- ./docker/blocks/elastic7/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
@@ -25,7 +25,7 @@
- ../data/log:/var/log/grafana:ro
metricbeat7:
image: docker.elastic.co/beats/metricbeat-oss:7.0.0
image: docker.elastic.co/beats/metricbeat-oss:7.17.0
command: metricbeat -e -strict.perms=false
user: root
volumes:

View File

@@ -7,7 +7,7 @@
promtail:
image: grafana/promtail:latest
volumes:
- ./docker/blocks/loki/config.yaml:/etc/promtail/docker-config.yaml
- ./docker/blocks/loki/promtail-config.yaml:/etc/promtail/docker-config.yaml
- /var/log:/var/log
- ../data/log:/var/log/grafana
command:

View File

@@ -14,7 +14,7 @@ Grafana has default and custom configuration files. You can customize your Grafa
## Configuration file location
The default settings for a Grafana instance are stored in the `$WORKING_DIR/conf/defaults.ini` file. _Do not_ change the location in this file.
The default settings for a Grafana instance are stored in the `$WORKING_DIR/conf/defaults.ini` file. _Do not_ change this file.
Depending on your OS, your custom configuration file is either the `$WORKING_DIR/conf/defaults.ini` file or the `/usr/local/etc/grafana/grafana.ini` file. The custom configuration file path can be overridden using the `--config` parameter.

View File

@@ -0,0 +1,100 @@
+++
title = "Manage user preferences"
weight = 400
description = "Learn how to update your user preferences and switch organizations"
keywords = ["password", "change", "organization", "change"]
aliases = ["/docs/grafana/latest/administration/change-your-password/", "docs/sources/administration/manage-user-preferences/_index.md"]
+++
# Manage user preferences
Grafana allows you to manage certain aspects of your user account, including your user name, email, and password.
You can also view important information about your account, such as the organizations and roles to which you are assigned and the Grafana sessions associated with your account.
## Change your Grafana password
You can change your Grafana password at any time.
> **Note**: If your Grafana instance uses an <!--[external authentication provider]({{< relref "../../auth/_index.md">}})--> external authentication provider, then you might not be able to change your password in Grafana. Contact your Grafana administrator for more information.
**To change your password**:
1. Sign in to Grafana.
1. Hover your mouse over the user icon in the lower-left corner of the page.
1. Click **Change Password**.
Grafana opens the **Change Password** tab.
1. Enter your old password and a new password.
1. Confirm your new password.
1. Click **Change Password**.
## Edit your profile
Your profile includes your name, user name, and email address, which you can update.
**To edit your profile**:
1. Sign in to Grafana.
1. Hover your cursor over the user icon in the lower-left corner of the page and click **Preferences**.
1. In the **Edit Profile** section, update your profile and click **Save**.
## Edit your preferences
You can choose the way you would like data to appear in Grafana, including the UI theme, home dashboard, timezone, and first day of the week. You can set these preferences for your own account, for a team, for an organization, or Grafana-wide using configuration settings. Your user preferences take precedence over team, organization, and Grafana default preferences. For more information, see [Grafana preferences]({{< relref "../../administration/preferences/_index.md">}}).
- **UI theme** determines whether Grafana appears in light mode or dark mode. By default, UI theme is set to dark mode.
- **Home dashboard** refers to the dashboard you see when you sign in to Grafana. By default, this is set to the Home dashboard.
- **Timezone** is used by dashboards when you set time ranges, so that you view data in your timezone instead of UTC.
- **Week start** is the first day of the week you want to use in dashboard time ranges, for example, `This week`.
**To edit your preferences**:
1. Sign in to Grafana.
1. Hover your cursor over the user icon in the lower-left corner of the page, and click **Preferences**.
1. Update any of the values in the **Preferences** section.
1. Click **Save** at the bottom of the Preferences section.
## Switch organizations
When you sign in to Grafana, the system signs you in to a default organization. If you are assigned to multiple organizations, then you might need to switch organizations. For example, if you need to view a dashboard not associated with your current organization, then you should switch organizations to view associated dashboards.
**To switch organizations**:
1. Sign in to Grafana.
1. Hover your cursor over the user icon in the lower-left corner of the page and click **Switch organization**.
1. Next to the organization that you want to sign in to, click **Switch to**.
## View your assigned organizations
Every user is a member of at least one organization. You can have different roles in each organization of which you are a member.
**To view your assigned organizations**:
1. Sign in to Grafana.
1. Hover your cursor over the user icon in the lower-left corner of the page and click **Preferences**.
1. Scroll down to the **Organizations** section and review the following information:
- **Name**: The name of the organizations of which you are a member.
- **Role**: The role to which you are assigned in the organization. For more information about roles and permissions, refer to [Organization users and permissions]({{< relref "../../administration/manage-users-and-permissions/about-users-and-permissions.md#organization-users-and-permissions" >}}).
- **Current**: Grafana indicates the organization that you are currently signed into as _Current_. If you are a member of multiple organizations, you can click **Select** to switch to that organization.
## View your Grafana sessions
Grafana logs your sessions in each Grafana instance. You can review this section if you suspect someone has misused your Grafana credentials.
**To view your Grafana sessions**:
1. Sign in to Grafana.
1. Hover your cursor over the user icon in the lower-left corner of the page, and click **Preferences**.
1. Scroll down to the **Sessions** section.
## Sign out a user session
You can sign out other sessions using your account in order to prevent other people from accessing Grafana using your credentials.
**To sign out one of your Grafana sessions**:
1. Sign in to Grafana.
1. Hover your cursor over the user icon in the lower-left corner of the page, and click **Preferences**.
1. Scroll down to the **Sessions** section.
1. Click the red "sign out" icon next to the session you would like to sign out.

View File

@@ -53,4 +53,4 @@ To change the team name or email, follow these steps:
## Change user name or email
To learn how to edit your user information, refer to [Grafana user account profile]({{< relref "../../manage-users/user-admin/user-profile.md" >}}).
To learn how to edit your user information, refer to [Edit your profile]({{< relref "../manage-user-preferences/_index.md#edit-your-profile" >}}).

View File

@@ -11,7 +11,7 @@ Annotations and labels are key value pairs associated with alerts originating fr
## Annotations
Annotations are key-value pairs that provide additional meta-information about an alert. For example: a description, a summary, and runbook URL. These are displayed in rule and alert details in the UI and can be used in contact point message templates.
Annotations are key-value pairs that provide additional meta-information about an alert. You can use the following annotations: `description`, `summary`, `runbook_url`, `alertId`, `dashboardUid`, and `panelId`. For example, a description, a summary, and a runbook URL. These are displayed in rule and alert details in the UI and can be used in contact point message templates.
## Labels
@@ -20,7 +20,7 @@ Labels are key-value pairs that contain information about, and are used to uniqu
### How are labels used?
- The complete set of labels for an alert is what uniquely identifies an alert within Grafana Alerts.
- The Alertmanager uses labels to match alerts for [silences]({{< relref "../silences/" >}}) and [alert groups]({{< relref "../alert-groups/" >}}) in [notification policies]({{< relref "../notification-policies/" >}}).
- The Alertmanager uses labels to match alerts for [silences]({{< relref "../silences/" >}}) and [alert groups]({{< relref "../alert-groups/" >}}) in [notification policies]({{< relref "../notifications/_index.md" >}}).
- The alerting UI displays labels for every alert instance generated by the evaluation of that rule.
- Contact points can access labels to dynamically generate notifications that contain information specific to the alert that is resulting in a notification.
- Labels can be added to an [alerting rule]({{< relref "../alerting-rules/" >}}). These manually configured labels are able to use template functions and reference other labels. Labels added to an alerting rule here take precedence in the event of a collision between labels.

View File

@@ -9,7 +9,7 @@ weight = 450
Notification policies determine how alerts are routed to contact points. Policies have a tree structure, where each policy can have one or more child policies. Each policy, except for the root policy, can also match specific alert labels. Each alert is evaluated by the root policy and subsequently by each child policy. If you enable the `Continue matching subsequent sibling nodes` option is enabled for a specific policy, then evaluation continues even after one or more matches. A parent policys configuration settings and contact point information govern the behavior of an alert that does not match any of the child policies. A root policy governs any alert that does not match a specific policy.
You can configure Grafana managed notification policies as well as notification policies for an [external Alertmanager data source]({{< relref "../../datasources/alertmanager.md" >}}). For more information, see [Alertmanager]({{< relref "./fundamentals/alertmanager.md" >}}).
You can configure Grafana managed notification policies as well as notification policies for an [external Alertmanager data source]({{< relref "../../../datasources/alertmanager.md" >}}). For more information, see [Alertmanager]({{< relref "../fundamentals/alertmanager.md" >}}).
## Grouping
@@ -33,7 +33,7 @@ You can configure grouping to be `group_by: [alertname]` (take note that the `en
1. Click **Notification policies**.
1. From the **Alertmanager** dropdown, select an external Alertmanager. By default, the Grafana Alertmanager is selected.
1. In the Root policy section, click **Edit** (pen icon).
1. In **Default contact point**, update the [contact point]({{< relref "./contact-points.md" >}}) to whom notifications should be sent for rules when alert rules do not match any specific policy.
1. In **Default contact point**, update the [contact point]({{< relref "../contact-points.md" >}}) to whom notifications should be sent for rules when alert rules do not match any specific policy.
1. In **Group by**, choose labels to group alerts by. If multiple alerts are matched for this policy, then they are grouped by these labels. A notification is sent per group. If the field is empty (default), then all notifications are sent in a single group. Use a special label `...` to group alerts by all labels (which effectively disables grouping).
1. In **Timing options**, select from the following options:
- **Group wait** Time to wait to buffer alerts of the same group before sending an initial notification. Default is 30 seconds.
@@ -48,7 +48,7 @@ You can configure grouping to be `group_by: [alertname]` (take note that the `en
1. From the **Alertmanager** dropdown, select an Alertmanager. By default, the Grafana Alertmanager is selected.
1. To add a top level specific policy, go to the **Specific routing** section and click **New specific policy**.
1. In **Matching labels** section, add one or more rules for matching alert labels. For more information, see ["How label matching works"](#how-label-matching-works).
1. In **Contact point**, add the [contact point]({{< relref "./contact-points.md" >}}) to send notification to if alert matches only this specific policy and not any of the nested policies.
1. In **Contact point**, add the [contact point]({{< relref "../contact-points.md" >}}) to send notification to if alert matches only this specific policy and not any of the nested policies.
1. Optionally, enable **Continue matching subsequent sibling nodes** to continue matching nested policies even after the alert matched the parent policy. When this option is enabled, you can get more than one notification. Use it to send notification to a catch-all contact point as well as to one of more specific contact points handled by nested policies.
1. Optionally, enable **Override grouping** to specify the same grouping as the root policy. If this option is not enabled, the root policy grouping is used.
1. Optionally, enable **Override general timings** to override the timing options configured in the group notification policy.

View File

@@ -11,7 +11,7 @@ A mute timing is a recurring interval of time when no new notifications for a po
Similar to silences, mute timings do not prevent alert rules from being evaluated, nor do they stop alert instances from being shown in the user interface. They only prevent notifications from being created.
You can configure Grafana managed mute timings as well as mute timings for an [external Alertmanager data source]({{< relref "../../datasources/alertmanager.md" >}}). For more information, see [Alertmanager]({{< relref "./fundamentals/alertmanager.md" >}}).
You can configure Grafana managed mute timings as well as mute timings for an [external Alertmanager data source]({{< relref "../../../datasources/alertmanager.md" >}}). For more information, see [Alertmanager]({{< relref "../fundamentals/alertmanager.md" >}}).
## Mute timings vs silences

View File

@@ -68,7 +68,7 @@ ssl_skip_verify = false
bind_dn = "cn=admin,dc=grafana,dc=org"
# Search user bind password
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
bind_password = 'grafana'
bind_password = "grafana"
# User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)"
# Allow login from email or username, example "(|(sAMAccountName=%s)(userPrincipalName=%s))"
@@ -236,7 +236,7 @@ use_ssl = false
start_tls = false
ssl_skip_verify = false
bind_dn = "cn=admin,dc=grafana,dc=org"
bind_password = 'grafana'
bind_password = "grafana"
search_filter = "(cn=%s)"
search_base_dns = ["dc=grafana,dc=org"]
@@ -263,7 +263,7 @@ use_ssl = false
start_tls = false
ssl_skip_verify = false
bind_dn = "cn=admin,dc=grafana,dc=org"
bind_password = 'grafana'
bind_password = "grafana"
search_filter = "(cn=%s)"
search_base_dns = ["ou=users,dc=grafana,dc=org"]
@@ -286,7 +286,7 @@ start_tls = false
ssl_skip_verify = false
bind_dn = "cn=admin,dc=grafana,dc=org"
bind_password = 'grafana'
bind_password = "grafana"
search_filter = "(cn=%s)"
search_base_dns = ["ou=users,dc=grafana,dc=org"]

View File

@@ -291,16 +291,27 @@ When configured, Grafana will pass the user's token to the plugin in an Authoriz
```go
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
for _, q := range req.Queries {
token := strings.Fields(q.Headers.Get("Authorization"))
token := strings.Fields(req.Headers["Authorization"])
var (
tokenType = token[0]
accessToken = token[1]
)
var (
tokenType = token[0]
accessToken = token[1]
)
for _, q := range req.Queries {
// ...
}
}
```
// ...
}
In addition, if the user's token includes an ID token, Grafana will pass the user's ID token to the plugin in an `X-ID-Token` header, available on the `QueryDataRequest` object on the `QueryData` request in your backend data source.
```go
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
idToken := req.Headers["X-ID-Token"]
for _, q := range req.Queries {
// ...
}
}
```

View File

@@ -23,7 +23,7 @@ You can use an encryption key from AWS Key Management Service to encrypt secrets
3. Create a [programmatic credential](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) (access key ID and secret access key), which has permission to view the key that you created.
<br><br>In AWS, you can control access to your KMS keys by using [key policies](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html), [IAM policies](https://docs.aws.amazon.com/kms/latest/developerguide/iam-policies.html), and [grants](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html). You can also create [temporary credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html), which must provide a session token along with an access key ID and a secret access key.
4. From within Grafana, turn on [envelope encryption]({{< relref "../../administration/envelope-encryption.md" >}}).
4. From within Grafana, turn on [envelope encryption]({{< relref "../../administration//database-encryption.md" >}}).
5. Add your AWS KMS details to the Grafana configuration file; depending on your operating system, it is usually named `grafana.ini`:
<br><br>a. Add a new section to the configuration file, with a name in the format of `[security.encryption.awskms.<KEY-NAME>]`, where `<KEY-NAME>` is any name that uniquely identifies this key among other provider keys.
<br><br>b. Fill in the section with the following values:

View File

@@ -24,7 +24,7 @@ You can use an encryption key from Azure Key Vault to encrypt secrets in the Gra
5. In the Key Permissions section, set encrypt and decrypt permissions, and click **Save**.
6. From within Grafana, turn on [envelope encryption]({{< relref "../../administration/envelope-encryption.md" >}}).
6. From within Grafana, turn on [envelope encryption]({{< relref "../../administration/database-encryption.md" >}}).
7. Add your Azure Key Vault details to the Grafana configuration file; depending on your operating system, is usually named `grafana.ini`:
<br><br>a. Add a new section to the configuration file, with a name in the format of `[security.encryption.azurekv.<KEY-NAME>]`, where `<KEY-NAME>` is any name that uniquely identifies this key among other provider keys.

View File

@@ -22,7 +22,7 @@ You can use an encryption key from Google Cloud Key Management Service to encryp
4. [Create a service account key and save its JSON file](https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating) to you computer, for example, as `~/.config/gcloud/sample-project-credentials.json`.
5. From within Grafana, turn on [envelope encryption]({{< relref "../../administration/envelope-encryption.md" >}}).
5. From within Grafana, turn on [envelope encryption]({{< relref "../../administration/database-encryption.md" >}}).
6. Add your Google Cloud KMS details to the Grafana configuration file; depending on your operating system, is usually named `grafana.ini`:
<br><br>a. Add a new section to the configuration file, with a name in the format of `[security.encryption.azurekv.<KEY-NAME>]`, where `<KEY-NAME>` is any name that uniquely identifies this key among other provider keys.

View File

@@ -20,7 +20,7 @@ You can use an encryption key from Hashicorp Vault to encrypt secrets in the Gra
3. [Create a periodic service token](https://learn.hashicorp.com/tutorials/vault/tokens#periodic-service-tokens).
4. From within Grafana, turn on [envelope encryption]({{< relref "../../administration/envelope-encryption.md" >}}).
4. From within Grafana, turn on [envelope encryption]({{< relref "../../administration/database-encryption.md" >}}).
5. Add your Hashicorp Vault details to the Grafana configuration file; depending on your operating system, is usually named `grafana.ini`:
<br><br>a. Add a new section to the configuration file, with a name in the format of `[security.encryption.hashicorpvault.<KEY-NAME>]`, where `<KEY-NAME>` is any name that uniquely identifies this key among other provider keys.

View File

@@ -31,7 +31,7 @@ If the data source does not support loading full range log volume histogram, the
For logs where a level label is specified, we use the value of the label to determine the log level and update color accordingly. If the log doesn't have a level label specified, we try to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In case Grafana is not able to determine a log level, it will be visualized with an unknown log level.
> **Tip:** If you use Loki data source and the "level" is in you log content, try to use parsers (JSON, logfmt, regex,..) to extract level information into level label that is used to determine log level.
> **Tip:** If you use Loki data source and the "level" is in your log-line, use parsers (JSON, logfmt, regex,..) to extract the level information into a level label that is used to determine log level. This will allow the histogram to show the various log levels in separate bars.
**Supported log levels and mapping of log level abbreviation and expressions:**

View File

@@ -67,7 +67,7 @@ Status Codes:
```
Status Codes:
Status Codes:
- **200** - Ok
- **401** - Unauthorized

View File

@@ -1,10 +0,0 @@
+++
title = "User account tasks"
weight = 400
+++
# User account tasks
Grafana allows you to manage certain aspects of your user account, including the user name, email, and password.
You can also view important aspects of your account, such as the organizations and roles assigned and the Grafana sessions associated with the account.

View File

@@ -1,21 +0,0 @@
+++
title = "Change your password"
description = "How to change your Grafana password"
keywords = ["grafana", "password", "change", "preferences"]
aliases = ["/docs/grafana/latest/administration/change-your-password/"]
weight = 200
+++
# Change your Grafana password
You can change your Grafana password in the Change Password tab.
> **Note:** If your Grafana instance uses an external authentication provider, then you might not be able to change your password. Contact your Grafana administrator for more information.
## Change your password
1. Hover your mouse over your user icon in the lower left corner of the screen.
1. Click **Change Password**. Grafana opens the Change Password tab.
1. Enter your **Old password** to authorize the change.
1. Enter your **New password** and then **Confirm password**.
1. Click **Change Password**.

View File

@@ -1,12 +0,0 @@
+++
title = "Switch organization"
description = "Change which organization you are logged in with"
weight = 300
+++
# Change the organization you are signed in to
When you sign in to Grafana, you are always signed in with a particular organization. If you are assigned to multiple organizations, then you might need to switch which organization you are signed in to. For example, if you need to view a dashboard associated with a different org, then you might switch organizations.
1. Hover your cursor over your user icon in the lower left corner of the screen, then click **Switch**.
1. Next to the organization that you want to sign in to, click **Switch to**.

View File

@@ -1,42 +0,0 @@
+++
title = "User account profile"
description = "View and edit your Grafana user profile"
weight = 100
+++
# Grafana user account profile
You can edit and view important information about your Grafana user account, including your assigned organizations, your sessions, and the information associated with your account.
## Edit your profile
Your profile includes your name, user name, and email address.
1. Navigate to the Preferences tab. Hover your cursor over your user icon in the lower left corner of the screen, and then click **Preferences.**
1. In the Edit Profile section, you can edit any of the following:
- **Name -** Edit this field to change the display name associated with your profile.
- **Email -** Edit this field to change the email address associated with your profile.
- **Username -** Edit this field to change your user name.
1. Click **Save**.
## View your assigned organizations
Every user is a member of at least one organization. You can have different roles in every organization that you are a member of.
1. Navigate to the Preferences tab. Hover your cursor over your user icon in the lower left corner of the screen, and then click **Preferences.**
1. Scroll down to the Organizations section.
- **Name -** The name of the organizations you are a member of in that Grafana instance.
- **Role -** The role you are assigned in the organization. Refer to [Organization users and permissions]({{< relref "../../administration/manage-users-and-permissions/about-users-and-permissions.md#organization-users-and-permissions" >}}) for more information about permissions assigned to each role.
- **Current -** Grafana tags the organization that you are currently signed in to as _Current_. If you are part of multiple organizations, then you can click **Select** to switch to that organization.
## View your Grafana sessions
Grafana logs your sessions in each Grafana instance. You can review this section if you suspect someone has misused your Grafana credentials.
1. Navigate to the Preferences tab. Hover your cursor over your user icon in the lower left corner of the screen, and then click **Preferences.**
1. Scroll down to the Sessions section. Grafana displays the following:
- **Last seen -** How long ago you logged on.
- **Logged on -** The date you logged on to the current Grafana instance.
- **IP address -** The IP address that you logged on from.
- **Browser & OS -** The web browser and operating system used to log on to Grafana.
- If you are a Grafana Admin for the instance, then you can revoke a session by clicking the red signout icon in the session row.

View File

@@ -8,8 +8,11 @@ weight = 10000
Here you can find detailed release notes that list everything that is included in every release as well as notices
about deprecations, breaking changes as well as changes that relate to plugin development.
- [Release notes for 8.4.3]({{< relref "release-notes-8-4-3" >}})
- [Release notes for 8.4.2]({{< relref "release-notes-8-4-2" >}})
- [Release notes for 8.4.1]({{< relref "release-notes-8-4-1" >}})
- [Release notes for 8.4.0-beta1]({{< relref "release-notes-8-4-0-beta1" >}})
- [Release notes for 8.3.7]({{< relref "release-notes-8-3-7" >}})
- [Release notes for 8.3.6]({{< relref "release-notes-8-3-6" >}})
- [Release notes for 8.3.5]({{< relref "release-notes-8-3-5" >}})
- [Release notes for 8.3.4]({{< relref "release-notes-8-3-4" >}})

View File

@@ -0,0 +1,12 @@
+++
title = "Release notes for Grafana 8.3.7"
hide_menu = true
+++
<!-- Auto generated by update changelog github action -->
# Release notes for Grafana 8.3.7
### Bug fixes
- **Provisioning:** Ensure that the default value for orgID is set when provisioning datasources to be deleted. [#44244](https://github.com/grafana/grafana/pull/44244), [@filewalkwithme](https://github.com/filewalkwithme)

View File

@@ -0,0 +1,17 @@
+++
title = "Release notes for Grafana 8.4.2"
hide_menu = true
+++
<!-- Auto generated by update changelog github action -->
# Release notes for Grafana 8.4.2
### Features and enhancements
- **OAuth:** Add setting to skip org assignment for external users. [#34834](https://github.com/grafana/grafana/pull/34834), [@baez90](https://github.com/baez90)
- **Tracing:** Add option to map tag names to log label names in trace to logs settings. [#45178](https://github.com/grafana/grafana/pull/45178), [@connorlindsey](https://github.com/connorlindsey)
### Bug fixes
- **Explore:** Fix closing split pane when logs panel is used. [#45602](https://github.com/grafana/grafana/pull/45602), [@ifrost](https://github.com/ifrost)

View File

@@ -0,0 +1,25 @@
+++
title = "Release notes for Grafana 8.4.3"
hide_menu = true
+++
<!-- Auto generated by update changelog github action -->
# Release notes for Grafana 8.4.3
### Features and enhancements
- **Alerting:** Grafana uses > instead of >= when checking the For duration. [#46010](https://github.com/grafana/grafana/issues/46010)
- **Alerting:** Use expanded labels in dashboard annotations. [#45726](https://github.com/grafana/grafana/pull/45726), [@grobinson-grafana](https://github.com/grobinson-grafana)
- **Logs:** Escape windows newline into single newline. [#45771](https://github.com/grafana/grafana/pull/45771), [@perosb](https://github.com/perosb)
### Bug fixes
- **Alerting:** Fix use of > instead of >= when checking the For duration. [#46011](https://github.com/grafana/grafana/pull/46011), [@grobinson-grafana](https://github.com/grobinson-grafana)
- **Azure Monitor:** Fixes broken log queries that use workspace. [#45820](https://github.com/grafana/grafana/pull/45820), [@sunker](https://github.com/sunker)
- **CloudWatch:** Remove error message when using multi-valued template vars in region field. [#45886](https://github.com/grafana/grafana/pull/45886), [@sunker](https://github.com/sunker)
- **Middleware:** Fix IPv6 host parsing in CSRF check. [#45911](https://github.com/grafana/grafana/pull/45911), [@ying-jeanne](https://github.com/ying-jeanne)
### Plugin development fixes & changes
- **ClipboardButton:** Use a fallback when the Clipboard API is unavailable. [#45831](https://github.com/grafana/grafana/pull/45831), [@ashharrison90](https://github.com/ashharrison90)

View File

@@ -96,6 +96,12 @@ If you have a field value that is an image URL or a base64 encoded image you can
{{< figure src="/static/img/docs/v73/table_hover.gif" max-width="900px" caption="Table hover" >}}
## Cell value inspect
Enables value inspection from table cell. The raw value is presented in a modal window.
> **Note:** Cell value inspection is only available when cell display mode is set to Auto, Color text, Color background or JSON View.
## Column filter
You can temporarily change how column data is displayed. For example, you can order values from highest to lowest or hide specific values. For more information, refer to [Filter table columns]({{< relref "./filter-table-columns.md" >}}).

View File

@@ -5,9 +5,8 @@ e2e.scenario({
itName: 'Tests dashboard links and variables in links',
addScenarioDataSource: false,
addScenarioDashBoard: false,
skipScenario: true, // Skipped because it was causing many failures in main.
skipScenario: false,
scenario: () => {
e2e.flows.openDashboard({ uid: 'yBCC3aKGk' });
e2e()
.intercept({
method: 'GET',
@@ -21,7 +20,11 @@ e2e.scenario({
})
.as('tagsDemoSearch');
// waiting for links to render, couldn't find a better way using routes for instance
e2e.flows.openDashboard({ uid: 'yBCC3aKGk' });
// waiting for network requests first
e2e().wait(['@tagsTemplatingSearch', '@tagsDemoSearch']);
// and then waiting for links to render
e2e().wait(1000);
const verifyLinks = (variableValue: string) => {
@@ -36,11 +39,7 @@ e2e.scenario({
});
};
e2e.components.DashboardLinks.dropDown()
.should('be.visible')
.click()
.wait('@tagsTemplatingSearch')
.wait('@tagsDemoSearch');
e2e.components.DashboardLinks.dropDown().should('be.visible').click().wait('@tagsTemplatingSearch');
// verify all links, should have All value
verifyLinks('All');

53
go.mod
View File

@@ -14,16 +14,16 @@ replace k8s.io/client-go => k8s.io/client-go v0.22.1
replace github.com/russellhaering/goxmldsig@v1.1.0 => github.com/russellhaering/goxmldsig v1.1.1
require (
cloud.google.com/go/storage v1.14.0
cloud.google.com/go/storage v1.18.2
cuelang.org/go v0.4.0
github.com/Azure/azure-sdk-for-go v57.1.0+incompatible
github.com/Azure/azure-sdk-for-go v59.3.0+incompatible
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.10.0
github.com/Azure/go-autorest/autorest v0.11.20
github.com/Azure/go-autorest/autorest v0.11.22
github.com/BurntSushi/toml v0.3.1
github.com/Masterminds/semver v1.5.0
github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f
github.com/aws/aws-sdk-go v1.40.37
github.com/aws/aws-sdk-go v1.42.8
github.com/beevik/etree v1.1.0
github.com/benbjohnson/clock v1.1.0
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
@@ -31,7 +31,7 @@ require (
github.com/cortexproject/cortex v1.10.1-0.20211014125347-85c378182d0d
github.com/crewjam/saml v0.4.6-0.20210521115923-29c6295245bd
github.com/davecgh/go-spew v1.1.1
github.com/denisenkom/go-mssqldb v0.10.0
github.com/denisenkom/go-mssqldb v0.11.0
github.com/dop251/goja v0.0.0-20210804101310-32956a348b49
github.com/fatih/color v1.10.0
github.com/gchaincl/sqlhooks v1.3.0
@@ -66,7 +66,7 @@ require (
github.com/json-iterator/go v1.1.12
github.com/jung-kurt/gofpdf v1.16.2
github.com/laher/mergefs v0.1.1
github.com/lib/pq v1.10.0
github.com/lib/pq v1.10.4
github.com/linkedin/goavro/v2 v2.10.0
github.com/m3db/prometheus_remote_client_golang v0.4.4
github.com/magefile/mage v1.12.1
@@ -103,16 +103,16 @@ require (
go.opentelemetry.io/otel/exporters/jaeger v1.0.0
go.opentelemetry.io/otel/sdk v1.0.0
go.opentelemetry.io/otel/trace v1.2.0
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
golang.org/x/exp v0.0.0-20210220032938-85be41e4509f // indirect
golang.org/x/net v0.0.0-20211013171255-e13a2654a71e
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
golang.org/x/exp v0.0.0-20210220032938-85be41e4509f
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
golang.org/x/tools v0.1.5
gonum.org/v1/gonum v0.9.3
google.golang.org/api v0.58.0
google.golang.org/grpc v1.41.0
google.golang.org/api v0.60.0
google.golang.org/grpc v1.42.0
google.golang.org/protobuf v1.27.1
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/ini.v1 v1.62.0
@@ -168,14 +168,14 @@ require (
github.com/go-openapi/errors v0.20.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/loads v0.20.2 // indirect
github.com/go-openapi/loads v0.20.2
github.com/go-openapi/runtime v0.19.29 // indirect
github.com/go-openapi/spec v0.20.4 // indirect
github.com/go-openapi/spec v0.20.4
github.com/go-openapi/swag v0.19.15 // indirect
github.com/go-openapi/validate v0.20.2 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/status v1.1.0 // indirect
github.com/golang-jwt/jwt/v4 v4.0.0 // indirect
github.com/golang-jwt/jwt/v4 v4.1.0 // indirect
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
@@ -207,7 +207,7 @@ require (
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/miekg/dns v1.1.43 // indirect
github.com/mitchellh/go-testing-interface v1.14.0 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/mitchellh/mapstructure v1.4.2 // indirect
github.com/mna/redisc v1.3.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
@@ -242,27 +242,32 @@ require (
go.mongodb.org/mongo-driver v1.7.0 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.9.0
go.uber.org/goleak v1.1.10 // indirect
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 // indirect
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20211018162055-cf77aa76bad2 // indirect
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
)
require (
cloud.google.com/go/kms v1.1.0
github.com/golang-migrate/migrate/v4 v4.7.0
gocloud.dev v0.24.0
)
require (
github.com/Azure/go-autorest/autorest/adal v0.9.15 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.17 // indirect
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect
github.com/containerd/containerd v1.5.9 // indirect
github.com/envoyproxy/go-control-plane v0.10.1 // indirect
github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect
github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/klauspost/compress v1.13.1 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/pierrec/lz4/v4 v4.1.8 // indirect
github.com/segmentio/asm v1.1.1 // indirect
@@ -274,3 +279,7 @@ replace github.com/crewjam/saml => github.com/grafana/saml v0.0.0-20211007135653
replace github.com/apache/thrift => github.com/apache/thrift v0.14.1
replace github.com/hashicorp/consul => github.com/hashicorp/consul v1.10.2
// TODO: remove once gocloud.dev releases 0.25.x
// `fileblob` implementation has buggy key ordering in 0.24.0
replace gocloud.dev v0.24.0 => github.com/google/go-cloud v0.24.1-0.20220209172924-99801bbb523a

187
go.sum
View File

@@ -20,10 +20,10 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.82.0/go.mod h1:vlKccHJGuFBFufnAnuB08dfEH9Y3H7dzDzRECFdC2TA=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
@@ -44,25 +44,33 @@ cloud.google.com/go/bigtable v1.3.0/go.mod h1:z5EyKrPE8OQmeg4h5MNdKvuSnI9CCT49Ki
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
cloud.google.com/go/kms v1.0.0/go.mod h1:nhUehi+w7zht2XrUfvTRNpxrfayBHqP4lu2NSywui/0=
cloud.google.com/go/kms v1.1.0 h1:1yc4rLqCkVDS9Zvc7m+3mJ47kw0Uo5Q5+sMjcmUVUeM=
cloud.google.com/go/kms v1.1.0/go.mod h1:WdbppnCDMDpOvoYBMn1+gNmOeEoZYqAv+HeuKARGCXI=
cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/pubsub v1.17.1/go.mod h1:4qDxMr1WsM9+aQAz36ltDwCIM+R0QdlseyFjBuNvnss=
cloud.google.com/go/secretmanager v1.0.0/go.mod h1:+Qkm5qxIJ5mk74xxIXA+87fseaY1JLYBcFPQoc/GQxg=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.3.0/go.mod h1:9IAwXhoyBJ7z9LcAwkj0/7NnPzYaPeZxxVp3zm+5IqA=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
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=
cloud.google.com/go/storage v1.14.0 h1:6RRlFMv1omScs6iq2hfE3IvgE+l6RfJPampq8UZc5TU=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
cloud.google.com/go/storage v1.18.2 h1:5NQw6tOn3eMm0oE8vTkfjau18kjL79FlMjy/CHTpmoY=
cloud.google.com/go/storage v1.18.2/go.mod h1:AiIj7BWXyhO5gGVmYJ+S8tbkCx3yb0IMjua8Aw4naVM=
cloud.google.com/go/trace v1.0.0/go.mod h1:4iErSByzxkyHWzzlAj63/Gmjz0NH1ASqhJguHpGcr6A=
code.cloudfoundry.org/clock v1.0.0/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8=
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs=
contrib.go.opencensus.io/exporter/prometheus v0.3.0/go.mod h1:rpCPVQKhiyH8oomWgm34ZmgIdZa8OVYO5WAIygPbBBE=
contrib.go.opencensus.io/exporter/stackdriver v0.13.10/go.mod h1:I5htMbyta491eUxufwwZPQdcKvvgzMB4O9ni41YnIM8=
contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
cuelang.org/go v0.4.0 h1:GLJblw6m2WGGCA3k1v6Wbk9gTOt2qto48ahO2MmSd6I=
cuelang.org/go v0.4.0/go.mod h1:tz/edkPi+T37AZcb5GlPY+WJkL6KiDlDVupKwL3vvjs=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
@@ -70,6 +78,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/azure-amqp-common-go/v3 v3.0.0/go.mod h1:SY08giD/XbhTz07tJdpw1SoxQXHPN30+DI3Z04SYqyg=
github.com/Azure/azure-amqp-common-go/v3 v3.2.1/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
github.com/Azure/azure-amqp-common-go/v3 v3.2.2/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
github.com/Azure/azure-event-hubs-go/v3 v3.2.0/go.mod h1:BPIIJNH/l/fVHYq3Rm6eg4clbrULrQ3q7+icmqHyyLc=
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
github.com/Azure/azure-pipeline-go v0.1.9/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
@@ -88,23 +98,29 @@ github.com/Azure/azure-sdk-for-go v44.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo
github.com/Azure/azure-sdk-for-go v45.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v46.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v48.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v51.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v52.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v54.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v55.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v57.1.0+incompatible h1:TKQ3ieyB0vVKkF6t9dsWbMjq56O1xU3eh3Ec09v6ajM=
github.com/Azure/azure-sdk-for-go v57.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v59.3.0+incompatible h1:dPIm0BO4jsMXFcCI/sLTPkBtE7mk8WMuRHA0JeWhlcQ=
github.com/Azure/azure-sdk-for-go v59.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0 h1:lhSJz9RMbJcTgxifR1hUNJnn6CNYtbgEDtQV22/9RBA=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.10.0 h1:jq5Urf8QJK6h0wr8CMiwggo4OSMkXwpArQlkSjSpaBk=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.10.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0 h1:v9p9TfTbf7AwNb5NYQt7hI41IfPoLFiFkLtb+bmGjT0=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
github.com/Azure/azure-service-bus-go v0.11.5/go.mod h1:MI6ge2CuQWBVq+ly456MY7XqNLJip5LO1iSFodbNLbU=
github.com/Azure/azure-storage-blob-go v0.6.0/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y=
github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=
github.com/Azure/azure-storage-blob-go v0.13.0/go.mod h1:pA9kNqtjUeQF2zOSu4s//nUdBD+e64lEuc4sVnuOfNs=
github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck=
github.com/Azure/azure-storage-queue-go v0.0.0-20181215014128-6ed74e755687/go.mod h1:K6am8mT+5iFXgingS9LUc7TmbsW6XBw3nxaRyaMyWc8=
github.com/Azure/go-amqp v0.12.6/go.mod h1:qApuH6OFTSKZFmCOxccvAv5rLizBQf4v8pRmG138DPo=
github.com/Azure/go-amqp v0.16.0/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg=
github.com/Azure/go-amqp v0.16.4/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v11.2.8+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
@@ -123,8 +139,9 @@ github.com/Azure/go-autorest/autorest v0.11.11/go.mod h1:eipySxLmqSyC5s5k1CLupqe
github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest v0.11.19/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest v0.11.20 h1:s8H1PbCZSqg/DH7JMlOz6YMig6htWLNPsjDdlLqCx3M=
github.com/Azure/go-autorest/autorest v0.11.20/go.mod h1:o3tqFY+QR40VOlk+pV4d77mORO64jOXSgEnPQgLK6JY=
github.com/Azure/go-autorest/autorest v0.11.22 h1:bXiQwDjrRmBQOE67bwlvUKAC1EU1yZTPQ38c+bstZws=
github.com/Azure/go-autorest/autorest v0.11.22/go.mod h1:BAWYUWGPEtKPzjVkp0Q6an0MJcJDsoh5Z1BFAEFs4Xs=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/adal v0.8.1-0.20191028180845-3492b2aff503/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
@@ -137,12 +154,15 @@ github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyC
github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.15 h1:X+p2GF0GWyOiSmqohIaEeuNFNDY4I4EOlVuUQvFdWMk=
github.com/Azure/go-autorest/autorest/adal v0.9.15/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A=
github.com/Azure/go-autorest/autorest/adal v0.9.17 h1:esOPl2dhcz9P3jqBSJ8tPGEj2EqzPPT6zfyuloiogKY=
github.com/Azure/go-autorest/autorest/adal v0.9.17/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.8/go.mod h1:kxyKZTSfKh8OVFWPAgOgQ/frrJgeYQJPyR5fLFmXko4=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.9/go.mod h1:hg3/1yw0Bq87O3KvvnJoAh34/0zbP7SFizX/qN5JvjU=
github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.4/go.mod h1:yAQ2b6eP/CmLPnmLvxtT1ALIY3OR1oFcCqVBi8vHiTc=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
@@ -183,6 +203,7 @@ github.com/FZambia/eagle v0.0.1 h1:FN1yTkPihMb5nE8SrlRjoCf7T9H9bTKJFQOm6ach2YU=
github.com/FZambia/eagle v0.0.1/go.mod h1:xq6u/JeNZ5/8mrAQ76MMhzNTodASh9FavQlCgg4j48w=
github.com/FZambia/sentinel v1.1.0 h1:qrCBfxc8SvJihYNjBWgwUI93ZCvFe/PJIPTHKmlp8a8=
github.com/FZambia/sentinel v1.1.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI=
github.com/GoogleCloudPlatform/cloudsql-proxy v1.27.0/go.mod h1:bn9iHmAjogMoIPkqBGyJ9R1m9cXGCjBE/cuhBs3oEsQ=
github.com/HdrHistogram/hdrhistogram-go v0.9.0/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qEclQKK70g0KxO61gFFZD4=
github.com/HdrHistogram/hdrhistogram-go v1.0.1/go.mod h1:BWJ+nMSHY3L41Zj7CA3uXnloDp7xxV0YvstAE7nKTaM=
github.com/HdrHistogram/hdrhistogram-go v1.1.0 h1:6dpdDPTRoo78HxAJ6T1HfMiKSnqhgRRqzCuPshRkQ7I=
@@ -306,6 +327,7 @@ github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/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.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.22.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
@@ -324,18 +346,57 @@ github.com/aws/aws-sdk-go v1.34.34/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/
github.com/aws/aws-sdk-go v1.35.5/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.35.30/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.35.31/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.37.8/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.3/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.60/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.68/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.40.11/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.40.37 h1:I+Q6cLctkFyMMrKukcDnj+i2kjrQ37LGiOM6xmsxC48=
github.com/aws/aws-sdk-go v1.40.37/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.42.8 h1:Tj2RP4Fas1mYchwbmw0qWLJIEATAseyp5iTa1D+LWYQ=
github.com/aws/aws-sdk-go v1.42.8/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aws/aws-sdk-go-v2 v1.7.0/go.mod h1:tb9wi5s61kTDA5qCkcDbt3KRVV74GGslQkl/DRdX/P4=
github.com/aws/aws-sdk-go-v2 v1.11.0 h1:HxyD62DyNhCfiFGUHqJ/xITD6rAjJ7Dm/2nLxLmO4Ag=
github.com/aws/aws-sdk-go-v2 v1.11.0/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0 h1:yVUAwvJC/0WNPbyl0nA3j1L6CW1CN8wBubCRqtG7JLI=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0/go.mod h1:Xn6sxgRuIDflLRJFj5Ev7UxABIkNbccFPV/p8itDReM=
github.com/aws/aws-sdk-go-v2/config v1.10.1 h1:z/ViqIjW6ZeuLWgTWMTSyZzaVWo/1cWeVf1Uu+RF01E=
github.com/aws/aws-sdk-go-v2/config v1.10.1/go.mod h1:auIv5pIIn3jIBHNRcVQcsczn6Pfa6Dyv80Fai0ueoJU=
github.com/aws/aws-sdk-go-v2/credentials v1.6.1 h1:A39JYth2fFCx+omN/gib/jIppx3rRnt2r7UKPq7Mh5Y=
github.com/aws/aws-sdk-go-v2/credentials v1.6.1/go.mod h1:QyvQk1IYTqBWSi1T6UgT/W8DMxBVa5pVuLFSRLLhGf8=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.0 h1:OpZjuUy8Jt3CA1WgJgBC5Bz+uOjE5Ppx4NFTRaooUuA=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.0/go.mod h1:5E1J3/TTYy6z909QNR0QnXGBpfESYGDqd3O0zqONghU=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.1 h1:p9Dys1g2YdaqMalnp6AwCA+tpMMdJNGw5YYKP/u3sUk=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.1/go.mod h1:wN/mvkow08GauDwJ70jnzJ1e+hE+Q3Q7TwpYLXOe9oI=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.0 h1:zY8cNmbBXt3pzjgWgdIbzpQ6qxoCwt+Nx9JbrAf2mbY=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.0/go.mod h1:NO3Q5ZTTQtO2xIg2+xTXYDiT7knSejfeDm7WGDaOo0U=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.0 h1:Z3aR/OXBnkYK9zXkNkfitHX6SmUBzSsx8VMHbH4Lvhw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.0/go.mod h1:anlUzBoEWglcUxUQwZA7HQOEVEnQALVZsizAapB2hq8=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.0 h1:c10Z7fWxtJCoyc8rv06jdh9xrKnu7bAJiRaKWvTb2mU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.0/go.mod h1:6oXGy4GLpypD3uCh8wcqztigGgmhLToMfjavgh+VySg=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.5.0/go.mod h1:acH3+MQoiMzozT/ivU+DbRg7Ooo2298RdRaWcOv+4vM=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0 h1:lPLbw4Gn59uoKqvOfSnkJr54XWk5Ak1NK20ZEiSWb3U=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0/go.mod h1:80NaCIH9YU3rzTTs/J/ECATjXuRqzo/wB6ukO6MZ0XY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.0 h1:qGZWS/WgiFY+Zgad2u0gwBHpJxz6Ne401JE7iQI1nKs=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.0/go.mod h1:Mq6AEc+oEjCUlBuLiK5YwW4shSOAKCQ3tXN0sQeYoBA=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.0 h1:0BOlTqnNnrEO04oYKzDxMMe68t107pmIotn18HtVonY=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.0/go.mod h1:xKCZ4YFSF2s4Hnb/J0TLeOsKuGzICzcElaOKNGrVnx4=
github.com/aws/aws-sdk-go-v2/service/kms v1.10.0/go.mod h1:ZkHWL8m5Nw1g9yMXqpCjnIJtSDToAmNbXXZ9gj0bO7s=
github.com/aws/aws-sdk-go-v2/service/s3 v1.19.0 h1:5mRAms4TjSTOGYsqKYte5kHr1PzpMJSyLThjF3J+hw0=
github.com/aws/aws-sdk-go-v2/service/s3 v1.19.0/go.mod h1:Gwz3aVctJe6mUY9T//bcALArPUaFmNAy2rTB9qN4No8=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.10.0/go.mod h1:qAgsrzF3Z2vvV01j79fs7D75ofCMQe81/OKBJx0rjFY=
github.com/aws/aws-sdk-go-v2/service/sns v1.11.0/go.mod h1:LIPf3BTbSY5UeVli+x/1y2Qw1w8T9DYyp7p18Qt8Zc8=
github.com/aws/aws-sdk-go-v2/service/sqs v1.12.0/go.mod h1:TDqDmQnsbgL2ZMIGUf3z9xTzCMqFX7FP1geAgIlYqvA=
github.com/aws/aws-sdk-go-v2/service/ssm v1.15.0/go.mod h1:kJa2uHklY03rKsNSbEsToeUgWJ1PambXBtRNacorRhg=
github.com/aws/aws-sdk-go-v2/service/sso v1.6.0 h1:JDgKIUZOmLFu/Rv6zXLrVTWCmzA0jcTdvsT8iFIKrAI=
github.com/aws/aws-sdk-go-v2/service/sso v1.6.0/go.mod h1:Q/l0ON1annSU+mc0JybDy1Gy6dnJxIcWjphO6qJPzvM=
github.com/aws/aws-sdk-go-v2/service/sts v1.10.0 h1:1jh8J+JjYRp+QWKOsaZt7rGUgoyrqiiVwIm+w0ymeUw=
github.com/aws/aws-sdk-go-v2/service/sts v1.10.0/go.mod h1:jLKCFqS+1T4i7HDqCP9GM4Uk75YW1cS0o82LdxpMyOE=
github.com/aws/smithy-go v1.5.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/aws/smithy-go v1.9.0 h1:c7FUdEqrQA1/UVKKCNDFQPNKGp4FQg3YW4Ck5SLTG58=
github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
@@ -395,6 +456,7 @@ github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/centrifugal/centrifuge v0.19.0 h1:YHws0dRpgsBiI73tRl1wwaB13gzuaI1AM4IFcQQQqcw=
github.com/centrifugal/centrifuge v0.19.0/go.mod h1:O2elf8q3Qkie3z97wkqVqxB52pnOpPsfFUa7L88Lpy0=
@@ -432,9 +494,14 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
github.com/cncf/udpa/go v0.0.0-20200313221541-5f7e5dd04533/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158 h1:CevA8fI91PAnP8vpnXuB8ZYAZ5wqY86nAbxfgK8tWO4=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/apd/v2 v2.0.1/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw=
@@ -722,11 +789,13 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.9/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021 h1:fP+fF0up6oPY49OrjPrhIJ8yQfdIM85NXMLkMg1EXVs=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.1 h1:cgDRLG7bs59Zd+apAWuzLQL95obVYAymNJek76W3mgw=
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.1 h1:4CF52PCseTFt4bE+Yk3dIpdVi7XWuPVMhPtm4FaIJPM=
github.com/envoyproxy/protoc-gen-validate v0.6.1/go.mod h1:txg5va2Qkip90uYoSKH+nkAAmXrb2j3iq4FLwdrCbXQ=
github.com/envoyproxy/protoc-gen-validate v0.6.2 h1:JiO+kJTpmYGjEodY7O1Zk8oZcNz1+f30UtwtXoFUPzE=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/ericchiang/k8s v1.2.0/go.mod h1:/OmBgSq2cd9IANnsGHGlEz27nwMZV2YxlpXuQtU3Bz4=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc=
@@ -761,8 +830,9 @@ github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P
github.com/frankban/quicktest v1.11.0/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
@@ -783,6 +853,8 @@ github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NB
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.7.3/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/glinton/ping v0.1.4-0.20200311211934-5ac87da8cd96/go.mod h1:uY+1eqFUyotrQxF1wYFNtMeHp/swbYRsoGzfcPZ8x3o=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
@@ -865,7 +937,6 @@ github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3Hfo
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
@@ -907,7 +978,6 @@ github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeE
github.com/go-openapi/spec v0.19.15/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU=
github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU=
github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ=
github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ=
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
@@ -951,8 +1021,13 @@ github.com/go-openapi/validate v0.19.15/go.mod h1:tbn/fdOwYHgrhPBzidZfJC2MIVvs9G
github.com/go-openapi/validate v0.20.1/go.mod h1:b60iJT+xNNLfaQJUqLI7946tYiFEOuE9E4k54HpKcJ0=
github.com/go-openapi/validate v0.20.2 h1:AhqDegYV3J3iQkMPJSXkvzymHKMTw0BST3RK3hTT4ts=
github.com/go-openapi/validate v0.20.2/go.mod h1:e7OJoKNgd0twXZwIn0A43tHbvIcr/rZIVCbJBpTUoY0=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v8 v8.0.0-beta.10.0.20200905143926-df7fe4e2ce72/go.mod h1:CJP1ZIHwhosNYwIdaHPZK9vHsM3+roNBaZ7U9Of1DXc=
@@ -1042,8 +1117,9 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
github.com/gogo/status v1.0.3/go.mod h1:SavQ51ycCLnc7dGyJxp8YAmudx8xqiVrRf+6IXRsugc=
github.com/gogo/status v1.1.0 h1:+eIkrewn5q6b30y+g/BJINVVdi2xH7je5MPJ3ZPK3JA=
github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0=
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-migrate/migrate/v4 v4.7.0 h1:gONcHxHApDTKXDyLH/H97gEHmpu1zcnnbAaq2zgrPrs=
github.com/golang-migrate/migrate/v4 v4.7.0/go.mod h1:Qvut3N4xKWjoH3sokBccML6WyHSnggXm/DvMMnTsQIc=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
@@ -1113,6 +1189,8 @@ github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv
github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v2.0.0+incompatible h1:dicJ2oXwypfwUGnB2/TYWYEKiuk9eYQlQO/AnOHl5mI=
github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cloud v0.24.1-0.20220209172924-99801bbb523a h1:Kw18HR30Firrm4cB1BzcVVaFrrdDlAtnrCKgHxemgMI=
github.com/google/go-cloud v0.24.1-0.20220209172924-99801bbb523a/go.mod h1:TqAL9Q5Q8jFUfIDNbDiFbU3w0z3MQ7q4r1wm57tBhmI=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -1132,13 +1210,16 @@ github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk=
github.com/google/go-replayers/httpreplay v1.0.0/go.mod h1:LJhKoTwS5Wy5Ld/peq8dFFG5OfJyHEz7ft+DsTUv25M=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.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/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE=
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ=
@@ -1158,12 +1239,12 @@ github.com/google/pprof v0.0.0-20201007051231-1066cbb265c7/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201117184057-ae444373da19/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210208152844-1612e9be7af6/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210323184331-8eee2492667d/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210504235042-3a04a4d88a10/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
@@ -1241,17 +1322,12 @@ github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f h1:FvvSVEbnGeM2bUivG
github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f/go.mod h1:uPG2nyK4CtgNDmWv7qyzYcdI+S90kHHRWvHnBtEMBXM=
github.com/grafana/go-mssqldb v0.0.0-20210326084033-d0ce3c521036 h1:GplhUk6Xes5JIhUUrggPcPBhOn+eT8+WsHiebvq7GgA=
github.com/grafana/go-mssqldb v0.0.0-20210326084033-d0ce3c521036/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/grafana/grafana-aws-sdk v0.9.1 h1:jMZlsLsWnqOwLt2UNcLUsJ2z6289hLYlscK35QgS158=
github.com/grafana/grafana-aws-sdk v0.9.1/go.mod h1:6KaQ8uUD4KpXr/b7bAC7zbfSXTVOiTk4XhIrwkGWn4w=
github.com/grafana/grafana-aws-sdk v0.10.0 h1:q7+mJtT/vsU5InDN57yM+BJ2z1kJDf1W4WwWPEZ0Cxw=
github.com/grafana/grafana-aws-sdk v0.10.0/go.mod h1:vFIOHEnY1u5nY0/tge1IHQjPuG6DRKr2ISf/HikUdjE=
github.com/grafana/grafana-aws-sdk v0.10.1 h1:Ksguhjx6EuGLN/5Oc7oZoxuDReJ5RxIH99yqSMpLGUs=
github.com/grafana/grafana-aws-sdk v0.10.1/go.mod h1:vFIOHEnY1u5nY0/tge1IHQjPuG6DRKr2ISf/HikUdjE=
github.com/grafana/grafana-google-sdk-go v0.0.0-20211104130251-b190293eaf58 h1:2ud7NNM7LrGPO4x0NFR8qLq68CqI4SmB7I2yRN2w9oE=
github.com/grafana/grafana-google-sdk-go v0.0.0-20211104130251-b190293eaf58/go.mod h1:Vo2TKWfDVmNTELBUM+3lkrZvFtBws0qSZdXhQxRdJrE=
github.com/grafana/grafana-plugin-sdk-go v0.94.0/go.mod h1:3VXz4nCv6wH5SfgB3mlW39s+c+LetqSCjFj7xxPC5+M=
github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
github.com/grafana/grafana-plugin-sdk-go v0.125.0 h1:wK2zopAaKhVIMkXzgbExKqZtt+x2ZTGfcY+3wvOuyYQ=
github.com/grafana/grafana-plugin-sdk-go v0.125.0/go.mod h1:9YiJ5GUxIsIEUC0qR9+BJVP5M7mCSP6uc6Ne62YKkgc=
github.com/grafana/grafana-plugin-sdk-go v0.126.0 h1:GFstod7B/r5Ls9QiYV18fnOVtpWAtfR8aYSXfBvbCjE=
github.com/grafana/grafana-plugin-sdk-go v0.126.0/go.mod h1:9YiJ5GUxIsIEUC0qR9+BJVP5M7mCSP6uc6Ne62YKkgc=
@@ -1284,6 +1360,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.15.0/go.mod h1:vO11I9oWA+KsxmfFQPhLnnI
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok=
github.com/hanwen/go-fuse/v2 v2.1.0/go.mod h1:oRyA5eK+pvJyv5otpO/DgccS8y/RvYMaO00GgRLGryc=
github.com/harlow/kinesis-consumer v0.3.1-0.20181230152818-2f58b136fee0/go.mod h1:dk23l2BruuUzRP8wbybQbPn3J7sZga2QHICCeaEy5rQ=
github.com/hashicorp/consul v1.10.2 h1:9YX5SX3hMifrXIt9wqN2jJsMnESSHfxEjW5N7qMAdjo=
github.com/hashicorp/consul v1.10.2/go.mod h1:EJMYpT39ZL2BnxjGRNTjfTH3s9893yd/DCX60PUnGUY=
@@ -1424,6 +1502,7 @@ github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbc
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/igm/sockjs-go/v3 v3.0.1 h1:rmgEkeKqBHCFf7uIAipYrYSX8x9LBB2nOxAac2sooak=
@@ -1570,13 +1649,15 @@ github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.1 h1:wXr2uRxZTJXHLly6qhJabee5JqIhTRoLBhDOA74hDEQ=
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
@@ -1621,14 +1702,16 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6Fm
github.com/leanovate/gopter v0.2.4/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8=
github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353/go.mod h1:N0SVk0uhy+E1PZ3C9ctsPRlvOPAFPkCNlcPBDkt0N3U=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165/go.mod h1:WZxr2/6a/Ar9bMDc2rN/LJrE/hF6bXE4LPyDSIxwAfg=
github.com/leoluk/perflib_exporter v0.1.0/go.mod h1:rpV0lYj7lemdTm31t7zpCqYqPnw7xs86f+BaaNBVYFM=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
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.0/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
@@ -1643,10 +1726,10 @@ github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lufia/iostat v1.1.0/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg=
github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/m3db/prometheus_remote_client_golang v0.4.4 h1:DsAIjVKoCp7Ym35tAOFL1OuMLIdIikAEHeNPHY+yyM8=
github.com/m3db/prometheus_remote_client_golang v0.4.4/go.mod h1:wHfVbA3eAK6dQvKjCkHhusWYegCk3bDGkA15zymSHdc=
github.com/magefile/mage v1.11.0 h1:C/55Ywp9BpgVVclD3lRnSYCwXTYxmSppIgLeDYlNuls=
github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magefile/mage v1.12.1 h1:oGdAbhIUd6iKamKlDGVtU6XGdy5SgNuCWn7gCTgHDtU=
github.com/magefile/mage v1.12.1/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
@@ -1769,8 +1852,9 @@ github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1-0.20210112042008-8ebf2d61a8b4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/mitchellh/pointerstructure v1.0.0/go.mod h1:k4XwG94++jLVsSiTxo7qdIfXA9pj9EAeo0QsNNJOLZ8=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
@@ -2485,6 +2569,7 @@ go.mongodb.org/mongo-driver v1.5.2/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS
go.mongodb.org/mongo-driver v1.7.0 h1:hHrvOBWlWB2c7+8Gh/Xi5jj82AgidK/t7KVXBZ+IyUA=
go.mongodb.org/mongo-driver v1.7.0/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8NzkI+yfU8=
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
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=
@@ -2534,13 +2619,15 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/automaxprocs v1.2.0/go.mod h1:YfO3fm683kQpzETxlTGZhGIVmXAhaw3gxeBADbpZtnU=
go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q=
go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@@ -2550,6 +2637,7 @@ go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go4.org/intern v0.0.0-20210108033219-3eb7198706b2/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
@@ -2600,8 +2688,11 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI=
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -2659,6 +2750,7 @@ golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hM
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -2739,9 +2831,12 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211013171255-e13a2654a71e h1:Xj+JO91noE97IN6F/7WZxzC5QE6yENAQPrwIYhW3bsA=
golang.org/x/net v0.0.0-20211013171255-e13a2654a71e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 h1:DZshvxDdVoeKIbudAdFEKi+f70l51luSy/7b76ibTY0=
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -2762,8 +2857,10 @@ golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
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=
@@ -2927,11 +3024,16 @@ golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -2961,8 +3063,9 @@ golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -3064,7 +3167,6 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
@@ -3129,8 +3231,10 @@ google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.58.0 h1:MDkAbYIB1JpSgCTOCYYoIec/coMlKK4oVbpnBLLcyT0=
google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E=
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
google.golang.org/api v0.60.0 h1:eq/zs5WPH4J9undYM9IP1O7dSr7Yh8Y0GtSCpzGzIUk=
google.golang.org/api v0.60.0/go.mod h1:d7rl65NZAkEQ90JFzqBjcRq1TVeG5ZoGV3sSpEnnVb4=
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.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -3199,9 +3303,7 @@ google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210312152112-fc591d9ea70f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -3209,6 +3311,7 @@ google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210517163617-5e0236093d7a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
@@ -3227,8 +3330,14 @@ google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEc
google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211018162055-cf77aa76bad2 h1:CUp93KYgL06Y/PdI8aRJaFiAHevPIGWQmijSqaUhue8=
google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211016002631-37fc39342514/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211018162055-cf77aa76bad2/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211019152133-63b7e35f4404/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
@@ -3268,8 +3377,9 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200910201057-6591123024b3/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -3471,6 +3581,7 @@ modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6
modernc.org/memory v1.0.1/go.mod h1:NSjvC08+g3MLOpcAxQbdctcThAEX4YlJ20WWHYEhvRg=
modernc.org/sqlite v1.7.4/go.mod h1:xse4RHCm8Fzw0COf5SJqAyiDrVeDwAQthAS1V/woNIA=
modernc.org/tcl v1.4.1/go.mod h1:8YCvzidU9SIwkz7RZwlCWK61mhV8X9UwfkRDRp7y5e0=
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

View File

@@ -1,4 +1,4 @@
{
"stable": "8.4.1",
"testing": "8.4.1"
"stable": "8.4.3",
"testing": "8.4.3"
}

View File

@@ -76,7 +76,7 @@
"@babel/plugin-proposal-object-rest-spread": "7.17.3",
"@babel/plugin-proposal-optional-chaining": "7.16.7",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/plugin-transform-react-constant-elements": "7.16.7",
"@babel/plugin-transform-react-constant-elements": "7.17.6",
"@babel/plugin-transform-runtime": "7.17.0",
"@babel/plugin-transform-typescript": "7.16.8",
"@babel/preset-env": "7.16.11",
@@ -155,8 +155,8 @@
"@types/testing-library__react-hooks": "^3.2.0",
"@types/tinycolor2": "1.4.3",
"@types/uuid": "8.3.4",
"@typescript-eslint/eslint-plugin": "5.12.1",
"@typescript-eslint/parser": "5.12.1",
"@typescript-eslint/eslint-plugin": "5.13.0",
"@typescript-eslint/parser": "5.13.0",
"@wojtekmaj/enzyme-adapter-react-17": "0.6.6",
"autoprefixer": "10.4.2",
"axios": "0.26.0",
@@ -167,16 +167,16 @@
"copy-webpack-plugin": "9.0.1",
"css-loader": "6.6.0",
"css-minimizer-webpack-plugin": "3.4.1",
"cypress": "9.3.1",
"cypress": "9.5.0",
"enzyme": "3.11.0",
"enzyme-to-json": "3.6.2",
"eslint": "8.9.0",
"eslint": "8.10.0",
"eslint-config-prettier": "8.4.0",
"eslint-plugin-jest": "^26.1.0",
"eslint-plugin-jsdoc": "37.9.1",
"eslint-plugin-lodash": "7.4.0",
"eslint-plugin-prettier": "4.0.0",
"eslint-plugin-react": "7.28.0",
"eslint-plugin-react": "7.29.2",
"eslint-plugin-react-hooks": "4.3.0",
"eslint-webpack-plugin": "3.1.1",
"expose-loader": "3.1.0",
@@ -224,7 +224,7 @@
"testing-library-selector": "0.2.1",
"ts-jest": "27.1.3",
"ts-loader": "9.2.6",
"ts-node": "10.5.0",
"ts-node": "10.6.0",
"typescript": "4.4.4",
"wait-on": "6.0.0",
"webpack": "5.69.1",
@@ -247,6 +247,8 @@
"@grafana/ui": "workspace:*",
"@jaegertracing/jaeger-ui-components": "workspace:*",
"@kusto/monaco-kusto": "4.1.3",
"@lezer/common": "^0.15.11",
"@lezer/lr": "^0.15.8",
"@lingui/core": "3.13.2",
"@lingui/react": "3.13.2",
"@opentelemetry/api": "1.1.0",
@@ -264,9 +266,9 @@
"@react-stately/menu": "3.2.3",
"@react-stately/tree": "3.2.0",
"@reduxjs/toolkit": "1.7.2",
"@sentry/browser": "6.17.4",
"@sentry/types": "6.17.4",
"@sentry/utils": "6.17.4",
"@sentry/browser": "6.18.1",
"@sentry/types": "6.18.1",
"@sentry/utils": "6.18.1",
"@visx/event": "2.6.0",
"@visx/gradient": "2.1.0",
"@visx/group": "2.1.0",
@@ -305,9 +307,7 @@
"jquery": "3.6.0",
"json-source-map": "0.6.1",
"jsurl": "^0.1.5",
"lezer": "0.13.5",
"lezer-promql": "0.20.0",
"lezer-tree": "0.13.2",
"lezer-promql": "0.22.0",
"lodash": "4.17.21",
"logfmt": "^1.3.2",
"lru-cache": "7.4.0",

View File

@@ -67,7 +67,7 @@
"@types/tinycolor2": "1.4.3",
"react-test-renderer": "17.0.2",
"rimraf": "3.0.2",
"rollup": "2.67.1",
"rollup": "2.69.0",
"rollup-plugin-sourcemaps": "0.6.3",
"rollup-plugin-terser": "7.0.2",
"sinon": "13.0.1",

View File

@@ -460,7 +460,7 @@ describe('getRawDisplayProcessor', () => {
${'a string'} | ${'a string'}
${null} | ${'null'}
${undefined} | ${'undefined'}
${{ value: 0, label: 'a label' }} | ${'[object Object]'}
${{ value: 0, label: 'a label' }} | ${'{"value":0,"label":"a label"}'}
`('when called with value:{$value}', ({ value, expected }) => {
const result = processor(value);

View File

@@ -11,6 +11,7 @@ import { KeyValue, TimeZone } from '../types';
import { getScaleCalculator } from './scale';
import { GrafanaTheme2 } from '../themes/types';
import { anyToNumber } from '../utils/anyToNumber';
import { getFieldTypeFromValue } from '../dataframe/processDataFrame';
interface DisplayProcessorOptions {
field: Partial<Field>;
@@ -168,7 +169,20 @@ function toStringProcessor(value: any): DisplayValue {
export function getRawDisplayProcessor(): DisplayProcessor {
return (value: any) => ({
text: `${value}`,
text: getFieldTypeFromValue(value) === 'other' ? `${JSON.stringify(value, getCircularReplacer())}` : `${value}`,
numeric: null as unknown as number,
});
}
const getCircularReplacer = () => {
const seen = new WeakSet();
return (_key: any, value: object | null) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};

View File

@@ -25,6 +25,7 @@ export { LayoutModes, LayoutMode } from './types/layout';
export { PanelPlugin, SetFieldConfigOptionsArgs, StandardOptionConfig } from './panel/PanelPlugin';
export { createFieldConfigRegistry } from './panel/registryFactories';
export { QueryRunner, QueryRunnerOptions } from './types/queryRunner';
export { GroupingToMatrixTransformerOptions } from './transformations/transformers/groupingToMatrix';
// Moved to `@grafana/schema`, in Grafana 9, this will be removed
export * from './schema';

View File

@@ -140,14 +140,14 @@ export const fieldReducers = new Registry<FieldReducerInfo>(() => [
standard: true,
reduce: calculateLast,
},
{ id: ReducerID.first, name: 'First', description: 'First Value', standard: true, reduce: calculateFirst },
{
id: ReducerID.firstNotNull,
name: 'First',
name: 'First *',
description: 'First non-null value',
standard: true,
reduce: calculateFirstNotNull,
},
{ id: ReducerID.first, name: 'First', description: 'First Value', standard: true, reduce: calculateFirst },
{ id: ReducerID.min, name: 'Min', description: 'Minimum Value', standard: true },
{ id: ReducerID.max, name: 'Max', description: 'Maximum Value', standard: true },
{ id: ReducerID.mean, name: 'Mean', description: 'Average Value', standard: true, aliasIds: ['avg'] },

View File

@@ -19,6 +19,7 @@ import { renameByRegexTransformer } from './transformers/renameByRegex';
import { filterByValueTransformer } from './transformers/filterByValue';
import { histogramTransformer } from './transformers/histogram';
import { convertFieldTypeTransformer } from './transformers/convertFieldType';
import { groupingToMatrixTransformer } from './transformers/groupingToMatrix';
export const standardTransformers = {
noopTransformer,
@@ -43,4 +44,5 @@ export const standardTransformers = {
renameByRegexTransformer,
histogramTransformer,
convertFieldTypeTransformer,
groupingToMatrixTransformer,
};

View File

@@ -0,0 +1,170 @@
import {
ArrayVector,
DataTransformerConfig,
DataTransformerID,
Field,
FieldType,
toDataFrame,
transformDataFrame,
} from '@grafana/data';
import { GroupingToMatrixTransformerOptions, groupingToMatrixTransformer } from './groupingToMatrix';
import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry';
describe('Grouping to Matrix', () => {
beforeAll(() => {
mockTransformationsRegistry([groupingToMatrixTransformer]);
});
it('generates Matrix with default fields', async () => {
const cfg: DataTransformerConfig<GroupingToMatrixTransformerOptions> = {
id: DataTransformerID.groupingToMatrix,
options: {},
};
const seriesA = toDataFrame({
name: 'A',
fields: [
{ name: 'Time', type: FieldType.time, values: [1000, 1001, 1002] },
{ name: 'Value', type: FieldType.number, values: [1, 2, 3] },
],
});
await expect(transformDataFrame([cfg], [seriesA])).toEmitValuesWith((received) => {
const processed = received[0];
const expected: Field[] = [
{
name: 'Time\\Time',
type: FieldType.string,
values: new ArrayVector([1000, 1001, 1002]),
config: {},
},
{
name: '1000',
type: FieldType.number,
values: new ArrayVector([1, '', '']),
config: {},
},
{
name: '1001',
type: FieldType.number,
values: new ArrayVector(['', 2, '']),
config: {},
},
{
name: '1002',
type: FieldType.number,
values: new ArrayVector(['', '', 3]),
config: {},
},
];
expect(processed[0].fields).toEqual(expected);
});
});
it('generates Matrix with multiple fields', async () => {
const cfg: DataTransformerConfig<GroupingToMatrixTransformerOptions> = {
id: DataTransformerID.groupingToMatrix,
options: {
columnField: 'Column',
rowField: 'Row',
valueField: 'Temp',
},
};
const seriesA = toDataFrame({
name: 'A',
fields: [
{ name: 'Column', type: FieldType.string, values: ['C1', 'C1', 'C2'] },
{ name: 'Row', type: FieldType.string, values: ['R1', 'R2', 'R1'] },
{ name: 'Temp', type: FieldType.number, values: [1, 4, 5] },
],
});
await expect(transformDataFrame([cfg], [seriesA])).toEmitValuesWith((received) => {
const processed = received[0];
const expected: Field[] = [
{
name: 'Row\\Column',
type: FieldType.string,
values: new ArrayVector(['R1', 'R2']),
config: {},
},
{
name: 'C1',
type: FieldType.number,
values: new ArrayVector([1, 4]),
config: {},
},
{
name: 'C2',
type: FieldType.number,
values: new ArrayVector([5, '']),
config: {},
},
];
expect(processed[0].fields).toEqual(expected);
});
});
it('generates Matrix with multiple fields and value type', async () => {
const cfg: DataTransformerConfig<GroupingToMatrixTransformerOptions> = {
id: DataTransformerID.groupingToMatrix,
options: {
columnField: 'Column',
rowField: 'Row',
valueField: 'Temp',
},
};
const seriesA = toDataFrame({
name: 'C',
fields: [
{ name: 'Column', type: FieldType.string, values: ['C1', 'C1', 'C2'] },
{ name: 'Row', type: FieldType.string, values: ['R1', 'R2', 'R1'] },
{ name: 'Temp', type: FieldType.number, values: [1, 4, 5], config: { units: 'celsius' } },
],
});
await expect(transformDataFrame([cfg], [seriesA])).toEmitValuesWith((received) => {
const processed = received[0];
expect(processed[0].fields).toMatchInlineSnapshot(`
Array [
Object {
"config": Object {},
"name": "Row\\\\Column",
"type": "string",
"values": Array [
"R1",
"R2",
],
},
Object {
"config": Object {
"units": "celsius",
},
"name": "C1",
"type": "number",
"values": Array [
1,
4,
],
},
Object {
"config": Object {
"units": "celsius",
},
"name": "C2",
"type": "number",
"values": Array [
5,
"",
],
},
]
`);
});
});
});

View File

@@ -0,0 +1,115 @@
import { map } from 'rxjs/operators';
import { DataFrame, DataTransformerInfo, Field, FieldType, Vector } from '../../types';
import { DataTransformerID } from './ids';
import { MutableDataFrame } from '../../dataframe';
import { getFieldDisplayName } from '../../field/fieldState';
export interface GroupingToMatrixTransformerOptions {
columnField?: string;
rowField?: string;
valueField?: string;
}
const DEFAULT_COLUMN_FIELD = 'Time';
const DEFAULT_ROW_FIELD = 'Time';
const DEFAULT_VALUE_FIELD = 'Value';
export const groupingToMatrixTransformer: DataTransformerInfo<GroupingToMatrixTransformerOptions> = {
id: DataTransformerID.groupingToMatrix,
name: 'Grouping to Matrix',
description: 'Groups series by field and return a matrix visualisation',
defaultOptions: {
columnField: DEFAULT_COLUMN_FIELD,
rowField: DEFAULT_ROW_FIELD,
valueField: DEFAULT_VALUE_FIELD,
},
operator: (options) => (source) =>
source.pipe(
map((data) => {
const columnFieldMatch = options.columnField || DEFAULT_COLUMN_FIELD;
const rowFieldMatch = options.rowField || DEFAULT_ROW_FIELD;
const valueFieldMatch = options.valueField || DEFAULT_VALUE_FIELD;
// Accept only single queries
if (data.length !== 1) {
return data;
}
const frame = data[0];
const keyColumnField = findKeyField(frame, columnFieldMatch);
const keyRowField = findKeyField(frame, rowFieldMatch);
const valueField = findKeyField(frame, valueFieldMatch);
const rowColumnField = `${rowFieldMatch}\\${columnFieldMatch}`;
if (!keyColumnField || !keyRowField || !valueField) {
return data;
}
const columnValues = uniqueValues(keyColumnField.values);
const rowValues = uniqueValues(keyRowField.values);
const matrixValues: { [key: string]: { [key: string]: any } } = {};
for (let index = 0; index < valueField.values.length; index++) {
const columnName = keyColumnField.values.get(index);
const rowName = keyRowField.values.get(index);
const value = valueField.values.get(index);
if (!matrixValues[columnName]) {
matrixValues[columnName] = {};
}
matrixValues[columnName][rowName] = value;
}
const resultFrame = new MutableDataFrame();
resultFrame.addField({
name: rowColumnField,
values: rowValues,
type: FieldType.string,
});
for (const columnName of columnValues) {
let values = [];
for (const rowName of rowValues) {
const value = matrixValues[columnName][rowName] ?? '';
values.push(value);
}
resultFrame.addField({
name: columnName.toString(),
values: values,
config: valueField.config,
type: valueField.type,
});
}
return [resultFrame];
})
),
};
function uniqueValues(values: Vector): any[] {
const unique = new Set();
for (let index = 0; index < values.length; index++) {
unique.add(values.get(index));
}
return Array.from(unique);
}
function findKeyField(frame: DataFrame, matchTitle: string): Field | null {
for (let fieldIndex = 0; fieldIndex < frame.fields.length; fieldIndex++) {
const field = frame.fields[fieldIndex];
if (matchTitle === getFieldDisplayName(field)) {
return field;
}
}
return null;
}

View File

@@ -31,4 +31,5 @@ export enum DataTransformerID {
heatmap = 'heatmap',
spatial = 'spatial',
extractFields = 'extractFields',
groupingToMatrix = 'groupingToMatrix',
}

View File

@@ -20,7 +20,8 @@ export enum LoadingState {
}
// Should be kept in sync with grafana-plugin-sdk-go/data/frame_meta.go
export type PreferredVisualisationType = 'graph' | 'table' | 'logs' | 'trace' | 'nodeGraph';
export const preferredVisualizationTypes = ['graph', 'table', 'logs', 'trace', 'nodeGraph'] as const;
export type PreferredVisualisationType = typeof preferredVisualizationTypes[number];
/**
* @public

View File

@@ -40,9 +40,11 @@ export interface FeatureToggles {
showFeatureFlagsInUI?: boolean;
disable_http_request_histogram?: boolean;
validatedQueries?: boolean;
lokiLive?: boolean;
swaggerUi?: boolean;
featureHighlights?: boolean;
dashboardComments?: boolean;
annotationComments?: boolean;
migrationLocking?: boolean;
fileStoreApi?: boolean;
}

View File

@@ -15,6 +15,12 @@ export type TraceLog = {
fields: TraceKeyValuePair[];
};
export type TraceSpanReference = {
traceID: string;
spanID: string;
tags?: TraceKeyValuePair[];
};
/**
* This describes the structure of the dataframe that should be returned from a tracing data source to show trace
* in a TraceView component.
@@ -31,7 +37,7 @@ export interface TraceSpanRow {
// Milliseconds
duration: number;
logs?: TraceLog[];
references?: TraceSpanReference[];
// Note: To mark spen as having error add tag error: true
tags?: TraceKeyValuePair[];
warnings?: string[];

View File

@@ -229,4 +229,4 @@ export const checkLogsError = (logRow: LogRowModel): { hasError: boolean; errorM
};
export const escapeUnescapedString = (string: string) =>
string.replace(/\\n|\\t|\\r/g, (match: string) => (match.slice(1) === 't' ? '\t' : '\n'));
string.replace(/\\r\\n|\\n|\\t|\\r/g, (match: string) => (match.slice(1) === 't' ? '\t' : '\n'));

View File

@@ -28,7 +28,7 @@
"@rollup/plugin-node-resolve": "13.1.3",
"@types/node": "16.11.22",
"rimraf": "3.0.2",
"rollup": "2.67.1",
"rollup": "2.69.0",
"rollup-plugin-sourcemaps": "0.6.3",
"rollup-plugin-terser": "7.0.2"
},

View File

@@ -37,7 +37,7 @@
"@types/lodash": "4.14.178",
"@types/node": "16.11.22",
"@types/uuid": "8.3.4",
"rollup": "2.67.1",
"rollup": "2.69.0",
"rollup-plugin-copy": "3.4.0",
"rollup-plugin-sourcemaps": "0.6.3",
"rollup-plugin-terser": "7.0.2",
@@ -55,7 +55,7 @@
"blink-diff": "1.0.13",
"chrome-remote-interface": "0.31.2",
"commander": "8.3.0",
"cypress": "9.3.1",
"cypress": "9.5.0",
"cypress-file-upload": "5.0.8",
"devtools-protocol": "0.0.967529",
"execa": "5.1.1",

View File

@@ -25,7 +25,7 @@
"@grafana/data": "8.5.0-pre",
"@grafana/e2e-selectors": "8.5.0-pre",
"@grafana/ui": "8.5.0-pre",
"@sentry/browser": "6.17.4",
"@sentry/browser": "6.18.1",
"history": "4.10.1",
"lodash": "4.17.21",
"react": "17.0.2",
@@ -50,7 +50,7 @@
"@types/systemjs": "^0.20.6",
"lodash": "4.17.21",
"rimraf": "3.0.2",
"rollup": "2.67.1",
"rollup": "2.69.0",
"rollup-plugin-sourcemaps": "0.6.3",
"rollup-plugin-terser": "7.0.2",
"typescript": "4.4.4"

View File

@@ -28,7 +28,7 @@
"@rollup/plugin-node-resolve": "13.1.3",
"@swc/helpers": "0.3.2",
"rimraf": "3.0.2",
"rollup": "2.67.1",
"rollup": "2.69.0",
"rollup-plugin-sourcemaps": "0.6.3",
"rollup-plugin-terser": "7.0.2",
"typescript": "4.4.4"

View File

@@ -283,6 +283,7 @@ export enum BarGaugeDisplayMode {
export interface TableFieldOptions {
align: string;
displayMode: TableCellDisplayMode;
inspect: boolean;
hidden?: boolean;
minWidth?: number;
width?: number;
@@ -292,6 +293,7 @@ export interface TableFieldOptions {
export const defaultTableFieldOptions: TableFieldOptions = {
align: 'auto',
displayMode: TableCellDisplayMode.Auto,
inspect: false,
};
export interface VizTooltipOptions {

View File

@@ -2,9 +2,11 @@ import { getStylesheetEntries, hasThemeStylesheets } from './loaders';
describe('Loaders', () => {
describe('stylesheet helpers', () => {
jest.spyOn(console, 'log').mockImplementation();
beforeEach(() => {
jest.spyOn(console, 'log').mockImplementation();
});
afterAll(() => {
afterEach(() => {
jest.restoreAllMocks();
});
@@ -23,12 +25,12 @@ describe('Loaders', () => {
describe('hasThemeStylesheets', () => {
it('throws when only one theme file is defined', () => {
jest.spyOn(console, 'error').mockImplementation();
const errorSpy = jest.spyOn(console, 'error').mockImplementation();
const result = () => {
hasThemeStylesheets(`${__dirname}/../mocks/stylesheetsSupport/missing-theme-file`);
};
expect(result).toThrow();
jest.restoreAllMocks();
errorSpy.mockRestore();
});
it('returns false when no theme files present', () => {

View File

@@ -45,7 +45,7 @@
"@react-aria/menu": "3.4.1",
"@react-aria/overlays": "3.7.3",
"@react-stately/menu": "3.2.3",
"@sentry/browser": "6.17.4",
"@sentry/browser": "6.18.1",
"ansicolor": "1.1.100",
"calculate-size": "1.1.1",
"classnames": "2.3.1",
@@ -72,7 +72,7 @@
"react-colorful": "5.5.1",
"react-custom-scrollbars-2": "4.4.0",
"react-dom": "17.0.2",
"react-dropzone": "11.5.1",
"react-dropzone": "12.0.4",
"react-highlight-words": "0.17.0",
"react-hook-form": "7.5.3",
"react-inlinesvg": "2.3.0",
@@ -136,7 +136,7 @@
"@types/prismjs": "1.26.0",
"@types/react": "17.0.39",
"@types/react-beautiful-dnd": "13.1.2",
"@types/react-calendar": "3.4.5",
"@types/react-calendar": "3.5.0",
"@types/react-color": "3.0.6",
"@types/react-dom": "17.0.11",
"@types/react-router-dom": "5.3.3",
@@ -166,7 +166,7 @@
"react-docgen-typescript-loader": "3.7.2",
"react-test-renderer": "17.0.2",
"rimraf": "3.0.2",
"rollup": "2.67.1",
"rollup": "2.69.0",
"rollup-plugin-sourcemaps": "0.6.3",
"rollup-plugin-terser": "7.0.2",
"sass-loader": "12.6.0",

View File

@@ -384,6 +384,28 @@ Card can have a disabled state, effectively making it and its actions non-clicka
</Card>
</Preview>
### Selectable
```jsx
<Card isSelected disabled>
<Card.Heading>Option #1</Card.Heading>
<Card.Meta>This is a really great option, you won't regret it.</Card.Meta>
<Card.Figure>
<img src={logo} alt="Grafana Logo" width="40" height="40" />
</Card.Figure>
</Card>
```
<Preview>
<Card isSelected disabled>
<Card.Heading>Option #1</Card.Heading>
<Card.Description>This is a really great option, you won't regret it.</Card.Description>
<Card.Figure>
<img src={logo} alt="Grafana Logo" width="40" height="40" />
</Card.Figure>
</Card>
</Preview>
### Props
<Props of={Card} />

View File

@@ -154,3 +154,27 @@ export const Full: Story<Props> = ({ disabled }) => {
</Card>
);
};
export const Selected: Story<Props> = () => {
return (
<Card isSelected>
<Card.Heading>Spaces</Card.Heading>
<Card.Description>Spaces are the superior form of indenting code.</Card.Description>
<Card.Figure>
<img src={logo} alt="Grafana Logo" width="40" height="40" />
</Card.Figure>
</Card>
);
};
export const NotSelected: Story<Props> = () => {
return (
<Card isSelected={false}>
<Card.Heading>Tabs</Card.Heading>
<Card.Description>Tabs are the preferred way of indentation.</Card.Description>
<Card.Figure>
<img src={logo} alt="Grafana Logo" width="40" height="40" />
</Card.Figure>
</Card>
);
};

View File

@@ -99,5 +99,33 @@ describe('Card', () => {
expect(screen.getByRole('button', { name: 'Click Me' })).not.toBeDisabled();
expect(screen.queryByRole('button', { name: 'Delete' })).not.toBeInTheDocument();
});
it('Should allow selectable cards', () => {
const { rerender } = render(
<Card isSelected={true}>
<Card.Heading>My Option</Card.Heading>
</Card>
);
expect(screen.getByRole('radio')).toBeInTheDocument();
expect(screen.getByRole('radio')).toBeChecked();
rerender(
<Card isSelected={false}>
<Card.Heading>My Option</Card.Heading>
</Card>
);
expect(screen.getByRole('radio')).toBeInTheDocument();
expect(screen.getByRole('radio')).not.toBeChecked();
rerender(
<Card>
<Card.Heading>My Option</Card.Heading>
</Card>
);
expect(screen.queryByRole('radio')).not.toBeInTheDocument();
});
});
});

View File

@@ -19,6 +19,7 @@ export interface Props extends Omit<CardContainerProps, 'disableEvents' | 'disab
heading?: ReactNode;
/** @deprecated Use `Card.Description` instead */
description?: string;
isSelected?: boolean;
}
export interface CardInterface extends FC<Props> {
@@ -35,6 +36,7 @@ const CardContext = React.createContext<{
href?: string;
onClick?: () => void;
disabled?: boolean;
isSelected?: boolean;
} | null>(null);
/**
@@ -49,6 +51,7 @@ export const Card: CardInterface = ({
children,
heading: deprecatedHeading,
description: deprecatedDescription,
isSelected,
className,
...htmlProps
}) => {
@@ -63,16 +66,17 @@ export const Card: CardInterface = ({
const disableHover = disabled || (!onClick && !href);
const onCardClick = onClick && !disabled ? onClick : undefined;
const theme = useTheme2();
const styles = getCardContainerStyles(theme, disabled, disableHover);
const styles = getCardContainerStyles(theme, disabled, disableHover, isSelected);
return (
<CardContainer
disableEvents={disabled}
disableHover={disableHover}
isSelected={isSelected}
className={cx(styles.container, className)}
{...htmlProps}
>
<CardContext.Provider value={{ href, onClick: onCardClick, disabled }}>
<CardContext.Provider value={{ href, onClick: onCardClick, disabled, isSelected }}>
{!hasHeadingComponent && <Heading />}
{deprecatedHeading && <Heading>{deprecatedHeading}</Heading>}
{deprecatedDescription && <Description>{deprecatedDescription}</Description>}
@@ -96,7 +100,7 @@ const Heading = ({ children, className, 'aria-label': ariaLabel }: ChildProps &
const context = useContext(CardContext);
const styles = useStyles2(getHeadingStyles);
const { href, onClick } = context ?? { href: undefined, onClick: undefined };
const { href, onClick, isSelected } = context ?? { href: undefined, onClick: undefined, isSelected: undefined };
return (
<h2 className={cx(styles.heading, className)}>
@@ -111,6 +115,7 @@ const Heading = ({ children, className, 'aria-label': ariaLabel }: ChildProps &
) : (
<>{children}</>
)}
{isSelected !== undefined && <input aria-label="option" type="radio" checked={isSelected} />}
</h2>
);
};

View File

@@ -39,6 +39,8 @@ export interface CardContainerProps extends HTMLAttributes<HTMLOrSVGElement>, Ca
disableEvents?: boolean;
/** No style change on hover */
disableHover?: boolean;
/** Makes the card selectable, set to "true" to apply selected styles */
isSelected?: boolean;
/** Custom container styles */
className?: string;
}
@@ -48,12 +50,13 @@ export const CardContainer = ({
children,
disableEvents,
disableHover,
isSelected,
className,
href,
...props
}: CardContainerProps) => {
const theme = useTheme2();
const { oldContainer } = getCardContainerStyles(theme, disableEvents, disableHover);
const { oldContainer } = getCardContainerStyles(theme, disableEvents, disableHover, isSelected);
return (
<div {...props} className={cx(oldContainer, className)}>
<CardInner href={href}>{children}</CardInner>
@@ -61,59 +64,71 @@ export const CardContainer = ({
);
};
export const getCardContainerStyles = stylesFactory((theme: GrafanaTheme2, disabled = false, disableHover = false) => {
return {
container: css({
display: 'grid',
position: 'relative',
gridTemplateColumns: 'auto 1fr auto',
gridTemplateRows: '1fr auto auto auto',
gridAutoColumns: '1fr',
gridAutoFlow: 'row',
gridTemplateAreas: `
export const getCardContainerStyles = stylesFactory(
(theme: GrafanaTheme2, disabled = false, disableHover = false, isSelected = false) => {
const isSelectable = isSelected !== undefined;
return {
container: css({
display: 'grid',
position: 'relative',
gridTemplateColumns: 'auto 1fr auto',
gridTemplateRows: '1fr auto auto auto',
gridAutoColumns: '1fr',
gridAutoFlow: 'row',
gridTemplateAreas: `
"Figure Heading Tags"
"Figure Meta Tags"
"Figure Description Tags"
"Figure Actions Secondary"`,
width: '100%',
padding: theme.spacing(2),
background: theme.colors.background.secondary,
borderRadius: theme.shape.borderRadius(),
marginBottom: '8px',
pointerEvents: disabled ? 'none' : 'auto',
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
duration: theme.transitions.duration.short,
}),
width: '100%',
padding: theme.spacing(2),
background: theme.colors.background.secondary,
borderRadius: theme.shape.borderRadius(),
marginBottom: '8px',
pointerEvents: disabled ? 'none' : 'auto',
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
duration: theme.transitions.duration.short,
}),
...(!disableHover && {
'&:hover': {
background: theme.colors.emphasize(theme.colors.background.secondary, 0.03),
cursor: 'pointer',
zIndex: 1,
},
'&:focus': styleMixins.getFocusStyles(theme),
}),
}),
oldContainer: css({
display: 'flex',
width: '100%',
background: theme.colors.background.secondary,
borderRadius: theme.shape.borderRadius(),
position: 'relative',
pointerEvents: disabled ? 'none' : 'auto',
marginBottom: theme.spacing(1),
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
duration: theme.transitions.duration.short,
}),
...(!disableHover && {
'&:hover': {
background: theme.colors.emphasize(theme.colors.background.secondary, 0.03),
cursor: 'pointer',
zIndex: 1,
},
'&:focus': styleMixins.getFocusStyles(theme),
}),
...(!disableHover && {
'&:hover': {
background: theme.colors.emphasize(theme.colors.background.secondary, 0.03),
...(isSelectable && {
cursor: 'pointer',
zIndex: 1,
},
'&:focus': styleMixins.getFocusStyles(theme),
}),
...(isSelected && {
outline: `solid 2px ${theme.colors.primary.border}`,
}),
}),
}),
};
});
oldContainer: css({
display: 'flex',
width: '100%',
background: theme.colors.background.secondary,
borderRadius: theme.shape.borderRadius(),
position: 'relative',
pointerEvents: disabled ? 'none' : 'auto',
marginBottom: theme.spacing(1),
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
duration: theme.transitions.duration.short,
}),
...(!disableHover && {
'&:hover': {
background: theme.colors.emphasize(theme.colors.background.secondary, 0.03),
cursor: 'pointer',
zIndex: 1,
},
'&:focus': styleMixins.getFocusStyles(theme),
}),
}),
};
}
);

View File

@@ -21,24 +21,46 @@ export interface Props extends ButtonProps {
const dummyClearFunc = () => {};
export function ClipboardButton({ onClipboardCopy, onClipboardError, children, getText, ...buttonProps }: Props) {
// Can be removed in 9.x
const buttonRef = useRef<null | HTMLButtonElement>(null);
const copyText = useCallback(() => {
const copiedText = getText();
const copyTextCallback = useCallback(async () => {
const textToCopy = getText();
// Can be removed in 9.x
const dummyEvent: ClipboardEvent = {
action: 'copy',
clearSelection: dummyClearFunc,
text: copiedText,
text: textToCopy,
trigger: buttonRef.current!,
};
navigator.clipboard
.writeText(copiedText)
.then(() => (onClipboardCopy?.(dummyEvent), () => onClipboardError?.(dummyEvent)));
try {
await copyText(textToCopy, buttonRef);
onClipboardCopy?.(dummyEvent);
} catch {
onClipboardError?.(dummyEvent);
}
}, [getText, onClipboardCopy, onClipboardError]);
return (
<Button onClick={copyText} {...buttonProps} ref={buttonRef}>
<Button onClick={copyTextCallback} {...buttonProps} ref={buttonRef}>
{children}
</Button>
);
}
const copyText = async (text: string, buttonRef: React.MutableRefObject<HTMLButtonElement | null>) => {
if (navigator.clipboard && window.isSecureContext) {
return navigator.clipboard.writeText(text);
} else {
// Use a fallback method for browsers/contexts that don't support the Clipboard API.
// See https://web.dev/async-clipboard/#feature-detection.
const input = document.createElement('input');
// Normally we'd append this to the body. However if we're inside a focus manager
// from react-aria, we can't focus anything outside of the managed area.
// Instead, let's append it to the button. Then we're guaranteed to be able to focus + copy.
buttonRef.current?.appendChild(input);
input.value = text;
input.focus();
input.select();
document.execCommand('copy');
input.remove();
}
};

View File

@@ -18,6 +18,7 @@ export interface FileDropzoneProps {
* maxSize: Infinity,
* minSize: 0,
* multiple: true,
* useFsAccessApi: false,
* maxFiles: 0,
* }
*/
@@ -135,7 +136,7 @@ export function FileDropzone({ options, children, readAs, onLoad, fileListRender
setFiles(newFiles);
};
const { getRootProps, getInputProps, isDragActive } = useDropzone({ ...options, onDrop });
const { getRootProps, getInputProps, isDragActive } = useDropzone({ ...options, useFsAccessApi: false, onDrop });
const theme = useTheme2();
const styles = getStyles(theme, isDragActive);
const fileList = files.map((file) => {

View File

@@ -116,7 +116,8 @@ export class GraphNG extends React.Component<GraphNGProps, GraphNGState> {
fields || {
x: fieldMatchers.get(FieldMatcherID.firstTimeField).get({}),
y: fieldMatchers.get(FieldMatcherID.numeric).get({}),
}
},
props.timeRange
);
pluginLog('GraphNG', false, 'data aligned', alignedFrame);

View File

@@ -97,6 +97,23 @@ describe('nullInsertThreshold Transformer', () => {
expect(result.fields[2].values.toArray()).toStrictEqual(['a', null, 'b', null, 'c']);
});
test('should insert trailing null at end +interval when timeRange.to.valueOf() exceeds threshold', () => {
const df = new MutableDataFrame({
refId: 'A',
fields: [
{ name: 'Time', type: FieldType.time, config: { interval: 1 }, values: [1, 3, 10] },
{ name: 'One', type: FieldType.number, values: [4, 6, 8] },
{ name: 'Two', type: FieldType.string, values: ['a', 'b', 'c'] },
],
});
const result = applyNullInsertThreshold(df, null, 13);
expect(result.fields[0].values.toArray()).toStrictEqual([1, 2, 3, 4, 10, 11]);
expect(result.fields[1].values.toArray()).toStrictEqual([4, null, 6, null, 8, null]);
expect(result.fields[2].values.toArray()).toStrictEqual(['a', null, 'b', null, 'c', null]);
});
// TODO: make this work
test.skip('should insert nulls at +threshold (when defined) instead of +interval', () => {
const df = new MutableDataFrame({
@@ -115,23 +132,6 @@ describe('nullInsertThreshold Transformer', () => {
expect(result.fields[2].values.toArray()).toStrictEqual(['a', null, 'b', null, 'c']);
});
test('should insert nulls at midpoints between adjacent > interval: 2', () => {
const df = new MutableDataFrame({
refId: 'A',
fields: [
{ name: 'Time', type: FieldType.time, config: { interval: 2 }, values: [5, 7, 11] },
{ name: 'One', type: FieldType.number, values: [4, 6, 8] },
{ name: 'Two', type: FieldType.string, values: ['a', 'b', 'c'] },
],
});
const result = applyNullInsertThreshold(df);
expect(result.fields[0].values.toArray()).toStrictEqual([5, 7, 9, 11]);
expect(result.fields[1].values.toArray()).toStrictEqual([4, 6, null, 8]);
expect(result.fields[2].values.toArray()).toStrictEqual(['a', 'b', null, 'c']);
});
test('should noop on fewer than two values', () => {
const df = new MutableDataFrame({
refId: 'A',
@@ -202,7 +202,8 @@ describe('nullInsertThreshold Transformer', () => {
expect(result).toBe(df);
});
test('perf stress test should be <= 10ms', () => {
// Leave this test skipped - it should be run manually
test.skip('perf stress test should be <= 10ms', () => {
// 10 fields x 3,000 values with 50% skip (output = 10 fields x 6,000 values)
let bigFrameA = genFrame();

View File

@@ -12,6 +12,7 @@ const INSERT_MODES = {
export function applyNullInsertThreshold(
frame: DataFrame,
refFieldName?: string | null,
refFieldPseudoMax: number | null = null,
insertMode: InsertMode = INSERT_MODES.threshold
): DataFrame {
if (frame.length < 2) {
@@ -48,7 +49,7 @@ export function applyNullInsertThreshold(
const frameValues = frame.fields.map((field) => field.values.toArray());
const filledFieldValues = nullInsertThreshold(refValues, frameValues, threshold, insertMode);
const filledFieldValues = nullInsertThreshold(refValues, frameValues, threshold, refFieldPseudoMax, insertMode);
if (filledFieldValues === frameValues) {
return frame;
@@ -70,7 +71,14 @@ export function applyNullInsertThreshold(
return frame;
}
function nullInsertThreshold(refValues: number[], frameValues: any[][], threshold: number, getInsertValue: InsertMode) {
function nullInsertThreshold(
refValues: number[],
frameValues: any[][],
threshold: number,
// will insert a trailing null when refFieldPseudoMax > last datapoint + threshold
refFieldPseudoMax: number | null = null,
getInsertValue: InsertMode
) {
const len = refValues.length;
let prevValue: number = refValues[0];
const refValuesNew: number[] = [prevValue];
@@ -87,6 +95,10 @@ function nullInsertThreshold(refValues: number[], frameValues: any[][], threshol
prevValue = curValue;
}
if (refFieldPseudoMax != null && prevValue + threshold <= refFieldPseudoMax) {
refValuesNew.push(getInsertValue(prevValue, refFieldPseudoMax, threshold));
}
const filledLen = refValuesNew.length;
if (filledLen === len) {

View File

@@ -1,5 +1,5 @@
import { XYFieldMatchers } from './types';
import { ArrayVector, DataFrame, FieldConfig, FieldType, outerJoinDataFrames } from '@grafana/data';
import { ArrayVector, DataFrame, FieldConfig, FieldType, outerJoinDataFrames, TimeRange } from '@grafana/data';
import { nullToUndefThreshold } from './nullToUndefThreshold';
import { applyNullInsertThreshold } from './nullInsertThreshold';
import { AxisPlacement, GraphFieldConfig, ScaleDistribution, ScaleDistributionConfig } from '@grafana/schema';
@@ -29,9 +29,9 @@ function applySpanNullsThresholds(frame: DataFrame) {
return frame;
}
export function preparePlotFrame(frames: DataFrame[], dimFields: XYFieldMatchers) {
export function preparePlotFrame(frames: DataFrame[], dimFields: XYFieldMatchers, timeRange?: TimeRange | null) {
let alignedFrame = outerJoinDataFrames({
frames: frames.map((frame) => applyNullInsertThreshold(frame)),
frames: frames.map((frame) => applyNullInsertThreshold(frame, null, timeRange?.to.valueOf())),
joinBy: dimFields.x,
keep: dimFields.y,
keepOriginIndices: true,

View File

@@ -43,7 +43,7 @@ export const Input = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
const styles = getInputStyles({ theme, invalid: !!invalid, width });
return (
<div className={cx(styles.wrapper, className)}>
<div className={cx(styles.wrapper, className)} data-testid={'input-wrapper'}>
{!!addonBefore && <div className={styles.addon}>{addonBefore}</div>}
<div className={styles.inputWrapper}>

View File

@@ -1,30 +1,43 @@
import React from 'react';
import { shallow } from 'enzyme';
import { QueryField } from './QueryField';
import { UnThemedQueryField } from './QueryField';
import { Editor } from 'slate';
import { createTheme } from '@grafana/data';
describe('<QueryField />', () => {
it('should render with null initial value', () => {
const wrapper = shallow(<QueryField query={null} onTypeahead={jest.fn()} portalOrigin="mock-origin" />);
const wrapper = shallow(
<UnThemedQueryField theme={createTheme()} query={null} onTypeahead={jest.fn()} portalOrigin="mock-origin" />
);
expect(wrapper.find('div').exists()).toBeTruthy();
});
it('should render with empty initial value', () => {
const wrapper = shallow(<QueryField query="" onTypeahead={jest.fn()} portalOrigin="mock-origin" />);
const wrapper = shallow(
<UnThemedQueryField theme={createTheme()} query="" onTypeahead={jest.fn()} portalOrigin="mock-origin" />
);
expect(wrapper.find('div').exists()).toBeTruthy();
});
it('should render with initial value', () => {
const wrapper = shallow(<QueryField query="my query" onTypeahead={jest.fn()} portalOrigin="mock-origin" />);
const wrapper = shallow(
<UnThemedQueryField theme={createTheme()} query="my query" onTypeahead={jest.fn()} portalOrigin="mock-origin" />
);
expect(wrapper.find('div').exists()).toBeTruthy();
});
it('should execute query on blur', () => {
const onRun = jest.fn();
const wrapper = shallow(
<QueryField query="my query" onTypeahead={jest.fn()} onRunQuery={onRun} portalOrigin="mock-origin" />
<UnThemedQueryField
theme={createTheme()}
query="my query"
onTypeahead={jest.fn()}
onRunQuery={onRun}
portalOrigin="mock-origin"
/>
);
const field = wrapper.instance() as QueryField;
const field = wrapper.instance() as UnThemedQueryField;
expect(onRun.mock.calls.length).toBe(0);
field.handleBlur(new Event('bogus'), new Editor({}), () => {});
expect(onRun.mock.calls.length).toBe(1);
@@ -33,9 +46,15 @@ describe('<QueryField />', () => {
it('should run onChange with clean text', () => {
const onChange = jest.fn();
const wrapper = shallow(
<QueryField query={`my\r clean query `} onTypeahead={jest.fn()} onChange={onChange} portalOrigin="mock-origin" />
<UnThemedQueryField
theme={createTheme()}
query={`my\r clean query `}
onTypeahead={jest.fn()}
onChange={onChange}
portalOrigin="mock-origin"
/>
);
const field = wrapper.instance() as QueryField;
const field = wrapper.instance() as UnThemedQueryField;
field.runOnChange();
expect(onChange.mock.calls.length).toBe(1);
expect(onChange.mock.calls[0][0]).toBe('my clean query ');
@@ -45,7 +64,8 @@ describe('<QueryField />', () => {
const onBlur = jest.fn();
const onRun = jest.fn();
const wrapper = shallow(
<QueryField
<UnThemedQueryField
theme={createTheme()}
query="my query"
onTypeahead={jest.fn()}
onBlur={onBlur}
@@ -53,7 +73,7 @@ describe('<QueryField />', () => {
portalOrigin="mock-origin"
/>
);
const field = wrapper.instance() as QueryField;
const field = wrapper.instance() as UnThemedQueryField;
expect(onBlur.mock.calls.length).toBe(0);
expect(onRun.mock.calls.length).toBe(0);
field.handleBlur(new Event('bogus'), new Editor({}), () => {});
@@ -62,14 +82,18 @@ describe('<QueryField />', () => {
});
describe('syntaxLoaded', () => {
it('should re-render the editor after syntax has fully loaded', () => {
const wrapper: any = shallow(<QueryField query="my query" portalOrigin="mock-origin" />);
const wrapper: any = shallow(
<UnThemedQueryField theme={createTheme()} query="my query" portalOrigin="mock-origin" />
);
const spyOnChange = jest.spyOn(wrapper.instance(), 'onChange').mockImplementation(jest.fn());
wrapper.instance().editor = { insertText: () => ({ deleteBackward: () => ({ value: 'fooo' }) }) };
wrapper.setProps({ syntaxLoaded: true });
expect(spyOnChange).toHaveBeenCalledWith('fooo', true);
});
it('should not re-render the editor if syntax is already loaded', () => {
const wrapper: any = shallow(<QueryField query="my query" portalOrigin="mock-origin" />);
const wrapper: any = shallow(
<UnThemedQueryField theme={createTheme()} query="my query" portalOrigin="mock-origin" />
);
const spyOnChange = jest.spyOn(wrapper.instance(), 'onChange').mockImplementation(jest.fn());
wrapper.setProps({ syntaxLoaded: true });
wrapper.instance().editor = {};
@@ -77,14 +101,18 @@ describe('<QueryField />', () => {
expect(spyOnChange).not.toBeCalled();
});
it('should not re-render the editor if editor itself is not defined', () => {
const wrapper: any = shallow(<QueryField query="my query" portalOrigin="mock-origin" />);
const wrapper: any = shallow(
<UnThemedQueryField theme={createTheme()} query="my query" portalOrigin="mock-origin" />
);
const spyOnChange = jest.spyOn(wrapper.instance(), 'onChange').mockImplementation(jest.fn());
wrapper.setProps({ syntaxLoaded: true });
expect(wrapper.instance().editor).toBeFalsy();
expect(spyOnChange).not.toBeCalled();
});
it('should not re-render the editor twice once syntax is fully loaded', () => {
const wrapper: any = shallow(<QueryField query="my query" portalOrigin="mock-origin" />);
const wrapper: any = shallow(
<UnThemedQueryField theme={createTheme()} query="my query" portalOrigin="mock-origin" />
);
const spyOnChange = jest.spyOn(wrapper.instance(), 'onChange').mockImplementation(jest.fn());
wrapper.instance().editor = { insertText: () => ({ deleteBackward: () => ({ value: 'fooo' }) }) };
wrapper.setProps({ syntaxLoaded: true });

View File

@@ -16,10 +16,22 @@ import {
SuggestionsPlugin,
} from '../../slate-plugins';
import { makeValue, SCHEMA, CompletionItemGroup, TypeaheadOutput, TypeaheadInput, SuggestionsState } from '../..';
import {
makeValue,
SCHEMA,
CompletionItemGroup,
TypeaheadOutput,
TypeaheadInput,
SuggestionsState,
Themeable2,
} from '../..';
import { selectors } from '@grafana/e2e-selectors';
import { css, cx } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { withTheme2 } from '../../themes';
import { getFocusStyles } from '../../themes/mixins';
export interface QueryFieldProps {
export interface QueryFieldProps extends Themeable2 {
additionalPlugins?: Plugin[];
cleanText?: (text: string) => string;
disabled?: boolean;
@@ -38,6 +50,7 @@ export interface QueryFieldProps {
portalOrigin: string;
syntax?: string;
syntaxLoaded?: boolean;
theme: GrafanaTheme2;
}
export interface QueryFieldState {
@@ -54,7 +67,7 @@ export interface QueryFieldState {
* This component can only process strings. Internally it uses Slate Value.
* Implement props.onTypeahead to use suggestions, see PromQueryField.tsx as an example.
*/
export class QueryField extends React.PureComponent<QueryFieldProps, QueryFieldState> {
export class UnThemedQueryField extends React.PureComponent<QueryFieldProps, QueryFieldState> {
plugins: Plugin[];
runOnChangeDebounced: Function;
lastExecutedValue: Value | null = null;
@@ -197,13 +210,14 @@ export class QueryField extends React.PureComponent<QueryFieldProps, QueryFieldS
}
render() {
const { disabled } = this.props;
const { disabled, theme } = this.props;
const wrapperClassName = classnames('slate-query-field__wrapper', {
'slate-query-field__wrapper--disabled': disabled,
});
const styles = getStyles(theme);
return (
<div className={wrapperClassName}>
<div className={cx(wrapperClassName, styles.wrapper)}>
<div className="slate-query-field" aria-label={selectors.components.QueryField.container}>
<Editor
ref={(editor) => (this.editor = editor!)}
@@ -227,4 +241,15 @@ export class QueryField extends React.PureComponent<QueryFieldProps, QueryFieldS
}
}
export default QueryField;
export const QueryField = withTheme2(UnThemedQueryField);
const getStyles = (theme: GrafanaTheme2) => {
const focusStyles = getFocusStyles(theme);
return {
wrapper: css`
&:focus-within {
${focusStyles}
}
`,
};
};

View File

@@ -0,0 +1,60 @@
import React, { useState, ChangeEvent } from 'react';
import { Story, Meta } from '@storybook/react';
import { SecretInput, Props } from './SecretInput';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
export default {
title: 'Forms/SecretInput',
component: SecretInput,
decorators: [withCenteredStory],
parameters: {
controls: {
exclude: [
'prefix',
'suffix',
'addonBefore',
'addonAfter',
'type',
'disabled',
'invalid',
'loading',
'before',
'after',
],
},
},
args: {
width: 50,
placeholder: 'Enter your secret...',
},
argTypes: {
width: { control: { type: 'range', min: 10, max: 200, step: 10 } },
},
} as Meta;
const Template: Story<Props> = (args) => {
const [secret, setSecret] = useState('');
return (
<SecretInput
width={args.width}
value={secret}
isConfigured={args.isConfigured}
placeholder={args.placeholder}
onChange={(event: ChangeEvent<HTMLInputElement>) => setSecret(event.target.value.trim())}
onReset={() => setSecret('')}
/>
);
};
export const basic = Template.bind({});
basic.args = {
isConfigured: false,
};
export const secretIsConfigured = Template.bind({});
secretIsConfigured.args = {
isConfigured: true,
};

View File

@@ -0,0 +1,65 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { SecretInput, RESET_BUTTON_TEXT, CONFIGURED_TEXT } from './SecretInput';
const PLACEHOLDER_TEXT = 'Your secret...';
describe('<SecretInput />', () => {
it('should render an input if the secret is not configured', () => {
render(<SecretInput isConfigured={false} onChange={() => {}} onReset={() => {}} placeholder={PLACEHOLDER_TEXT} />);
const input = screen.getByPlaceholderText(PLACEHOLDER_TEXT);
// Should show an enabled input
expect(input).toBeInTheDocument();
expect(input).not.toBeDisabled();
// Should not show a "Reset" button
expect(screen.queryByRole('button', { name: RESET_BUTTON_TEXT })).not.toBeInTheDocument();
});
it('should render a disabled input with a reset button if the secret is already configured', () => {
render(<SecretInput isConfigured={true} onChange={() => {}} onReset={() => {}} placeholder={PLACEHOLDER_TEXT} />);
const input = screen.getByPlaceholderText(PLACEHOLDER_TEXT);
// Should show a disabled input
expect(input).toBeInTheDocument();
expect(input).toBeDisabled();
expect(input).toHaveValue(CONFIGURED_TEXT);
// Should show a reset button
expect(screen.queryByRole('button', { name: RESET_BUTTON_TEXT })).toBeInTheDocument();
});
it('should be possible to reset a configured secret', () => {
const onReset = jest.fn();
render(<SecretInput isConfigured={true} onChange={() => {}} onReset={onReset} placeholder={PLACEHOLDER_TEXT} />);
// Should show a reset button and a disabled input
expect(screen.queryByPlaceholderText(PLACEHOLDER_TEXT)).toBeDisabled();
expect(screen.queryByRole('button', { name: RESET_BUTTON_TEXT })).toBeInTheDocument();
// Click on "Reset"
userEvent.click(screen.getByRole('button', { name: RESET_BUTTON_TEXT }));
expect(onReset).toHaveBeenCalledTimes(1);
});
it('should be possible to change the value of the secret', () => {
const onChange = jest.fn();
render(<SecretInput isConfigured={false} onChange={onChange} onReset={() => {}} placeholder={PLACEHOLDER_TEXT} />);
const input = screen.getByPlaceholderText(PLACEHOLDER_TEXT);
expect(input).toHaveValue('');
userEvent.type(input, 'Foo');
expect(onChange).toHaveBeenCalled();
expect(input).toHaveValue('Foo');
});
});

View File

@@ -0,0 +1,26 @@
import * as React from 'react';
import { Input } from '../Input/Input';
import { HorizontalGroup } from '../Layout/Layout';
import { Button } from '../Button';
export type Props = React.ComponentProps<typeof Input> & {
/** TRUE if the secret was already configured. (It is needed as often the backend doesn't send back the actual secret, only the information that it was configured) */
isConfigured: boolean;
/** Called when the user clicks on the "Reset" button in order to clear the secret */
onReset: () => void;
};
export const CONFIGURED_TEXT = 'configured';
export const RESET_BUTTON_TEXT = 'Reset';
export const SecretInput = ({ isConfigured, onReset, ...props }: Props) => (
<HorizontalGroup>
{!isConfigured && <Input {...props} type="password" />}
{isConfigured && <Input {...props} type="text" disabled={true} value={CONFIGURED_TEXT} />}
{isConfigured && (
<Button onClick={onReset} variant="secondary">
{RESET_BUTTON_TEXT}
</Button>
)}
</HorizontalGroup>
);

View File

@@ -0,0 +1 @@
export { SecretInput } from './SecretInput';

View File

@@ -0,0 +1,70 @@
import React, { useCallback, useState } from 'react';
import { IconSize } from '../../types/icon';
import { IconButton } from '../IconButton/IconButton';
import { HorizontalGroup } from '../Layout/Layout';
import { TooltipPlacement } from '../Tooltip';
import { TableCellInspectModal } from './TableCellInspectModal';
import { FILTER_FOR_OPERATOR, FILTER_OUT_OPERATOR, TableCellProps, TableFieldOptions } from './types';
import { getTextAlign } from './utils';
interface CellActionProps extends TableCellProps {
previewMode: 'text' | 'code';
}
export function CellActions({ field, cell, previewMode, onCellFilterAdded }: CellActionProps) {
const [isInspecting, setIsInspecting] = useState(false);
const isRightAligned = getTextAlign(field) === 'flex-end';
const showFilters = Boolean(field.config.filterable) && cell.value !== undefined;
const inspectEnabled = Boolean((field.config.custom as TableFieldOptions)?.inspect);
const commonButtonProps = {
size: 'sm' as IconSize,
tooltipPlacement: 'top' as TooltipPlacement,
};
const onFilterFor = useCallback(
(event: React.MouseEvent<HTMLButtonElement>) =>
onCellFilterAdded({ key: field.name, operator: FILTER_FOR_OPERATOR, value: cell.value }),
[cell, field, onCellFilterAdded]
);
const onFilterOut = useCallback(
(event: React.MouseEvent<HTMLButtonElement>) =>
onCellFilterAdded({ key: field.name, operator: FILTER_OUT_OPERATOR, value: cell.value }),
[cell, field, onCellFilterAdded]
);
return (
<>
<div className={`cellActions ${isRightAligned ? 'cellActionsLeft' : ''}`}>
<HorizontalGroup spacing="xs">
{inspectEnabled && (
<IconButton
name="eye"
tooltip="Inspect value"
onClick={() => {
setIsInspecting(true);
}}
{...commonButtonProps}
/>
)}
{showFilters && (
<IconButton name={'search-plus'} onClick={onFilterFor} tooltip="Filter for value" {...commonButtonProps} />
)}
{showFilters && (
<IconButton name={'search-minus'} onClick={onFilterOut} tooltip="Filter out value" {...commonButtonProps} />
)}
</HorizontalGroup>
</div>
{isInspecting && (
<TableCellInspectModal
mode={previewMode}
value={cell.value}
onDismiss={() => {
setIsInspecting(false);
}}
/>
)}
</>
);
}

View File

@@ -1,15 +1,16 @@
import React, { FC, ReactElement } from 'react';
import { DisplayValue, Field, formattedValueToString } from '@grafana/data';
import { TableCellDisplayMode, TableCellProps } from './types';
import { TableCellDisplayMode, TableCellProps, TableFieldOptions } from './types';
import tinycolor from 'tinycolor2';
import { TableStyles } from './styles';
import { FilterActions } from './FilterActions';
import { getTextColorForBackground, getCellLinks } from '../../utils';
import { CellActions } from './CellActions';
export const DefaultCell: FC<TableCellProps> = (props) => {
const { field, cell, tableStyles, row, cellProps } = props;
const inspectEnabled = Boolean((field.config.custom as TableFieldOptions)?.inspect);
const displayValue = field.display!(cell.value);
let value: string | ReactElement;
@@ -19,8 +20,9 @@ export const DefaultCell: FC<TableCellProps> = (props) => {
value = formattedValueToString(displayValue);
}
const cellStyle = getCellStyle(tableStyles, field, displayValue);
const showFilters = field.config.filterable;
const showActions = (showFilters && cell.value !== undefined) || inspectEnabled;
const cellStyle = getCellStyle(tableStyles, field, displayValue, inspectEnabled);
const { link, onClick } = getCellLinks(field, row);
@@ -32,20 +34,25 @@ export const DefaultCell: FC<TableCellProps> = (props) => {
{value}
</a>
)}
{showFilters && cell.value !== undefined && <FilterActions {...props} />}
{showActions && <CellActions {...props} previewMode="text" />}
</div>
);
};
function getCellStyle(tableStyles: TableStyles, field: Field, displayValue: DisplayValue) {
function getCellStyle(
tableStyles: TableStyles,
field: Field,
displayValue: DisplayValue,
disableOverflowOnHover = false
) {
if (field.config.custom?.displayMode === TableCellDisplayMode.ColorText) {
return tableStyles.buildCellContainerStyle(displayValue.color);
return tableStyles.buildCellContainerStyle(displayValue.color, undefined, !disableOverflowOnHover);
}
if (field.config.custom?.displayMode === TableCellDisplayMode.ColorBackgroundSolid) {
const bgColor = tinycolor(displayValue.color);
const textColor = getTextColorForBackground(displayValue.color!);
return tableStyles.buildCellContainerStyle(textColor, bgColor.toRgbString());
return tableStyles.buildCellContainerStyle(textColor, bgColor.toRgbString(), !disableOverflowOnHover);
}
if (field.config.custom?.displayMode === TableCellDisplayMode.ColorBackground) {
@@ -59,9 +66,10 @@ function getCellStyle(tableStyles: TableStyles, field: Field, displayValue: Disp
return tableStyles.buildCellContainerStyle(
textColor,
`linear-gradient(120deg, ${bgColor2}, ${displayValue.color})`
`linear-gradient(120deg, ${bgColor2}, ${displayValue.color})`,
!disableOverflowOnHover
);
}
return tableStyles.cellContainer;
return disableOverflowOnHover ? tableStyles.cellContainerNoOverflow : tableStyles.cellContainer;
}

View File

@@ -1,31 +0,0 @@
import React, { FC, useCallback } from 'react';
import { FILTER_FOR_OPERATOR, FILTER_OUT_OPERATOR, TableCellProps } from './types';
import { Icon, Tooltip } from '..';
export const FilterActions: FC<TableCellProps> = ({ cell, field, tableStyles, onCellFilterAdded }) => {
const onFilterFor = useCallback(
(event: React.MouseEvent<HTMLDivElement>) =>
onCellFilterAdded({ key: field.name, operator: FILTER_FOR_OPERATOR, value: cell.value }),
[cell, field, onCellFilterAdded]
);
const onFilterOut = useCallback(
(event: React.MouseEvent<HTMLDivElement>) =>
onCellFilterAdded({ key: field.name, operator: FILTER_OUT_OPERATOR, value: cell.value }),
[cell, field, onCellFilterAdded]
);
return (
<div className={tableStyles.filterWrapper}>
<div className={tableStyles.filterItem}>
<Tooltip content="Filter for value" placement="top">
<Icon name={'search-plus'} onClick={onFilterFor} />
</Tooltip>
</div>
<div className={tableStyles.filterItem}>
<Tooltip content="Filter out value" placement="top">
<Icon name={'search-minus'} onClick={onFilterOut} />
</Tooltip>
</div>
</div>
);
};

View File

@@ -1,15 +1,12 @@
import React from 'react';
import { css, cx } from '@emotion/css';
import { isString } from 'lodash';
import { Tooltip } from '../Tooltip/Tooltip';
import { JSONFormatter } from '../JSONFormatter/JSONFormatter';
import { useStyles2 } from '../../themes';
import { TableCellProps } from './types';
import { GrafanaTheme2 } from '@grafana/data';
import { TableCellProps, TableFieldOptions } from './types';
import { CellActions } from './CellActions';
export function JSONViewCell(props: TableCellProps): JSX.Element {
const { cell, tableStyles, cellProps } = props;
const { cell, tableStyles, cellProps, field } = props;
const inspectEnabled = Boolean((field.config.custom as TableFieldOptions)?.inspect);
const txt = css`
cursor: pointer;
font-family: monospace;
@@ -26,41 +23,10 @@ export function JSONViewCell(props: TableCellProps): JSX.Element {
displayValue = JSON.stringify(value, null, ' ');
}
const content = <JSONTooltip value={value} />;
return (
<Tooltip placement="auto-start" content={content} theme="info" interactive>
<div {...cellProps} className={tableStyles.cellContainer}>
<div className={cx(tableStyles.cellText, txt)}>{displayValue}</div>
</div>
</Tooltip>
);
}
interface PopupProps {
value: any;
}
function JSONTooltip(props: PopupProps): JSX.Element {
const styles = useStyles2(getStyles);
return (
<div className={styles.container}>
<div>
<JSONFormatter json={props.value} open={4} className={styles.json} />
</div>
<div {...cellProps} className={inspectEnabled ? tableStyles.cellContainerNoOverflow : tableStyles.cellContainer}>
<div className={cx(tableStyles.cellText, txt)}>{displayValue}</div>
{inspectEnabled && <CellActions {...props} previewMode="code" />}
</div>
);
}
function getStyles(theme: GrafanaTheme2) {
return {
container: css`
padding: ${theme.spacing(0.5)};
`,
json: css`
width: fit-content;
max-height: 70vh;
overflow-y: auto;
`,
};
}

View File

@@ -0,0 +1,75 @@
import { isString } from 'lodash';
import React, { useEffect, useState } from 'react';
import { ClipboardButton } from '../ClipboardButton/ClipboardButton';
import { Icon } from '../Icon/Icon';
import { Modal } from '../Modal/Modal';
import { CodeEditor } from '../Monaco/CodeEditor';
interface TableCellInspectModalProps {
value: any;
onDismiss: () => void;
mode: 'code' | 'text';
}
export function TableCellInspectModal({ value, onDismiss, mode }: TableCellInspectModalProps) {
const [isInClipboard, setIsInClipboard] = useState(false);
const timeoutRef = React.useRef<number>();
useEffect(() => {
if (isInClipboard) {
timeoutRef.current = window.setTimeout(() => {
setIsInClipboard(false);
}, 2000);
}
return () => {
if (timeoutRef.current) {
window.clearTimeout(timeoutRef.current);
}
};
}, [isInClipboard]);
let displayValue = value;
if (isString(value)) {
try {
value = JSON.parse(value);
} catch {} // ignore errors
} else {
displayValue = JSON.stringify(value, null, ' ');
}
let text = displayValue;
if (mode === 'code') {
text = JSON.stringify(value, null, ' ');
}
return (
<Modal onDismiss={onDismiss} isOpen={true} title="Inspect value">
{mode === 'code' ? (
<CodeEditor
width="100%"
height={500}
language="json"
showLineNumbers={true}
showMiniMap={(text && text.length) > 100}
value={text}
readOnly={true}
/>
) : (
<pre>{text}</pre>
)}
<Modal.ButtonRow>
<ClipboardButton getText={() => text} onClipboardCopy={() => setIsInClipboard(true)}>
{!isInClipboard ? (
'Copy to Clipboard'
) : (
<>
<Icon name="check" />
Copied to clipboard
</>
)}
</ClipboardButton>
</Modal.ButtonRow>
</Modal>
);
}

View File

@@ -1,4 +1,4 @@
import { css, cx } from '@emotion/css';
import { css, CSSObject } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { getScrollbarWidth } from '../../utils';
@@ -14,8 +14,27 @@ export const getTableStyles = (theme: GrafanaTheme2) => {
const rowHoverBg = theme.colors.emphasize(theme.colors.background.primary, 0.03);
const lastChildExtraPadding = Math.max(getScrollbarWidth(), cellPadding);
const buildCellContainerStyle = (color?: string, background?: string) => {
const buildCellContainerStyle = (color?: string, background?: string, overflowOnHover?: boolean) => {
const cellActionsOverflow: CSSObject = {
margin: theme.spacing(0, -0.5, 0, 0.5),
};
const cellActionsNoOverflow: CSSObject = {
position: 'absolute',
top: 0,
right: 0,
margin: 'auto',
};
const onHoverOverflow: CSSObject = {
overflow: 'visible',
width: 'auto !important',
boxShadow: `0 0 2px ${theme.colors.primary.main}`,
background: background ?? rowHoverBg,
zIndex: 1,
};
return css`
label: ${overflowOnHover ? 'cellContainerOverflow' : 'cellContainerNoOverflow'};
padding: ${cellPadding}px;
width: 100%;
height: 100%;
@@ -33,19 +52,42 @@ export const getTableStyles = (theme: GrafanaTheme2) => {
}
&:hover {
overflow: visible;
width: auto !important;
box-shadow: 0 0 2px ${theme.colors.primary.main};
background: ${background ?? rowHoverBg};
z-index: 1;
.cell-filter-actions  {
display: inline-flex;
${overflowOnHover && onHoverOverflow};
.cellActions {
visibility: visible;
opacity: 1;
width: auto;
}
}
a {
color: inherit;
}
.cellActions {
display: flex;
${overflowOnHover ? cellActionsOverflow : cellActionsNoOverflow}
visibility: hidden;
opacity: 0;
width: 0;
align-items: center;
height: 100%;
padding: ${theme.spacing(1, 0.5, 1, 0.5)};
background: ${background ? 'none' : theme.colors.emphasize(theme.colors.background.primary, 0.03)};
svg {
color: ${color};
}
}
.cellActionsLeft {
right: auto !important;
left: 0;
}
.cellActionsTransparent {
background: none;
}
`;
};
@@ -102,7 +144,8 @@ export const getTableStyles = (theme: GrafanaTheme2) => {
display: flex;
margin-right: ${theme.spacing(0.5)};
`,
cellContainer: buildCellContainerStyle(),
cellContainer: buildCellContainerStyle(undefined, undefined, true),
cellContainerNoOverflow: buildCellContainerStyle(undefined, undefined, false),
cellText: css`
overflow: hidden;
text-overflow: ellipsis;
@@ -161,22 +204,6 @@ export const getTableStyles = (theme: GrafanaTheme2) => {
opacity: 1;
}
`,
filterWrapper: cx(
css`
label: filterWrapper;
display: none;
justify-content: flex-end;
flex-grow: 1;
opacity: 0.6;
padding-left: ${theme.spacing(0.25)};
`,
'cell-filter-actions'
),
filterItem: css`
label: filterItem;
cursor: pointer;
padding: 0 ${theme.spacing(0.025)};
`,
typeIcon: css`
margin-right: ${theme.spacing(1)};
color: ${theme.colors.text.secondary};

View File

@@ -14,16 +14,15 @@
import React from 'react';
import { css } from '@emotion/css';
import { stylesFactory, Tooltip } from '@grafana/ui';
import { Tooltip, useStyles2 } from '@grafana/ui';
import { TraceSpanReference } from '../types/trace';
import ReferenceLink from '../url/ReferenceLink';
export const getStyles = stylesFactory(() => {
export const getStyles = () => {
return {
MultiParent: css`
padding: 0 5px;
color: #000;
& ~ & {
margin-left: 5px;
}
@@ -39,7 +38,7 @@ export const getStyles = stylesFactory(() => {
max-width: none;
`,
};
});
};
type TReferencesButtonProps = {
references: TraceSpanReference[];
@@ -48,19 +47,19 @@ type TReferencesButtonProps = {
focusSpan: (spanID: string) => void;
};
export default class ReferencesButton extends React.PureComponent<TReferencesButtonProps> {
render() {
const { references, children, tooltipText, focusSpan } = this.props;
const styles = getStyles();
const ReferencesButton = (props: TReferencesButtonProps) => {
const { references, children, tooltipText, focusSpan } = props;
const styles = useStyles2(getStyles);
// TODO: handle multiple items with some dropdown
const ref = references[0];
return (
<Tooltip content={tooltipText}>
<ReferenceLink reference={ref} focusSpan={focusSpan} className={styles.MultiParent}>
{children}
</ReferenceLink>
</Tooltip>
);
}
}
// TODO: handle multiple items with some dropdown
const ref = references[0];
return (
<Tooltip content={tooltipText}>
<ReferenceLink reference={ref} focusSpan={focusSpan} className={styles.MultiParent}>
{children}
</ReferenceLink>
</Tooltip>
);
};
export default ReferencesButton;

View File

@@ -54,6 +54,7 @@ describe('<SpanBarRow>', () => {
},
spanID,
logs: [],
references: [],
},
};
@@ -84,29 +85,27 @@ describe('<SpanBarRow>', () => {
});
it('render references button', () => {
const span = Object.assign(
{
references: [
{
refType: 'CHILD_OF',
traceID: 'trace1',
const newSpan = Object.assign({}, props.span);
const span = Object.assign(newSpan, {
references: [
{
refType: 'CHILD_OF',
traceID: 'trace1',
spanID: 'span0',
span: {
spanID: 'span0',
span: {
spanID: 'span0',
},
},
{
refType: 'CHILD_OF',
traceID: 'otherTrace',
},
{
refType: 'CHILD_OF',
traceID: 'otherTrace',
spanID: 'span1',
span: {
spanID: 'span1',
span: {
spanID: 'span1',
},
},
],
},
props.span
);
},
],
});
const spanRow = shallow(<SpanBarRow {...props} span={span} />)
.dive()

View File

@@ -13,13 +13,13 @@
// limitations under the License.
import * as React from 'react';
import IoAlert from 'react-icons/lib/io/alert';
import IoArrowRightA from 'react-icons/lib/io/arrow-right-a';
import IoNetwork from 'react-icons/lib/io/network';
import MdFileUpload from 'react-icons/lib/md/file-upload';
import { css, keyframes } from '@emotion/css';
import cx from 'classnames';
import { stylesFactory, withTheme2 } from '@grafana/ui';
import { Icon, stylesFactory, withTheme2 } from '@grafana/ui';
import { GrafanaTheme2 } from '@grafana/data';
import ReferencesButton from './ReferencesButton';
@@ -510,7 +510,7 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
tooltipText="Contains multiple references"
focusSpan={focusSpan}
>
<IoNetwork />
<Icon name="link" />
</ReferencesButton>
)}
{span.subsidiarilyReferencedBy && span.subsidiarilyReferencedBy.length > 0 && (

View File

@@ -104,7 +104,7 @@ describe('<References>', () => {
expect(serviceName).toBe(span.process.serviceName);
expect(endpointName).toBe(span.operationName);
} else {
expect(serviceName).toBe('< span in another trace >');
expect(serviceName).toBe('View Linked Span ');
}
});
});

View File

@@ -14,17 +14,51 @@
import * as React from 'react';
import { css } from '@emotion/css';
import cx from 'classnames';
import { useStyles2 } from '@grafana/ui';
import { Icon, useStyles2 } from '@grafana/ui';
import AccordianKeyValues from './AccordianKeyValues';
import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down';
import IoIosArrowRight from 'react-icons/lib/io/ios-arrow-right';
import { TraceSpanReference } from '../../types/trace';
import ReferenceLink from '../../url/ReferenceLink';
import { uAlignIcon } from '../../uberUtilityStyles';
import { uAlignIcon, ubMb1 } from '../../uberUtilityStyles';
import { GrafanaTheme2 } from '@grafana/data';
import { autoColor } from '../../Theme';
const getStyles = () => {
const getStyles = (theme: GrafanaTheme2) => {
return {
AccordianReferenceItem: css`
border-bottom: 1px solid ${autoColor(theme, '#d8d8d8')};
`,
AccordianKeyValues: css`
margin-left: 10px;
`,
AccordianReferences: css`
label: AccordianReferences;
border: 1px solid ${autoColor(theme, '#d8d8d8')};
position: relative;
margin-bottom: 0.25rem;
`,
AccordianReferencesHeader: css`
label: AccordianReferencesHeader;
background: ${autoColor(theme, '#e4e4e4')};
color: inherit;
display: block;
padding: 0.25rem 0.5rem;
&:hover {
background: ${autoColor(theme, '#dadada')};
}
`,
AccordianReferencesContent: css`
label: AccordianReferencesContent;
background: ${autoColor(theme, '#f0f0f0')};
border-top: 1px solid ${autoColor(theme, '#d8d8d8')};
padding: 0.5rem 0.5rem 0.25rem 0.5rem;
`,
AccordianReferencesFooter: css`
label: AccordianReferencesFooter;
color: ${autoColor(theme, '#999')};
`,
ReferencesList: css`
background: #fff;
border: 1px solid #ddd;
@@ -53,6 +87,9 @@ const getStyles = () => {
debugInfo: css`
letter-spacing: 0.25px;
margin: 0.5em 0 0;
flex-wrap: wrap;
display: flex;
justify-content: flex-end;
`,
debugLabel: css`
margin: 0 5px 0 5px;
@@ -69,86 +106,117 @@ type AccordianReferencesProps = {
highContrast?: boolean;
interactive?: boolean;
isOpen: boolean;
openedItems?: Set<TraceSpanReference>;
onItemToggle?: (reference: TraceSpanReference) => void;
onToggle?: null | (() => void);
focusSpan: (uiFind: string) => void;
};
type ReferenceItemProps = {
data: TraceSpanReference[];
interactive?: boolean;
openedItems?: Set<TraceSpanReference>;
onItemToggle?: (reference: TraceSpanReference) => void;
focusSpan: (uiFind: string) => void;
};
// export for test
export function References(props: ReferenceItemProps) {
const { data, focusSpan } = props;
const { data, focusSpan, openedItems, onItemToggle, interactive } = props;
const styles = useStyles2(getStyles);
return (
<div className={cx(styles.ReferencesList)}>
<ul className={styles.list}>
{data.map((reference) => {
return (
<li className={styles.item} key={`${reference.spanID}`}>
<ReferenceLink reference={reference} focusSpan={focusSpan}>
<span className={styles.itemContent}>
{reference.span ? (
<span>
<span className="span-svc-name">{reference.span.process.serviceName}</span>
<small className="endpoint-name">{reference.span.operationName}</small>
</span>
) : (
<span className="span-svc-name">&lt; span in another trace &gt;</span>
)}
<small className={styles.debugInfo}>
<span className={styles.debugLabel} data-label="Reference Type:">
{reference.refType}
</span>
<span className={styles.debugLabel} data-label="SpanID:">
{reference.spanID}
</span>
</small>
</span>
</ReferenceLink>
</li>
);
})}
</ul>
<div className={styles.AccordianReferencesContent}>
{data.map((reference, i) => (
<div className={i < data.length - 1 ? styles.AccordianReferenceItem : undefined} key={reference.spanID}>
<div className={styles.item} key={`${reference.spanID}`}>
<ReferenceLink reference={reference} focusSpan={focusSpan}>
<span className={styles.itemContent}>
{reference.span ? (
<span>
<span className="span-svc-name">{reference.span.process.serviceName}</span>
<small className="endpoint-name">{reference.span.operationName}</small>
</span>
) : (
<span className="span-svc-name">
View Linked Span <Icon name="external-link-alt" />
</span>
)}
<small className={styles.debugInfo}>
<span className={styles.debugLabel} data-label="TraceID:">
{reference.traceID}
</span>
<span className={styles.debugLabel} data-label="SpanID:">
{reference.spanID}
</span>
</small>
</span>
</ReferenceLink>
</div>
{!!reference.tags?.length && (
<div className={styles.AccordianKeyValues}>
<AccordianKeyValues
className={i < data.length - 1 ? ubMb1 : null}
data={reference.tags || []}
highContrast
interactive={interactive}
isOpen={openedItems ? openedItems.has(reference) : false}
label={'attributes'}
linksGetter={null}
onToggle={interactive && onItemToggle ? () => onItemToggle(reference) : null}
/>
</div>
)}
</div>
))}
</div>
);
}
export default class AccordianReferences extends React.PureComponent<AccordianReferencesProps> {
static defaultProps: Partial<AccordianReferencesProps> = {
highContrast: false,
interactive: true,
onToggle: null,
};
render() {
const { data, interactive, isOpen, onToggle, focusSpan } = this.props;
const isEmpty = !Array.isArray(data) || !data.length;
const iconCls = uAlignIcon;
let arrow: React.ReactNode | null = null;
let headerProps: {} | null = null;
if (interactive) {
arrow = isOpen ? <IoIosArrowDown className={iconCls} /> : <IoIosArrowRight className={iconCls} />;
headerProps = {
'aria-checked': isOpen,
onClick: isEmpty ? null : onToggle,
role: 'switch',
};
}
return (
<div>
<div {...headerProps}>
{arrow}
<strong>
<span>References</span>
</strong>{' '}
({data.length})
</div>
{isOpen && <References data={data} focusSpan={focusSpan} />}
</div>
);
const AccordianReferences: React.FC<AccordianReferencesProps> = ({
data,
interactive = true,
isOpen,
onToggle,
onItemToggle,
openedItems,
focusSpan,
}) => {
const isEmpty = !Array.isArray(data) || !data.length;
let arrow: React.ReactNode | null = null;
let HeaderComponent: 'span' | 'a' = 'span';
let headerProps: {} | null = null;
if (interactive) {
arrow = isOpen ? <IoIosArrowDown className={uAlignIcon} /> : <IoIosArrowRight className={uAlignIcon} />;
HeaderComponent = 'a';
headerProps = {
'aria-checked': isOpen,
onClick: isEmpty ? null : onToggle,
role: 'switch',
};
}
}
const styles = useStyles2(getStyles);
return (
<div className={styles.AccordianReferences}>
<HeaderComponent className={styles.AccordianReferencesHeader} {...headerProps}>
{arrow}
<strong>
<span>References</span>
</strong>{' '}
({data.length})
</HeaderComponent>
{isOpen && (
<References
data={data}
openedItems={openedItems}
focusSpan={focusSpan}
onItemToggle={onItemToggle}
interactive={interactive}
/>
)}
</div>
);
};
export default React.memo(AccordianReferences);

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { TraceLog } from '../../types/trace';
import { TraceLog, TraceSpanReference } from '../../types/trace';
/**
* Which items of a {@link SpanDetail} component are expanded.
@@ -21,6 +21,7 @@ export default class DetailState {
isTagsOpen: boolean;
isProcessOpen: boolean;
logs: { isOpen: boolean; openedItems: Set<TraceLog> };
references: { isOpen: boolean; openedItems: Set<TraceSpanReference> };
isWarningsOpen: boolean;
isStackTracesOpen: boolean;
isReferencesOpen: boolean;
@@ -33,6 +34,7 @@ export default class DetailState {
isWarningsOpen,
isStackTracesOpen,
logs,
references,
}: DetailState | Record<string, undefined> = oldState || {};
this.isTagsOpen = Boolean(isTagsOpen);
this.isProcessOpen = Boolean(isProcessOpen);
@@ -43,6 +45,10 @@ export default class DetailState {
isOpen: Boolean(logs && logs.isOpen),
openedItems: logs && logs.openedItems ? new Set(logs.openedItems) : new Set(),
};
this.references = {
isOpen: Boolean(references && references.isOpen),
openedItems: references && references.openedItems ? new Set(references.openedItems) : new Set(),
};
}
toggleTags() {
@@ -59,7 +65,17 @@ export default class DetailState {
toggleReferences() {
const next = new DetailState(this);
next.isReferencesOpen = !this.isReferencesOpen;
next.references.isOpen = !this.references.isOpen;
return next;
}
toggleReferenceItem(reference: TraceSpanReference) {
const next = new DetailState(this);
if (next.references.openedItems.has(reference)) {
next.references.openedItems.delete(reference);
} else {
next.references.openedItems.add(reference);
}
return next;
}

View File

@@ -26,23 +26,24 @@ import DetailState from './DetailState';
import { formatDuration } from '../utils';
import LabeledList from '../../common/LabeledList';
import { SpanLinkFunc, TNil } from '../../types';
import { TraceKeyValuePair, TraceLink, TraceLog, TraceSpan } from '../../types/trace';
import { TraceKeyValuePair, TraceLink, TraceLog, TraceSpan, TraceSpanReference } from '../../types/trace';
import AccordianReferences from './AccordianReferences';
import { autoColor } from '../../Theme';
import { uAlignIcon, ubM0, ubMb1, ubMy1, ubTxRightAlign } from '../../uberUtilityStyles';
import { Divider } from '../../common/Divider';
import {
uAlignIcon,
ubFlex,
ubFlexAuto,
ubItemsCenter,
ubM0,
ubMb1,
ubMy1,
ubTxRightAlign,
} from '../../uberUtilityStyles';
const getStyles = (theme: GrafanaTheme2) => {
return {
header: css`
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 0 1rem;
margin-bottom: 0.25rem;
`,
listWrapper: css`
overflow: hidden;
`,
debugInfo: css`
label: debugInfo;
display: block;
@@ -110,6 +111,7 @@ type SpanDetailProps = {
traceStartTime: number;
warningsToggle: (spanID: string) => void;
stackTracesToggle: (spanID: string) => void;
referenceItemToggle: (spanID: string, reference: TraceSpanReference) => void;
referencesToggle: (spanID: string) => void;
focusSpan: (uiFind: string) => void;
createSpanLink?: SpanLinkFunc;
@@ -130,6 +132,7 @@ export default function SpanDetail(props: SpanDetailProps) {
warningsToggle,
stackTracesToggle,
referencesToggle,
referenceItemToggle,
focusSpan,
createSpanLink,
createFocusSpanLink,
@@ -139,7 +142,7 @@ export default function SpanDetail(props: SpanDetailProps) {
isProcessOpen,
logs: logsState,
isWarningsOpen,
isReferencesOpen,
references: referencesState,
isStackTracesOpen,
} = detailState;
const {
@@ -171,6 +174,15 @@ export default function SpanDetail(props: SpanDetailProps) {
label: 'Start Time:',
value: formatDuration(relativeStartTime),
},
...(span.childSpanCount > 0
? [
{
key: 'child_count',
label: 'Child Count:',
value: span.childSpanCount,
},
]
: []),
];
const styles = useStyles2(getStyles);
const link = createSpanLink?.(span);
@@ -178,9 +190,11 @@ export default function SpanDetail(props: SpanDetailProps) {
return (
<div>
<div className={cx(ubFlex, ubItemsCenter, ubMb1)}>
<h2 className={cx(ubFlexAuto, ubM0)}>{operationName}</h2>
<LabeledList className={ubTxRightAlign} items={overviewItems} />
<div className={styles.header}>
<h2 className={cx(ubM0)}>{operationName}</h2>
<div className={styles.listWrapper}>
<LabeledList className={ubTxRightAlign} divider={true} items={overviewItems} />
</div>
</div>
{link ? (
<DataLinkButton link={{ ...link, title: 'Logs for this span' } as any} buttonProps={{ icon: 'gf-logs' }} />
@@ -258,8 +272,10 @@ export default function SpanDetail(props: SpanDetailProps) {
{references && references.length > 0 && (references.length > 1 || references[0].refType !== 'CHILD_OF') && (
<AccordianReferences
data={references}
isOpen={isReferencesOpen}
isOpen={referencesState.isOpen}
openedItems={referencesState.openedItems}
onToggle={() => referencesToggle(spanID)}
onItemToggle={(reference) => referenceItemToggle(spanID, reference)}
focusSpan={focusSpan}
/>
)}

View File

@@ -23,7 +23,7 @@ import { autoColor } from '../Theme';
import { stylesFactory, withTheme2 } from '@grafana/ui';
import { GrafanaTheme2, LinkModel } from '@grafana/data';
import { TraceLog, TraceSpan, TraceKeyValuePair, TraceLink } from '../types/trace';
import { TraceLog, TraceSpan, TraceKeyValuePair, TraceLink, TraceSpanReference } from '../types/trace';
import { SpanLinkFunc } from '../types';
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
@@ -77,6 +77,7 @@ type SpanDetailRowProps = {
logItemToggle: (spanID: string, log: TraceLog) => void;
logsToggle: (spanID: string) => void;
processToggle: (spanID: string) => void;
referenceItemToggle: (spanID: string, reference: TraceSpanReference) => void;
referencesToggle: (spanID: string) => void;
warningsToggle: (spanID: string) => void;
stackTracesToggle: (spanID: string) => void;
@@ -111,6 +112,7 @@ export class UnthemedSpanDetailRow extends React.PureComponent<SpanDetailRowProp
logItemToggle,
logsToggle,
processToggle,
referenceItemToggle,
referencesToggle,
warningsToggle,
stackTracesToggle,
@@ -156,6 +158,7 @@ export class UnthemedSpanDetailRow extends React.PureComponent<SpanDetailRowProp
logItemToggle={logItemToggle}
logsToggle={logsToggle}
processToggle={processToggle}
referenceItemToggle={referenceItemToggle}
referencesToggle={referencesToggle}
warningsToggle={warningsToggle}
stackTracesToggle={stackTracesToggle}

View File

@@ -35,7 +35,7 @@ import {
import { Accessors } from '../ScrollManager';
import { getColorByKey } from '../utils/color-generator';
import { SpanLinkFunc, TNil } from '../types';
import { TraceLog, TraceSpan, Trace, TraceKeyValuePair, TraceLink } from '../types/trace';
import { TraceLog, TraceSpan, Trace, TraceKeyValuePair, TraceLink, TraceSpanReference } from '../types/trace';
import TTraceTimeline from '../types/TTraceTimeline';
import { PEER_SERVICE } from '../constants/tag-keys';
@@ -75,6 +75,7 @@ type TVirtualizedTraceViewOwnProps = {
detailWarningsToggle: (spanID: string) => void;
detailStackTracesToggle: (spanID: string) => void;
detailReferencesToggle: (spanID: string) => void;
detailReferenceItemToggle: (spanID: string, reference: TraceSpanReference) => void;
detailProcessToggle: (spanID: string) => void;
detailTagsToggle: (spanID: string) => void;
detailToggle: (spanID: string) => void;
@@ -440,6 +441,7 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
detailLogsToggle,
detailProcessToggle,
detailReferencesToggle,
detailReferenceItemToggle,
detailWarningsToggle,
detailStackTracesToggle,
detailStates,
@@ -474,6 +476,7 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
logItemToggle={detailLogItemToggle}
logsToggle={detailLogsToggle}
processToggle={detailProcessToggle}
referenceItemToggle={detailReferenceItemToggle}
referencesToggle={detailReferencesToggle}
warningsToggle={detailWarningsToggle}
stackTracesToggle={detailStackTracesToggle}

Some files were not shown because too many files have changed in this diff Show More