Merge branch 'main' into gio/feat/create-correlation-api

This commit is contained in:
Elfo404 2022-07-07 15:27:34 +02:00
commit 8a4aa19588
No known key found for this signature in database
GPG Key ID: 586539D9491F0726
673 changed files with 27186 additions and 10375 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,18 @@
import { regexp } from '@betterer/regexp'; import { regexp } from '@betterer/regexp';
import { eslint } from '@betterer/eslint';
import { BettererFileTest } from '@betterer/betterer'; import { BettererFileTest } from '@betterer/betterer';
import { ESLint, Linter } from 'eslint';
import { existsSync } from 'fs';
export default { export default {
'no enzyme tests': () => regexp(/from 'enzyme'/g).include('**/*.test.*'), 'no enzyme tests': () => regexp(/from 'enzyme'/g).include('**/*.test.*'),
'better eslint': () => 'better eslint': () => countEslintErrors().include('**/*.{ts,tsx}'),
eslint({ 'no undocumented stories': () => countUndocumentedStories().include('**/*.story.tsx'),
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/consistent-type-assertions': [
'error',
{
assertionStyle: 'never',
},
],
}).include('**/*.{ts,tsx}'),
'no undocumented stories': () => countUndocumentedStories().include('**/*.{story.tsx,mdx}'),
}; };
function countUndocumentedStories() { function countUndocumentedStories() {
return new BettererFileTest(async (filePaths, fileTestResult) => { return new BettererFileTest(async (filePaths, fileTestResult) => {
const storyFilePaths = filePaths.filter((filePath) => filePath.endsWith('story.tsx')); filePaths.forEach((filePath) => {
const mdxFilePaths = filePaths.filter((filePath) => filePath.endsWith('mdx')); if (!existsSync(filePath.replace(/\.story.tsx$/, '.mdx'))) {
storyFilePaths.forEach((filePath) => {
if (!mdxFilePaths.includes(filePath.replace(/\.story.tsx$/, '.mdx'))) {
// In this case the file contents don't matter: // In this case the file contents don't matter:
const file = fileTestResult.addFile(filePath, ''); const file = fileTestResult.addFile(filePath, '');
// Add the issue to the first character of the file: // Add the issue to the first character of the file:
@ -31,3 +21,49 @@ function countUndocumentedStories() {
}); });
}); });
} }
function countEslintErrors() {
return new BettererFileTest(async (filePaths, fileTestResult, resolver) => {
const { baseDirectory } = resolver;
const cli = new ESLint({ cwd: baseDirectory });
await Promise.all(
filePaths.map(async (filePath) => {
const linterOptions = (await cli.calculateConfigForFile(filePath)) as Linter.Config;
const rules: Partial<Linter.RulesRecord> = {
'@typescript-eslint/no-explicit-any': 'error',
};
if (!filePath.endsWith('.test.tsx') && !filePath.endsWith('.test.ts')) {
rules['@typescript-eslint/consistent-type-assertions'] = [
'error',
{
assertionStyle: 'never',
},
];
}
const runner = new ESLint({
baseConfig: {
...linterOptions,
rules,
},
useEslintrc: false,
cwd: baseDirectory,
});
const lintResults = await runner.lintFiles([filePath]);
lintResults
.filter((lintResult) => lintResult.source)
.forEach((lintResult) => {
const { messages } = lintResult;
const file = fileTestResult.addFile(filePath, '');
messages.forEach((message, index) => {
file.addIssue(0, 0, message.message, `${index}`);
});
});
})
);
});
}

View File

@ -15,7 +15,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -91,7 +91,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -197,7 +197,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -243,7 +243,6 @@ steps:
from_secret: drone_token from_secret: drone_token
- commands: - commands:
- ./bin/grabpl build-backend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} - ./bin/grabpl build-backend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER}
--variants linux-amd64,linux-amd64-musl,darwin-amd64,windows-amd64
depends_on: depends_on:
- gen-version - gen-version
- wire-install - wire-install
@ -455,7 +454,7 @@ services:
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -542,7 +541,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -632,7 +631,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -721,7 +720,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -789,7 +788,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -884,7 +883,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -979,7 +978,7 @@ steps:
image: grafana/build-container:1.5.7 image: grafana/build-container:1.5.7
name: build-frontend-packages name: build-frontend-packages
- commands: - commands:
- ./bin/grabpl build-plugins --jobs 8 --edition oss --sign --signing-admin - ./bin/grabpl build-plugins --jobs 8 --edition oss
depends_on: depends_on:
- gen-version - gen-version
- yarn-install - yarn-install
@ -1230,7 +1229,7 @@ steps:
repo: repo:
- grafana/grafana - grafana/grafana
- commands: - commands:
- ./bin/grabpl upload-packages --edition oss --packages-bucket grafana-downloads - ./bin/grabpl upload-packages --edition oss
depends_on: depends_on:
- end-to-end-tests-dashboards-suite - end-to-end-tests-dashboards-suite
- end-to-end-tests-panels-suite - end-to-end-tests-panels-suite
@ -1247,7 +1246,7 @@ steps:
repo: repo:
- grafana/grafana - grafana/grafana
- commands: - commands:
- ./bin/grabpl upload-cdn --edition oss --src-bucket "grafana-static-assets" - ./bin/grabpl upload-cdn --edition oss
depends_on: depends_on:
- grafana-server - grafana-server
environment: environment:
@ -1308,7 +1307,7 @@ services:
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -1398,7 +1397,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- $$ProgressPreference = "SilentlyContinue" - $$ProgressPreference = "SilentlyContinue"
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/windows/grabpl.exe - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/windows/grabpl.exe
-OutFile grabpl.exe -OutFile grabpl.exe
image: grafana/ci-wix:0.1.1 image: grafana/ci-wix:0.1.1
name: windows-init name: windows-init
@ -1486,10 +1485,16 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
- commands:
- ./bin/grabpl gen-version --build-id ${DRONE_BUILD_NUMBER}
depends_on:
- grabpl
image: grafana/build-container:1.5.7
name: gen-version
- commands: - commands:
- echo $DRONE_RUNNER_NAME - echo $DRONE_RUNNER_NAME
image: alpine:3.15 image: alpine:3.15
@ -1571,7 +1576,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -1628,7 +1633,7 @@ steps:
image: grafana/build-container:1.5.7 image: grafana/build-container:1.5.7
name: build-frontend-packages name: build-frontend-packages
- commands: - commands:
- ./bin/grabpl build-plugins --jobs 8 --edition oss --sign --signing-admin - ./bin/grabpl build-plugins --jobs 8 --edition oss
depends_on: depends_on:
- gen-version - gen-version
- yarn-install - yarn-install
@ -1778,8 +1783,7 @@ steps:
image: grafana/build-container:1.5.7 image: grafana/build-container:1.5.7
name: build-storybook name: build-storybook
- commands: - commands:
- ./bin/grabpl upload-cdn --edition oss --src-bucket "$${PRERELEASE_BUCKET}" --src-dir - ./bin/grabpl upload-cdn --edition oss
artifacts/static-assets
depends_on: depends_on:
- grafana-server - grafana-server
environment: environment:
@ -1790,7 +1794,7 @@ steps:
image: grafana/grafana-ci-deploy:1.3.1 image: grafana/grafana-ci-deploy:1.3.1
name: upload-cdn-assets name: upload-cdn-assets
- commands: - commands:
- ./bin/grabpl upload-packages --edition oss --packages-bucket $${PRERELEASE_BUCKET}/artifacts/downloads - ./bin/grabpl upload-packages --edition oss
depends_on: depends_on:
- end-to-end-tests-dashboards-suite - end-to-end-tests-dashboards-suite
- end-to-end-tests-panels-suite - end-to-end-tests-panels-suite
@ -1869,7 +1873,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -2004,7 +2008,7 @@ services:
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -2098,7 +2102,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- $$ProgressPreference = "SilentlyContinue" - $$ProgressPreference = "SilentlyContinue"
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/windows/grabpl.exe - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/windows/grabpl.exe
-OutFile grabpl.exe -OutFile grabpl.exe
image: grafana/ci-wix:0.1.1 image: grafana/ci-wix:0.1.1
name: windows-init name: windows-init
@ -2157,7 +2161,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -2244,7 +2248,7 @@ steps:
image: grafana/build-container:1.5.7 image: grafana/build-container:1.5.7
name: build-frontend-packages name: build-frontend-packages
- commands: - commands:
- ./bin/grabpl build-plugins --jobs 8 --edition enterprise --sign --signing-admin - ./bin/grabpl build-plugins --jobs 8 --edition enterprise
depends_on: depends_on:
- gen-version - gen-version
- yarn-install - yarn-install
@ -2393,8 +2397,7 @@ steps:
- success - success
- failure - failure
- commands: - commands:
- ./bin/grabpl upload-cdn --edition enterprise --src-bucket "$${PRERELEASE_BUCKET}" - ./bin/grabpl upload-cdn --edition enterprise
--src-dir artifacts/static-assets
depends_on: depends_on:
- package - package
environment: environment:
@ -2405,7 +2408,7 @@ steps:
image: grafana/grafana-ci-deploy:1.3.1 image: grafana/grafana-ci-deploy:1.3.1
name: upload-cdn-assets name: upload-cdn-assets
- commands: - commands:
- ./bin/grabpl upload-packages --edition enterprise --packages-bucket $${PRERELEASE_BUCKET}/artifacts/downloads - ./bin/grabpl upload-packages --edition enterprise
depends_on: depends_on:
- package - package
environment: environment:
@ -2446,8 +2449,7 @@ steps:
image: grafana/build-container:1.5.7 image: grafana/build-container:1.5.7
name: package-enterprise2 name: package-enterprise2
- commands: - commands:
- ./bin/grabpl upload-cdn --edition enterprise2 --src-bucket "$${PRERELEASE_BUCKET}" - ./bin/grabpl upload-cdn --edition enterprise2
--src-dir artifacts/static-assets
depends_on: depends_on:
- package-enterprise2 - package-enterprise2
environment: environment:
@ -2458,7 +2460,7 @@ steps:
image: grafana/grafana-ci-deploy:1.3.1 image: grafana/grafana-ci-deploy:1.3.1
name: upload-cdn-assets-enterprise2 name: upload-cdn-assets-enterprise2
- commands: - commands:
- ./bin/grabpl upload-packages --edition enterprise2 --packages-bucket $${PRERELEASE_BUCKET}/artifacts/downloads-enterprise2 - ./bin/grabpl upload-packages --edition enterprise2
depends_on: depends_on:
- package-enterprise2 - package-enterprise2
environment: environment:
@ -2505,7 +2507,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -2688,7 +2690,7 @@ services:
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -2830,7 +2832,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- $$ProgressPreference = "SilentlyContinue" - $$ProgressPreference = "SilentlyContinue"
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/windows/grabpl.exe - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/windows/grabpl.exe
-OutFile grabpl.exe -OutFile grabpl.exe
- git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git" - git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"
- cd grafana-enterprise - cd grafana-enterprise
@ -2905,7 +2907,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -2983,7 +2985,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3044,7 +3046,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3123,7 +3125,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3185,7 +3187,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3223,7 +3225,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3261,7 +3263,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3317,7 +3319,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3365,7 +3367,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3414,7 +3416,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3471,7 +3473,7 @@ steps:
image: grafana/build-container:1.5.7 image: grafana/build-container:1.5.7
name: build-frontend-packages name: build-frontend-packages
- commands: - commands:
- ./bin/grabpl build-plugins --jobs 8 --edition oss --sign --signing-admin - ./bin/grabpl build-plugins --jobs 8 --edition oss
depends_on: depends_on:
- gen-version - gen-version
- yarn-install - yarn-install
@ -3621,7 +3623,7 @@ steps:
image: grafana/build-container:1.5.7 image: grafana/build-container:1.5.7
name: build-storybook name: build-storybook
- commands: - commands:
- ./bin/grabpl upload-cdn --edition oss --src-bucket "grafana-static-assets" - ./bin/grabpl upload-cdn --edition oss
depends_on: depends_on:
- grafana-server - grafana-server
environment: environment:
@ -3635,7 +3637,7 @@ steps:
repo: repo:
- grafana/grafana - grafana/grafana
- commands: - commands:
- ./bin/grabpl upload-packages --edition oss --packages-bucket grafana-downloads - ./bin/grabpl upload-packages --edition oss
depends_on: depends_on:
- end-to-end-tests-dashboards-suite - end-to-end-tests-dashboards-suite
- end-to-end-tests-panels-suite - end-to-end-tests-panels-suite
@ -3682,7 +3684,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3811,7 +3813,7 @@ services:
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -3899,7 +3901,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- $$ProgressPreference = "SilentlyContinue" - $$ProgressPreference = "SilentlyContinue"
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/windows/grabpl.exe - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/windows/grabpl.exe
-OutFile grabpl.exe -OutFile grabpl.exe
image: grafana/ci-wix:0.1.1 image: grafana/ci-wix:0.1.1
name: windows-init name: windows-init
@ -3947,7 +3949,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -4032,7 +4034,7 @@ steps:
image: grafana/build-container:1.5.7 image: grafana/build-container:1.5.7
name: build-frontend-packages name: build-frontend-packages
- commands: - commands:
- ./bin/grabpl build-plugins --jobs 8 --edition enterprise --sign --signing-admin - ./bin/grabpl build-plugins --jobs 8 --edition enterprise
depends_on: depends_on:
- gen-version - gen-version
- yarn-install - yarn-install
@ -4193,7 +4195,7 @@ steps:
image: grafana/build-container:1.5.7 image: grafana/build-container:1.5.7
name: build-storybook name: build-storybook
- commands: - commands:
- ./bin/grabpl upload-cdn --edition enterprise --src-bucket "grafana-static-assets" - ./bin/grabpl upload-cdn --edition enterprise
depends_on: depends_on:
- package - package
environment: environment:
@ -4207,7 +4209,7 @@ steps:
repo: repo:
- grafana/grafana - grafana/grafana
- commands: - commands:
- ./bin/grabpl upload-packages --edition enterprise --packages-bucket grafana-downloads - ./bin/grabpl upload-packages --edition enterprise
depends_on: depends_on:
- package - package
environment: environment:
@ -4241,7 +4243,7 @@ steps:
image: grafana/build-container:1.5.7 image: grafana/build-container:1.5.7
name: package-enterprise2 name: package-enterprise2
- commands: - commands:
- ./bin/grabpl upload-cdn --edition enterprise2 --src-bucket "grafana-static-assets" - ./bin/grabpl upload-cdn --edition enterprise2
depends_on: depends_on:
- package-enterprise2 - package-enterprise2
environment: environment:
@ -4252,7 +4254,7 @@ steps:
image: grafana/grafana-ci-deploy:1.3.1 image: grafana/grafana-ci-deploy:1.3.1
name: upload-cdn-assets-enterprise2 name: upload-cdn-assets-enterprise2
- commands: - commands:
- ./bin/grabpl upload-packages --edition enterprise2 --packages-bucket grafana-downloads-enterprise2 - ./bin/grabpl upload-packages --edition enterprise2
depends_on: depends_on:
- package-enterprise2 - package-enterprise2
environment: environment:
@ -4293,7 +4295,7 @@ services: []
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -4467,7 +4469,7 @@ services:
steps: steps:
- commands: - commands:
- mkdir -p bin - mkdir -p bin
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/grabpl - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/grabpl
- chmod +x bin/grabpl - chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8 image: byrnedo/alpine-curl:0.1.8
name: grabpl name: grabpl
@ -4600,7 +4602,7 @@ steps:
name: identify-runner name: identify-runner
- commands: - commands:
- $$ProgressPreference = "SilentlyContinue" - $$ProgressPreference = "SilentlyContinue"
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.50/windows/grabpl.exe - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.52/windows/grabpl.exe
-OutFile grabpl.exe -OutFile grabpl.exe
- git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git" - git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"
- cd grafana-enterprise - cd grafana-enterprise
@ -4797,6 +4799,6 @@ kind: secret
name: gcp_upload_artifacts_key name: gcp_upload_artifacts_key
--- ---
kind: signature kind: signature
hmac: 12fbd61337ed1ae006e8c0ff71d1290e27b5910211369cdd47e1d604afd9befa hmac: b885bb4e5374691a66b4fa8c6f53cdcebeef573895ea629d4e8b0af715573cea
... ...

13
.github/CODEOWNERS vendored
View File

@ -31,9 +31,9 @@ go.sum @grafana/backend-platform
/pkg/build/ @grafana/grafana-release-eng /pkg/build/ @grafana/grafana-release-eng
# Cloud Datasources backend code # Cloud Datasources backend code
/pkg/tsdb/cloudwatch @grafana/cloud-datasources /pkg/tsdb/cloudwatch @grafana/aws-plugins
/pkg/tsdb/azuremonitor @grafana/cloud-datasources /pkg/tsdb/azuremonitor @grafana/cloud-provider-plugins
/pkg/tsdb/cloudmonitoring @grafana/cloud-datasources /pkg/tsdb/cloudmonitoring @grafana/cloud-provider-plugins
# Observability backend code # Observability backend code
/pkg/tsdb/prometheus @grafana/observability-metrics /pkg/tsdb/prometheus @grafana/observability-metrics
@ -108,6 +108,7 @@ pkg/tsdb/testdatasource/sims/ @grafana/grafana-edge-squad
/public/app/features/comments/ @grafana/grafana-edge-squad /public/app/features/comments/ @grafana/grafana-edge-squad
/public/app/features/dimensions/ @grafana/grafana-edge-squad /public/app/features/dimensions/ @grafana/grafana-edge-squad
/public/app/features/geo/ @grafana/grafana-edge-squad /public/app/features/geo/ @grafana/grafana-edge-squad
/public/app/features/storage/ @grafana/grafana-edge-squad
/public/app/features/live/ @grafana/grafana-edge-squad /public/app/features/live/ @grafana/grafana-edge-squad
/public/app/features/explore/ @grafana/observability-experience-squad /public/app/features/explore/ @grafana/observability-experience-squad
/public/app/features/plugins @grafana/plugins-platform-frontend /public/app/features/plugins @grafana/plugins-platform-frontend
@ -148,9 +149,9 @@ lerna.json @grafana/frontend-ops
*.mdx @marcusolsson @jessover9000 @grafana/plugins-platform-frontend *.mdx @marcusolsson @jessover9000 @grafana/plugins-platform-frontend
# Core datasources # Core datasources
/public/app/plugins/datasource/cloudwatch @grafana/cloud-datasources /public/app/plugins/datasource/cloudwatch @grafana/aws-plugins
/public/app/plugins/datasource/elasticsearch @grafana/observability-logs-and-traces /public/app/plugins/datasource/elasticsearch @grafana/observability-logs-and-traces
/public/app/plugins/datasource/grafana-azure-monitor-datasource @grafana/cloud-datasources /public/app/plugins/datasource/grafana-azure-monitor-datasource @grafana/cloud-provider-plugins
/public/app/plugins/datasource/graphite @grafana/observability-metrics /public/app/plugins/datasource/graphite @grafana/observability-metrics
/public/app/plugins/datasource/influxdb @grafana/observability-metrics /public/app/plugins/datasource/influxdb @grafana/observability-metrics
/public/app/plugins/datasource/jaeger @grafana/observability-logs-and-traces /public/app/plugins/datasource/jaeger @grafana/observability-logs-and-traces
@ -160,7 +161,7 @@ lerna.json @grafana/frontend-ops
/public/app/plugins/datasource/opentsdb @grafana/backend-platform /public/app/plugins/datasource/opentsdb @grafana/backend-platform
/public/app/plugins/datasource/postgres @grafana/grafana-bi-squad /public/app/plugins/datasource/postgres @grafana/grafana-bi-squad
/public/app/plugins/datasource/prometheus @grafana/observability-metrics /public/app/plugins/datasource/prometheus @grafana/observability-metrics
/public/app/plugins/datasource/cloud-monitoring @grafana/cloud-datasources /public/app/plugins/datasource/cloud-monitoring @grafana/cloud-provider-plugins
/public/app/plugins/datasource/zipkin @grafana/observability-logs-and-traces /public/app/plugins/datasource/zipkin @grafana/observability-logs-and-traces
/public/app/plugins/datasource/tempo @grafana/observability-logs-and-traces /public/app/plugins/datasource/tempo @grafana/observability-logs-and-traces
/public/app/plugins/datasource/alertmanager @grafana/alerting-squad /public/app/plugins/datasource/alertmanager @grafana/alerting-squad

16
.github/workflows/doc-validator.yml vendored Normal file
View File

@ -0,0 +1,16 @@
name: "doc-validator"
on:
pull_request:
paths: ["docs/sources/**"]
workflow_dispatch:
jobs:
doc-validator:
runs-on: "ubuntu-latest"
container:
image: "grafana/doc-validator:latest"
steps:
- name: "Checkout code"
uses: "actions/checkout@v3"
- name: "Run doc-validator tool"
# Ensure that the CI always passes until all errors are resolved.
run: "doc-validator ./docs/sources || true"

View File

@ -2,9 +2,95 @@
Grafana uses a _bus_ to pass messages between different parts of the application. All communication over the bus happens synchronously. Grafana uses a _bus_ to pass messages between different parts of the application. All communication over the bus happens synchronously.
> **Deprecated:** The bus has officially been deprecated, however, we're still using the command/query objects paradigms. ## Commands and queries
There are three types of messages: _events_, _commands_, and _queries_. Grafana structures arguments to [services](services.md) using a command/query
separation where commands are instructions for a mutation and queries retrieve
records from a service.
Services should define their methods as `func[T, U any](ctx context.Context, args T) (U, error)`.
Each function should take two arguments. First, a `context.Context` that
carries information about the tracing span, cancellation, and similar
runtime information that might be relevant to the call. Secondly, `T` is
a `struct` defined in the service's root package (see the instructions
for [package hierarchy](package-hierarchy.md)) that contains zero or
more arguments that can be passed to the method.
The return values is more flexible, and may consist of none, one, or two
values. If there are two values returned, the second value should be
either an `bool` or `error` indicating the success or failure of the
call. The first value `U` carries a value of any exported type that
makes sense for the service.
Following is an example of an interface providing method signatures for
some calls adhering to these guidelines:
```
type Alphabetical interface {
// GetLetter returns either an error or letter.
GetLetter(context.Context, GetLetterQuery) (Letter, error)
// ListCachedLetters cannot fail, and doesn't return an error.
ListCachedLetters(context.Context, ListCachedLettersQuery) Letters
// DeleteLetter doesn't have any return values other than errors, so it
// returns only an error.
DeleteLetter(context.Contxt, DeleteLetterCommand) error
}
```
> Because we request an operation to be performed, command are written in imperative mood, such as `CreateFolderCommand`, `GetDashboardQuery` and `DeletePlaylistCommand`.
The use of complex types for arguments in Go means a few different
things for us, it provides us with the equivalent of named parameters
from other languages, and it reduces the headache of figuring out which
argument is which that often occurs with three or more arguments.
On the flip-side, it means that all input parameters are optional and
that it is up to the programmer to make sure that the zero value is
useful or at least safe for all fields and that while it's easy to add
another field, if that field must be set for the correct function of the
service that is not detectable at compile time.
### Queries with Result fields
Some queries have a Result field that is mutated and populated by the
method being called. This is a remainder from when the _bus_ was used
for sending commands and queries as well as for events.
All bus commands and queries had to implement the Go type
`func(ctx context.Context, msg interface{}) error`
and mutation of the `msg` variable or returning structured information in
`error` were the two most convenient ways to communicate with the caller.
All `Result` fields should be refactored so that they are returned from
the query method:
```
type GetQuery struct {
Something int
Result ResultType
}
func (s *Service) Get(ctx context.Context, cmd *GetQuery) error {
// ...do something
cmd.Result = result
return nil
}
```
should become
```
type GetQuery struct {
Something int
}
func (s *Service) Get(ctx context.Context, cmd GetQuery) (ResultType, error) {
// ...do something
return result, nil
}
```
## Events ## Events
@ -44,92 +130,3 @@ if err := s.bus.Publish(event); err != nil {
return err return err
} }
``` ```
## Commands
A command is a request for an action to be taken. Unlike an event's fire-and-forget approach, a command can fail as it is handled. The handler will then return an error.
> Because we request an operation to be performed, command are written in imperative mood, such as `CreateFolderCommand`, and `DeletePlaylistCommand`.
### Dispatch a command
To dispatch a command, pass the `context.Context` and object to the `DispatchCtx` method:
```go
// context.Context from caller
ctx := req.Request.Context()
cmd := &models.SendStickersCommand {
UserID: "taylor",
Count: 1,
}
if err := s.bus.DispatchCtx(ctx, cmd); err != nil {
if err == bus.ErrHandlerNotFound {
return nil
}
return err
}
```
> **Note:** `DispatchCtx` will return an error if no handler is registered for that command.
> **Note:** `Dispatch` currently exists and requires no `context.Context` to be provided, but it's strongly suggested to not use this since there's an ongoing refactoring to remove usage of non-context-aware functions/methods and use context.Context everywhere.
**Tip:** Browse the available commands in the `models` package.
### Handle commands
Let other parts of the application dispatch commands to a service, by registering a _command handler_:
To handle a command, register a command handler in the `Init` function.
```go
func (s *MyService) Init() error {
s.bus.AddHandlerCtx(s.SendStickers)
return nil
}
func (s *MyService) SendStickers(ctx context.Context, cmd *models.SendStickersCommand) error {
// ...
}
```
> **Note:** The handler method may return an error if unable to complete the command.
> **Note:** `AddHandler` currently exists and requires no `context.Context` to be provided, but it's strongly suggested to not use this since there's an ongoing refactoring to remove usage of non-context-aware functions/methods and use context.Context everywhere.
## Queries
A command handler can optionally populate the command sent to it. This pattern is commonly used to implement _queries_.
### Making a query
To make a query, dispatch the query instance just like you would a command. When the `DispatchCtx` method returns, the `Results` field contains the result of the query.
```go
// context.Context from caller
ctx := req.Request.Context()
query := &models.FindDashboardQuery{
ID: "foo",
}
if err := bus.Dispatch(ctx, query); err != nil {
return err
}
// The query now contains a result.
for _, item := range query.Results {
// ...
}
```
> **Note:** `Dispatch` currently exists and requires no `context.Context` to be provided, but it's strongly suggested to not use this since there's an ongoing refactoring to remove usage of non-context-aware functions/methods and use context.Context everywhere.
### Return query results
To return results for a query, set any of the fields on the query argument before returning:
```go
func (s *MyService) FindDashboard(ctx context.Context, query *models.FindDashboardQuery) error {
// ...
query.Result = dashboard
return nil
}
```

View File

@ -0,0 +1,81 @@
# Errors
Grafana introduced its own error type `github.com/grafana/grafana/pkg/util/errutil.Error`
in June 2022. It's built on top of the Go `error` interface extended to
contain all the information necessary by Grafana to handle errors in an
informative and safe way.
Previously, Grafana has passed around regular Go errors and have had to
rely on bespoke solutions in API handlers to communicate informative
messages to the end-user. With the new `errutil.Error`, the API handlers
can be slimmed as information about public messaging, structured data
related to the error, localization metadata, log level, HTTP status
code, and so forth are carried by the error.
## Basic use
### Declaring errors
For a service, declare the different categories of errors that may occur
from your service (this corresponds to what you might want to have
specific public error messages or their templates for) by globally
constructing variables using the `errutil.NewBase(status, messageID, opts...)`
function.
The status code loosely corresponds to HTTP status codes and provides a
default log level for errors to ensure that the request logging is
properly informing administrators about various errors occurring in
Grafana (e.g. `StatusBadRequest` is generally speaking not as relevant
as `StatusInternal`). All available status codes live in the `errutil`
package and have names starting with `Status`.
The messageID is constructed as `<servicename>.<error-identifier>` where
the `<servicename>` corresponds to the root service directory per
[the package hierarchy](package-hierarchy.md) and `<error-identifier>`
is a short identifier using dashes for word separation that identifies
the specific category of errors within the service.
To set a static message sent to the client when the error occurs, the
`errutil.WithPublicMessage(message string)` option may be appended to
the NewBase function call. For dynamic messages or more options, refer
to the `errutil` package's GoDocs.
Errors are then constructed using the `Base.Errorf` method, which
functions like the [fmt.Errorf](https://pkg.go.dev/fmt#Errorf) method
except that it creates an `errutil.Error`.
```go
package main
import (
"errors"
"github.com/grafana/grafana/pkg/util/errutil"
"example.org/thing"
)
var ErrBaseNotFound = errutil.NewBase(errutil.StatusNotFound, "main.not-found", errutil.WithPublicMessage("Thing not found"))
func Look(id int) (*Thing, error) {
t, err := thing.GetByID(id)
if errors.Is(err, thing.ErrNotFound) {
return nil, ErrBaseNotFound.Errorf("did not find thing with ID %d: %w", id, err)
}
return t, nil
}
```
Check out [errutil's GoDocs](https://pkg.go.dev/github.com/grafana/grafana@v0.0.0-20220621133844-0f4fc1290421/pkg/util/errutil)
for details on how to construct and use Grafana style errors.
### Handling errors in the API
API handlers use the `github.com/grafana/grafana/pkg/api/response.Err`
function to create responses based on `errutil.Error`s.
> **Note:** (@sakjur 2022-06) `response.Err` requires all errors to be
> `errutil.Error` or it'll be considered an internal server error.
> This is something that should be fixed in the near future to allow
> fallback behavior to make it possible to correctly handle Grafana
> style errors if they're present but allow fallback to a reasonable
> default otherwise.

View File

@ -1,16 +1,217 @@
# Package hierarchy # Package hierarchy
The Go package hierarchy in Grafana should be organized logically (Ben Johnson's The Go packages in Grafana should be packaged by feature, keeping
[article](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1) served as inspiration), according to the packages as small as reasonable while retaining a clear sole ownership
following principles: of a single domain.
- Domain types and interfaces should be in "root" packages (not necessarily at the very top, of the hierarchy, but [Ben Johnson's standard package layout](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1) serves as
logical roots) inspiration for the way we organize packages.
- Sub-packages should depend on roots - sub-packages here typically contain implementations, for example of services
## Principles of how to structure a service in Grafana
[](services.md)
### Domain types and interfaces should be in local "root" packages
Let's say you're creating a _tea pot_ service, place everything another
service needs to interact with the tea pot service in
_pkg/services/teapot_, choosing a name according to
[Go's package naming conventions](https://go.dev/blog/package-names).
Typically, you'd have one or more interfaces that your service provides
in the root package along with any types, errors, and other constants
that makes sense for another service interacting with this service to
use.
Avoid depending on other services when structuring the root package to
reduce the risk of running into circular dependencies.
### Sub-packages should depend on roots, not the other way around
Small-to-medium sized packages should be able to have only a single
sub-package containing the implementation of the service. By moving the
implementation into a separate package we reduce the risk of triggering
circular dependencies (in Go, circular dependencies are evaluated per
package and this structure logically moves it to be per type or function
declaration).
Large packages may need utilize multiple sub-packages at the discretion
of the implementor. Keep interfaces and domain types to the root
package.
### Try to name sub-packages for project wide uniqueness
Prefix sub-packages with the service name or an abbreviation of the
service name (whichever is more appropriate) to provide an ideally
unique package name. This allows `teaimpl` to be distinguished from
`coffeeimpl` without the need for package aliases, and encourages the
use of the same name to reference your package throughout the codebase.
### A well-behaving service provides test doubles for itself
Other services may depend on your service, and it's good practice to
provide means for those services to set up a test instance of the
dependency as needed. Refer to
[Google Testing's Testing on the Toilet: Know Your Test Doubles](https://testing.googleblog.com/2013/07/testing-on-toilet-know-your-test-doubles.html) for a brief
explanation of how we semantically aim to differentiate fakes, mocks,
and stubs within our codebase.
Place test doubles in a sub-package to your root package named
`<servicename>test` or `<service-abbreviation>test`, such that the `teapot` service may have the
`teapottest` or `teatest`
A stub or mock may be sufficient if the service is not a dependency of a
lot of services or if it's called primarily for side effects so that a
no-op default behavior makes sense.
Services which serve many other services and where it's feasible should
provide an in-memory backed test fake that can be used like the
regular service without the need of complicated setup.
### Separate store and logic
When building a new service, data validation, manipulation, scheduled
events and so forth should be collected in a service implementation that
is built to be agnostic about its store.
The storage should be an interface that is not directly called from
outside the service and should be kept to a minimum complexity to
provide the functionality necessary for the service.
A litmus test to reduce the complexity of the storage interface is
whether an in-memory implementation is a feasible test double to build
to test the service.
### Outside the service root
Some parts of the service definition remains outside the
service directory and reflects the legacy package hierarchy.
As of June 2022, the parts that remain outside the service are:
#### Migrations
`pkg/services/sqlstore/migrations` contains all migrations for SQL
databases, for all services (not including Grafana Enterprise).
Migrations are written per the [database.md](database.md#migrations) document.
#### API endpoints
`pkg/api/api.go` contains the endpoint definitions for the most of
Grafana HTTP API (not including Grafana Enterprise).
## Practical example ## Practical example
The `pkg/plugins` package contains plugin domain types, for example `DataPlugin`, and also interfaces The following is a simplified example of the package structure for a
such as `RequestHandler`. Then you have the `pkg/plugins/managers` subpackage, which contains concrete implementations service that doesn't do anything in particular.
such as the service `PluginManager`. The subpackage `pkg/plugins/backendplugin/coreplugin` contains `plugins.DataPlugin`
implementations. None of the methods or functions are populated and in practice most
packages will consist of multiple files. There isn't a Grafana-wide
convention for which files should exist and contain what.
`pkg/services/alphabetical`
```
package alphabetical
type Alphabetical interface {
// GetLetter returns either an error or letter.
GetLetter(context.Context, GetLetterQuery) (Letter, error)
// ListCachedLetters cannot fail, and doesn't return an error.
ListCachedLetters(context.Context, ListCachedLettersQuery) Letters
// DeleteLetter doesn't have any return values other than errors, so it
// returns only an error.
DeleteLetter(context.Contxt, DeltaCommand) error
}
type Letter byte
type Letters []Letter
type GetLetterQuery struct {
ID int
}
// Create queries/commands for methods even if they are empty.
type ListCachedLettersQuery struct {}
type DeleteLetterCommand struct {
ID int
}
```
`pkg/services/alphabetical/alphabeticalimpl`
```
package alphabeticalimpl
// this name can be whatever, it's not supposed to be used from outside
// the service except for in Wire.
type Svc struct { … }
func ProviceSvc(numbers numerical.Numerical, db db.DB) Svc { … }
func (s *Svc) GetLetter(ctx context.Context, q root.GetLetterQuery) (root.Letter, error) { … }
func (s *Svc) ListCachedLetters(ctx context.Context, q root.ListCachedLettersQuery) root.Letters { … }
func (s *Svc) DeleteLetter(ctx context.Context, q root.DeleteLetterCommand) error { … }
type letterStore interface {
Get(ctx.Context, id int) (root.Letter, error)
Delete(ctx.Context, root.DeleteLetterCommand) error
}
type sqlLetterStore struct {
db.DB
}
func (s *sqlStore) Get(ctx.Context, id int) (root.Letter, error) { … }
func (s *sqlStore) Delete(ctx.Context, root.DeleteLetterCommand) error { … }
```
## Legacy package hierarchy
> **Note:** A lot of services still adhere to the legacy model as outlined below. While it is ok to
> extend existing services based on the legacy model, you are _strongly_ encouraged to structure any
> new services or major refactorings using the new package layout.
Grafana has long used a package-by-layer layout where domain types
are placed in **pkg/models**, all SQL logic in **pkg/services/sqlstore**,
and so forth.
This is an example of how the _tea pot_ service could be structured
throughout the codebase in the legacy model.
- _pkg/_
- _api/_
- _api.go_ contains the endpoints for the
- _tea_pot.go_ contains methods on the _pkg/api.HTTPServer_ type
that interacts with the service based on queries coming in via the HTTP
API.
- _dtos/tea_pot.go_ extends the _pkg/models_ file with types
that are meant for translation to and from the API. It's not as commonly
present as _pkg/models_.
- _models/tea_pot.go_ contains the models for the service, this
includes the _command_ and _query_ structs that are used when calling
the service or SQL store methods related to the service and also any
models representing an abstraction provided by the service.
- _services/_
- _sqlstore_
- _tea_pot.go_ contains SQL queries for
interacting with stored objects related to the tea pot service.
- _migrations/tea_pot.go_ contains the migrations necessary to
build the
- _teapot/\*_ contains functions or a service for doing
logical operations beyond those done in _pkg/api_ or _pkg/services/sqlstore_
for the service.
The implementation of legacy services varies widely from service to
service, some or more of these files may be missing and there may be
more files related to a service than those listed here.
Some legacy services providing infrastructure will also take care of the
integration with several domains. The cleanup service both
provides the infrastructure to occasionally run cleanup scripts and
defines the cleanup scripts. Ideally, this would be migrated
to only handle the scheduling and synchronization of clean up jobs.
The logic for the individual jobs would be placed with a service that is
related to whatever is being cleaned up.

View File

@ -1 +0,0 @@
http-bind-address: :8086

View File

@ -5,6 +5,7 @@
- '8086:8086' - '8086:8086'
environment: environment:
INFLUXD_REPORTING_DISABLED: 'true' INFLUXD_REPORTING_DISABLED: 'true'
INFLUXD_HTTP_BIND_ADDRESS: ':8086'
DOCKER_INFLUXDB_INIT_MODE: 'setup' DOCKER_INFLUXDB_INIT_MODE: 'setup'
DOCKER_INFLUXDB_INIT_USERNAME: 'grafana' DOCKER_INFLUXDB_INIT_USERNAME: 'grafana'
DOCKER_INFLUXDB_INIT_PASSWORD: 'grafana12345' DOCKER_INFLUXDB_INIT_PASSWORD: 'grafana12345'
@ -12,7 +13,6 @@
DOCKER_INFLUXDB_INIT_BUCKET: 'mybucket' DOCKER_INFLUXDB_INIT_BUCKET: 'mybucket'
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: 'mytoken' DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: 'mytoken'
volumes: volumes:
- ./docker/blocks/influxdb/config.yaml:/etc/influxdb2/config.yaml
- ./docker/blocks/influxdb/setup_influxql.sh:/docker-entrypoint-initdb.d/setup_influxql.sh - ./docker/blocks/influxdb/setup_influxql.sh:/docker-entrypoint-initdb.d/setup_influxql.sh
telegraf: telegraf:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
#/bin/sh
VERSION=12.0.1 # set version here
cd /tmp
git clone git@github.com:keycloak/keycloak-containers.git
cd keycloak-containers/server
git checkout $VERSION
docker build -t "quay.io/keycloak/keycloak:${VERSION}" .

View File

@ -0,0 +1,30 @@
oauthkeycloakdb:
image: postgres:12.2
container_name: oauthkeycloakdb
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
volumes:
- ./docker/blocks/oauth/cloak.sql:/docker-entrypoint-initdb.d/cloak.sql
restart: unless-stopped
oauthkeycloak:
image: quay.io/keycloak/keycloak:12.0.1
container_name: oauthkeycloak
environment:
DB_VENDOR: POSTGRES
DB_ADDR: oauthkeycloakdb
DB_DATABASE: keycloak
DB_USER: keycloak
DB_PASSWORD: password
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: admin
PROXY_ADDRESS_FORWARDING: "true"
ports:
- 8087:8080
depends_on:
- oauthkeycloakdb
links:
- "oauthkeycloakdb:oauthkeycloakdb"
restart: unless-stopped

View File

@ -0,0 +1,65 @@
# OAUTH BLOCK
## Devenv setup
To launch the block, use the oauth source. Ex:
```bash
make devenv sources="oauth"
```
Here is the conf you need to add to your configuration file (conf/custom.ini):
```ini
[auth]
signout_redirect_url = http://localhost:8087/auth/realms/grafana/protocol/openid-connect/logout?redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Flogin
[auth.generic_oauth]
enabled = true
name = Keycloak-OAuth
allow_sign_up = true
client_id = grafana-oauth
client_secret = d17b9ea9-bcb1-43d2-b132-d339e55872a8
empty_scopes = true
email_attribute_path = email
login_attribute_path = login
name_attribute_path = name
auth_url = http://localhost:8087/auth/realms/grafana/protocol/openid-connect/auth
token_url = http://localhost:8087/auth/realms/grafana/protocol/openid-connect/token
api_url = http://localhost:8087/auth/realms/grafana/protocol/openid-connect/userinfo
role_attribute_path = contains(roles[*], 'admin') && 'Admin' || contains(roles[*], 'editor') && 'Editor' || 'Viewer'
```
## Backing up keycloak DB
In case you want to make changes to the devenv setup, you can dump keycloack's DB:
```bash
cd devenv;
docker-compose exec -T oauthkeycloakdb bash -c "pg_dump -U keycloak keycloak" > docker/blocks/oauth/cloak.sql
```
## Connecting to keycloack:
- keycloak admin: http://localhost:8087
- keycloak admin login: admin:admin
- grafana oauth viewer login: oauth-viewer:grafana
- grafana oauth editor login: oauth-editor:grafana
- grafana oauth admin login: oauth-admin:grafana
# Troubleshooting
## Mac M1 Users
The new arm64 architecture does not build for the latest docker image of keycloack. Refer to https://github.com/docker/for-mac/issues/5310 for the issue to see if it resolved.
Until then you need to build the docker image locally and then run `devenv`.
1. Remove any lingering keycloack image
```sh
$ docker rmi $(docker images | grep 'keycloack')
```
1. Build keycloack image locally
```sh
$ ./docker-build-keycloack-m1-image.sh
```
1. Start from beginning of this readme

View File

@ -233,7 +233,10 @@ datasources:
> This feature is available from v7.1 > This feature is available from v7.1
You can manage plugins in Grafana by adding one or more YAML config files in the [`provisioning/plugins`]({{< relref "../../setup-grafana/configure-grafana/#provisioning" >}}) directory. Each config file can contain a list of `apps` that will be updated during start up. Grafana updates each app to match the configuration file. You can manage plugin applications in Grafana by adding one or more YAML config files in the [`provisioning/plugins`]({{< relref "../../setup-grafana/configure-grafana/#provisioning" >}}) directory. Each config file can contain a list of `apps` that will be updated during start up. Grafana updates each app to match the configuration file.
> **Note:** This feature enables you to provision plugin configurations, not the plugins themselves.
> The plugins must already be installed on the grafana instance
### Example plugin configuration file ### Example plugin configuration file

View File

@ -74,7 +74,7 @@ The following tables list permissions associated with basic and fixed roles.
| `fixed:settings:reader` | `settings:read` | Read Grafana instance settings. | | `fixed:settings:reader` | `settings:read` | Read Grafana instance settings. |
| `fixed:settings:writer` | All permissions from `fixed:settings:reader` and<br>`settings:write` | Read and update Grafana instance settings. | | `fixed:settings:writer` | All permissions from `fixed:settings:reader` and<br>`settings:write` | Read and update Grafana instance settings. |
| `fixed:stats:reader` | `server.stats:read` | Read Grafana instance statistics. | | `fixed:stats:reader` | `server.stats:read` | Read Grafana instance statistics. |
| `fixed:teams:creator` | `teams:create`<br>`org.users:read` | Create a team and list organization users (required to manage the created team). | | `fixed:teams:creator` | `teams:create`<br>`org.users:read`<br>`serviceaccounts:read` | Create a team and list organization users and service accounts (required to manage the created team). |
| `fixed:teams:writer` | `teams:create`<br>`teams:delete`<br>`teams:read`<br>`teams:write`<br>`teams.permissions:read`<br>`teams.permissions:write` | Create, read, update and delete teams and manage team memberships. | | `fixed:teams:writer` | `teams:create`<br>`teams:delete`<br>`teams:read`<br>`teams:write`<br>`teams.permissions:read`<br>`teams.permissions:write` | Create, read, update and delete teams and manage team memberships. |
| `fixed:users:reader` | `users:read`<br>`users.quotas:read`<br>`users.authtoken:read`<br>` | Read all users and their information, such as team memberships, authentication tokens, and quotas. | | `fixed:users:reader` | `users:read`<br>`users.quotas:read`<br>`users.authtoken:read`<br>` | Read all users and their information, such as team memberships, authentication tokens, and quotas. |
| `fixed:users:writer` | All permissions from `fixed:users:reader` and <br>`users:write`<br>`users:create`<br>`users:delete`<br>`users:enable`<br>`users:disable`<br>`users.password:write`<br>`users.permissions:write`<br>`users:logout`<br>`users.authtoken:write`<br>`users.quotas:write` | Read and update all attributes and settings for all users in Grafana: update user information, read user information, create or enable or disable a user, make a user a Grafana administrator, sign out a user, update a users authentication token, or update quotas for all users. | | `fixed:users:writer` | All permissions from `fixed:users:reader` and <br>`users:write`<br>`users:create`<br>`users:delete`<br>`users:enable`<br>`users:disable`<br>`users.password:write`<br>`users.permissions:write`<br>`users:logout`<br>`users.authtoken:write`<br>`users.quotas:write` | Read and update all attributes and settings for all users in Grafana: update user information, read user information, create or enable or disable a user, make a user a Grafana administrator, sign out a user, update a users authentication token, or update quotas for all users. |

View File

@ -19,7 +19,7 @@ Watch this video to learn more about Grafana Alerting: {{< vimeo 720001629 >}}
The following diagram gives you an overview of how Grafana Alerting works and introduces you to some of the key concepts that work together and form the core of our flexible and powerful alerting engine. The following diagram gives you an overview of how Grafana Alerting works and introduces you to some of the key concepts that work together and form the core of our flexible and powerful alerting engine.
{{< figure src="/static/img/docs/alerting/unified/about-alerting-flow-diagram.jpg" caption="Grafana Alerting overview" >}} {{< figure src="/static/img/docs/alerting/unified/about-alerting-flow-diagram-latest.png" caption="Grafana Alerting overview" >}}
1. Alert rules 1. Alert rules

View File

@ -16,7 +16,7 @@ weight: 401
# Annotations and labels for alerting rules # Annotations and labels for alerting rules
Annotations and labels are key value pairs associated with alerts originating from the alerting rule, datasource response, and as a result of alerting rule evaluation. They can be used in alert notifications directly or in [templates]({{< relref "../../contact-points/message-templating/" >}}) and [template functions]({{< relref "../../contact-points/message-templating/template-functions/" >}}) to create notification contact dynamically. Annotations and labels are key value pairs associated with alerts originating from the alerting rule, datasource response, and as a result of alerting rule evaluation. They can be used in alert notifications directly or in [templates]({{< relref "../../contact-points/message-templating/" >}}) and [template functions]({{< relref "../../contact-points/fundamentals/annotation-label/template-functions/" >}}) to create notification contact dynamically.
## Annotations ## Annotations

View File

@ -1,9 +1,7 @@
--- ---
aliases: aliases:
- /docs/grafana/latest/alerting/contact-points/message-templating/example-template-functions/ - /docs/grafana/latest/alerting/contact-points/message-templating/example-template-functions/
- /docs/grafana/latest/alerting/contact-points/message-templating/template-functions/ - /docs/grafana/latest/alerting/fundamentals/annotation-label/example-template-functions/
- /docs/grafana/latest/alerting/message-templating/template-functions/
- /docs/grafana/latest/alerting/unified-alerting/message-templating/template-functions/
keywords: keywords:
- grafana - grafana
- alerting - alerting

View File

@ -3,6 +3,8 @@ aliases:
- /docs/grafana/latest/alerting/contact-points/message-templating/template-functions/ - /docs/grafana/latest/alerting/contact-points/message-templating/template-functions/
- /docs/grafana/latest/alerting/message-templating/template-functions/ - /docs/grafana/latest/alerting/message-templating/template-functions/
- /docs/grafana/latest/alerting/unified-alerting/message-templating/template-functions/ - /docs/grafana/latest/alerting/unified-alerting/message-templating/template-functions/
- /docs/grafana/latest/alerting/fundamentals/annotation-label/template-functions/
- /docs/grafana/latest/alerting/unified-alerting/fundamentals/annotation-label/template-functions/
keywords: keywords:
- grafana - grafana
- alerting - alerting
@ -15,7 +17,7 @@ weight: 125
# Template Functions # Template Functions
Template functions allow you to process labels and annotations to generate dynamic notifications. Template functions allow you to process alert evaluation results to generate dynamic notifications.
| Name | Argument type | Return type | Description | | Name | Argument type | Return type | Description |
| ----------------------------------------- | ------------------------------------------------------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | ----------------------------------------- | ------------------------------------------------------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |

View File

@ -0,0 +1,39 @@
---
aliases:
- /docs/grafana/latest/alerting/fundamentals/data-source-alerting/
description: Data sources in Grafana Alerting
title: Data sources
weight: 100
---
# Data sources
There are a number of data sources that are compatible with Grafana Alerting. Each data source is supported by a plugin. You can use one of the built-in data sources listed below, use [external data source plugins](https://grafana.com/grafana/plugins/?type=datasource), or create your own data source plugin.
If you are creating your own data source plugin, make sure it is a backend plugin as Grafana Alerting requires this in order to be able to evaluate rules using the data source. Frontend data sources are not supported, because the evaluation engine runs on the backend.
Specifying { "alerting": true, “backend”: true } in the plugin.json file indicates that the data source plugin is compatible with Grafana Alerting and includes the backend data-fetching code. For more information, refer to [Build a data source backend plugin](https://grafana.com/tutorials/build-a-data-source-backend-plugin/).
These are the data sources that are compatible with and supported by Grafana Alerting.
- [AWS CloudWatch]({{< relref "../../datasources/aws-cloudwatch/" >}})
- [Azure Monitor]({{< relref "../../datasources/azuremonitor/" >}})
- [Elasticsearch]({{< relref "../../datasources/elasticsearch/" >}})
- [Google Cloud Monitoring]({{< relref "../../google-cloud-monitoring/" >}})
- [Graphite]({{< relref "../../datasources/graphite/" >}})
- [InfluxDB]({{< relref "influxdb/" >}})
- [Loki]({{< relref "../../datasources/loki/" >}})
- ]Microsoft SQL Server (MSSQL)]({{< relref "../../datasources/mssql/" >}})
- [MySQL]({{< relref "../../datasources/mysql/" >}})
- [Open TSDB]({{< relref "../../datasources/opentsdb/" >}})
- [PostgreSQL]({{< relref "../../datasources/postgres/" >}})
- [Prometheus]({{< relref "../../datasources/prometheus/" >}})
- [Jaeger]({{< relref "../../datasources/jaeger/" >}})
- [Zipkin]({{< relref "../../datasources/zipkin/" >}})
- [Tempo]({{< relref "../../datasources/tempo/" >}})
- [Testdata]({{< relref "../../datasources/testdata/" >}})
## Useful links
- [Grafana data sources]({{< relref "../../data-sources/" >}})
- [Add a data source]({{< relref "../../data-sources/add-a-data-source/" >}})

View File

@ -51,6 +51,6 @@ Once you have a strategy or design guidelines, write them down to help maintain
- Use the left and right Y-axes when displaying time series with different units or ranges. - Use the left and right Y-axes when displaying time series with different units or ranges.
- Add documentation to dashboards and panels. - Add documentation to dashboards and panels.
- To add documentation to a dashboard, add a [Text panel visualization]({{< relref "../visualizations/text-panel/" >}}) to the dashboard. Record things like the purpose of the dashboard, useful resource links, and any instructions users might need to interact with the dashboard. Check out this [Wikimedia example](https://grafana.wikimedia.org/d/000000066/resourceloader?orgId=1). - To add documentation to a dashboard, add a [Text panel visualization]({{< relref "../visualizations/text-panel/" >}}) to the dashboard. Record things like the purpose of the dashboard, useful resource links, and any instructions users might need to interact with the dashboard. Check out this [Wikimedia example](https://grafana.wikimedia.org/d/000000066/resourceloader?orgId=1).
- To add documentation to a panel, [edit the panel settings]({{< relref "../panels/working-with-panels/add-panel/" >}}) and add a description. Any text you add will appear if you hover your cursor over the small `i` in the top left corner of the panel. - To add documentation to a panel, edit the panel settings and add a description. Any text you add will appear if you hover your cursor over the small `i` in the top left corner of the panel.
- Reuse your dashboards and enforce consistency by using [templates and variables]({{< relref "../variables/" >}}). - Reuse your dashboards and enforce consistency by using [templates and variables]({{< relref "../variables/" >}}).
- Be careful with stacking graph data. The visualizations can be misleading, and hide important data. We recommend turning it off in most cases. - Be careful with stacking graph data. The visualizations can be misleading, and hide important data. We recommend turning it off in most cases.

View File

@ -0,0 +1,108 @@
---
aliases:
- /docs/grafana/latest/panels/working-with-panels/navigate-panel-editor/
- /docs/grafana/latest/panels/working-with-panels/navigate-inspector-panel/
- /docs/grafana/latest/dashboards/dashboard-create/
- /docs/grafana/latest/features/dashboard/dashboards/
- /docs/grafana/latest/panels/working-with-panels/add-panel/
- /docs/grafana/latest/dashboards/add-organize-panels/
title: Add and organize panels
menuTitle: Add and organize panels
weight: 2
---
# Add and organize panels
This section describes the areas of the Grafana panel editor.
1. Panel header: The header section lists the dashboard in which the panel appears and the following controls:
- **Dashboard settings (gear) icon -** Click to access the dashboard settings.
- **Discard -** Discards changes you have made to the panel since you last saved the dashboard.
- **Save -** Saves changes you made to the panel.
- **Apply -** Applies changes you made and closes the panel editor, returning you to the dashboard. You will have to save the dashboard to persist the applied changes.
1. Visualization preview: The visualization preview section contains the following options:
- **Table view -** Convert any visualization to a table so that you can see the data. Table views are useful for troubleshooting.
- **Fill -** The visualization preview fills the available space. If you change the width of the side pane or height of the bottom pane the visualization changes to fill the available space.
- **Actual -** The visualization preview will have the exact size as the size on the dashboard. If not enough space is available, the visualization will scale down preserving the aspect ratio.
- **Time range controls -** For more information, refer to [Time range controls]({{< relref "time-range-controls/" >}}).
1. Data section: The data section contains tabs where you enter queries, transform your data, and create alert rules (if applicable).
- **Query tab -** Select your data source and enter queries here. For more information, refer to [Add a query]({{< relref "../panels/query-a-data-source/add-a-query/" >}}).
- **Transform tab -** Apply data transformations. For more information, refer to [Transform data]({{< relref "../panels/transform-data/" >}}).
- **Alert tab -** Write alert rules. For more information, refer to [Overview of Grafana 8 alerting]({{< relref "../alerting/" >}}).
1. Panel display options: The display options section contains tabs where you configure almost every aspect of your data visualization, including:
- [Apply color to series and fields]({{< relref "../panels/working-with-panels/apply-color-to-series/" >}})
- [Format a standard field]({{< relref "../panels/working-with-panels/format-standard-fields/" >}})
- [Add a title and description to a panel]({{< relref "../panels/working-with-panels/add-title-and-description/" >}})
> Not all options are available for each visualization.
{{< figure src="/static/img/docs/panel-editor/panel-editor-8-0.png" class="docs-image--no-shadow" max-width="1500px" >}}
## Open the panel inspect drawer
The inspect drawer helps you understand and troubleshoot your panels. You can view the raw data for any panel, export that data to a comma-separated values (CSV) file, view query requests, and export panel and data JSON.
> **Note:** Not all panel types include all tabs. For example, dashboard list panels do not have raw data to inspect, so they do not display the Stats, Data, or Query tabs.
The panel inspector consists of the following options:
1. The panel inspect drawer displays opens a drawer on the right side. Click the arrow in the upper right corner to expand or reduce the drawer pane.
1. **Data tab -** Shows the raw data returned by the query with transformations applied. Field options such as overrides and value mappings are not applied by default.
1. **Stats tab -** Shows how long your query takes and how much it returns.
1. **JSON tab -** Allows you to view and copy the panel JSON, panel data JSON, and data frame structure JSON. This is useful if you are provisioning or administering Grafana.
1. **Query tab -** Shows you the requests to the server sent when Grafana queries the data source.
1. **Error tab -** Shows the error. Only visible when query returns error.
## Create a dashboard and add a panel
Dashboards and panels allow you to show your data in visual form. Each panel needs at least one query to display a visualization.
**Before you begin:**
- Ensure that you have the proper permissions. For more information about permissions, refer to [About users and permissions]({{< relref "../administration/roles-and-permissions/" >}}).
- Identify the dashboard to which you want to add the panel.
- Understand the query language of the target data source.
- Ensure that data source for which you are writing a query has been added. For more information about adding a data source, refer to [Add a data source]({{< relref "../datasources/add-a-data-source/" >}}) if you need instructions.
**To create a dashboard and add a panel**:
1. Sign in to Grafana, hover your cursor over **Dashboard**, and click **+ New Dashboard**.
1. Click **Add a new panel**.
1. In the first line of the **Query** tab, click the drop-down list and select a data source.
1. Write or construct a query in the query language of your data source.
For more information about data sources, refer to [Data sources]({{< relref "../datasources/" >}}) for specific guidelines.
1. In the Visualization list, select a visualization type.
Grafana displays a preview of your query results with the visualization applied.
![](/static/img/docs/panel-editor/select-visualization-8-0.png)
For more information about individual visualizations, refer to [Visualizations options]({{< relref "../visualizations/" >}}).
1. Refer to the following documentation for ways you can adjust panel settings.
While not required, most visualizations need some adjustment before they properly display the information that you need.
- [Format data using value mapping]({{< relref "../panels/format-data/about-value-mapping/" >}})
- [Visualization-specific options]({{< relref "../visualizations/" >}})
- [Override field values]({{< relref "../panels/override-field-values/about-field-overrides/" >}})
- [Configure thresholds]({{< relref "../panels/configure-thresholds/" >}})
- [Apply color to series and fields]({{< relref "../panels/working-with-panels/apply-color-to-series/" >}})
1. Add a note to describe the visualization (or describe your changes) and then click **Save** in the upper-right corner of the page.
Notes can be helpful if you need to revert the dashboard to a previous version.

View File

@ -0,0 +1,87 @@
---
aliases:
- /docs/grafana/latest/panels/panel-library/
- /docs/grafana/latest/panels/library-panels/
- /docs/grafana/latest/panels/library-panels/create-library-panel/
- /docs/grafana/latest/panels/library-panels/add-library-panel/
- /docs/grafana/latest/panels/library-panels/unlink-library-panel/
- /docs/grafana/latest/panels/library-panels/manage-library-panel/
- /docs/grafana/latest/panels/library-panels/delete-library-panel/
- /docs/grafana/latest/dashboards/manage-library-panels/
title: Manage Grafana library panels
menuTitle: Manage library panels
weight: 3
---
# Manage Grafana library panels
A library panel is a reusable panel that you can use in any dashboard. When you make a change to a library panel, that change propagates to all instances of where the panel is used. Library panels streamline reuse of panels across multiple dashboards.
You can save a library panel in a folder alongside saved dashboards.
## Create a library panel
When you create a library panel, the panel on the source dashboard is converted to a library panel as well. You need to save the original dashboard once a panel is converted.
1. Open a panel in edit mode.
1. In the panel display options, click the down arrow option to bring changes to the visualization.
{{< figure src="/static/img/docs/library-panels/create-lib-panel-from-edit-8-0.png" class="docs-image--no-shadow" max-width= "800px" caption="Screenshot of the edit panel" >}}
1. Click the **Library panels** option, and then click **Create library panel** to open the create dialog.
{{< figure src="/static/img/docs/library-panels/create-lib-panel-8-0.png" class="docs-image--no-shadow" max-width= "500px" caption="Screenshot of the create library panel dialog" >}}
1. In **Library panel name**, enter the name.
1. In **Save in folder**, select the folder to save the library panel.
1. Click **Create library panel** to save your changes.
1. Save the dashboard.
Once created, you can modify the library panel using any dashboard on which it appears. After you save the changes, all instances of the library panel reflect these modifications.
{{< figure src="/static/img/docs/library-panels/create-from-more-8-0.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the edit panel" >}}
## Add a library panel to a dashboard
Add a Grafana library panel to a dashboard when you want to provide visualizations to other dashboard users.
1. Hover over the **Dashboards** option on the left menu, then select **New dashboard** from the drop-down options.
The **Add** panel dialog opens.
{{< figure src="/static/img/docs/library-panels/add-library-panel-8-0.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the edit panel" >}}
1. Click the **Add a panel from the panel library** option.
You will see a list of your library panels.
1. Filter the list or search to find the panel you want to add.
1. Click a panel to add it to the dashboard.
## Unlink a library panel
Unlink a library panel when you want to make a change to the panel and not affect other instances of the library panel.
1. Hover over **Dashboard** on the left menu, and then click **Library panels**.
1. Select a library panel that is being used in different dashboards.
1. Select the panel you want to unlink.
1. Click the title of the panel and then click **Edit**. The panel opens in edit mode.
1. Click the **Unlink** option on the top right corner of the page.
## View a list of library panels
You can view a list of available library panels and search for a library panel.
1. Hover over the **Dashboard** option on the left menu, then click **Library panels**.
You can see a list of previously defined library panels.
{{< figure src="/static/img/docs/library-panels/library-panel-list-8-0.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the edit panel" >}}
1. Search for a specific library panel if you know its name.
You can also filter the panels by folder or type.
## Delete a library panel
Delete a library panel when you no longer need it.
1. Hover over **Dashboard** on the left menu, and select **Library panels**.
1. Select the panel you want to delete.
1. Click the delete icon next to the library panel name.

View File

@ -10,7 +10,7 @@ aliases:
- /docs/grafana/latest/reference/search/ - /docs/grafana/latest/reference/search/
title: 'Use dashboards' title: 'Use dashboards'
menuTitle: Use dashboards menuTitle: Use dashboards
weight: 2 weight: 1
keywords: keywords:
- dashboard - dashboard
- search - search

View File

@ -103,7 +103,7 @@ Further documentation on multi-dimensional metrics is available [here](https://d
#### Supported Azure Monitor metrics #### Supported Azure Monitor metrics
Not all metrics returned by the Azure Monitor Metrics API have values. To make it easier for you when building a query, the Grafana data source has a list of supported metrics and ignores metrics which will never have values. This list is updated regularly as new services and metrics are added to the Azure cloud. For more information about the list of metrics, refer to [current supported namespaces](https://github.com/grafana/grafana/blob/main/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/supported_namespaces.ts). Not all metrics returned by the Azure Monitor Metrics API have values. To make it easier for you when building a query, the Grafana data source has a list of supported metrics and ignores metrics which will never have values. This list is updated regularly as new services and metrics are added to the Azure cloud. For more information about the list of metrics, refer to [current supported namespaces](https://github.com/grafana/grafana/blob/main/public/app/plugins/datasource/grafana-azure-monitor-datasource/azureMetadata/metricNamespaces.ts).
### Querying Azure Monitor Logs ### Querying Azure Monitor Logs

View File

@ -66,6 +66,16 @@ This is a configuration for the beta Node Graph visualization. The Node Graph is
-- **Enable Node Graph -** Enables the Node Graph visualization. -- **Enable Node Graph -** Enables the Node Graph visualization.
### Span bar label
You can configure the span bar label. The span bar label allows you add additional information to the span bar row.
Select one of the following four options. The default selection is Duration.
- **None -** Do not show any additional information on the span bar row.
- **Duration -** Show the span duration on the span bar row.
- **Tag -** Show the span tag on the span bar row. Note: You will also need to specify the tag key to use to get the tag value. For example, `span.kind`.
## Query traces ## Query traces
You can query and display traces from Jaeger via [Explore]({{< relref "../explore/" >}}). You can query and display traces from Jaeger via [Explore]({{< relref "../explore/" >}}).

View File

@ -84,6 +84,16 @@ This is a configuration for the Loki search query type.
-- **Data source -** The Loki instance in which you want to search traces. You must configure derived fields in the Loki instance. -- **Data source -** The Loki instance in which you want to search traces. You must configure derived fields in the Loki instance.
### Span bar label
You can configure the span bar label. The span bar label allows you add additional information to the span bar row.
Select one of the following four options. The default selection is Duration.
- **None -** Do not show any additional information on the span bar row.
- **Duration -** Show the span duration on the span bar row.
- **Tag -** Show the span tag on the span bar row. Note: You will also need to specify the tag key to use to get the tag value. For example, `span.kind`.
## Query traces ## Query traces
You can query and display traces from Tempo via [Explore]({{< relref "../explore/" >}}). You can query and display traces from Tempo via [Explore]({{< relref "../explore/" >}}).

View File

@ -65,6 +65,16 @@ This is a configuration for the beta Node Graph visualization. The Node Graph is
-- **Enable Node Graph -** Enables the Node Graph visualization. -- **Enable Node Graph -** Enables the Node Graph visualization.
### Span bar label
You can configure the span bar label. The span bar label allows you add additional information to the span bar row.
Select one of the following four options. The default selection is Duration.
- **None -** Do not show any additional information on the span bar row.
- **Duration -** Show the span duration on the span bar row.
- **Tag -** Show the span tag on the span bar row. Note: You will also need to specify the tag key to use to get the tag value. For example, `span.kind`.
## Query traces ## Query traces
Querying and displaying traces from Zipkin is available via [Explore]({{< relref "../explore/" >}}). Querying and displaying traces from Zipkin is available via [Explore]({{< relref "../explore/" >}}).

View File

@ -12,7 +12,6 @@ You can change a value mapping at any time.
## Before you begin ## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
- Ensure you have an existing value mapping to edit. - Ensure you have an existing value mapping to edit.
**To edit a value mapping**: **To edit a value mapping**:

View File

@ -10,12 +10,6 @@ weight: 30
Map a range of values when you want to format multiple, continuous values. Map a range of values when you want to format multiple, continuous values.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
**To map a range**:
1. Edit the panel for which you want to map a range of values. 1. Edit the panel for which you want to map a range of values.
1. In panel display options, in the **Value mappings** section, click **Add value mappings**. 1. In panel display options, in the **Value mappings** section, click **Add value mappings**.
1. Click **Add a new mapping** and then select **Range**. 1. Click **Add a new mapping** and then select **Range**.

View File

@ -10,14 +10,8 @@ weight: 40
Map a regular expression when you want to format the text and color of a regular expression value. Map a regular expression when you want to format the text and color of a regular expression value.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
**To map a regular expression**:
1. Edit the panel for which you want to map a regular expression. 1. Edit the panel for which you want to map a regular expression.
1. In the panel display options, in the **Value mappings** section, click **Add value mappings**. 1. In the **Value mappings** section of the panel display options, click **Add value mappings**.
1. Click **Add a new mapping** and then select **Regex**. 1. Click **Add a new mapping** and then select **Regex**.
1. Enter the regular expression pattern for Grafana to match. 1. Enter the regular expression pattern for Grafana to match.
1. (Optional) Enter display text. 1. (Optional) Enter display text.

View File

@ -10,12 +10,6 @@ weight: 50
Map a special value when you want to format uncommon, boolean, or empty values. Map a special value when you want to format uncommon, boolean, or empty values.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
**To map a special value**:
1. Edit the panel for which you want to map a special value. 1. Edit the panel for which you want to map a special value.
1. In panel display options, locate the **Value mappings** section and click **Add value mappings**. 1. In panel display options, locate the **Value mappings** section and click **Add value mappings**.
1. Click **Add a new mapping** and then select **Special**. 1. Click **Add a new mapping** and then select **Special**.

View File

@ -10,12 +10,6 @@ weight: 20
Map a value when you want to format a single value. Map a value when you want to format a single value.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
**To map a value**:
1. Open a panel for which you want to map a value. 1. Open a panel for which you want to map a value.
1. In panel display options, locate the **Value mappings** section and click **Add value mappings**. 1. In panel display options, locate the **Value mappings** section and click **Add value mappings**.
1. Click **Add a new mapping** and then select **Value**. 1. Click **Add a new mapping** and then select **Value**.

View File

@ -1,14 +0,0 @@
---
aliases:
- /docs/grafana/latest/panels/library-panels/
- /docs/grafana/latest/panels/panel-library/
- /docs/sources/panels/library-panels/
title: Create reusable Grafana panels
weight: 700
---
# Create reusable Grafana panels
Library panels enable you to create reusable panels that you can add to any dashboard in your organization.
{{< section >}}

View File

@ -1,13 +0,0 @@
---
aliases:
- /docs/grafana/latest/panels/library-panels/about-library-panels/
- /docs/sources/panels/library-panels/about-library-panels/
title: About Grafana library panels
weight: 10
---
# About Grafana panel libraries
A library panel is a reusable panel that you can use in any dashboard. When you make a change to a library panel, that change propagates to all instances of where the panel is used. Library panels streamline reuse of panels across multiple dashboards.
You can save a library panel in a folder alongside saved dashboards.

View File

@ -1,29 +0,0 @@
---
aliases:
- /docs/grafana/latest/panels/library-panels/add-library-panel/
- /docs/sources/panels/library-panels/add-library-panel/
title: Add a Grafana library panel to a dashboard
weight: 30
---
# Add a Grafana library panel to a dashboard
Add a Grafana library panel to a dashboard when you want to provide visualizations to other dashboard users.
## Before you begin
- [Create a library panel]({{< relref "create-library-panel/" >}}).
**To add a library panel to a dashboard**:
1. Hover over the **Dashboards** option on the left menu, then select **New dashboard** from the drop-down options.
The **Add** panel dialog opens.
{{< figure src="/static/img/docs/library-panels/add-library-panel-8-0.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the edit panel" >}}
1. Click the **Add a panel from the panel library** option.
You will see a list of your library panels.
1. Filter the list or search to find the panel you want to add.
1. Click a panel to add it to the dashboard.

View File

@ -1,31 +0,0 @@
---
aliases:
- /docs/grafana/latest/panels/library-panels/create-library-panel/
- /docs/sources/panels/library-panels/create-library-panel/
title: Create a Grafana library panel
weight: 20
---
# Create a Grafana library panel
When you create a library panel, the panel on the source dashboard is converted to a library panel as well. You need to save the original dashboard once a panel is converted.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
**To create a library panel**:
1. Open a panel in edit mode.
1. In the panel display options, click the down arrow option to bring changes to the visualization.
{{< figure src="/static/img/docs/library-panels/create-lib-panel-from-edit-8-0.png" class="docs-image--no-shadow" max-width= "800px" caption="Screenshot of the edit panel" >}}
1. Click the **Library panels** option, and then click **Create new library panel** to open the create dialog.
{{< figure src="/static/img/docs/library-panels/create-lib-panel-8-0.png" class="docs-image--no-shadow" max-width= "500px" caption="Screenshot of the create library panel dialog" >}}
1. In **Library panel name**, enter the name.
1. In **Save in folder**, select the folder to save the library panel.
1. Click **Create library panel** to save your changes.
1. Save the dashboard.
Once created, you can modify the library panel using any dashboard on which it appears. After you save the changes, all instances of the library panel reflect these modifications.
{{< figure src="/static/img/docs/library-panels/create-from-more-8-0.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the edit panel" >}}

View File

@ -1,25 +0,0 @@
---
aliases:
- /docs/grafana/latest/panels/library-panels/delete-library-panel/
- /docs/sources/panels/library-panels/delete-library-panel/
title: Delete a Grafana library panel
weight: 60
---
# Delete a Grafana library panel
Delete a library panel when you no longer need it.
## Before you begin
- Verify that the panel does not appear on a dashboard.
**To delete a library panel**:
1. Hover over **Dashboard** on the left menu, and select Library panels from the drop-down options.
1. Select a library panel that is being used in different dashboards.
You will see a list of all the dashboards.
1. Select the panel you want to delete.
1. Click the delete icon next to the library panel name.

View File

@ -1,26 +0,0 @@
---
aliases:
- /docs/grafana/latest/panels/library-panels/manage-library-panel/
- /docs/sources/panels/library-panels/manage-library-panel/
title: Manage Grafana library panels
weight: 40
---
# Manage Grafana library panels
You can adjust library panel configuration at any time.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
**To view and manage a library panel**:
1. Hover over the **Dashboard** option on the left menu, then click **Library panels**.
You can see a list of previously defined library panels.
{{< figure src="/static/img/docs/library-panels/library-panel-list-8-0.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the edit panel" >}}
1. Search for a specific library panel if you know its name.
You can also filter the panels by folder or type.

View File

@ -1,23 +0,0 @@
---
aliases:
- /docs/grafana/latest/panels/library-panels/unlink-library-panel/
- /docs/sources/panels/library-panels/unlink-library-panel/
title: Unlink a Grafana library panel
weight: 50
---
# Unlink a Grafana library panel
Unlink a library panel when you want to make a change to the panel and not affect other instances of the library panel.
## Before you begin
- Identify the panel you want to unlink.
**To unlink a library panel from a dashboard**:
1. Hover over **Dashboard** on the left menu, and then click **Library panels**.
1. Select a library panel that is being used in different dashboards.
1. Select the panel you want to unlink.
1. Click the title of the panel and then click **Edit**. The panel opens in edit mode.
1. Click the **Unlink** option on the top right corner of the page.

View File

@ -10,12 +10,6 @@ weight: 30
You can override a field when you want to change the display of the value in the visualization. You can override a field when you want to change the display of the value in the visualization.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
**To add a field override**:
1. Edit the panel to which you want to add an override. 1. Edit the panel to which you want to add an override.
1. In the panel display options, in the **Overrides** section, click **Add field override**. 1. In the panel display options, in the **Overrides** section, click **Add field override**.

View File

@ -12,13 +12,6 @@ Delete a field override when you no longer need it.
When you delete an override, the appearance of value defaults to its original format. This change impacts dashboards and dashboard users that rely on an affected panel. When you delete an override, the appearance of value defaults to its original format. This change impacts dashboards and dashboard users that rely on an affected panel.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
- [Add a field override]({{< relref "add-a-field-override/" >}}).
**To delete a field override**:
1. Edit the panel that contains the override you want to delete. 1. Edit the panel that contains the override you want to delete.
1. In panel display options, click the **Overrides** tab. 1. In panel display options, click the **Overrides** tab.
1. Click the override you want to delete and then click the associated trash icon. 1. Click the override you want to delete and then click the associated trash icon.

View File

@ -10,11 +10,6 @@ weight: 40
Edit a field override when you want to make changes to an override setting. Edit a field override when you want to make changes to an override setting.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
- [Add a field override]({{< relref "add-a-field-override/" >}}).
**To edit a field override**: **To edit a field override**:
1. Edit the panel that contains the overrides you want to edit. 1. Edit the panel that contains the overrides you want to edit.

View File

@ -10,11 +10,6 @@ weight: 20
You can view field overrides in the panel display options. You can view field overrides in the panel display options.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
- [Add a field override]({{< relref "add-a-field-override/" >}}).
**To view field overrides**: **To view field overrides**:
1. Open for edit the panel that contains the overrides you want to view. 1. Open for edit the panel that contains the overrides you want to view.

View File

@ -14,7 +14,6 @@ A query returns data that Grafana visualizes in dashboards. When you create a pa
- [Add a data source](../../../datasources/add-a-data-source). - [Add a data source](../../../datasources/add-a-data-source).
- Ensure that you know the query language of the data source. - Ensure that you know the query language of the data source.
- [Add a panel]({{< relref "../working-with-panels/add-panel/" >}}).
**To add a query**: **To add a query**:

View File

@ -10,13 +10,6 @@ weight: 70
Grafana generates a CSV file that contains your data, including any transformations to that data. You can choose to view the data before or after the panel applies field options or field option overrides. Grafana generates a CSV file that contains your data, including any transformations to that data. You can choose to view the data before or after the panel applies field options or field option overrides.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
- [Add a query]({{< relref "add-a-query/" >}}).
**To download raw query results**:
1. Edit the panel that contains the query data you want to download. 1. Edit the panel that contains the query data you want to download.
1. In the query editor, click **Query Inspector**. 1. In the query editor, click **Query Inspector**.
1. Click **Data**. 1. Click **Data**.

View File

@ -10,13 +10,6 @@ weight: 80
The **Stats** tab displays statistics that tell you how long your query takes, how many queries you send, and the number of rows returned. This information can help you troubleshoot your queries, especially if any of the numbers are unexpectedly high or low. The **Stats** tab displays statistics that tell you how long your query takes, how many queries you send, and the number of rows returned. This information can help you troubleshoot your queries, especially if any of the numbers are unexpectedly high or low.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
- [Add a query]({{< relref "add-a-query/" >}}).
**To inspect query performance**:
1. Edit the panel that contains the query with performance you want to inspect. 1. Edit the panel that contains the query with performance you want to inspect.
1. In the query editor, click **Query Inspector**. 1. In the query editor, click **Query Inspector**.
1. Click **Stats**. 1. Click **Stats**.

View File

@ -10,13 +10,6 @@ weight: 90
Inspect query request and response data when you want to troubleshoot a query that returns unexpected results, or fails to return expected results. Inspect query request and response data when you want to troubleshoot a query that returns unexpected results, or fails to return expected results.
## Before you begin
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
- [Add a query]({{< relref "add-a-query/" >}}).
**To inspect query request and response data**:
1. Edit the panel that contains the query you want to export. 1. Edit the panel that contains the query you want to export.
1. In the query editor, click **Query Inspector**. 1. In the query editor, click **Query Inspector**.
1. Click **Refresh**. 1. Click **Refresh**.

View File

@ -14,9 +14,7 @@ The Dashboard data source lets you select a panel in your dashboard that contain
This strategy can drastically reduce the number of queries being made when you for example have several panels visualizing the same data. This strategy can drastically reduce the number of queries being made when you for example have several panels visualizing the same data.
**To share data source queries with another panel**: 1. [Create a dashboard and add a panel]({{< relref "../../dashboards/add-organize-panels/#create-a-dashboard-and-add-a-panel" >}}).
1. [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
1. Change the title to "Source panel". You'll use this panel as a source for the other panels. 1. Change the title to "Source panel". You'll use this panel as a source for the other panels.
1. Define the [query]({{< relref "add-a-query/" >}}) or queries that you want share. 1. Define the [query]({{< relref "add-a-query/" >}}) or queries that you want share.

View File

@ -12,12 +12,6 @@ If your data source supports them, then Grafana displays the **Expression** butt
For more information about expressions, refer to [About expressions]({{< relref "about-expressions/" >}}). For more information about expressions, refer to [About expressions]({{< relref "about-expressions/" >}}).
## Before you begin
- [Add a panel]({{< relref "../../working-with-panels/add-panel/" >}}).
**To write an expression**:
1. Open the panel. 1. Open the panel.
1. Below the query, click **Expression**. 1. Below the query, click **Expression**.
1. In the **Operation** field, select the type of expression you want to write. 1. In the **Operation** field, select the type of expression you want to write.

View File

@ -1,57 +0,0 @@
---
aliases:
- /docs/grafana/latest/panels/working-with-panels/add-panel/
- /docs/sources/panels/working-with-panels/add-panel/
title: Add a panel to a dashboard
weight: 20
---
# Add a panel to a dashboard
Panels allow you to show your data in visual form. Each panel needs at least one query to display a visualization.
## Before you begin
- Ensure that you have the proper permissions. For more information about permissions, refer to [About users and permissions]({{< relref "../../administration/manage-users-and-permissions/about-users-and-permissions/" >}}).
- Identify the dashboard to which you want to add the panel.
- Understand the query language of the target data source.
- Ensure that data source for which you are writing a query has been added. For more information about adding a data source, refer to [Add a data source]({{< relref "../../datasources/add-a-data-source/" >}}) if you need instructions.
**To add a panel to a dashboard**:
1. Navigate to the dashboard to which you want to add a panel.
1. Click the **Add panel** icon.
![](/static/img/docs/panels/add-panel-icon-7-0.png)
1. Click **Add an empty panel**.
Grafana creates an empty time-series panel and selects the default data source.
1. In the first line of the **Query** tab, click the drop-down list and select a data source.
1. Write or construct a query in the query language of your data source.
For more information about data sources, refer to [Data sources]({{< relref "../../datasources/" >}}) for specific guidelines.
1. In the Visualization list, select a visualization type.
Grafana displays a preview of your query results with the visualization applied.
![](/static/img/docs/panel-editor/select-visualization-8-0.png)
For more information about individual visualizations, refer to [Visualizations options]({{< relref "../../visualizations/" >}}).
1. Refer to the following documentation for ways you adjust panel settings.
While not required, most visualizations need some adjustment before they properly display the information that you need.
- [Format data using value mapping]({{< relref "../format-data/about-value-mapping/" >}})
- [Visualization-specific options]({{< relref "../../visualizations/" >}})
- [Override field values]({{< relref "../override-field-values/about-field-overrides/" >}})
- [Configure thresholds]({{< relref "../configure-thresholds/" >}})
- [Apply color to series and fields]({{< relref "apply-color-to-series/" >}})
1. Add a note to describe the visualization (or describe your changes) and then click **Save** in the upper-right corner of the page.
Notes can be helpful if you need to revert the dashboard to a previous version.

View File

@ -10,12 +10,6 @@ weight: 30
Add a title and description to a panel to share with users any important information about the visualization. For example, use the description to document the purpose of the visualization. Add a title and description to a panel to share with users any important information about the visualization. For example, use the description to document the purpose of the visualization.
## Before you begin:
- [Add a panel to a dashboard]({{< relref "add-panel/" >}}).
**To add a title and description to a panel**:
1. Open a panel. 1. Open a panel.
1. In the panel display options pane, locate the **Panel options** section. 1. In the panel display options pane, locate the **Panel options** section.

View File

@ -13,12 +13,6 @@ In addition to specifying color based on thresholds, you can configure the color
You can specify a single color, or select a continuous (gradient) color schemes, based on a value. You can specify a single color, or select a continuous (gradient) color schemes, based on a value.
Continuous color interpolates a color using the percentage of a value relative to min and max. Continuous color interpolates a color using the percentage of a value relative to min and max.
## Before you begin
- [Add a panel to a dashboard]({{< relref "add-panel/" >}}).
**To apply color to series and fields**:
1. In panel display options, scroll to the **Standard options** or **override** section. 1. In panel display options, scroll to the **Standard options** or **override** section.
1. Click the **Standard options Color scheme** drop-down, and select one of the following palettes: 1. Click the **Standard options Color scheme** drop-down, and select one of the following palettes:

View File

@ -16,12 +16,6 @@ Visualizations can often be visually complex, and include many data series. You
When you apply your changes, the visualization changes appear to all users of the panel. When you apply your changes, the visualization changes appear to all users of the panel.
### Before you begin
- [Add a panel to a dashboard]({{< relref "add-panel/" >}}).
**To isolate series data in a visualization**:
1. Open the panel. 1. Open the panel.
1. In the legend, click the label of the series you want to isolate. 1. In the legend, click the label of the series you want to isolate.

View File

@ -16,12 +16,6 @@ For a complete list of field formatting options, refer to [Standard field defini
> You can apply standard options to most built-in Grafana panels. Some older panels and community panels that have not updated to the new panel and data model will be missing either all or some of these field options. > You can apply standard options to most built-in Grafana panels. Some older panels and community panels that have not updated to the new panel and data model will be missing either all or some of these field options.
## Before you begin
- [Add a panel to a dashboard]({{< relref "add-panel/" >}}).
**To format a standard field**:
1. Open a dashboard, click the panel title, and click **Edit**. 1. Open a dashboard, click the panel title, and click **Edit**.
1. In the panel display options pane, locate the **Standard options** section. 1. In the panel display options pane, locate the **Standard options** section.

View File

@ -1,42 +0,0 @@
---
aliases:
- /docs/grafana/latest/panels/working-with-panels/navigate-panel-editor/
- /docs/sources/panels/working-with-panels/navigate-panel-editor/
title: Navigate the Grafana panel editor
weight: 10
---
# Navigate the Grafana panel editor
This page describes the parts of the Grafana panel editor.
1. Panel header: The header section lists the dashboard in which the panel appears and the following controls:
- **Dashboard settings (gear) icon -** Click to access the dashboard settings.
- **Discard -** Discards changes you have made to the panel since you last saved the dashboard.
- **Save -** Saves changes you made to the panel.
- **Apply -** Applies changes you made and closes the panel editor, returning you to the dashboard. You will have to save the dashboard to persist the applied changes.
2. Visualization preview: The visualization preview section contains the following options:
- **Table view -** Convert any visualization to a table so that you can see the data. Table views are useful for troubleshooting.
- **Fill -** The visualization preview fills the available space. If you change the width of the side pane or height of the bottom pane the visualization changes to fill the available space.
- **Actual -** The visualization preview will have the exact size as the size on the dashboard. If not enough space is available, the visualization will scale down preserving the aspect ratio.
- **Time range controls -** For more information, refer to [Time range controls]({{< relref "../../dashboards/time-range-controls/" >}}).
3. Data section: The data section contains tabs where you enter queries, transform your data, and create alert rules (if applicable).
- **Query tab -** Select your data source and enter queries here. For more information, refer to [Add a query]({{< relref "../query-a-data-source/add-a-query/" >}}).
- **Transform tab -** Apply data transformations. For more information, refer to [Transform data]({{< relref "../transform-data/" >}}).
- **Alert tab -** Write alert rules. For more information, refer to [Overview of Grafana 8 alerting]({{< relref "../../alerting/" >}}).
4. Panel display options: The display options section contains tabs where you configure almost every aspect of your data visualization, including:
- [Apply color to series and fields]({{< relref "apply-color-to-series/" >}})
- [Format a standard field]({{< relref "format-standard-fields/" >}})
- [Add a title and description to a panel]({{< relref "add-title-and-description/" >}})
> Not all options are available for each visualization.
{{< figure src="/static/img/docs/panel-editor/panel-editor-8-0.png" class="docs-image--no-shadow" max-width="1500px" >}}

View File

@ -10,12 +10,6 @@ weight: 100
Explore and export panel, panel data, and data frame JSON models. Explore and export panel, panel data, and data frame JSON models.
## Before you begin:
- [Add a panel to a dashboard]({{< relref "add-panel/" >}}).
**To view a panel JSON model**:
1. Open the panel inspector and then click the **JSON** tab or in the panel menu click **Inspect > Panel JSON**. 1. Open the panel inspector and then click the **JSON** tab or in the panel menu click **Inspect > Panel JSON**.
1. In Select source, choose one of the following options: 1. In Select source, choose one of the following options:

View File

@ -51,6 +51,7 @@ tls_client_cert =
tls_client_key = tls_client_key =
tls_client_ca = tls_client_ca =
use_pkce = true use_pkce = true
auth_style =
``` ```
Set `api_url` to the resource that returns [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo) compatible information. Set `api_url` to the resource that returns [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo) compatible information.
@ -63,6 +64,9 @@ You can also specify the SSL/TLS configuration used by the client.
`tls_skip_verify_insecure` controls whether a client verifies the server's certificate chain and host name. If it is true, then SSL/TLS accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. `tls_skip_verify_insecure` controls whether a client verifies the server's certificate chain and host name. If it is true, then SSL/TLS accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks.
`auth_style` controls which [OAuth2 AuthStyle](https://pkg.go.dev/golang.org/x/oauth2#AuthStyle) is used when token is requested from OAuth provider. It determines how `client_id` and `client_secret` are sent to Oauth provider.
Available values are `AutoDetect`, `InParams` and `InHeader`. By default, `AutoDetect` is used.
Set `empty_scopes` to true to use an empty scope during authentication. By default, Grafana uses `user:email` as scope. Set `empty_scopes` to true to use an empty scope during authentication. By default, Grafana uses `user:email` as scope.
### Email address ### Email address

View File

@ -10,7 +10,7 @@ weight: 75
Grafana offers a variety of visualizations to support different use cases. This section of the documentation highlights the built-in panels, their options and typical usage. Grafana offers a variety of visualizations to support different use cases. This section of the documentation highlights the built-in panels, their options and typical usage.
> **Note:** If you are unsure which visualization to pick, Grafana can provide visualization suggestions based on the panel query. When you select a visualization, Grafana will show a preview with that visualization applied. For more information, see the [add a panel]({{< relref "../panels/working-with-panels/add-panel/" >}}) documentation. > **Note:** If you are unsure which visualization to pick, Grafana can provide visualization suggestions based on the panel query. When you select a visualization, Grafana will show a preview with that visualization applied.
- Graphs & charts - Graphs & charts
- [Time series]({{< relref "time-series/" >}}) is the default and main Graph visualization. - [Time series]({{< relref "time-series/" >}}) is the default and main Graph visualization.

View File

@ -18,9 +18,7 @@ This section explains how to use Time series field options to visualize time ser
For more information about the time series visualization, refer to [Time series]({{< relref "_index.md" >}}). For more information about the time series visualization, refer to [Time series]({{< relref "_index.md" >}}).
## Create the panel 1. [Create a dashboard and add a panel]({{< relref "../../dashboards/add-organize-panels/#create-a-dashboard-and-add-a-panel" >}}).
1. [Add a panel]({{< relref "../../panels/working-with-panels/add-panel/" >}}).
1. Select the **Time series** visualization. 1. Select the **Time series** visualization.
1. In the Panel editor side pane, click **Graph styles** to expand it. 1. In the Panel editor side pane, click **Graph styles** to expand it.
1. In Style, click **Bars**. 1. In Style, click **Bars**.

View File

@ -16,9 +16,8 @@ weight: 200
This section explains how to use Time series field options to visualize time series data as lines and illustrates what the options do. This section explains how to use Time series field options to visualize time series data as lines and illustrates what the options do.
## Create the panel 1. [Create a dashboard and add a panel]({{< relref "../../dashboards/add-organize-panels/#create-a-dashboard-and-add-a-panel" >}}).
1. Select the [Time series]({{< relref "_index.md" >}}) visualization.
1. [Add a panel]({{< relref "../../panels/working-with-panels/add-panel/" >}}). Select the [Time series]({{< relref "_index.md" >}}) visualization.
1. In the Panel editor side pane, click **Graph styles** to expand it. 1. In the Panel editor side pane, click **Graph styles** to expand it.
1. In Style, click **Lines**. 1. In Style, click **Lines**.

View File

@ -16,9 +16,8 @@ weight: 300
This section explains how to use Time series field options to visualize time series data as points and illustrates what the options do. This section explains how to use Time series field options to visualize time series data as points and illustrates what the options do.
## Create the panel 1. [Create a dashboard and add a panel]({{< relref "../../dashboards/add-organize-panels/#create-a-dashboard-and-add-a-panel" >}}).
1. Select the [Time series]({{< relref "_index.md" >}}) visualization.
1. [Add a panel]({{< relref "../../panels/working-with-panels/add-panel/" >}}). Select the [Time series]({{< relref "_index.md" >}}) visualization.
1. In the Panel editor side pane, click **Graph styles** to expand it. 1. In the Panel editor side pane, click **Graph styles** to expand it.
1. In Style, click **Points**. 1. In Style, click **Points**.

View File

@ -15,7 +15,7 @@ title: What's new in Grafana v7.5
weight: -32 weight: -32
--- ---
# Whats new in Grafana v7.5 # What's new in Grafana v7.5
This topic includes the release notes for Grafana v7.5. For all details, read the full [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md). This topic includes the release notes for Grafana v7.5. For all details, read the full [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md).

View File

@ -15,7 +15,7 @@ title: What's new in Grafana v8.0
weight: -33 weight: -33
--- ---
# Whats new in Grafana v8.0 # What's new in Grafana v8.0
This topic includes the release notes for Grafana v8.0. For all details, read the full [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md). This topic includes the release notes for Grafana v8.0. For all details, read the full [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md).

View File

@ -15,7 +15,7 @@ title: What's new in Grafana v8.1
weight: -33 weight: -33
--- ---
# Whats new in Grafana v8.1 # What's new in Grafana v8.1
> **Note:** This topic will be updated frequently between now and the final release. > **Note:** This topic will be updated frequently between now and the final release.

View File

@ -15,7 +15,7 @@ title: What's new in Grafana v8.2
weight: -33 weight: -33
--- ---
# Whats new in Grafana v8.2 # What's new in Grafana v8.2
Grafana 8.2 continues to build on the foundation of Grafana 8.0 & 8.1. Grafana 8.2 also marks the start of our work to bring Grafana closer to all users with a focus on increasing Grafanas accessibility, part of its continuing mission to democratize metrics _for everyone_. Grafana 8.2 continues to build on the foundation of Grafana 8.0 & 8.1. Grafana 8.2 also marks the start of our work to bring Grafana closer to all users with a focus on increasing Grafanas accessibility, part of its continuing mission to democratize metrics _for everyone_.

View File

@ -15,7 +15,7 @@ title: What's new in Grafana v8.3
weight: -33 weight: -33
--- ---
# Whats new in Grafana v8.3 # What's new in Grafana v8.3
Grafana 8.3 is an exciting release for Grafana Labs. This release includes the new Candlestick Panel, a new visualization suggestions engine and, for enterprise users, Recorded Queries. Grafana 8.3 is an exciting release for Grafana Labs. This release includes the new Candlestick Panel, a new visualization suggestions engine and, for enterprise users, Recorded Queries.

View File

@ -15,7 +15,7 @@ title: What's new in Grafana v8.4
weight: -33 weight: -33
--- ---
# Whats new in Grafana v8.4 # What's new in Grafana v8.4
Were excited to announce Grafana v8.4, with a variety of improvements that focus on Grafanas usability, performance, and security. Read on to learn about Alerting enhancements like a WeCom contact point, improved Alert panel and custom mute timings, as well as visualization improvements and details to help you share playlists more easily. In Grafana Enterprise, weve made caching more powerful to save you time and money while loading dashboards, boosted database encryption to keep secrets safe in your Grafana database, and made usability improvements to Recorded Queries, which allow you to track any data point over time. Were excited to announce Grafana v8.4, with a variety of improvements that focus on Grafanas usability, performance, and security. Read on to learn about Alerting enhancements like a WeCom contact point, improved Alert panel and custom mute timings, as well as visualization improvements and details to help you share playlists more easily. In Grafana Enterprise, weve made caching more powerful to save you time and money while loading dashboards, boosted database encryption to keep secrets safe in your Grafana database, and made usability improvements to Recorded Queries, which allow you to track any data point over time.

View File

@ -15,7 +15,7 @@ title: What's new in Grafana v8.5
weight: -33 weight: -33
--- ---
# Whats new in Grafana v8.5 # What's new in Grafana v8.5
Were excited to announce Grafana v8.5, with a variety of improvements that focus on Grafanas usability, performance, and security. Were excited to announce Grafana v8.5, with a variety of improvements that focus on Grafanas usability, performance, and security.

View File

@ -15,7 +15,7 @@ title: What's new in Grafana v9.0
weight: -33 weight: -33
--- ---
# Whats new in Grafana v9.0 # What's new in Grafana v9.0
As tradition goes, GrafanaCon — our yearly community event for Grafana open source users — is also where we launch the latest software release of Grafana. Keeping up with tradition, we are excited to be announcing Grafana v9.0: a release that elevates Grafanas ease of use, discovery of data through new and improved visualizations and a default Grafana Alerting experience. As tradition goes, GrafanaCon — our yearly community event for Grafana open source users — is also where we launch the latest software release of Grafana. Keeping up with tradition, we are excited to be announcing Grafana v9.0: a release that elevates Grafanas ease of use, discovery of data through new and improved visualizations and a default Grafana Alerting experience.

20
go.mod
View File

@ -34,6 +34,7 @@ require (
github.com/fatih/color v1.13.0 github.com/fatih/color v1.13.0
github.com/gchaincl/sqlhooks v1.3.0 github.com/gchaincl/sqlhooks v1.3.0
github.com/getsentry/sentry-go v0.13.0 github.com/getsentry/sentry-go v0.13.0
github.com/go-git/go-git/v5 v5.4.2
github.com/go-kit/kit v0.11.0 github.com/go-kit/kit v0.11.0
github.com/go-openapi/strfmt v0.20.2 github.com/go-openapi/strfmt v0.20.2
github.com/go-redis/redis/v8 v8.11.4 github.com/go-redis/redis/v8 v8.11.4
@ -41,7 +42,7 @@ require (
github.com/go-sql-driver/mysql v1.6.0 github.com/go-sql-driver/mysql v1.6.0
github.com/go-stack/stack v1.8.0 github.com/go-stack/stack v1.8.0
github.com/gobwas/glob v0.2.3 github.com/gobwas/glob v0.2.3
github.com/gofrs/uuid v4.0.0+incompatible github.com/gofrs/uuid v4.0.0+incompatible // indirect
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
github.com/golang/mock v1.6.0 github.com/golang/mock v1.6.0
github.com/golang/snappy v0.0.4 github.com/golang/snappy v0.0.4
@ -213,7 +214,7 @@ require (
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
github.com/segmentio/encoding v0.3.2 github.com/segmentio/encoding v0.3.2
github.com/sercand/kuberesolver v2.4.0+incompatible // indirect github.com/sercand/kuberesolver v2.4.0+incompatible // indirect
github.com/sergi/go-diff v1.0.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect github.com/sirupsen/logrus v1.8.1 // indirect
@ -240,8 +241,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.4.0 github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.4.0
github.com/Azure/go-autorest/autorest/adal v0.9.17 github.com/Azure/go-autorest/autorest/adal v0.9.17
github.com/armon/go-radix v1.0.0 github.com/armon/go-radix v1.0.0
github.com/blugelabs/bluge v0.2.1 github.com/blugelabs/bluge v0.1.9
github.com/blugelabs/bluge_segment_api v0.2.0
github.com/getkin/kin-openapi v0.94.0 github.com/getkin/kin-openapi v0.94.0
github.com/golang-migrate/migrate/v4 v4.7.0 github.com/golang-migrate/migrate/v4 v4.7.0
github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f
@ -256,6 +256,7 @@ require (
require ( require (
cloud.google.com/go v0.100.2 // indirect cloud.google.com/go v0.100.2 // indirect
github.com/armon/go-metrics v0.3.10 // indirect github.com/armon/go-metrics v0.3.10 // indirect
github.com/blugelabs/bluge_segment_api v0.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/google/gofuzz v1.2.0 // indirect github.com/google/gofuzz v1.2.0 // indirect
github.com/gosimple/unidecode v1.0.1 // indirect github.com/gosimple/unidecode v1.0.1 // indirect
@ -273,7 +274,9 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.2.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.2.1 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 // indirect
github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
github.com/RoaringBitmap/roaring v0.9.4 // indirect github.com/RoaringBitmap/roaring v0.9.4 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f // indirect github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f // indirect
github.com/bits-and-blooms/bitset v1.2.0 // indirect github.com/bits-and-blooms/bitset v1.2.0 // indirect
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
@ -282,24 +285,29 @@ require (
github.com/blevesearch/snowballstem v0.9.0 // indirect github.com/blevesearch/snowballstem v0.9.0 // indirect
github.com/blevesearch/vellum v1.0.7 // indirect github.com/blevesearch/vellum v1.0.7 // indirect
github.com/blugelabs/ice v1.0.0 // indirect github.com/blugelabs/ice v1.0.0 // indirect
github.com/blugelabs/ice/v2 v2.0.1 // indirect
github.com/caio/go-tdigest v3.1.0+incompatible // indirect github.com/caio/go-tdigest v3.1.0+incompatible // indirect
github.com/chromedp/cdproto v0.0.0-20220208224320-6efb837e6bc2 // indirect github.com/chromedp/cdproto v0.0.0-20220208224320-6efb837e6bc2 // indirect
github.com/containerd/containerd v1.6.6 // indirect github.com/containerd/containerd v1.6.6 // indirect
github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc // indirect github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc // indirect
github.com/elazarl/goproxy v0.0.0-20220115173737-adb46da277ac // indirect github.com/elazarl/goproxy v0.0.0-20220115173737-adb46da277ac // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 // indirect github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.3.1 // indirect
github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect github.com/imdario/mergo v0.3.12 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/klauspost/compress v1.15.2 // indirect github.com/klauspost/compress v1.15.2 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labstack/echo/v4 v4.7.2 // indirect github.com/labstack/echo/v4 v4.7.2 // indirect
github.com/labstack/gommon v0.3.1 // indirect github.com/labstack/gommon v0.3.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mschoch/smat v0.2.0 // indirect github.com/mschoch/smat v0.2.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
@ -308,11 +316,13 @@ require (
github.com/smartystreets/goconvey v1.7.2 // indirect github.com/smartystreets/goconvey v1.7.2 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect github.com/valyala/fasttemplate v1.2.1 // indirect
github.com/wk8/go-ordered-map v1.0.0 github.com/wk8/go-ordered-map v1.0.0
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xlab/treeprint v1.1.0 // indirect github.com/xlab/treeprint v1.1.0 // indirect
github.com/yudai/pp v2.0.1+incompatible // indirect github.com/yudai/pp v2.0.1+incompatible // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.6.3 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.6.3 // indirect
go.opentelemetry.io/proto/otlp v0.15.0 // indirect go.opentelemetry.io/proto/otlp v0.15.0 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
k8s.io/api v0.22.5 // indirect k8s.io/api v0.22.5 // indirect
k8s.io/apimachinery v0.22.5 // indirect k8s.io/apimachinery v0.22.5 // indirect
k8s.io/klog/v2 v2.30.0 // indirect k8s.io/klog/v2 v2.30.0 // indirect

43
go.sum
View File

@ -254,6 +254,8 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/OneOfOne/xxhash v1.2.6/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/OneOfOne/xxhash v1.2.6/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
@ -275,6 +277,8 @@ github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrU
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f h1:HR5nRmUQgXrwqZOwZ2DAc/aCi3Bu3xENpspW935vxu0= github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f h1:HR5nRmUQgXrwqZOwZ2DAc/aCi3Bu3xENpspW935vxu0=
github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f/go.mod h1:f3HiCrHjHBdcm6E83vGaXh1KomZMA2P6aeo3hKx/wg0= github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f/go.mod h1:f3HiCrHjHBdcm6E83vGaXh1KomZMA2P6aeo3hKx/wg0=
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
@ -294,6 +298,8 @@ github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible/go.mod h1:T/Aws4fEfogEE9
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM=
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antonmedv/expr v1.8.9/go.mod h1:5qsM3oLGDND7sDmQGDXHkYfkjYMUX14qsgqmHhwGEk8= github.com/antonmedv/expr v1.8.9/go.mod h1:5qsM3oLGDND7sDmQGDXHkYfkjYMUX14qsgqmHhwGEk8=
@ -316,6 +322,7 @@ github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
@ -435,14 +442,13 @@ github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulN
github.com/blevesearch/vellum v1.0.5/go.mod h1:atE0EH3fvk43zzS7t1YNdNC7DbmcC3uz+eMD5xZ2OyQ= github.com/blevesearch/vellum v1.0.5/go.mod h1:atE0EH3fvk43zzS7t1YNdNC7DbmcC3uz+eMD5xZ2OyQ=
github.com/blevesearch/vellum v1.0.7 h1:+vn8rfyCRHxKVRgDLeR0FAXej2+6mEb5Q15aQE/XESQ= github.com/blevesearch/vellum v1.0.7 h1:+vn8rfyCRHxKVRgDLeR0FAXej2+6mEb5Q15aQE/XESQ=
github.com/blevesearch/vellum v1.0.7/go.mod h1:doBZpmRhwTsASB4QdUZANlJvqVAUdUyX0ZK7QJCTeBE= github.com/blevesearch/vellum v1.0.7/go.mod h1:doBZpmRhwTsASB4QdUZANlJvqVAUdUyX0ZK7QJCTeBE=
github.com/blugelabs/bluge v0.2.1 h1:lgd6IhAAIDoq6my9HQOwk3p6xqJBmR49+lpFmpeFHgU= github.com/blugelabs/bluge v0.1.9 h1:bPgXlcsWugrXNjzeoLdOnvfJpHsyODKpYaAndayl/SM=
github.com/blugelabs/bluge v0.2.1/go.mod h1:am1LU9jS8dZgWkRzkGLQN3757EgMs3upWrU2fdN9foE= github.com/blugelabs/bluge v0.1.9/go.mod h1:5d7LktUkQgvbh5Bmi6tPWtvo4+6uRTm6gAwP+5z6FqQ=
github.com/blugelabs/bluge_segment_api v0.2.0 h1:cCX1Y2y8v0LZ7+EEJ6gH7dW6TtVTW4RhG0vp3R+N2Lo= github.com/blugelabs/bluge_segment_api v0.2.0 h1:cCX1Y2y8v0LZ7+EEJ6gH7dW6TtVTW4RhG0vp3R+N2Lo=
github.com/blugelabs/bluge_segment_api v0.2.0/go.mod h1:95XA+ZXfRj/IXADm7gZ+iTcWOJPg5jQTY1EReIzl3LA= github.com/blugelabs/bluge_segment_api v0.2.0/go.mod h1:95XA+ZXfRj/IXADm7gZ+iTcWOJPg5jQTY1EReIzl3LA=
github.com/blugelabs/ice v0.2.0/go.mod h1:7foiDf4V83FIYYnGh2LOoRWsbNoCqAAMNgKn879Iyu0=
github.com/blugelabs/ice v1.0.0 h1:um7wf9e6jbkTVCrOyQq3tKK43fBMOvLUYxbj3Qtc4eo= github.com/blugelabs/ice v1.0.0 h1:um7wf9e6jbkTVCrOyQq3tKK43fBMOvLUYxbj3Qtc4eo=
github.com/blugelabs/ice v1.0.0/go.mod h1:gNfFPk5zM+yxJROhthxhVQYjpBO9amuxWXJQ2Lo+IbQ= github.com/blugelabs/ice v1.0.0/go.mod h1:gNfFPk5zM+yxJROhthxhVQYjpBO9amuxWXJQ2Lo+IbQ=
github.com/blugelabs/ice/v2 v2.0.1 h1:mzHbntLjk2v7eDRgoXCgzOsPKN1Tenu9Svo6l9cTLS4=
github.com/blugelabs/ice/v2 v2.0.1/go.mod h1:QxAWSPNwZwsIqS25c3lbIPFQrVvT1sphf5x5DfMLH5M=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
@ -784,6 +790,8 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT
github.com/emicklei/proto v1.6.15/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= github.com/emicklei/proto v1.6.15/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A=
github.com/emicklei/proto v1.10.0 h1:pDGyFRVV5RvV+nkBK9iy3q67FBy9Xa7vwrOTE+g5aGw= github.com/emicklei/proto v1.10.0 h1:pDGyFRVV5RvV+nkBK9iy3q67FBy9Xa7vwrOTE+g5aGw=
github.com/emicklei/proto v1.10.0/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= github.com/emicklei/proto v1.10.0/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -817,6 +825,7 @@ github.com/felixge/fgprof v0.9.1/go.mod h1:7/HK6JFtFaARhIljgP2IV8rJLIoHDoOYoUphs
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
@ -852,6 +861,8 @@ github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ER
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= 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= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
@ -864,6 +875,15 @@ github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0
github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -1558,6 +1578,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jaegertracing/jaeger v1.24.0/go.mod h1:mqdtFDA447va5j0UewDaAWyNlGreGQyhGxXVhbF58gQ= github.com/jaegertracing/jaeger v1.24.0/go.mod h1:mqdtFDA447va5j0UewDaAWyNlGreGQyhGxXVhbF58gQ=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
@ -1619,6 +1641,8 @@ github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@ -1730,6 +1754,7 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
@ -2227,8 +2252,9 @@ github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfP
github.com/sercand/kuberesolver v2.1.0+incompatible/go.mod h1:lWF3GL0xptCB/vCiJPl/ZshwPsX/n4Y7u0CW9E7aQIQ= github.com/sercand/kuberesolver v2.1.0+incompatible/go.mod h1:lWF3GL0xptCB/vCiJPl/ZshwPsX/n4Y7u0CW9E7aQIQ=
github.com/sercand/kuberesolver v2.4.0+incompatible h1:WE2OlRf6wjLxHwNkkFLQGaZcVLEXjMjBPjjEU5vksH8= github.com/sercand/kuberesolver v2.4.0+incompatible h1:WE2OlRf6wjLxHwNkkFLQGaZcVLEXjMjBPjjEU5vksH8=
github.com/sercand/kuberesolver v2.4.0+incompatible/go.mod h1:lWF3GL0xptCB/vCiJPl/ZshwPsX/n4Y7u0CW9E7aQIQ= github.com/sercand/kuberesolver v2.4.0+incompatible/go.mod h1:lWF3GL0xptCB/vCiJPl/ZshwPsX/n4Y7u0CW9E7aQIQ=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v3.21.6+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.6+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
@ -2427,6 +2453,8 @@ github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr
github.com/wk8/go-ordered-map v1.0.0 h1:BV7z+2PaK8LTSd/mWgY12HyMAo5CEgkHqbkVq2thqr8= github.com/wk8/go-ordered-map v1.0.0 h1:BV7z+2PaK8LTSd/mWgY12HyMAo5CEgkHqbkVq2thqr8=
github.com/wk8/go-ordered-map v1.0.0/go.mod h1:9ZIbRunKbuvfPKyBP1SIKLcXNlv74YCOZ3t3VTS6gRk= github.com/wk8/go-ordered-map v1.0.0/go.mod h1:9ZIbRunKbuvfPKyBP1SIKLcXNlv74YCOZ3t3VTS6gRk=
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
@ -2610,6 +2638,7 @@ golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -2645,6 +2674,7 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/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-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@ -2786,6 +2816,7 @@ golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210324051636-2c4c8ecb7826/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210324051636-2c4c8ecb7826/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
@ -2985,6 +3016,7 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -3460,6 +3492,7 @@ gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -217,7 +217,6 @@
"mutationobserver-shim": "0.3.7", "mutationobserver-shim": "0.3.7",
"ngtemplate-loader": "2.1.0", "ngtemplate-loader": "2.1.0",
"node-notifier": "10.0.1", "node-notifier": "10.0.1",
"nodemon": "2.0.16",
"postcss": "8.4.14", "postcss": "8.4.14",
"postcss-loader": "7.0.0", "postcss-loader": "7.0.0",
"postcss-reporter": "7.0.5", "postcss-reporter": "7.0.5",
@ -259,7 +258,7 @@
"@grafana/e2e-selectors": "workspace:*", "@grafana/e2e-selectors": "workspace:*",
"@grafana/experimental": "^0.0.2-canary.32", "@grafana/experimental": "^0.0.2-canary.32",
"@grafana/google-sdk": "0.0.3", "@grafana/google-sdk": "0.0.3",
"@grafana/lezer-logql": "^0.0.12", "@grafana/lezer-logql": "^0.0.13",
"@grafana/runtime": "workspace:*", "@grafana/runtime": "workspace:*",
"@grafana/schema": "workspace:*", "@grafana/schema": "workspace:*",
"@grafana/slate-react": "0.22.10-grafana", "@grafana/slate-react": "0.22.10-grafana",
@ -354,6 +353,7 @@
"rc-time-picker": "3.7.3", "rc-time-picker": "3.7.3",
"re-resizable": "6.9.9", "re-resizable": "6.9.9",
"react": "17.0.2", "react": "17.0.2",
"react-awesome-query-builder": "^5.1.2",
"react-beautiful-dnd": "13.1.0", "react-beautiful-dnd": "13.1.0",
"react-diff-viewer": "^3.1.1", "react-diff-viewer": "^3.1.1",
"react-dom": "17.0.2", "react-dom": "17.0.2",
@ -385,7 +385,6 @@
"rst2html": "github:thoward/rst2html#990cb89f2a300cdd9151790be377c4c0840df809", "rst2html": "github:thoward/rst2html#990cb89f2a300cdd9151790be377c4c0840df809",
"rxjs": "7.5.5", "rxjs": "7.5.5",
"sass": "link:./public/sass", "sass": "link:./public/sass",
"search-query-parser": "1.6.0",
"selecto": "1.16.2", "selecto": "1.16.2",
"semver": "7.3.7", "semver": "7.3.7",
"slate": "0.47.8", "slate": "0.47.8",
@ -404,10 +403,10 @@
"resolutions": { "resolutions": {
"underscore": "1.13.3", "underscore": "1.13.3",
"@types/slate": "0.47.2", "@types/slate": "0.47.2",
"@microsoft/api-extractor-model": "7.20.3", "@microsoft/api-extractor-model": "7.21.0",
"@rushstack/node-core-library": "3.49.0", "@rushstack/node-core-library": "3.49.0",
"@rushstack/rig-package": "0.3.11", "@rushstack/rig-package": "0.3.11",
"@rushstack/ts-command-line": "4.11.0", "@rushstack/ts-command-line": "4.12.1",
"@storybook/react/webpack": "5.73.0", "@storybook/react/webpack": "5.73.0",
"node-fetch": "2.6.7" "node-fetch": "2.6.7"
}, },

View File

@ -160,13 +160,13 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform
for (const frame of frames) { for (const frame of frames) {
for (const field of frame.fields) { for (const field of frame.fields) {
if (field.type === FieldType.number) { if (field.type === FieldType.number) {
allValues = allValues.concat( allValues = allValues.concat(field.values.toArray());
field.values.toArray().map((val: number) => Number(val.toFixed(field.config.decimals ?? 0)))
);
} }
} }
} }
allValues = allValues.filter((v) => v != null);
allValues.sort((a, b) => a - b); allValues.sort((a, b) => a - b);
let smallestDelta = Infinity; let smallestDelta = Infinity;
@ -204,6 +204,9 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform
const getBucket = (v: number) => incrRoundDn(v - bucketOffset, bucketSize!) + bucketOffset; const getBucket = (v: number) => incrRoundDn(v - bucketOffset, bucketSize!) + bucketOffset;
// guess number of decimals
let bucketDecimals = (('' + bucketSize).match(/\.\d+$/) ?? ['.'])[0].length - 1;
let histograms: AlignedData[] = []; let histograms: AlignedData[] = [];
let counts: Field[] = []; let counts: Field[] = [];
let config: FieldConfig | undefined = undefined; let config: FieldConfig | undefined = undefined;
@ -220,7 +223,7 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform
unit: undefined, unit: undefined,
}, },
}); });
if (!config && Object.keys(field.config).length) { if (!config && field.config.unit) {
config = field.config; config = field.config;
} }
} }
@ -251,7 +254,13 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform
values: new ArrayVector(joinedHists[0]), values: new ArrayVector(joinedHists[0]),
type: FieldType.number, type: FieldType.number,
state: undefined, state: undefined,
config: config ?? {}, config:
bucketDecimals === 0
? config ?? {}
: {
...config,
decimals: bucketDecimals,
},
}; };
const bucketMax = { const bucketMax = {
...bucketMin, ...bucketMin,

View File

@ -483,7 +483,6 @@ export interface DataQueryRequest<TQuery extends DataQuery = DataQuery> {
timeInfo?: string; // The query time description (blue text in the upper right) timeInfo?: string; // The query time description (blue text in the upper right)
panelId?: number; panelId?: number;
dashboardId?: number; dashboardId?: number;
// Temporary prop for public dashboards, to be replaced by publicAccessKey
publicDashboardAccessToken?: string; publicDashboardAccessToken?: string;
// Request Timing // Request Timing

View File

@ -56,6 +56,7 @@ export interface FeatureToggles {
autoMigrateGraphPanels?: boolean; autoMigrateGraphPanels?: boolean;
prometheusWideSeries?: boolean; prometheusWideSeries?: boolean;
canvasPanelNesting?: boolean; canvasPanelNesting?: boolean;
scenes?: boolean;
useLegacyHeatmapPanel?: boolean; useLegacyHeatmapPanel?: boolean;
cloudMonitoringExperimentalUI?: boolean; cloudMonitoringExperimentalUI?: boolean;
logRequestsInstrumentedAsUnknown?: boolean; logRequestsInstrumentedAsUnknown?: boolean;

View File

@ -56,10 +56,6 @@ export interface NavModel {
* This is the current active tab/navigation. * This is the current active tab/navigation.
*/ */
node: NavModelItem; node: NavModelItem;
/**
* Describes breadcrumbs that are used in places such as data source settings., folder page and plugins page.
*/
breadcrumbs?: NavModelItem[];
} }
export interface NavModelBreadcrumb { export interface NavModelBreadcrumb {

View File

@ -11,7 +11,7 @@ import { AbsoluteTimeRange, FieldConfigSource, PanelData } from '@grafana/data';
* @internal * @internal
*/ */
export interface PanelRendererProps<P extends object = any, F extends object = any> { export interface PanelRendererProps<P extends object = any, F extends object = any> {
data: PanelData; data?: PanelData;
pluginId: string; pluginId: string;
title: string; title: string;
options?: Partial<P>; options?: Partial<P>;

View File

@ -143,17 +143,17 @@ export function isFetchError(e: unknown): e is FetchError {
* @public * @public
*/ */
export interface BackendSrv { export interface BackendSrv {
get(url: string, params?: any, requestId?: string): Promise<any>; get<T = any>(url: string, params?: any, requestId?: string): Promise<T>;
delete(url: string, data?: any): Promise<any>; delete<T = any>(url: string, data?: any): Promise<T>;
post(url: string, data?: any): Promise<any>; post<T = any>(url: string, data?: any): Promise<T>;
patch(url: string, data?: any): Promise<any>; patch<T = any>(url: string, data?: any): Promise<T>;
put(url: string, data?: any): Promise<any>; put<T = any>(url: string, data?: any): Promise<T>;
/** /**
* @deprecated Use the fetch function instead. If you prefer to work with a promise * @deprecated Use the fetch function instead. If you prefer to work with a promise
* wrap the Observable returned by fetch with the lastValueFrom function. * wrap the Observable returned by fetch with the lastValueFrom function.
*/ */
request(options: BackendSrvRequest): Promise<any>; request<T = any>(options: BackendSrvRequest): Promise<T>;
/** /**
* Special function used to communicate with datasources that will emit core * Special function used to communicate with datasources that will emit core

View File

@ -1,9 +1,14 @@
import { of } from 'rxjs'; import { of } from 'rxjs';
import { BackendSrv, BackendSrvRequest } from 'src/services'; import { BackendSrv, BackendSrvRequest } from 'src/services';
import { DataQueryRequest, DataSourceRef } from '@grafana/data'; import { DataQueryRequest, DataSourceInstanceSettings, DataSourceRef } from '@grafana/data';
import { PublicDashboardDataSource } from '../../../../public/app/features/dashboard/services/PublicDashboardDataSource'; import {
PUBLIC_DATASOURCE,
PublicDashboardDataSource,
} from '../../../../public/app/features/dashboard/services/PublicDashboardDataSource';
import { DataSourceWithBackend } from './DataSourceWithBackend';
const mockDatasourceRequest = jest.fn(); const mockDatasourceRequest = jest.fn();
@ -28,7 +33,7 @@ describe('PublicDashboardDatasource', () => {
mockDatasourceRequest.mockReset(); mockDatasourceRequest.mockReset();
mockDatasourceRequest.mockReturnValue(Promise.resolve({})); mockDatasourceRequest.mockReturnValue(Promise.resolve({}));
const ds = new PublicDashboardDataSource(); const ds = new PublicDashboardDataSource('public');
const panelId = 1; const panelId = 1;
const publicDashboardAccessToken = 'abc123'; const publicDashboardAccessToken = 'abc123';
@ -47,4 +52,27 @@ describe('PublicDashboardDatasource', () => {
`/api/public/dashboards/${publicDashboardAccessToken}/panels/${panelId}/query` `/api/public/dashboards/${publicDashboardAccessToken}/panels/${panelId}/query`
); );
}); });
test('returns public datasource uid when datasource passed in is null', () => {
let ds = new PublicDashboardDataSource(null);
expect(ds.uid).toBe(PUBLIC_DATASOURCE);
});
test('returns datasource when datasource passed in is a string', () => {
let ds = new PublicDashboardDataSource('theDatasourceUid');
expect(ds.uid).toBe('theDatasourceUid');
});
test('returns datasource uid when datasource passed in is a DataSourceRef implementation', () => {
const datasource = { type: 'datasource', uid: 'abc123' };
let ds = new PublicDashboardDataSource(datasource);
expect(ds.uid).toBe('abc123');
});
test('returns datasource uid when datasource passed in is a DatasourceApi instance', () => {
const settings: DataSourceInstanceSettings = { id: 1, uid: 'abc123' } as DataSourceInstanceSettings;
const datasource = new DataSourceWithBackend(settings);
let ds = new PublicDashboardDataSource(datasource);
expect(ds.uid).toBe('abc123');
});
}); });

View File

@ -41,7 +41,7 @@ chmod 755 /usr/local/bin/golangci-lint
# Install code climate # Install code climate
get_file "https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64" \ get_file "https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64" \
"/usr/local/bin/cc-test-reporter" \ "/usr/local/bin/cc-test-reporter" \
"9fbe34cd207924d8f51ac0f3ffa690df4169e055cd7134a2370f6650f5b356e1" "9e6c3e628b1258aefbc6e3550438a691abb0d1924d63c038881031d3d343c7d0"
chmod 755 /usr/local/bin/cc-test-reporter chmod 755 /usr/local/bin/cc-test-reporter
wget -O /usr/local/bin/grabpl "https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.27/grabpl" wget -O /usr/local/bin/grabpl "https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.27/grabpl"

View File

@ -9,6 +9,7 @@ import { IconName } from '../../types/icon';
import { ComponentSize } from '../../types/size'; import { ComponentSize } from '../../types/size';
import { getPropertiesForButtonSize } from '../Forms/commonStyles'; import { getPropertiesForButtonSize } from '../Forms/commonStyles';
import { Icon } from '../Icon/Icon'; import { Icon } from '../Icon/Icon';
import { PopoverContent, Tooltip, TooltipPlacement } from '../Tooltip';
export type ButtonVariant = 'primary' | 'secondary' | 'destructive'; export type ButtonVariant = 'primary' | 'secondary' | 'destructive';
export const allButtonVariants: ButtonVariant[] = ['primary', 'secondary', 'destructive']; export const allButtonVariants: ButtonVariant[] = ['primary', 'secondary', 'destructive'];
@ -24,6 +25,10 @@ type CommonProps = {
children?: React.ReactNode; children?: React.ReactNode;
fullWidth?: boolean; fullWidth?: boolean;
type?: string; type?: string;
/** Tooltip content to display on hover */
tooltip?: PopoverContent;
/** Position of the tooltip */
tooltipPlacement?: TooltipPlacement;
}; };
export type ButtonProps = CommonProps & ButtonHTMLAttributes<HTMLButtonElement>; export type ButtonProps = CommonProps & ButtonHTMLAttributes<HTMLButtonElement>;
@ -79,6 +84,8 @@ export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
onBlur, onBlur,
onFocus, onFocus,
disabled, disabled,
tooltip,
tooltipPlacement,
...otherProps ...otherProps
}, },
ref ref
@ -103,12 +110,22 @@ export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
className className
); );
return ( const button = (
<a className={linkButtonStyles} {...otherProps} tabIndex={disabled ? -1 : 0} ref={ref}> <a className={linkButtonStyles} {...otherProps} tabIndex={disabled ? -1 : 0} ref={ref}>
{icon && <Icon name={icon} size={size} className={styles.icon} />} {icon && <Icon name={icon} size={size} className={styles.icon} />}
{children && <span className={styles.content}>{children}</span>} {children && <span className={styles.content}>{children}</span>}
</a> </a>
); );
if (tooltip) {
return (
<Tooltip content={tooltip} placement={tooltipPlacement}>
{button}
</Tooltip>
);
}
return button;
} }
); );

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React from 'react'; import React, { CSSProperties } from 'react';
import { LinkModel } from '@grafana/data'; import { LinkModel } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
@ -12,6 +12,7 @@ import { MenuItem } from '../Menu/MenuItem';
interface DataLinksContextMenuProps { interface DataLinksContextMenuProps {
children: (props: DataLinksContextMenuApi) => JSX.Element; children: (props: DataLinksContextMenuApi) => JSX.Element;
links: () => LinkModel[]; links: () => LinkModel[];
style?: CSSProperties;
} }
export interface DataLinksContextMenuApi { export interface DataLinksContextMenuApi {
@ -19,7 +20,7 @@ export interface DataLinksContextMenuApi {
targetClassName?: string; targetClassName?: string;
} }
export const DataLinksContextMenu: React.FC<DataLinksContextMenuProps> = ({ children, links }) => { export const DataLinksContextMenu: React.FC<DataLinksContextMenuProps> = ({ children, links, style }) => {
const itemsGroup: MenuItemsGroup[] = [{ items: linkModelToContextMenuItems(links), label: 'Data links' }]; const itemsGroup: MenuItemsGroup[] = [{ items: linkModelToContextMenuItems(links), label: 'Data links' }];
const linksCounter = itemsGroup[0].items.length; const linksCounter = itemsGroup[0].items.length;
const renderMenuGroupItems = () => { const renderMenuGroupItems = () => {
@ -61,7 +62,7 @@ export const DataLinksContextMenu: React.FC<DataLinksContextMenuProps> = ({ chil
onClick={linkModel.onClick} onClick={linkModel.onClick}
target={linkModel.target} target={linkModel.target}
title={linkModel.title} title={linkModel.title}
style={{ display: 'flex', width: '100%' }} style={style}
aria-label={selectors.components.DataLinksContextMenu.singleLink} aria-label={selectors.components.DataLinksContextMenu.singleLink}
> >
{children({})} {children({})}

View File

@ -118,7 +118,7 @@ export function UnthemedTimeRangePicker(props: TimeRangePickerProps): ReactEleme
</ToolbarButton> </ToolbarButton>
</Tooltip> </Tooltip>
{isOpen && ( {isOpen && (
<FocusScope contain autoFocus restoreFocus> <FocusScope contain autoFocus>
<section ref={ref} {...overlayProps} {...dialogProps}> <section ref={ref} {...overlayProps} {...dialogProps}>
<TimePickerContent <TimePickerContent
timeZone={timeZone} timeZone={timeZone}

View File

@ -0,0 +1,43 @@
import { Meta, Preview, Props } from '@storybook/addon-docs/blocks';
import { PluginSignatureBadge } from './PluginSignatureBadge';
<Meta title="MDX|PluginSignatureBadge" component={PluginSignatureBadge} />
# Plugin Signature Badge
The Plugin Signature Badge can be found in each information plugin card of the configuration plugins panel (Grafana menu > Configuration > Plugins).
This is a security measure to make sure plugins haven't been tampered with. Upon loading, Grafana checks to see the plugin signature status.
## Badges:
1.- Core: this badge indicates that the plugin has been built into Grafana.
<Preview>
<PluginSignatureBadge status="internal" />
</Preview>
2.- Signed: the plugin's signature was successfully verified.
<Preview>
<PluginSignatureBadge status="valid" />
</Preview>
3.- Invalid signature: this plugin has a invalid signature.
<Preview>
<PluginSignatureBadge status="invalid" />
</Preview>
4.- Modified signature: this plugin has changed since it was signed. This may indicate malicious intent.
<Preview>
<PluginSignatureBadge status="modified" />
</Preview>
5.- Unsigned: the plugin is not signed. In this case, as upon loading Grafana checks the plugins signature, Grafana will not load or start it. Furthermore, it will write an error message to the server log.
<Preview>
<PluginSignatureBadge status="unsigned" />
</Preview>
<Props of={PluginSignatureBadge} />

View File

@ -6,6 +6,8 @@ import { PluginSignatureBadge } from '@grafana/ui';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import mdx from './PluginSignatureBadge.mdx';
export default { export default {
title: 'Data Display/PluginSignatureBadge', title: 'Data Display/PluginSignatureBadge',
decorators: [withCenteredStory], decorators: [withCenteredStory],
@ -24,6 +26,11 @@ export default {
], ],
}, },
}, },
parameters: {
docs: {
page: mdx,
},
},
}; };
export const Basic: Story = (args) => { export const Basic: Story = (args) => {

View File

@ -0,0 +1,28 @@
import { Props } from '@storybook/addon-docs/blocks';
import { SecretInput } from './SecretInput';
# Secret Input
Used for secret/password input. It has 2 states: **_configured_** and **_not configured_**.
- If configured it will disable the input and add a reset button that will
clear the input and make it accessible.
- In non configured state it behaves like a normal password input.
This is used for passwords or anything that is encrypted on the server and is
later returned encrypted to the user (like datasource passwords).
### Usage
```tsx
import {SecretInput} from '@grafana/ui';
<SecretInput
value={...}
isConfigured={...}
onChange={...}
onReset={...}
/>
```
<Props of={SecretInput} />

View File

@ -4,12 +4,16 @@ import React, { useState, ChangeEvent } from 'react';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { SecretInput, Props } from './SecretInput'; import { SecretInput, Props } from './SecretInput';
import mdx from './SecretInput.mdx';
export default { const meta: Meta = {
title: 'Forms/SecretInput', title: 'Forms/SecretInput',
component: SecretInput, component: SecretInput,
decorators: [withCenteredStory], decorators: [withCenteredStory],
parameters: { parameters: {
docs: {
page: mdx,
},
controls: { controls: {
exclude: [ exclude: [
'prefix', 'prefix',
@ -32,7 +36,9 @@ export default {
argTypes: { argTypes: {
width: { control: { type: 'range', min: 10, max: 200, step: 10 } }, width: { control: { type: 'range', min: 10, max: 200, step: 10 } },
}, },
} as Meta; };
export default meta;
const Template: Story<Props> = (args) => { const Template: Story<Props> = (args) => {
const [secret, setSecret] = useState(''); const [secret, setSecret] = useState('');

View File

@ -50,7 +50,7 @@ export const BarGaugeCell: FC<TableCellProps> = (props) => {
return field.getLinks({ valueRowIndex: row.index }); return field.getLinks({ valueRowIndex: row.index });
}; };
const hasLinks = !!getLinks().length; const hasLinks = Boolean(getLinks().length);
const renderComponent = (menuProps: DataLinksContextMenuApi) => { const renderComponent = (menuProps: DataLinksContextMenuApi) => {
const { openMenu, targetClassName } = menuProps; const { openMenu, targetClassName } = menuProps;
@ -76,7 +76,11 @@ export const BarGaugeCell: FC<TableCellProps> = (props) => {
return ( return (
<div {...cellProps} className={tableStyles.cellContainer}> <div {...cellProps} className={tableStyles.cellContainer}>
{hasLinks && <DataLinksContextMenu links={getLinks}>{(api) => renderComponent(api)}</DataLinksContextMenu>} {hasLinks && (
<DataLinksContextMenu links={getLinks} style={{ display: 'flex', width: '100%' }}>
{(api) => renderComponent(api)}
</DataLinksContextMenu>
)}
{!hasLinks && ( {!hasLinks && (
<BarGauge <BarGauge
width={innerWidth} width={innerWidth}

View File

@ -11,7 +11,7 @@ export const ImageCell: FC<TableCellProps> = (props) => {
const displayValue = field.display!(cell.value); const displayValue = field.display!(cell.value);
const hasLinks = getCellLinks(field, row)?.length; const hasLinks = Boolean(getCellLinks(field, row)?.length);
return ( return (
<div {...cellProps} className={tableStyles.cellContainer}> <div {...cellProps} className={tableStyles.cellContainer}>

View File

@ -27,7 +27,7 @@ export function JSONViewCell(props: TableCellProps): JSX.Element {
displayValue = JSON.stringify(value, null, ' '); displayValue = JSON.stringify(value, null, ' ');
} }
const hasLinks = getCellLinks(field, row)?.length; const hasLinks = Boolean(getCellLinks(field, row)?.length);
return ( return (
<div {...cellProps} className={inspectEnabled ? tableStyles.cellContainerNoOverflow : tableStyles.cellContainer}> <div {...cellProps} className={inspectEnabled ? tableStyles.cellContainerNoOverflow : tableStyles.cellContainer}>

View File

@ -165,7 +165,6 @@ export const getTableStyles = (theme: GrafanaTheme2) => {
imageCellLink: css` imageCellLink: css`
cursor: pointer; cursor: pointer;
overflow: hidden; overflow: hidden;
width: 100%;
height: 100%; height: 100%;
`, `,
headerFilter: css` headerFilter: css`

View File

@ -0,0 +1,96 @@
import { css, cx } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { useStyles2 } from '../../themes/ThemeContext';
import { Icon } from '../Icon/Icon';
import { Counter } from './Counter';
import { TabProps } from './Tab';
export const VerticalTab = React.forwardRef<HTMLAnchorElement, TabProps>(
({ label, active, icon, counter, className, suffix: Suffix, onChangeTab, href, ...otherProps }, ref) => {
const tabsStyles = useStyles2(getTabStyles);
const content = () => (
<>
{icon && <Icon name={icon} />}
{label}
{typeof counter === 'number' && <Counter value={counter} />}
{Suffix && <Suffix className={tabsStyles.suffix} />}
</>
);
const linkClass = cx(tabsStyles.link, active && tabsStyles.activeStyle);
return (
<li className={tabsStyles.item}>
<a
href={href}
className={linkClass}
{...otherProps}
onClick={onChangeTab}
aria-label={otherProps['aria-label'] || selectors.components.Tab.title(label)}
role="tab"
aria-selected={active}
ref={ref}
>
{content()}
</a>
</li>
);
}
);
VerticalTab.displayName = 'Tab';
const getTabStyles = (theme: GrafanaTheme2) => {
return {
item: css`
list-style: none;
margin-right: ${theme.spacing(2)};
position: relative;
display: block;
margin-bottom: 4px;
`,
link: css`
padding: 6px 12px;
display: block;
height: 100%;
cursor: pointer;
color: ${theme.colors.text.primary};
svg {
margin-right: ${theme.spacing(1)};
}
&:hover,
&:focus {
text-decoration: underline;
}
`,
activeStyle: css`
label: activeTabStyle;
color: ${theme.colors.text.maxContrast};
font-weight: 500;
overflow: hidden;
&::before {
display: block;
content: ' ';
position: absolute;
left: 0;
width: 4px;
bottom: 0;
top: 0;
border-radius: 2px;
background-image: linear-gradient(0deg, #f05a28 30%, #fbca0a 99%);
}
`,
suffix: css`
margin-left: ${theme.spacing(1)};
`,
};
};

View File

@ -1,6 +1,8 @@
import { Story, Preview, Props } from '@storybook/addon-docs/blocks'; import { Story, Preview, Props } from '@storybook/addon-docs/blocks';
import { Tag } from './Tag'; import { Tag } from './Tag';
<Meta title="MDX|Tag" component={Tag} />
# Tag # Tag
Used for displaying metadata, for example to add more details to search results. Background and border colors are generated from the tag name. Used for displaying metadata, for example to add more details to search results. Background and border colors are generated from the tag name.

View File

@ -1,10 +1,10 @@
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { Story } from '@storybook/react';
import React from 'react'; import React from 'react';
import { Tag } from '@grafana/ui';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { Props as TagProps, Tag } from './Tag';
import mdx from './Tag.mdx'; import mdx from './Tag.mdx';
export default { export default {
@ -15,9 +15,28 @@ export default {
docs: { docs: {
page: mdx, page: mdx,
}, },
controls: {
exclude: ['onClick'],
},
},
args: {
name: 'Tag',
colorIndex: 0,
showIcon: false,
}, },
}; };
export const single = () => { interface StoryProps extends TagProps {
return <Tag name="Tag" onClick={action('Tag clicked')} />; showIcon?: boolean;
}
export const Single: Story<StoryProps> = (args) => {
return (
<Tag
name={args.name}
colorIndex={args.colorIndex}
onClick={action('Tag clicked')}
icon={args.showIcon ? args.icon : undefined}
/>
);
}; };

View File

@ -64,13 +64,15 @@ const getTagStyles = (theme: GrafanaTheme, name: string, colorIndex?: number) =>
font-weight: ${theme.typography.weight.semibold}; font-weight: ${theme.typography.weight.semibold};
font-size: ${theme.typography.size.sm}; font-size: ${theme.typography.size.sm};
line-height: ${theme.typography.lineHeight.xs}; line-height: ${theme.typography.lineHeight.xs};
vertical-align: baseline;
background-color: ${colors.color}; background-color: ${colors.color};
color: ${theme.palette.gray98}; color: ${theme.palette.gray98};
white-space: nowrap; white-space: nowrap;
text-shadow: none; text-shadow: none;
padding: 3px 6px; padding: 3px 6px;
border-radius: ${theme.border.radius.md}; border-radius: ${theme.border.radius.md};
display: flex;
align-items: center;
gap: 3px;
`, `,
hover: css` hover: css`
&:hover { &:hover {

View File

@ -79,6 +79,7 @@ export { TableCellDisplayMode, TableSortByFieldState } from './Table/types';
export { TableInputCSV } from './TableInputCSV/TableInputCSV'; export { TableInputCSV } from './TableInputCSV/TableInputCSV';
export { TabsBar } from './Tabs/TabsBar'; export { TabsBar } from './Tabs/TabsBar';
export { Tab } from './Tabs/Tab'; export { Tab } from './Tabs/Tab';
export { VerticalTab } from './Tabs/VerticalTab';
export { TabContent } from './Tabs/TabContent'; export { TabContent } from './Tabs/TabContent';
export { Counter } from './Tabs/Counter'; export { Counter } from './Tabs/Counter';

View File

@ -16,6 +16,8 @@ import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event'; import userEvent from '@testing-library/user-event';
import React from 'react'; import React from 'react';
import { NONE, DURATION, TAG } from '../settings/SpanBarSettings';
import SpanBarRow from './SpanBarRow'; import SpanBarRow from './SpanBarRow';
describe('<SpanBarRow>', () => { describe('<SpanBarRow>', () => {
@ -43,11 +45,10 @@ describe('<SpanBarRow>', () => {
showErrorIcon: false, showErrorIcon: false,
getViewedBounds: () => ({ start: 0, end: 1 }), getViewedBounds: () => ({ start: 0, end: 1 }),
span: { span: {
duration: 'test-duration', duration: 9000,
hasChildren: true, hasChildren: true,
process: { process: {
serviceName: 'service-name', serviceName: 'service-name',
tags: [],
}, },
spanID, spanID,
logs: [], logs: [],
@ -181,4 +182,89 @@ describe('<SpanBarRow>', () => {
); );
expect(screen.getAllByTestId('SpanLinksMenu')).toHaveLength(1); expect(screen.getAllByTestId('SpanLinksMenu')).toHaveLength(1);
}); });
describe('render span bar label', () => {
it('with default value', () => {
render(<SpanBarRow {...props} />);
expect(screen.getByText('(9ms)')).toBeInTheDocument();
});
it('with none value', () => {
const testProps = Object.assign(
{
spanBarOptions: {
type: NONE,
},
},
props
);
render(<SpanBarRow {...testProps} />);
expect(screen.queryByText('(9ms)')).not.toBeInTheDocument();
});
it('with duration value', () => {
const testProps = Object.assign(
{
spanBarOptions: {
type: DURATION,
},
},
props
);
render(<SpanBarRow {...testProps} />);
expect(screen.getByText('(9ms)')).toBeInTheDocument();
});
it('with tag value', () => {
const testProps = Object.assign(
{
spanBarOptions: {
type: TAG,
tag: 'tag',
},
},
{
...props,
span: {
process: {},
tags: [
{
key: 'tag',
value: 'tag-value',
},
],
},
}
);
render(<SpanBarRow {...testProps} />);
expect(screen.getByText('(tag-value)')).toBeInTheDocument();
});
it('with process value', () => {
let testProps = Object.assign(
{
spanBarOptions: {
type: TAG,
tag: 'tag',
},
},
{
...props,
span: {
process: {
tags: [
{
key: 'tag',
value: 'process-value',
},
],
},
tags: [],
},
}
);
render(<SpanBarRow {...testProps} />);
expect(screen.getByText('(process-value)')).toBeInTheDocument();
});
});
}); });

View File

@ -18,11 +18,12 @@ import * as React from 'react';
import IoAlert from 'react-icons/lib/io/alert'; import IoAlert from 'react-icons/lib/io/alert';
import IoArrowRightA from 'react-icons/lib/io/arrow-right-a'; import IoArrowRightA from 'react-icons/lib/io/arrow-right-a';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2, TraceKeyValuePair } from '@grafana/data';
import { stylesFactory, withTheme2 } from '@grafana/ui'; import { stylesFactory, withTheme2 } from '@grafana/ui';
import { autoColor } from '../Theme'; import { autoColor } from '../Theme';
import { SpanLinkFunc, TNil } from '../types'; import { DURATION, NONE, TAG } from '../settings/SpanBarSettings';
import { SpanBarOptions, SpanLinkFunc, TNil } from '../types';
import { SpanLinks } from '../types/links'; import { SpanLinks } from '../types/links';
import { TraceSpan } from '../types/trace'; import { TraceSpan } from '../types/trace';
@ -290,6 +291,7 @@ type SpanBarRowProps = {
className?: string; className?: string;
theme: GrafanaTheme2; theme: GrafanaTheme2;
color: string; color: string;
spanBarOptions: SpanBarOptions | undefined;
columnDivision: number; columnDivision: number;
isChildrenExpanded: boolean; isChildrenExpanded: boolean;
isDetailExpanded: boolean; isDetailExpanded: boolean;
@ -352,6 +354,7 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
const { const {
className, className,
color, color,
spanBarOptions,
columnDivision, columnDivision,
isChildrenExpanded, isChildrenExpanded,
isDetailExpanded, isDetailExpanded,
@ -379,6 +382,7 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
process: { serviceName }, process: { serviceName },
} = span; } = span;
const label = formatDuration(duration); const label = formatDuration(duration);
const viewBounds = getViewedBounds(span.startTime, span.startTime + span.duration); const viewBounds = getViewedBounds(span.startTime, span.startTime + span.duration);
const viewStart = viewBounds.start; const viewStart = viewBounds.start;
const viewEnd = viewBounds.end; const viewEnd = viewBounds.end;
@ -473,7 +477,7 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
)} )}
</span> </span>
<small className={styles.endpointName}>{rpc ? rpc.operationName : operationName}</small> <small className={styles.endpointName}>{rpc ? rpc.operationName : operationName}</small>
<small className={styles.endpointName}> | {label}</small> <small className={styles.endpointName}> {this.getSpanBarLabel(span, spanBarOptions, label)}</small>
</a> </a>
{createSpanLink && {createSpanLink &&
(() => { (() => {
@ -542,6 +546,35 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
</TimelineRow> </TimelineRow>
); );
} }
getSpanBarLabel = (span: TraceSpan, spanBarOptions: SpanBarOptions | undefined, duration: string) => {
const type = spanBarOptions?.type ?? '';
if (type === NONE) {
return '';
} else if (type === '' || type === DURATION) {
return `(${duration})`;
} else if (type === TAG) {
const tagKey = spanBarOptions?.tag?.trim() ?? '';
if (tagKey !== '' && span.tags) {
const tag = span.tags?.find((tag: TraceKeyValuePair) => {
return tag.key === tagKey;
});
const process = span.process?.tags?.find((process: TraceKeyValuePair) => {
return process.key === tagKey;
});
if (tag) {
return `(${tag.value})`;
}
if (process) {
return `(${process.value})`;
}
}
}
return '';
};
} }
export default withTheme2(UnthemedSpanBarRow); export default withTheme2(UnthemedSpanBarRow);

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