mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'main' into gio/feat/create-correlation-api
This commit is contained in:
commit
8a4aa19588
File diff suppressed because it is too large
Load Diff
68
.betterer.ts
68
.betterer.ts
@ -1,28 +1,18 @@
|
||||
import { regexp } from '@betterer/regexp';
|
||||
import { eslint } from '@betterer/eslint';
|
||||
import { BettererFileTest } from '@betterer/betterer';
|
||||
import { ESLint, Linter } from 'eslint';
|
||||
import { existsSync } from 'fs';
|
||||
|
||||
export default {
|
||||
'no enzyme tests': () => regexp(/from 'enzyme'/g).include('**/*.test.*'),
|
||||
'better eslint': () =>
|
||||
eslint({
|
||||
'@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}'),
|
||||
'better eslint': () => countEslintErrors().include('**/*.{ts,tsx}'),
|
||||
'no undocumented stories': () => countUndocumentedStories().include('**/*.story.tsx'),
|
||||
};
|
||||
|
||||
function countUndocumentedStories() {
|
||||
return new BettererFileTest(async (filePaths, fileTestResult) => {
|
||||
const storyFilePaths = filePaths.filter((filePath) => filePath.endsWith('story.tsx'));
|
||||
const mdxFilePaths = filePaths.filter((filePath) => filePath.endsWith('mdx'));
|
||||
storyFilePaths.forEach((filePath) => {
|
||||
if (!mdxFilePaths.includes(filePath.replace(/\.story.tsx$/, '.mdx'))) {
|
||||
filePaths.forEach((filePath) => {
|
||||
if (!existsSync(filePath.replace(/\.story.tsx$/, '.mdx'))) {
|
||||
// In this case the file contents don't matter:
|
||||
const file = fileTestResult.addFile(filePath, '');
|
||||
// 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}`);
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
124
.drone.yml
124
.drone.yml
@ -15,7 +15,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -91,7 +91,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -197,7 +197,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -243,7 +243,6 @@ steps:
|
||||
from_secret: drone_token
|
||||
- commands:
|
||||
- ./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:
|
||||
- gen-version
|
||||
- wire-install
|
||||
@ -455,7 +454,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -542,7 +541,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -632,7 +631,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -721,7 +720,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -789,7 +788,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -884,7 +883,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -979,7 +978,7 @@ steps:
|
||||
image: grafana/build-container:1.5.7
|
||||
name: build-frontend-packages
|
||||
- commands:
|
||||
- ./bin/grabpl build-plugins --jobs 8 --edition oss --sign --signing-admin
|
||||
- ./bin/grabpl build-plugins --jobs 8 --edition oss
|
||||
depends_on:
|
||||
- gen-version
|
||||
- yarn-install
|
||||
@ -1230,7 +1229,7 @@ steps:
|
||||
repo:
|
||||
- grafana/grafana
|
||||
- commands:
|
||||
- ./bin/grabpl upload-packages --edition oss --packages-bucket grafana-downloads
|
||||
- ./bin/grabpl upload-packages --edition oss
|
||||
depends_on:
|
||||
- end-to-end-tests-dashboards-suite
|
||||
- end-to-end-tests-panels-suite
|
||||
@ -1247,7 +1246,7 @@ steps:
|
||||
repo:
|
||||
- grafana/grafana
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition oss --src-bucket "grafana-static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition oss
|
||||
depends_on:
|
||||
- grafana-server
|
||||
environment:
|
||||
@ -1308,7 +1307,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -1398,7 +1397,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$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
|
||||
image: grafana/ci-wix:0.1.1
|
||||
name: windows-init
|
||||
@ -1486,10 +1485,16 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
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:
|
||||
- echo $DRONE_RUNNER_NAME
|
||||
image: alpine:3.15
|
||||
@ -1571,7 +1576,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -1628,7 +1633,7 @@ steps:
|
||||
image: grafana/build-container:1.5.7
|
||||
name: build-frontend-packages
|
||||
- commands:
|
||||
- ./bin/grabpl build-plugins --jobs 8 --edition oss --sign --signing-admin
|
||||
- ./bin/grabpl build-plugins --jobs 8 --edition oss
|
||||
depends_on:
|
||||
- gen-version
|
||||
- yarn-install
|
||||
@ -1778,8 +1783,7 @@ steps:
|
||||
image: grafana/build-container:1.5.7
|
||||
name: build-storybook
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition oss --src-bucket "$${PRERELEASE_BUCKET}" --src-dir
|
||||
artifacts/static-assets
|
||||
- ./bin/grabpl upload-cdn --edition oss
|
||||
depends_on:
|
||||
- grafana-server
|
||||
environment:
|
||||
@ -1790,7 +1794,7 @@ steps:
|
||||
image: grafana/grafana-ci-deploy:1.3.1
|
||||
name: upload-cdn-assets
|
||||
- commands:
|
||||
- ./bin/grabpl upload-packages --edition oss --packages-bucket $${PRERELEASE_BUCKET}/artifacts/downloads
|
||||
- ./bin/grabpl upload-packages --edition oss
|
||||
depends_on:
|
||||
- end-to-end-tests-dashboards-suite
|
||||
- end-to-end-tests-panels-suite
|
||||
@ -1869,7 +1873,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -2004,7 +2008,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -2098,7 +2102,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$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
|
||||
image: grafana/ci-wix:0.1.1
|
||||
name: windows-init
|
||||
@ -2157,7 +2161,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -2244,7 +2248,7 @@ steps:
|
||||
image: grafana/build-container:1.5.7
|
||||
name: build-frontend-packages
|
||||
- commands:
|
||||
- ./bin/grabpl build-plugins --jobs 8 --edition enterprise --sign --signing-admin
|
||||
- ./bin/grabpl build-plugins --jobs 8 --edition enterprise
|
||||
depends_on:
|
||||
- gen-version
|
||||
- yarn-install
|
||||
@ -2393,8 +2397,7 @@ steps:
|
||||
- success
|
||||
- failure
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition enterprise --src-bucket "$${PRERELEASE_BUCKET}"
|
||||
--src-dir artifacts/static-assets
|
||||
- ./bin/grabpl upload-cdn --edition enterprise
|
||||
depends_on:
|
||||
- package
|
||||
environment:
|
||||
@ -2405,7 +2408,7 @@ steps:
|
||||
image: grafana/grafana-ci-deploy:1.3.1
|
||||
name: upload-cdn-assets
|
||||
- commands:
|
||||
- ./bin/grabpl upload-packages --edition enterprise --packages-bucket $${PRERELEASE_BUCKET}/artifacts/downloads
|
||||
- ./bin/grabpl upload-packages --edition enterprise
|
||||
depends_on:
|
||||
- package
|
||||
environment:
|
||||
@ -2446,8 +2449,7 @@ steps:
|
||||
image: grafana/build-container:1.5.7
|
||||
name: package-enterprise2
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition enterprise2 --src-bucket "$${PRERELEASE_BUCKET}"
|
||||
--src-dir artifacts/static-assets
|
||||
- ./bin/grabpl upload-cdn --edition enterprise2
|
||||
depends_on:
|
||||
- package-enterprise2
|
||||
environment:
|
||||
@ -2458,7 +2460,7 @@ steps:
|
||||
image: grafana/grafana-ci-deploy:1.3.1
|
||||
name: upload-cdn-assets-enterprise2
|
||||
- commands:
|
||||
- ./bin/grabpl upload-packages --edition enterprise2 --packages-bucket $${PRERELEASE_BUCKET}/artifacts/downloads-enterprise2
|
||||
- ./bin/grabpl upload-packages --edition enterprise2
|
||||
depends_on:
|
||||
- package-enterprise2
|
||||
environment:
|
||||
@ -2505,7 +2507,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -2688,7 +2690,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -2830,7 +2832,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$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
|
||||
- git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"
|
||||
- cd grafana-enterprise
|
||||
@ -2905,7 +2907,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -2983,7 +2985,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3044,7 +3046,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3123,7 +3125,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3185,7 +3187,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3223,7 +3225,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3261,7 +3263,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3317,7 +3319,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3365,7 +3367,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3414,7 +3416,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3471,7 +3473,7 @@ steps:
|
||||
image: grafana/build-container:1.5.7
|
||||
name: build-frontend-packages
|
||||
- commands:
|
||||
- ./bin/grabpl build-plugins --jobs 8 --edition oss --sign --signing-admin
|
||||
- ./bin/grabpl build-plugins --jobs 8 --edition oss
|
||||
depends_on:
|
||||
- gen-version
|
||||
- yarn-install
|
||||
@ -3621,7 +3623,7 @@ steps:
|
||||
image: grafana/build-container:1.5.7
|
||||
name: build-storybook
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition oss --src-bucket "grafana-static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition oss
|
||||
depends_on:
|
||||
- grafana-server
|
||||
environment:
|
||||
@ -3635,7 +3637,7 @@ steps:
|
||||
repo:
|
||||
- grafana/grafana
|
||||
- commands:
|
||||
- ./bin/grabpl upload-packages --edition oss --packages-bucket grafana-downloads
|
||||
- ./bin/grabpl upload-packages --edition oss
|
||||
depends_on:
|
||||
- end-to-end-tests-dashboards-suite
|
||||
- end-to-end-tests-panels-suite
|
||||
@ -3682,7 +3684,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3811,7 +3813,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -3899,7 +3901,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$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
|
||||
image: grafana/ci-wix:0.1.1
|
||||
name: windows-init
|
||||
@ -3947,7 +3949,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -4032,7 +4034,7 @@ steps:
|
||||
image: grafana/build-container:1.5.7
|
||||
name: build-frontend-packages
|
||||
- commands:
|
||||
- ./bin/grabpl build-plugins --jobs 8 --edition enterprise --sign --signing-admin
|
||||
- ./bin/grabpl build-plugins --jobs 8 --edition enterprise
|
||||
depends_on:
|
||||
- gen-version
|
||||
- yarn-install
|
||||
@ -4193,7 +4195,7 @@ steps:
|
||||
image: grafana/build-container:1.5.7
|
||||
name: build-storybook
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition enterprise --src-bucket "grafana-static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition enterprise
|
||||
depends_on:
|
||||
- package
|
||||
environment:
|
||||
@ -4207,7 +4209,7 @@ steps:
|
||||
repo:
|
||||
- grafana/grafana
|
||||
- commands:
|
||||
- ./bin/grabpl upload-packages --edition enterprise --packages-bucket grafana-downloads
|
||||
- ./bin/grabpl upload-packages --edition enterprise
|
||||
depends_on:
|
||||
- package
|
||||
environment:
|
||||
@ -4241,7 +4243,7 @@ steps:
|
||||
image: grafana/build-container:1.5.7
|
||||
name: package-enterprise2
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition enterprise2 --src-bucket "grafana-static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition enterprise2
|
||||
depends_on:
|
||||
- package-enterprise2
|
||||
environment:
|
||||
@ -4252,7 +4254,7 @@ steps:
|
||||
image: grafana/grafana-ci-deploy:1.3.1
|
||||
name: upload-cdn-assets-enterprise2
|
||||
- commands:
|
||||
- ./bin/grabpl upload-packages --edition enterprise2 --packages-bucket grafana-downloads-enterprise2
|
||||
- ./bin/grabpl upload-packages --edition enterprise2
|
||||
depends_on:
|
||||
- package-enterprise2
|
||||
environment:
|
||||
@ -4293,7 +4295,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -4467,7 +4469,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- 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
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@ -4600,7 +4602,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$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
|
||||
- git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"
|
||||
- cd grafana-enterprise
|
||||
@ -4797,6 +4799,6 @@ kind: secret
|
||||
name: gcp_upload_artifacts_key
|
||||
---
|
||||
kind: signature
|
||||
hmac: 12fbd61337ed1ae006e8c0ff71d1290e27b5910211369cdd47e1d604afd9befa
|
||||
hmac: b885bb4e5374691a66b4fa8c6f53cdcebeef573895ea629d4e8b0af715573cea
|
||||
|
||||
...
|
||||
|
13
.github/CODEOWNERS
vendored
13
.github/CODEOWNERS
vendored
@ -31,9 +31,9 @@ go.sum @grafana/backend-platform
|
||||
/pkg/build/ @grafana/grafana-release-eng
|
||||
|
||||
# Cloud Datasources backend code
|
||||
/pkg/tsdb/cloudwatch @grafana/cloud-datasources
|
||||
/pkg/tsdb/azuremonitor @grafana/cloud-datasources
|
||||
/pkg/tsdb/cloudmonitoring @grafana/cloud-datasources
|
||||
/pkg/tsdb/cloudwatch @grafana/aws-plugins
|
||||
/pkg/tsdb/azuremonitor @grafana/cloud-provider-plugins
|
||||
/pkg/tsdb/cloudmonitoring @grafana/cloud-provider-plugins
|
||||
|
||||
# Observability backend code
|
||||
/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/dimensions/ @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/explore/ @grafana/observability-experience-squad
|
||||
/public/app/features/plugins @grafana/plugins-platform-frontend
|
||||
@ -148,9 +149,9 @@ lerna.json @grafana/frontend-ops
|
||||
*.mdx @marcusolsson @jessover9000 @grafana/plugins-platform-frontend
|
||||
|
||||
# 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/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/influxdb @grafana/observability-metrics
|
||||
/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/postgres @grafana/grafana-bi-squad
|
||||
/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/tempo @grafana/observability-logs-and-traces
|
||||
/public/app/plugins/datasource/alertmanager @grafana/alerting-squad
|
||||
|
16
.github/workflows/doc-validator.yml
vendored
Normal file
16
.github/workflows/doc-validator.yml
vendored
Normal 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"
|
@ -2,9 +2,95 @@
|
||||
|
||||
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
|
||||
|
||||
@ -44,92 +130,3 @@ if err := s.bus.Publish(event); err != nil {
|
||||
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
|
||||
}
|
||||
```
|
||||
|
81
contribute/architecture/backend/errors.md
Normal file
81
contribute/architecture/backend/errors.md
Normal 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.
|
@ -1,16 +1,217 @@
|
||||
# Package hierarchy
|
||||
|
||||
The Go package hierarchy in Grafana should be organized logically (Ben Johnson's
|
||||
[article](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1) served as inspiration), according to the
|
||||
following principles:
|
||||
The Go packages in Grafana should be packaged by feature, keeping
|
||||
packages as small as reasonable while retaining a clear sole ownership
|
||||
of a single domain.
|
||||
|
||||
- Domain types and interfaces should be in "root" packages (not necessarily at the very top, of the hierarchy, but
|
||||
logical roots)
|
||||
- Sub-packages should depend on roots - sub-packages here typically contain implementations, for example of services
|
||||
[Ben Johnson's standard package layout](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1) serves as
|
||||
inspiration for the way we organize packages.
|
||||
|
||||
## 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
|
||||
|
||||
The `pkg/plugins` package contains plugin domain types, for example `DataPlugin`, and also interfaces
|
||||
such as `RequestHandler`. Then you have the `pkg/plugins/managers` subpackage, which contains concrete implementations
|
||||
such as the service `PluginManager`. The subpackage `pkg/plugins/backendplugin/coreplugin` contains `plugins.DataPlugin`
|
||||
implementations.
|
||||
The following is a simplified example of the package structure for a
|
||||
service that doesn't do anything in particular.
|
||||
|
||||
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.
|
||||
|
@ -1 +0,0 @@
|
||||
http-bind-address: :8086
|
@ -5,6 +5,7 @@
|
||||
- '8086:8086'
|
||||
environment:
|
||||
INFLUXD_REPORTING_DISABLED: 'true'
|
||||
INFLUXD_HTTP_BIND_ADDRESS: ':8086'
|
||||
DOCKER_INFLUXDB_INIT_MODE: 'setup'
|
||||
DOCKER_INFLUXDB_INIT_USERNAME: 'grafana'
|
||||
DOCKER_INFLUXDB_INIT_PASSWORD: 'grafana12345'
|
||||
@ -12,7 +13,6 @@
|
||||
DOCKER_INFLUXDB_INIT_BUCKET: 'mybucket'
|
||||
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: 'mytoken'
|
||||
volumes:
|
||||
- ./docker/blocks/influxdb/config.yaml:/etc/influxdb2/config.yaml
|
||||
- ./docker/blocks/influxdb/setup_influxql.sh:/docker-entrypoint-initdb.d/setup_influxql.sh
|
||||
|
||||
telegraf:
|
||||
|
5487
devenv/docker/blocks/oauth/cloak.sql
Normal file
5487
devenv/docker/blocks/oauth/cloak.sql
Normal file
File diff suppressed because it is too large
Load Diff
@ -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}" .
|
30
devenv/docker/blocks/oauth/docker-compose.yaml
Normal file
30
devenv/docker/blocks/oauth/docker-compose.yaml
Normal 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
|
65
devenv/docker/blocks/oauth/readme.md
Normal file
65
devenv/docker/blocks/oauth/readme.md
Normal 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
|
||||
|
@ -233,7 +233,10 @@ datasources:
|
||||
|
||||
> 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
|
||||
|
||||
|
@ -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: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: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: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 user’s authentication token, or update quotas for all users. |
|
||||
|
@ -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.
|
||||
|
||||
{{< 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
|
||||
|
||||
|
@ -16,7 +16,7 @@ weight: 401
|
||||
|
||||
# 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
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
---
|
||||
aliases:
|
||||
- /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/message-templating/template-functions/
|
||||
- /docs/grafana/latest/alerting/unified-alerting/message-templating/template-functions/
|
||||
- /docs/grafana/latest/alerting/fundamentals/annotation-label/example-template-functions/
|
||||
keywords:
|
||||
- grafana
|
||||
- alerting
|
@ -3,6 +3,8 @@ aliases:
|
||||
- /docs/grafana/latest/alerting/contact-points/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/fundamentals/annotation-label/template-functions/
|
||||
- /docs/grafana/latest/alerting/unified-alerting/fundamentals/annotation-label/template-functions/
|
||||
keywords:
|
||||
- grafana
|
||||
- alerting
|
||||
@ -15,7 +17,7 @@ weight: 125
|
||||
|
||||
# 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 |
|
||||
| ----------------------------------------- | ------------------------------------------------------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
39
docs/sources/alerting/fundamentals/data-source-alerting.md
Normal file
39
docs/sources/alerting/fundamentals/data-source-alerting.md
Normal 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/" >}})
|
@ -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.
|
||||
- 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 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/" >}}).
|
||||
- Be careful with stacking graph data. The visualizations can be misleading, and hide important data. We recommend turning it off in most cases.
|
||||
|
108
docs/sources/dashboards/add-organize-panels.md
Normal file
108
docs/sources/dashboards/add-organize-panels.md
Normal 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.
|
||||
|
||||

|
||||
|
||||
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.
|
87
docs/sources/dashboards/manage-library-panels.md
Normal file
87
docs/sources/dashboards/manage-library-panels.md
Normal 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.
|
@ -10,7 +10,7 @@ aliases:
|
||||
- /docs/grafana/latest/reference/search/
|
||||
title: 'Use dashboards'
|
||||
menuTitle: Use dashboards
|
||||
weight: 2
|
||||
weight: 1
|
||||
keywords:
|
||||
- dashboard
|
||||
- search
|
||||
|
@ -103,7 +103,7 @@ Further documentation on multi-dimensional metrics is available [here](https://d
|
||||
|
||||
#### 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
|
||||
|
||||
|
@ -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.
|
||||
|
||||
### 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
|
||||
|
||||
You can query and display traces from Jaeger via [Explore]({{< relref "../explore/" >}}).
|
||||
|
@ -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.
|
||||
|
||||
### 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
|
||||
|
||||
You can query and display traces from Tempo via [Explore]({{< relref "../explore/" >}}).
|
||||
|
@ -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.
|
||||
|
||||
### 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
|
||||
|
||||
Querying and displaying traces from Zipkin is available via [Explore]({{< relref "../explore/" >}}).
|
||||
|
@ -12,7 +12,6 @@ You can change a value mapping at any time.
|
||||
|
||||
## Before you begin
|
||||
|
||||
- [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
|
||||
- Ensure you have an existing value mapping to edit.
|
||||
|
||||
**To edit a value mapping**:
|
||||
|
@ -10,12 +10,6 @@ weight: 30
|
||||
|
||||
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. In panel display options, in the **Value mappings** section, click **Add value mappings**.
|
||||
1. Click **Add a new mapping** and then select **Range**.
|
||||
|
@ -10,14 +10,8 @@ weight: 40
|
||||
|
||||
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. 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. Enter the regular expression pattern for Grafana to match.
|
||||
1. (Optional) Enter display text.
|
||||
|
@ -10,12 +10,6 @@ weight: 50
|
||||
|
||||
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. In panel display options, locate the **Value mappings** section and click **Add value mappings**.
|
||||
1. Click **Add a new mapping** and then select **Special**.
|
||||
|
@ -10,12 +10,6 @@ weight: 20
|
||||
|
||||
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. 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,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 >}}
|
@ -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.
|
@ -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.
|
@ -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" >}}
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -10,12 +10,6 @@ weight: 30
|
||||
|
||||
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. In the panel display options, in the **Overrides** section, click **Add field override**.
|
||||
|
||||
|
@ -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.
|
||||
|
||||
## 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. In panel display options, click the **Overrides** tab.
|
||||
1. Click the override you want to delete and then click the associated trash icon.
|
||||
|
@ -10,11 +10,6 @@ weight: 40
|
||||
|
||||
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**:
|
||||
|
||||
1. Edit the panel that contains the overrides you want to edit.
|
||||
|
@ -10,11 +10,6 @@ weight: 20
|
||||
|
||||
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**:
|
||||
|
||||
1. Open for edit the panel that contains the overrides you want to view.
|
||||
|
@ -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).
|
||||
- Ensure that you know the query language of the data source.
|
||||
- [Add a panel]({{< relref "../working-with-panels/add-panel/" >}}).
|
||||
|
||||
**To add a query**:
|
||||
|
||||
|
@ -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.
|
||||
|
||||
## 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. In the query editor, click **Query Inspector**.
|
||||
1. Click **Data**.
|
||||
|
@ -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.
|
||||
|
||||
## 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. In the query editor, click **Query Inspector**.
|
||||
1. Click **Stats**.
|
||||
|
@ -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.
|
||||
|
||||
## 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. In the query editor, click **Query Inspector**.
|
||||
1. Click **Refresh**.
|
||||
|
@ -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.
|
||||
|
||||
**To share data source queries with another panel**:
|
||||
|
||||
1. [Add a panel to a dashboard]({{< relref "../working-with-panels/add-panel/" >}}).
|
||||
1. [Create a dashboard and add a panel]({{< relref "../../dashboards/add-organize-panels/#create-a-dashboard-and-add-a-panel" >}}).
|
||||
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.
|
||||
|
||||
|
@ -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/" >}}).
|
||||
|
||||
## Before you begin
|
||||
|
||||
- [Add a panel]({{< relref "../../working-with-panels/add-panel/" >}}).
|
||||
|
||||
**To write an expression**:
|
||||
|
||||
1. Open the panel.
|
||||
1. Below the query, click **Expression**.
|
||||
1. In the **Operation** field, select the type of expression you want to write.
|
||||
|
@ -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.
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
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.
|
@ -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.
|
||||
|
||||
## 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. In the panel display options pane, locate the **Panel options** section.
|
||||
|
@ -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.
|
||||
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. Click the **Standard options Color scheme** drop-down, and select one of the following palettes:
|
||||
|
@ -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.
|
||||
|
||||
### Before you begin
|
||||
|
||||
- [Add a panel to a dashboard]({{< relref "add-panel/" >}}).
|
||||
|
||||
**To isolate series data in a visualization**:
|
||||
|
||||
1. Open the panel.
|
||||
|
||||
1. In the legend, click the label of the series you want to isolate.
|
||||
|
@ -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.
|
||||
|
||||
## 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. In the panel display options pane, locate the **Standard options** section.
|
||||
|
@ -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" >}}
|
@ -10,12 +10,6 @@ weight: 100
|
||||
|
||||
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. In Select source, choose one of the following options:
|
||||
|
@ -51,6 +51,7 @@ tls_client_cert =
|
||||
tls_client_key =
|
||||
tls_client_ca =
|
||||
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.
|
||||
@ -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.
|
||||
|
||||
`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.
|
||||
|
||||
### Email address
|
||||
|
@ -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.
|
||||
|
||||
> **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
|
||||
- [Time series]({{< relref "time-series/" >}}) is the default and main Graph visualization.
|
||||
|
@ -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" >}}).
|
||||
|
||||
## Create the panel
|
||||
|
||||
1. [Add a panel]({{< relref "../../panels/working-with-panels/add-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** visualization.
|
||||
1. In the Panel editor side pane, click **Graph styles** to expand it.
|
||||
1. In Style, click **Bars**.
|
||||
|
@ -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.
|
||||
|
||||
## Create the panel
|
||||
|
||||
1. [Add a panel]({{< relref "../../panels/working-with-panels/add-panel/" >}}). Select the [Time series]({{< relref "_index.md" >}}) visualization.
|
||||
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. In the Panel editor side pane, click **Graph styles** to expand it.
|
||||
1. In Style, click **Lines**.
|
||||
|
||||
|
@ -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.
|
||||
|
||||
## Create the panel
|
||||
|
||||
1. [Add a panel]({{< relref "../../panels/working-with-panels/add-panel/" >}}). Select the [Time series]({{< relref "_index.md" >}}) visualization.
|
||||
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. In the Panel editor side pane, click **Graph styles** to expand it.
|
||||
1. In Style, click **Points**.
|
||||
|
||||
|
@ -15,7 +15,7 @@ title: What's new in Grafana v7.5
|
||||
weight: -32
|
||||
---
|
||||
|
||||
# What’s 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).
|
||||
|
||||
|
@ -15,7 +15,7 @@ title: What's new in Grafana v8.0
|
||||
weight: -33
|
||||
---
|
||||
|
||||
# What’s 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).
|
||||
|
||||
|
@ -15,7 +15,7 @@ title: What's new in Grafana v8.1
|
||||
weight: -33
|
||||
---
|
||||
|
||||
# What’s 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.
|
||||
|
||||
|
@ -15,7 +15,7 @@ title: What's new in Grafana v8.2
|
||||
weight: -33
|
||||
---
|
||||
|
||||
# What’s 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 Grafana’s accessibility, part of its continuing mission to democratize metrics _for everyone_.
|
||||
|
||||
|
@ -15,7 +15,7 @@ title: What's new in Grafana v8.3
|
||||
weight: -33
|
||||
---
|
||||
|
||||
# What’s 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.
|
||||
|
||||
|
@ -15,7 +15,7 @@ title: What's new in Grafana v8.4
|
||||
weight: -33
|
||||
---
|
||||
|
||||
# What’s new in Grafana v8.4
|
||||
# What's new in Grafana v8.4
|
||||
|
||||
We’re excited to announce Grafana v8.4, with a variety of improvements that focus on Grafana’s 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, we’ve 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.
|
||||
|
||||
|
@ -15,7 +15,7 @@ title: What's new in Grafana v8.5
|
||||
weight: -33
|
||||
---
|
||||
|
||||
# What’s new in Grafana v8.5
|
||||
# What's new in Grafana v8.5
|
||||
|
||||
We’re excited to announce Grafana v8.5, with a variety of improvements that focus on Grafana’s usability, performance, and security.
|
||||
|
||||
|
@ -15,7 +15,7 @@ title: What's new in Grafana v9.0
|
||||
weight: -33
|
||||
---
|
||||
|
||||
# What’s 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 Grafana’s ease of use, discovery of data through new and improved visualizations and a default Grafana Alerting experience.
|
||||
|
||||
|
20
go.mod
20
go.mod
@ -34,6 +34,7 @@ require (
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/gchaincl/sqlhooks v1.3.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-openapi/strfmt v0.20.2
|
||||
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-stack/stack v1.8.0
|
||||
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/golang/mock v1.6.0
|
||||
github.com/golang/snappy v0.0.4
|
||||
@ -213,7 +214,7 @@ require (
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
|
||||
github.com/segmentio/encoding v0.3.2
|
||||
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/vfsgen v0.0.0-20200824052919-0d455de96546 // 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/go-autorest/autorest/adal v0.9.17
|
||||
github.com/armon/go-radix v1.0.0
|
||||
github.com/blugelabs/bluge v0.2.1
|
||||
github.com/blugelabs/bluge_segment_api v0.2.0
|
||||
github.com/blugelabs/bluge v0.1.9
|
||||
github.com/getkin/kin-openapi v0.94.0
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0
|
||||
github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f
|
||||
@ -256,6 +256,7 @@ require (
|
||||
require (
|
||||
cloud.google.com/go v0.100.2 // 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/google/gofuzz v1.2.0 // 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/AzureAD/microsoft-authentication-library-for-go v0.4.0 // 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/acomagu/bufpipe v1.0.3 // indirect
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f // indirect
|
||||
github.com/bits-and-blooms/bitset v1.2.0 // 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/vellum v1.0.7 // 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/chromedp/cdproto v0.0.0-20220208224320-6efb837e6bc2 // indirect
|
||||
github.com/containerd/containerd v1.6.6 // indirect
|
||||
github.com/coreos/go-semver v0.3.0 // indirect
|
||||
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc // 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/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/stdr v1.2.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // 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/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/labstack/echo/v4 v4.7.2 // 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/mschoch/smat v0.2.0 // 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/valyala/fasttemplate v1.2.1 // indirect
|
||||
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/yudai/pp v2.0.1+incompatible // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.6.3 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.15.0 // 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/apimachinery v0.22.5 // indirect
|
||||
k8s.io/klog/v2 v2.30.0 // indirect
|
||||
|
43
go.sum
43
go.sum
@ -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.5/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.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
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/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/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/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=
|
||||
@ -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/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM=
|
||||
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 v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
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 v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
||||
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/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=
|
||||
@ -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.7 h1:+vn8rfyCRHxKVRgDLeR0FAXej2+6mEb5Q15aQE/XESQ=
|
||||
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.2.1/go.mod h1:am1LU9jS8dZgWkRzkGLQN3757EgMs3upWrU2fdN9foE=
|
||||
github.com/blugelabs/bluge v0.1.9 h1:bPgXlcsWugrXNjzeoLdOnvfJpHsyODKpYaAndayl/SM=
|
||||
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/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/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/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
|
||||
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.10.0 h1:pDGyFRVV5RvV+nkBK9iy3q67FBy9Xa7vwrOTE+g5aGw=
|
||||
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.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=
|
||||
@ -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.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
|
||||
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.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=
|
||||
@ -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/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/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-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
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/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-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/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=
|
||||
@ -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.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
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/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=
|
||||
@ -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/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||
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.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
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/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||
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/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
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.4.0+incompatible h1:WE2OlRf6wjLxHwNkkFLQGaZcVLEXjMjBPjjEU5vksH8=
|
||||
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.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/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=
|
||||
@ -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/go.mod h1:9ZIbRunKbuvfPKyBP1SIKLcXNlv74YCOZ3t3VTS6gRk=
|
||||
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/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
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-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-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-20190320223903-b7391e95e576/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-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-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-20210616213533-5ff15b29337e/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-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-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-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||
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-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-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-20210503173754-0981d6026fa6/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/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/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
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.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
@ -217,7 +217,6 @@
|
||||
"mutationobserver-shim": "0.3.7",
|
||||
"ngtemplate-loader": "2.1.0",
|
||||
"node-notifier": "10.0.1",
|
||||
"nodemon": "2.0.16",
|
||||
"postcss": "8.4.14",
|
||||
"postcss-loader": "7.0.0",
|
||||
"postcss-reporter": "7.0.5",
|
||||
@ -259,7 +258,7 @@
|
||||
"@grafana/e2e-selectors": "workspace:*",
|
||||
"@grafana/experimental": "^0.0.2-canary.32",
|
||||
"@grafana/google-sdk": "0.0.3",
|
||||
"@grafana/lezer-logql": "^0.0.12",
|
||||
"@grafana/lezer-logql": "^0.0.13",
|
||||
"@grafana/runtime": "workspace:*",
|
||||
"@grafana/schema": "workspace:*",
|
||||
"@grafana/slate-react": "0.22.10-grafana",
|
||||
@ -354,6 +353,7 @@
|
||||
"rc-time-picker": "3.7.3",
|
||||
"re-resizable": "6.9.9",
|
||||
"react": "17.0.2",
|
||||
"react-awesome-query-builder": "^5.1.2",
|
||||
"react-beautiful-dnd": "13.1.0",
|
||||
"react-diff-viewer": "^3.1.1",
|
||||
"react-dom": "17.0.2",
|
||||
@ -385,7 +385,6 @@
|
||||
"rst2html": "github:thoward/rst2html#990cb89f2a300cdd9151790be377c4c0840df809",
|
||||
"rxjs": "7.5.5",
|
||||
"sass": "link:./public/sass",
|
||||
"search-query-parser": "1.6.0",
|
||||
"selecto": "1.16.2",
|
||||
"semver": "7.3.7",
|
||||
"slate": "0.47.8",
|
||||
@ -404,10 +403,10 @@
|
||||
"resolutions": {
|
||||
"underscore": "1.13.3",
|
||||
"@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/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",
|
||||
"node-fetch": "2.6.7"
|
||||
},
|
||||
|
@ -160,13 +160,13 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform
|
||||
for (const frame of frames) {
|
||||
for (const field of frame.fields) {
|
||||
if (field.type === FieldType.number) {
|
||||
allValues = allValues.concat(
|
||||
field.values.toArray().map((val: number) => Number(val.toFixed(field.config.decimals ?? 0)))
|
||||
);
|
||||
allValues = allValues.concat(field.values.toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allValues = allValues.filter((v) => v != null);
|
||||
|
||||
allValues.sort((a, b) => a - b);
|
||||
|
||||
let smallestDelta = Infinity;
|
||||
@ -204,6 +204,9 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform
|
||||
|
||||
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 counts: Field[] = [];
|
||||
let config: FieldConfig | undefined = undefined;
|
||||
@ -220,7 +223,7 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform
|
||||
unit: undefined,
|
||||
},
|
||||
});
|
||||
if (!config && Object.keys(field.config).length) {
|
||||
if (!config && field.config.unit) {
|
||||
config = field.config;
|
||||
}
|
||||
}
|
||||
@ -251,7 +254,13 @@ export function buildHistogram(frames: DataFrame[], options?: HistogramTransform
|
||||
values: new ArrayVector(joinedHists[0]),
|
||||
type: FieldType.number,
|
||||
state: undefined,
|
||||
config: config ?? {},
|
||||
config:
|
||||
bucketDecimals === 0
|
||||
? config ?? {}
|
||||
: {
|
||||
...config,
|
||||
decimals: bucketDecimals,
|
||||
},
|
||||
};
|
||||
const bucketMax = {
|
||||
...bucketMin,
|
||||
|
@ -483,7 +483,6 @@ export interface DataQueryRequest<TQuery extends DataQuery = DataQuery> {
|
||||
timeInfo?: string; // The query time description (blue text in the upper right)
|
||||
panelId?: number;
|
||||
dashboardId?: number;
|
||||
// Temporary prop for public dashboards, to be replaced by publicAccessKey
|
||||
publicDashboardAccessToken?: string;
|
||||
|
||||
// Request Timing
|
||||
|
@ -56,6 +56,7 @@ export interface FeatureToggles {
|
||||
autoMigrateGraphPanels?: boolean;
|
||||
prometheusWideSeries?: boolean;
|
||||
canvasPanelNesting?: boolean;
|
||||
scenes?: boolean;
|
||||
useLegacyHeatmapPanel?: boolean;
|
||||
cloudMonitoringExperimentalUI?: boolean;
|
||||
logRequestsInstrumentedAsUnknown?: boolean;
|
||||
|
@ -56,10 +56,6 @@ export interface NavModel {
|
||||
* This is the current active tab/navigation.
|
||||
*/
|
||||
node: NavModelItem;
|
||||
/**
|
||||
* Describes breadcrumbs that are used in places such as data source settings., folder page and plugins page.
|
||||
*/
|
||||
breadcrumbs?: NavModelItem[];
|
||||
}
|
||||
|
||||
export interface NavModelBreadcrumb {
|
||||
|
@ -11,7 +11,7 @@ import { AbsoluteTimeRange, FieldConfigSource, PanelData } from '@grafana/data';
|
||||
* @internal
|
||||
*/
|
||||
export interface PanelRendererProps<P extends object = any, F extends object = any> {
|
||||
data: PanelData;
|
||||
data?: PanelData;
|
||||
pluginId: string;
|
||||
title: string;
|
||||
options?: Partial<P>;
|
||||
|
@ -143,17 +143,17 @@ export function isFetchError(e: unknown): e is FetchError {
|
||||
* @public
|
||||
*/
|
||||
export interface BackendSrv {
|
||||
get(url: string, params?: any, requestId?: string): Promise<any>;
|
||||
delete(url: string, data?: any): Promise<any>;
|
||||
post(url: string, data?: any): Promise<any>;
|
||||
patch(url: string, data?: any): Promise<any>;
|
||||
put(url: string, data?: any): Promise<any>;
|
||||
get<T = any>(url: string, params?: any, requestId?: string): Promise<T>;
|
||||
delete<T = any>(url: string, data?: any): Promise<T>;
|
||||
post<T = any>(url: string, data?: any): Promise<T>;
|
||||
patch<T = any>(url: string, data?: any): Promise<T>;
|
||||
put<T = any>(url: string, data?: any): Promise<T>;
|
||||
|
||||
/**
|
||||
* @deprecated Use the fetch function instead. If you prefer to work with a promise
|
||||
* 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
|
||||
|
@ -1,9 +1,14 @@
|
||||
import { of } from 'rxjs';
|
||||
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();
|
||||
|
||||
@ -28,7 +33,7 @@ describe('PublicDashboardDatasource', () => {
|
||||
mockDatasourceRequest.mockReset();
|
||||
mockDatasourceRequest.mockReturnValue(Promise.resolve({}));
|
||||
|
||||
const ds = new PublicDashboardDataSource();
|
||||
const ds = new PublicDashboardDataSource('public');
|
||||
const panelId = 1;
|
||||
const publicDashboardAccessToken = 'abc123';
|
||||
|
||||
@ -47,4 +52,27 @@ describe('PublicDashboardDatasource', () => {
|
||||
`/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');
|
||||
});
|
||||
});
|
||||
|
@ -41,7 +41,7 @@ chmod 755 /usr/local/bin/golangci-lint
|
||||
# Install code climate
|
||||
get_file "https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64" \
|
||||
"/usr/local/bin/cc-test-reporter" \
|
||||
"9fbe34cd207924d8f51ac0f3ffa690df4169e055cd7134a2370f6650f5b356e1"
|
||||
"9e6c3e628b1258aefbc6e3550438a691abb0d1924d63c038881031d3d343c7d0"
|
||||
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"
|
||||
|
@ -9,6 +9,7 @@ import { IconName } from '../../types/icon';
|
||||
import { ComponentSize } from '../../types/size';
|
||||
import { getPropertiesForButtonSize } from '../Forms/commonStyles';
|
||||
import { Icon } from '../Icon/Icon';
|
||||
import { PopoverContent, Tooltip, TooltipPlacement } from '../Tooltip';
|
||||
|
||||
export type ButtonVariant = 'primary' | 'secondary' | 'destructive';
|
||||
export const allButtonVariants: ButtonVariant[] = ['primary', 'secondary', 'destructive'];
|
||||
@ -24,6 +25,10 @@ type CommonProps = {
|
||||
children?: React.ReactNode;
|
||||
fullWidth?: boolean;
|
||||
type?: string;
|
||||
/** Tooltip content to display on hover */
|
||||
tooltip?: PopoverContent;
|
||||
/** Position of the tooltip */
|
||||
tooltipPlacement?: TooltipPlacement;
|
||||
};
|
||||
|
||||
export type ButtonProps = CommonProps & ButtonHTMLAttributes<HTMLButtonElement>;
|
||||
@ -79,6 +84,8 @@ export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
|
||||
onBlur,
|
||||
onFocus,
|
||||
disabled,
|
||||
tooltip,
|
||||
tooltipPlacement,
|
||||
...otherProps
|
||||
},
|
||||
ref
|
||||
@ -103,12 +110,22 @@ export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
|
||||
className
|
||||
);
|
||||
|
||||
return (
|
||||
const button = (
|
||||
<a className={linkButtonStyles} {...otherProps} tabIndex={disabled ? -1 : 0} ref={ref}>
|
||||
{icon && <Icon name={icon} size={size} className={styles.icon} />}
|
||||
{children && <span className={styles.content}>{children}</span>}
|
||||
</a>
|
||||
);
|
||||
|
||||
if (tooltip) {
|
||||
return (
|
||||
<Tooltip content={tooltip} placement={tooltipPlacement}>
|
||||
{button}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { css } from '@emotion/css';
|
||||
import React from 'react';
|
||||
import React, { CSSProperties } from 'react';
|
||||
|
||||
import { LinkModel } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
@ -12,6 +12,7 @@ import { MenuItem } from '../Menu/MenuItem';
|
||||
interface DataLinksContextMenuProps {
|
||||
children: (props: DataLinksContextMenuApi) => JSX.Element;
|
||||
links: () => LinkModel[];
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
export interface DataLinksContextMenuApi {
|
||||
@ -19,7 +20,7 @@ export interface DataLinksContextMenuApi {
|
||||
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 linksCounter = itemsGroup[0].items.length;
|
||||
const renderMenuGroupItems = () => {
|
||||
@ -61,7 +62,7 @@ export const DataLinksContextMenu: React.FC<DataLinksContextMenuProps> = ({ chil
|
||||
onClick={linkModel.onClick}
|
||||
target={linkModel.target}
|
||||
title={linkModel.title}
|
||||
style={{ display: 'flex', width: '100%' }}
|
||||
style={style}
|
||||
aria-label={selectors.components.DataLinksContextMenu.singleLink}
|
||||
>
|
||||
{children({})}
|
||||
|
@ -118,7 +118,7 @@ export function UnthemedTimeRangePicker(props: TimeRangePickerProps): ReactEleme
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
{isOpen && (
|
||||
<FocusScope contain autoFocus restoreFocus>
|
||||
<FocusScope contain autoFocus>
|
||||
<section ref={ref} {...overlayProps} {...dialogProps}>
|
||||
<TimePickerContent
|
||||
timeZone={timeZone}
|
||||
|
@ -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} />
|
@ -6,6 +6,8 @@ import { PluginSignatureBadge } from '@grafana/ui';
|
||||
|
||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||
|
||||
import mdx from './PluginSignatureBadge.mdx';
|
||||
|
||||
export default {
|
||||
title: 'Data Display/PluginSignatureBadge',
|
||||
decorators: [withCenteredStory],
|
||||
@ -24,6 +26,11 @@ export default {
|
||||
],
|
||||
},
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Basic: Story = (args) => {
|
||||
|
@ -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} />
|
@ -4,12 +4,16 @@ import React, { useState, ChangeEvent } from 'react';
|
||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||
|
||||
import { SecretInput, Props } from './SecretInput';
|
||||
import mdx from './SecretInput.mdx';
|
||||
|
||||
export default {
|
||||
const meta: Meta = {
|
||||
title: 'Forms/SecretInput',
|
||||
component: SecretInput,
|
||||
decorators: [withCenteredStory],
|
||||
parameters: {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
controls: {
|
||||
exclude: [
|
||||
'prefix',
|
||||
@ -32,7 +36,9 @@ export default {
|
||||
argTypes: {
|
||||
width: { control: { type: 'range', min: 10, max: 200, step: 10 } },
|
||||
},
|
||||
} as Meta;
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
const Template: Story<Props> = (args) => {
|
||||
const [secret, setSecret] = useState('');
|
||||
|
@ -50,7 +50,7 @@ export const BarGaugeCell: FC<TableCellProps> = (props) => {
|
||||
return field.getLinks({ valueRowIndex: row.index });
|
||||
};
|
||||
|
||||
const hasLinks = !!getLinks().length;
|
||||
const hasLinks = Boolean(getLinks().length);
|
||||
|
||||
const renderComponent = (menuProps: DataLinksContextMenuApi) => {
|
||||
const { openMenu, targetClassName } = menuProps;
|
||||
@ -76,7 +76,11 @@ export const BarGaugeCell: FC<TableCellProps> = (props) => {
|
||||
|
||||
return (
|
||||
<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 && (
|
||||
<BarGauge
|
||||
width={innerWidth}
|
||||
|
@ -11,7 +11,7 @@ export const ImageCell: FC<TableCellProps> = (props) => {
|
||||
|
||||
const displayValue = field.display!(cell.value);
|
||||
|
||||
const hasLinks = getCellLinks(field, row)?.length;
|
||||
const hasLinks = Boolean(getCellLinks(field, row)?.length);
|
||||
|
||||
return (
|
||||
<div {...cellProps} className={tableStyles.cellContainer}>
|
||||
|
@ -27,7 +27,7 @@ export function JSONViewCell(props: TableCellProps): JSX.Element {
|
||||
displayValue = JSON.stringify(value, null, ' ');
|
||||
}
|
||||
|
||||
const hasLinks = getCellLinks(field, row)?.length;
|
||||
const hasLinks = Boolean(getCellLinks(field, row)?.length);
|
||||
|
||||
return (
|
||||
<div {...cellProps} className={inspectEnabled ? tableStyles.cellContainerNoOverflow : tableStyles.cellContainer}>
|
||||
|
@ -165,7 +165,6 @@ export const getTableStyles = (theme: GrafanaTheme2) => {
|
||||
imageCellLink: css`
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
`,
|
||||
headerFilter: css`
|
||||
|
96
packages/grafana-ui/src/components/Tabs/VerticalTab.tsx
Normal file
96
packages/grafana-ui/src/components/Tabs/VerticalTab.tsx
Normal 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)};
|
||||
`,
|
||||
};
|
||||
};
|
@ -1,6 +1,8 @@
|
||||
import { Story, Preview, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Tag } from './Tag';
|
||||
|
||||
<Meta title="MDX|Tag" component={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.
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { Story } from '@storybook/react';
|
||||
import React from 'react';
|
||||
|
||||
import { Tag } from '@grafana/ui';
|
||||
|
||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||
|
||||
import { Props as TagProps, Tag } from './Tag';
|
||||
import mdx from './Tag.mdx';
|
||||
|
||||
export default {
|
||||
@ -15,9 +15,28 @@ export default {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
controls: {
|
||||
exclude: ['onClick'],
|
||||
},
|
||||
},
|
||||
args: {
|
||||
name: 'Tag',
|
||||
colorIndex: 0,
|
||||
showIcon: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const single = () => {
|
||||
return <Tag name="Tag" onClick={action('Tag clicked')} />;
|
||||
interface StoryProps extends TagProps {
|
||||
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}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -64,13 +64,15 @@ const getTagStyles = (theme: GrafanaTheme, name: string, colorIndex?: number) =>
|
||||
font-weight: ${theme.typography.weight.semibold};
|
||||
font-size: ${theme.typography.size.sm};
|
||||
line-height: ${theme.typography.lineHeight.xs};
|
||||
vertical-align: baseline;
|
||||
background-color: ${colors.color};
|
||||
color: ${theme.palette.gray98};
|
||||
white-space: nowrap;
|
||||
text-shadow: none;
|
||||
padding: 3px 6px;
|
||||
border-radius: ${theme.border.radius.md};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
`,
|
||||
hover: css`
|
||||
&:hover {
|
||||
|
@ -79,6 +79,7 @@ export { TableCellDisplayMode, TableSortByFieldState } from './Table/types';
|
||||
export { TableInputCSV } from './TableInputCSV/TableInputCSV';
|
||||
export { TabsBar } from './Tabs/TabsBar';
|
||||
export { Tab } from './Tabs/Tab';
|
||||
export { VerticalTab } from './Tabs/VerticalTab';
|
||||
export { TabContent } from './Tabs/TabContent';
|
||||
export { Counter } from './Tabs/Counter';
|
||||
|
||||
|
@ -16,6 +16,8 @@ import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
|
||||
import { NONE, DURATION, TAG } from '../settings/SpanBarSettings';
|
||||
|
||||
import SpanBarRow from './SpanBarRow';
|
||||
|
||||
describe('<SpanBarRow>', () => {
|
||||
@ -43,11 +45,10 @@ describe('<SpanBarRow>', () => {
|
||||
showErrorIcon: false,
|
||||
getViewedBounds: () => ({ start: 0, end: 1 }),
|
||||
span: {
|
||||
duration: 'test-duration',
|
||||
duration: 9000,
|
||||
hasChildren: true,
|
||||
process: {
|
||||
serviceName: 'service-name',
|
||||
tags: [],
|
||||
},
|
||||
spanID,
|
||||
logs: [],
|
||||
@ -181,4 +182,89 @@ describe('<SpanBarRow>', () => {
|
||||
);
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -18,11 +18,12 @@ import * as React from 'react';
|
||||
import IoAlert from 'react-icons/lib/io/alert';
|
||||
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 { 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 { TraceSpan } from '../types/trace';
|
||||
|
||||
@ -290,6 +291,7 @@ type SpanBarRowProps = {
|
||||
className?: string;
|
||||
theme: GrafanaTheme2;
|
||||
color: string;
|
||||
spanBarOptions: SpanBarOptions | undefined;
|
||||
columnDivision: number;
|
||||
isChildrenExpanded: boolean;
|
||||
isDetailExpanded: boolean;
|
||||
@ -352,6 +354,7 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
|
||||
const {
|
||||
className,
|
||||
color,
|
||||
spanBarOptions,
|
||||
columnDivision,
|
||||
isChildrenExpanded,
|
||||
isDetailExpanded,
|
||||
@ -379,6 +382,7 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
|
||||
process: { serviceName },
|
||||
} = span;
|
||||
const label = formatDuration(duration);
|
||||
|
||||
const viewBounds = getViewedBounds(span.startTime, span.startTime + span.duration);
|
||||
const viewStart = viewBounds.start;
|
||||
const viewEnd = viewBounds.end;
|
||||
@ -473,7 +477,7 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
|
||||
)}
|
||||
</span>
|
||||
<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>
|
||||
{createSpanLink &&
|
||||
(() => {
|
||||
@ -542,6 +546,35 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
|
||||
</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);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user