Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9db8aaa6b1 | ||
|
|
5f687c8a4f | ||
|
|
b22be8f498 |
@@ -5489,7 +5489,10 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "6"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "9"]
|
||||
],
|
||||
"public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/response_parser.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
|
||||
40
.drone.star
40
.drone.star
@@ -11,28 +11,22 @@ load("scripts/drone/events/pr.star", "pr_pipelines")
|
||||
load("scripts/drone/events/main.star", "main_pipelines")
|
||||
load(
|
||||
"scripts/drone/events/release.star",
|
||||
"artifacts_page_pipeline",
|
||||
"enterprise2_pipelines",
|
||||
"enterprise_pipelines",
|
||||
"integration_test_pipelines",
|
||||
"oss_pipelines",
|
||||
"publish_artifacts_pipelines",
|
||||
"publish_npm_pipelines",
|
||||
"publish_packages_pipeline",
|
||||
)
|
||||
load(
|
||||
"scripts/drone/rgm.star",
|
||||
"rgm",
|
||||
)
|
||||
load(
|
||||
"scripts/drone/pipelines/publish_images.star",
|
||||
"publish_image_pipelines_public",
|
||||
"publish_image_pipelines_security",
|
||||
)
|
||||
load(
|
||||
"scripts/drone/pipelines/ci_images.star",
|
||||
"publish_ci_build_container_image_pipeline",
|
||||
"publish_ci_windows_test_image_pipeline",
|
||||
)
|
||||
load(
|
||||
"scripts/drone/pipelines/windows.star",
|
||||
"windows_test_backend",
|
||||
)
|
||||
load("scripts/drone/pipelines/github.star", "publish_github_pipeline")
|
||||
load("scripts/drone/pipelines/aws_marketplace.star", "publish_aws_marketplace_pipeline")
|
||||
load("scripts/drone/version.star", "version_branch_pipelines")
|
||||
load("scripts/drone/events/cron.star", "cronjobs")
|
||||
load("scripts/drone/vault.star", "secrets")
|
||||
@@ -41,19 +35,25 @@ def main(_ctx):
|
||||
return (
|
||||
pr_pipelines() +
|
||||
main_pipelines() +
|
||||
oss_pipelines() +
|
||||
enterprise_pipelines() +
|
||||
enterprise2_pipelines() +
|
||||
enterprise2_pipelines(
|
||||
prefix = "custom-",
|
||||
trigger = {"event": ["custom"]},
|
||||
) +
|
||||
publish_image_pipelines_public() +
|
||||
publish_image_pipelines_security() +
|
||||
publish_github_pipeline("public") +
|
||||
publish_github_pipeline("security") +
|
||||
publish_aws_marketplace_pipeline("public") +
|
||||
publish_artifacts_pipelines("security") +
|
||||
publish_artifacts_pipelines("public") +
|
||||
publish_npm_pipelines() +
|
||||
publish_packages_pipeline() +
|
||||
rgm() +
|
||||
[windows_test_backend({
|
||||
"event": ["promote"],
|
||||
"target": ["test-windows"],
|
||||
}, "oss", "testing")] +
|
||||
artifacts_page_pipeline() +
|
||||
version_branch_pipelines() +
|
||||
integration_test_pipelines() +
|
||||
publish_ci_windows_test_image_pipeline() +
|
||||
publish_ci_build_container_image_pipeline() +
|
||||
cronjobs() +
|
||||
secrets()
|
||||
)
|
||||
|
||||
5343
.drone.yml
5343
.drone.yml
File diff suppressed because it is too large
Load Diff
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@@ -234,7 +234,6 @@ WORKFLOW.md @torkelo
|
||||
/Dockerfile @grafana/grafana-delivery
|
||||
/Makefile @grafana/grafana-delivery
|
||||
/scripts/build/ @grafana/grafana-delivery
|
||||
/scripts/list-release-artifacts.sh @grafana/grafana-delivery
|
||||
|
||||
# OSS Plugin Partnerships backend code
|
||||
/pkg/tsdb/cloudwatch/ @grafana/aws-plugins
|
||||
@@ -577,7 +576,6 @@ embed.go @grafana/grafana-as-code
|
||||
/.github/pr-commands.json @marefr
|
||||
/.github/renovate.json5 @grafana/frontend-ops
|
||||
/.github/teams.yml @armandgrillet
|
||||
/.github/workflows/auto-milestone.yml @grafana/grafana-delivery
|
||||
/.github/workflows/backport.yml @grafana/grafana-delivery
|
||||
/.github/workflows/bump-version.yml @grafana/grafana-delivery
|
||||
/.github/workflows/close-milestone.yml @grafana/grafana-delivery
|
||||
@@ -600,8 +598,6 @@ embed.go @grafana/grafana-as-code
|
||||
/.github/workflows/pr-codeql-analysis-python.yml @DanCech
|
||||
/.github/workflows/pr-commands-closed.yml @tolzhabayev
|
||||
/.github/workflows/pr-commands.yml @marefr
|
||||
/.github/workflows/pr-patch-check.yml @grafana/grafana-delivery
|
||||
/.github/workflows/sync-mirror.yml @grafana/grafana-delivery
|
||||
/.github/workflows/publish-technical-documentation-next.yml @grafana/docs-grafana
|
||||
/.github/workflows/publish-technical-documentation-release.yml @grafana/docs-grafana
|
||||
/.github/workflows/remove-milestone.yml @grafana/user-essentials
|
||||
|
||||
2
.github/pr-checks.json
vendored
2
.github/pr-checks.json
vendored
@@ -46,4 +46,4 @@
|
||||
},
|
||||
"targetUrl": "https://github.com/grafana/grafana/blob/main/contribute/merge-pull-request.md#include-in-changelog-and-release-notes"
|
||||
}
|
||||
]
|
||||
]
|
||||
24
.github/workflows/auto-milestone.yml
vendored
24
.github/workflows/auto-milestone.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Auto-milestone
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- closed
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Generate token"
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
|
||||
with:
|
||||
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
|
||||
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
|
||||
|
||||
- name: Run auto-milestone
|
||||
uses: grafana/grafana-github-actions-go/auto-milestone@main
|
||||
with:
|
||||
pr: ${{ github.event.pull_request.number }}
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
8
.github/workflows/backport.yml
vendored
8
.github/workflows/backport.yml
vendored
@@ -17,16 +17,10 @@ jobs:
|
||||
ref: main
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: "Generate token"
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
|
||||
with:
|
||||
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
|
||||
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
|
||||
- name: Run backport
|
||||
uses: ./actions/backport
|
||||
with:
|
||||
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
token: ${{secrets.GH_BOT_ACCESS_TOKEN}}
|
||||
labelsToAdd: "backport,no-changelog"
|
||||
title: "[{{base}}] {{originalTitle}}"
|
||||
|
||||
14
.github/workflows/bump-version.yml
vendored
14
.github/workflows/bump-version.yml
vendored
@@ -6,12 +6,12 @@ on:
|
||||
description: 'Needs to match, exactly, the name of a milestone. The version to be released please respect: major.minor.patch or major.minor.patch-beta<number> format. example: 7.4.3 or 7.4.3-beta1'
|
||||
required: true
|
||||
env:
|
||||
YARN_ENABLE_IMMUTABLE_INSTALLS: false
|
||||
YARN_ENABLE_IMMUTABLE_INSTALLS: false
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
- uses: actions-ecosystem/action-regex-match@v2.0.2
|
||||
if: ${{ github.event.inputs.version != '' }}
|
||||
id: regex-match
|
||||
@@ -68,14 +68,8 @@ jobs:
|
||||
node-version: '16'
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: "Generate token"
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
|
||||
with:
|
||||
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
|
||||
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
|
||||
- name: Run bump version (manually invoked)
|
||||
- name: Run bump version (manually invoked)
|
||||
uses: ./actions/bump-version
|
||||
with:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
token: ${{ secrets.GH_BOT_ACCESS_TOKEN }}
|
||||
metricsWriteAPIKey: ${{ secrets.GRAFANA_MISC_STATS_API_KEY }}
|
||||
|
||||
14
.github/workflows/close-milestone.yml
vendored
14
.github/workflows/close-milestone.yml
vendored
@@ -11,7 +11,9 @@ on:
|
||||
description: Needs to match, exactly, the name of a milestone
|
||||
required: true
|
||||
type: string
|
||||
|
||||
secrets:
|
||||
token:
|
||||
required: true
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -24,20 +26,14 @@ jobs:
|
||||
ref: main
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: "Generate token"
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
|
||||
with:
|
||||
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
|
||||
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
|
||||
- name: Close milestone (manually invoked)
|
||||
if: ${{ github.event.inputs.version != '' }}
|
||||
uses: ./actions/close-milestone
|
||||
with:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
token: ${{ secrets.GH_BOT_ACCESS_TOKEN }}
|
||||
- name: Close milestone (workflow invoked)
|
||||
if: ${{ inputs.version_call != '' }}
|
||||
uses: ./actions/close-milestone
|
||||
with:
|
||||
version_call: ${{ inputs.version_call }}
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
token: ${{ secrets.token }}
|
||||
|
||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
name: Set go version
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20.10'
|
||||
go-version: '1.19.2'
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
12
.github/workflows/github-release.yml
vendored
12
.github/workflows/github-release.yml
vendored
@@ -3,7 +3,7 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
required: true
|
||||
required: true
|
||||
description: Needs to match, exactly, the name of a milestone (NO v prefix)
|
||||
jobs:
|
||||
main:
|
||||
@@ -14,17 +14,11 @@ jobs:
|
||||
with:
|
||||
repository: "grafana/grafana-github-actions"
|
||||
path: ./actions
|
||||
ref: main
|
||||
ref: main
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: "Generate token"
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
|
||||
with:
|
||||
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
|
||||
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
|
||||
- name: Run github release action
|
||||
uses: ./actions/github-release
|
||||
with:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
token: ${{secrets.GH_BOT_ACCESS_TOKEN}}
|
||||
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
|
||||
|
||||
8
.github/workflows/milestone.yml
vendored
8
.github/workflows/milestone.yml
vendored
@@ -10,10 +10,12 @@ jobs:
|
||||
uses: grafana/grafana/.github/workflows/remove-milestone.yml@main
|
||||
with:
|
||||
version_call: ${{ github.event.inputs.version_input }}
|
||||
secrets: inherit
|
||||
secrets:
|
||||
token: ${{ secrets.GH_BOT_ACCESS_TOKEN }}
|
||||
call-close-milestone:
|
||||
uses: grafana/grafana/.github/workflows/close-milestone.yml@main
|
||||
with:
|
||||
version_call: ${{ github.event.inputs.version_input }}
|
||||
secrets: inherit
|
||||
needs: call-remove-milestone
|
||||
secrets:
|
||||
token: ${{ secrets.GH_BOT_ACCESS_TOKEN }}
|
||||
needs: call-remove-milestone
|
||||
2
.github/workflows/pr-codeql-analysis-go.yml
vendored
2
.github/workflows/pr-codeql-analysis-go.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
- name: Set go version
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20.10'
|
||||
go-version: '1.19.2'
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
24
.github/workflows/pr-patch-check.yml
vendored
24
.github/workflows/pr-patch-check.yml
vendored
@@ -1,24 +0,0 @@
|
||||
# Owned by grafana-delivery-squad
|
||||
# Intended to be dropped into the base repo Ex: grafana/grafana
|
||||
name: Check for patch conflicts
|
||||
run-name: check-patch-conflicts-${{ github.base_ref }}-${{ github.head_ref }}
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
branches:
|
||||
- "main"
|
||||
- "v*.*.*"
|
||||
- "release-*"
|
||||
|
||||
# Since this is run on a pull request, we want to apply the patches intended for the
|
||||
# target branch onto the source branch, to verify compatibility before merging.
|
||||
jobs:
|
||||
trigger_downstream_patch_check:
|
||||
uses: grafana/security-patch-actions/.github/workflows/test-patches.yml@main
|
||||
with:
|
||||
src_repo: "${{ github.repository }}"
|
||||
src_ref: "${{ github.head_ref }}" # this is the source branch name, Ex: "feature/newthing"
|
||||
patch_repo: "${{ github.repository }}-security-patches"
|
||||
patch_ref: "${{ github.base_ref }}" # this is the target branch name, Ex: "main"
|
||||
secrets: inherit
|
||||
14
.github/workflows/remove-milestone.yml
vendored
14
.github/workflows/remove-milestone.yml
vendored
@@ -11,7 +11,9 @@ on:
|
||||
description: Needs to match, exactly, the name of a milestone
|
||||
required: true
|
||||
type: string
|
||||
|
||||
secrets:
|
||||
token:
|
||||
required: true
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -24,20 +26,14 @@ jobs:
|
||||
ref: main
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: "Generate token"
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
|
||||
with:
|
||||
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
|
||||
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
|
||||
- name: Remove milestone from open issues (manually invoked)
|
||||
if: ${{ github.event.inputs.version != '' }}
|
||||
uses: ./actions/remove-milestone
|
||||
with:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
token: ${{ secrets.GH_BOT_ACCESS_TOKEN }}
|
||||
- name: Remove milestone from open issues (workflow invoked)
|
||||
if: ${{ inputs.version_call != '' }}
|
||||
uses: ./actions/remove-milestone
|
||||
with:
|
||||
version_call: ${{ inputs.version_call }}
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
token: ${{ secrets.token }}
|
||||
|
||||
25
.github/workflows/sync-mirror.yml
vendored
25
.github/workflows/sync-mirror.yml
vendored
@@ -1,25 +0,0 @@
|
||||
# Owned by grafana-delivery-squad
|
||||
# Intended to be dropped into the base repo, Ex: grafana/grafana
|
||||
name: Sync to mirror
|
||||
run-name: sync-to-mirror-${{ github.ref_name }}
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
- "v*.*.*"
|
||||
- "release-*"
|
||||
|
||||
# This is run after the pull request has been merged, so we'll run against the target branch
|
||||
jobs:
|
||||
trigger_downstream_patch_mirror:
|
||||
concurrency: patch-mirror-${{ github.ref_name }}
|
||||
uses: grafana/security-patch-actions/.github/workflows/mirror-branch-and-apply-patches.yml@main
|
||||
if: github.repository == 'grafana/grafana'
|
||||
with:
|
||||
ref: "${{ github.ref_name }}" # this is the target branch name, Ex: "main"
|
||||
src_repo: "${{ github.repository }}"
|
||||
dest_repo: "${{ github.repository }}-security-mirror"
|
||||
patch_repo: "${{ github.repository }}-security-patches"
|
||||
secrets: inherit
|
||||
|
||||
10
.github/workflows/update-changelog.yml
vendored
10
.github/workflows/update-changelog.yml
vendored
@@ -9,12 +9,6 @@ jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Generate token"
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
|
||||
with:
|
||||
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
|
||||
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -23,8 +17,8 @@ jobs:
|
||||
ref: main
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: Run update changelog (manually invoked)
|
||||
- name: Run update changelog (manually invoked)
|
||||
uses: ./actions/update-changelog
|
||||
with:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
token: ${{ secrets.GH_BOT_ACCESS_TOKEN }}
|
||||
metricsWriteAPIKey: ${{ secrets.GRAFANA_MISC_STATS_API_KEY }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -186,6 +186,3 @@ public/locales/*/grafana_old.json
|
||||
deployment_tools_config.json
|
||||
|
||||
.betterer.cache
|
||||
|
||||
# Temporary file for backporting PRs
|
||||
.pr-body.txt
|
||||
|
||||
84
CHANGELOG.md
84
CHANGELOG.md
@@ -1,87 +1,3 @@
|
||||
<!-- 9.4.15 START -->
|
||||
|
||||
# 9.4.15 (2023-09-18)
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
- **Chore:** Upgrade Alpine base image to 3.18.3. [#74996](https://github.com/grafana/grafana/issues/74996), [@zerok](https://github.com/zerok)
|
||||
- **Chore:** Upgrade Go to 1.20.8. [#74981](https://github.com/grafana/grafana/issues/74981), [@zerok](https://github.com/zerok)
|
||||
|
||||
<!-- 9.4.15 END -->
|
||||
<!-- 9.4.14 START -->
|
||||
|
||||
# 9.4.14 (2023-09-05)
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
- **Prometheus:** Add present_over_time syntax highlighting. [#72366](https://github.com/grafana/grafana/issues/72366), [@arnaudlemaignen](https://github.com/arnaudlemaignen)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **LDAP:** Fix user disabling. [#74318](https://github.com/grafana/grafana/issues/74318), [@gamab](https://github.com/gamab)
|
||||
- **Plugins:** Only configure plugin proxy transport once. [#71740](https://github.com/grafana/grafana/issues/71740), [@wbrowne](https://github.com/wbrowne)
|
||||
- **InfluxDB:** Interpolate retention policies. [#71202](https://github.com/grafana/grafana/issues/71202), [@itsmylife](https://github.com/itsmylife)
|
||||
- **Azure Monitor:** Fix bug that did not show alert rule preview. [#68561](https://github.com/grafana/grafana/issues/68561), [@alyssabull](https://github.com/alyssabull)
|
||||
|
||||
<!-- 9.4.14 END -->
|
||||
<!-- 9.4.13 START -->
|
||||
|
||||
# 9.4.13 (2023-06-22)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **Auth:** Fixed CVE-2023-3128. [#70579](https://github.com/grafana/grafana/issues/70579), [@zerok](https://github.com/zerok)
|
||||
|
||||
<!-- 9.4.13 END -->
|
||||
<!-- 9.4.12 START -->
|
||||
|
||||
# 9.4.12 (2023-06-06)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **Query:** Prevent crash while executing concurrent mixed queries
|
||||
- **Alerting:** Require alert.notifications:write permissions to test receivers and templates
|
||||
- **RBAC:** Remove legacy AC editor and admin role on new dashboard route. [#68775](https://github.com/grafana/grafana/issues/68775), [@grafanabot](https://github.com/grafanabot)
|
||||
- **Revert:** Allow editors to access GET /datasources. [#68653](https://github.com/grafana/grafana/issues/68653), [@grafanabot](https://github.com/grafanabot)
|
||||
- **Explore:** Remove data source onboarding page. [#68642](https://github.com/grafana/grafana/issues/68642), [@grafanabot](https://github.com/grafanabot)
|
||||
|
||||
<!-- 9.4.12 END -->
|
||||
<!-- 9.4.10 START -->
|
||||
|
||||
# 9.4.10 (2023-05-08)
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
- **Chore:** Upgrade Go to 1.20.4. [#67760](https://github.com/grafana/grafana/issues/67760), [@papagian](https://github.com/papagian)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **AzureMonitor:** Fix logs query multi-resource and timespan values. [#67931](https://github.com/grafana/grafana/issues/67931), [@grafanabot](https://github.com/grafanabot)
|
||||
- **TimeSeries:** Fix leading null-fill for missing intervals. [#67572](https://github.com/grafana/grafana/issues/67572), [@leeoniya](https://github.com/leeoniya)
|
||||
- **Alerting:** Fix misleading status code in provisioning API. [#67357](https://github.com/grafana/grafana/issues/67357), [@grafanabot](https://github.com/grafanabot)
|
||||
- **Azure Monitor:** Fix bug that was not showing resources for certain locations. [#66617](https://github.com/grafana/grafana/issues/66617), [@grafanabot](https://github.com/grafanabot)
|
||||
|
||||
<!-- 9.4.10 END -->
|
||||
<!-- 9.4.9 START -->
|
||||
|
||||
# 9.4.9 (2023-04-24)
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
- **Chore:** Upgrade Go to 1.20.3. [#66836](https://github.com/grafana/grafana/issues/66836), [@sakjur](https://github.com/sakjur)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **Expressions/threshold:** Fix incorrect thresholds args length. [#66925](https://github.com/grafana/grafana/issues/66925), [@gillesdemey](https://github.com/gillesdemey)
|
||||
- **Alerting:** Fix share URL for Prometheus rules on subpath (#66752). [#66802](https://github.com/grafana/grafana/issues/66802), [@gillesdemey](https://github.com/gillesdemey)
|
||||
- **Trace View:** Update the queryType to traceql for checking if same trace when clicking span link. [#66670](https://github.com/grafana/grafana/issues/66670), [@ericmustin](https://github.com/ericmustin)
|
||||
- **Google Cloud Monitoring:** Fix project variable. [#66602](https://github.com/grafana/grafana/issues/66602), [@asimpson](https://github.com/asimpson)
|
||||
- **InfluxDB:** Fix querying with hardcoded retention policy. [#66587](https://github.com/grafana/grafana/issues/66587), [@itsmylife](https://github.com/itsmylife)
|
||||
- **Auth:** Remove the session cookie only if it's invalid or revoked. [#66430](https://github.com/grafana/grafana/issues/66430), [@mgyongyosi](https://github.com/mgyongyosi)
|
||||
- **AccessControl:** Allow editors to access GET /api/datasources. [#66375](https://github.com/grafana/grafana/issues/66375), [@mgyongyosi](https://github.com/mgyongyosi)
|
||||
- **CloudMonitoring:** Add project selector for MQL editor[fix]. [#65844](https://github.com/grafana/grafana/issues/65844), [@alyssabull](https://github.com/alyssabull)
|
||||
|
||||
<!-- 9.4.9 END -->
|
||||
<!-- 9.4.7 START -->
|
||||
|
||||
# 9.4.7 (2023-03-16)
|
||||
|
||||
10
Dockerfile
10
Dockerfile
@@ -1,8 +1,8 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG BASE_IMAGE=alpine:3.18.3
|
||||
ARG JS_IMAGE=node:18-alpine3.18
|
||||
ARG GO_IMAGE=golang:1.20.10-alpine3.18
|
||||
ARG BASE_IMAGE=alpine:3.17
|
||||
ARG JS_IMAGE=node:18-alpine3.17
|
||||
ARG GO_IMAGE=golang:1.20.3-alpine3.17
|
||||
|
||||
ARG GO_SRC=go-builder
|
||||
ARG JS_SRC=js-builder
|
||||
@@ -55,7 +55,6 @@ COPY pkg pkg
|
||||
COPY scripts scripts
|
||||
COPY conf conf
|
||||
COPY .github .github
|
||||
COPY LICENSE ./
|
||||
|
||||
RUN make build-go
|
||||
|
||||
@@ -99,7 +98,7 @@ RUN if grep -i -q alpine /etc/issue; then \
|
||||
elif grep -i -q ubuntu /etc/issue; then \
|
||||
DEBIAN_FRONTEND=noninteractive && \
|
||||
apt-get update && \
|
||||
apt-get install -y ca-certificates curl tzdata musl && \
|
||||
apt-get install -y ca-certificates curl tzdata && \
|
||||
apt-get autoremove -y && \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
else \
|
||||
@@ -154,7 +153,6 @@ RUN if [ ! $(getent group "$GF_GID") ]; then \
|
||||
|
||||
COPY --from=go-src /tmp/grafana/bin/grafana* /tmp/grafana/bin/*/grafana* ./bin/
|
||||
COPY --from=js-src /tmp/grafana/public ./public
|
||||
COPY --from=go-src /tmp/grafana/LICENSE ./
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -173,7 +173,7 @@ build-docker-full-ubuntu: ## Build Docker image based on Ubuntu for development.
|
||||
DOCKER_BUILDKIT=1 \
|
||||
docker build \
|
||||
--build-arg BASE_IMAGE=ubuntu:20.04 \
|
||||
--build-arg GO_IMAGE=golang:1.20.10 \
|
||||
--build-arg GO_IMAGE=golang:1.20.3 \
|
||||
--tag grafana/grafana:dev-ubuntu .
|
||||
|
||||
##@ Services
|
||||
|
||||
@@ -504,9 +504,6 @@ sigv4_verbose_logging = false
|
||||
# Set to true to enable Azure authentication option for HTTP-based datasources
|
||||
azure_auth_enabled = false
|
||||
|
||||
# Use email lookup in addition to the unique ID provided by the IdP
|
||||
oauth_allow_insecure_email_lookup = false
|
||||
|
||||
#################################### Anonymous Auth ######################
|
||||
[auth.anonymous]
|
||||
# enable anonymous access
|
||||
@@ -538,11 +535,6 @@ allowed_organizations =
|
||||
role_attribute_path =
|
||||
role_attribute_strict = false
|
||||
allow_assign_grafana_admin = false
|
||||
skip_org_role_sync = false
|
||||
tls_skip_verify_insecure = false
|
||||
tls_client_cert =
|
||||
tls_client_key =
|
||||
tls_client_ca =
|
||||
|
||||
#################################### GitLab Auth #########################
|
||||
[auth.gitlab]
|
||||
|
||||
@@ -508,9 +508,6 @@
|
||||
# Set to skip the organization role from JWT login and use system's role assignment instead.
|
||||
; skip_org_role_sync = false
|
||||
|
||||
# Use email lookup in addition to the unique ID provided by the IdP
|
||||
;oauth_allow_insecure_email_lookup = false
|
||||
|
||||
#################################### Anonymous Auth ######################
|
||||
[auth.anonymous]
|
||||
# enable anonymous access
|
||||
@@ -542,7 +539,6 @@
|
||||
;role_attribute_path =
|
||||
;role_attribute_strict = false
|
||||
;allow_assign_grafana_admin = false
|
||||
;skip_org_role_sync = false
|
||||
|
||||
#################################### GitLab Auth #########################
|
||||
[auth.gitlab]
|
||||
|
||||
@@ -13,6 +13,7 @@ The following checklist/summary should give you a quick overview of what to ask/
|
||||
- Reviewed and approved?
|
||||
- All checks passed?
|
||||
- Proper pull request title?
|
||||
- Milestone assigned?
|
||||
- Add to changelog/release notes?
|
||||
- Needs backporting?
|
||||
|
||||
@@ -39,18 +40,10 @@ See [formatting guidelines](create-pull-request.md#formatting-guidelines) for mo
|
||||
|
||||
### Assign a milestone
|
||||
|
||||
Several things in the Grafana release process requires at least pull requests to be in a milestone, for example [generating changelog/release notes](#include-in-changelog-and-release-notes).
|
||||
A milestone **should** be added to every pull request. Several things in the Grafana release process requires at least pull requests to be in a milestone, for example [generating changelog/release notes](#include-in-changelog-and-release-notes).
|
||||
|
||||
This makes it easier to track what changes go into a certain release. Without this information, release managers have to go through git commits which is not an efficient process.
|
||||
|
||||
That being said, _you don't have to assign a milestone manually_ to a pull request.
|
||||
Instead, when it is merged & closed then a bot will look for the most appropriate miletone and assign it to the pull request.
|
||||
|
||||
That milestone should always reflect the branch that the pull request is merged into.
|
||||
For every major and minor release there is a milestone ending with `.x` (e.g. `10.0.x` for the 10.0.x releases).
|
||||
Pull requests targetting `main` should use the `.x` milestone of the next minor (or major) version (you can find that version number inside the `package.json` file).
|
||||
Backport pull requestss should use the version of the target branch (e.g. `9.4.x` for the `v9.4.x` branch).
|
||||
|
||||
### Include in changelog and release notes?
|
||||
|
||||
At Grafana we generate the [changelog](https://github.com/grafana/grafana/blob/main/CHANGELOG.md) and [release notes](https://grafana.com/docs/grafana/latest/release-notes/) based on merged pull requests. Including changes in the changelog/release notes is very important to provide a somewhat complete picture of what changes a Grafana release actually includes.
|
||||
@@ -85,15 +78,15 @@ The changelog/release notes are divided into sections and here's a description o
|
||||
|
||||
**Features and enhancements:**
|
||||
|
||||
Labeled with `add to changelog` and any of the other section rules don't apply.
|
||||
Milestone assigned and labeled with `add to changelog` and any of the other section rules don't apply.
|
||||
|
||||
**Bug fixes:**
|
||||
|
||||
Labeled with `add to changelog` and either labeled with `type/bug` or the pull request title contains `fix` or `fixes`.
|
||||
Milestone assigned and labeled with `add to changelog` and either labeled with `type/bug` or the pull request title contains `fix` or `fixes`.
|
||||
|
||||
**Plugin development fixes & changes:**
|
||||
|
||||
Labeled with `area/grafana/toolkit`, `area/grafana/ui` or `area/grafana/runtime`.
|
||||
Milestone assigned and labeled with `area/grafana/toolkit`, `area/grafana/ui` or `area/grafana/runtime`.
|
||||
|
||||
**Deprecations:**
|
||||
|
||||
|
||||
@@ -29,13 +29,12 @@ function Foo(props: FooProps) {
|
||||
const styles = useStyles2(getStyles);
|
||||
// Use styles with className
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) =>
|
||||
css({
|
||||
padding: theme.spacing(1, 2),
|
||||
});
|
||||
```
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => css({
|
||||
padding: theme.spacing(1,2)
|
||||
});
|
||||
|
||||
#### Get the theme object
|
||||
|
||||
```tsx
|
||||
|
||||
@@ -1,8 +1,33 @@
|
||||
.ONESHELL:
|
||||
.DELETE_ON_ERROR:
|
||||
export SHELL := bash
|
||||
export SHELLOPTS := pipefail:errexit
|
||||
MAKEFLAGS += --warn-undefined-variables
|
||||
MAKEFLAGS += --no-builtin-rule
|
||||
.PHONY: pull docs docs-quick docs-no-pull docs-test docs-local-static
|
||||
|
||||
include docs.mk
|
||||
PODMAN = $(shell if command -v podman >/dev/null 2>&1; then echo podman; else echo docker; fi)
|
||||
IMAGE = grafana/docs-base:latest
|
||||
CONTENT_PATH = /hugo/content/docs/grafana/latest
|
||||
LOCAL_STATIC_PATH = ../../website/static
|
||||
PORT = 3002:3002
|
||||
|
||||
pull:
|
||||
$(PODMAN) pull $(IMAGE)
|
||||
|
||||
docs: pull
|
||||
$(PODMAN) run --init -v $(shell pwd)/sources:$(CONTENT_PATH):Z -p $(PORT) --rm -it $(IMAGE) make server
|
||||
|
||||
docs-preview: pull
|
||||
$(PODMAN) run --init -v $(shell pwd)/sources:$(CONTENT_PATH):Z -p $(PORT) --rm -it $(IMAGE) make server BUILD_DRAFTS=true
|
||||
|
||||
docs-no-pull:
|
||||
$(PODMAN) run --init -v $(shell pwd)/sources:$(CONTENT_PATH):Z -p $(PORT) --rm -it $(IMAGE) make server
|
||||
|
||||
docs-test: pull
|
||||
$(PODMAN) run --init -v $(shell pwd)/sources:$(CONTENT_PATH):Z --rm -it $(IMAGE) make prod
|
||||
|
||||
# expects that you have grafana/website checked out in same path as the grafana repo.
|
||||
docs-local-static: pull
|
||||
if [ ! -d "$(LOCAL_STATIC_PATH)" ]; then echo "local path (website project) $(LOCAL_STATIC_PATH) not found"]; exit 1; fi
|
||||
$(PODMAN) run --init -v $(shell pwd)/sources:$(CONTENT_PATH):Z \
|
||||
-v $(shell pwd)/$(LOCAL_STATIC_PATH):/hugo/static:Z -p $(PORT) --rm -it $(IMAGE)
|
||||
|
||||
.PHONY: doc-validator/%
|
||||
doc-validator/%: ## Run doc-validator on a specific path. To lint the path /docs/sources/administration, run 'make doc-validator/administration'.
|
||||
doc-validator/%:
|
||||
$(PODMAN) run --init -v "$(shell pwd)/sources:/sources" grafana/doc-validator:latest --skip-image-validation --include=$(subst doc-validator/,,$@) ./sources /docs/grafana/latest
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
# Building the docs locally
|
||||
|
||||
When you contribute to documentation, it's a good practice to build the docs on your local machine to make sure your changes appear as you expect. This README explains the process for doing that.
|
||||
|
||||
To build a local version, you need to run a process in a Docker container.
|
||||
Grafana periodically updates the Docker image, [`docs-base`](https://hub.docker.com/r/grafana/docs-base), to update the styling of the Docs.
|
||||
When you contribute to documentation, it is a good practice to build the docs on your local machine to make sure your changes appear as you expect. This README explains the process for doing that.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Docker >= 2.1.0.3
|
||||
- Yarn >= 1.22.4
|
||||
Docker >= 2.1.0.3
|
||||
Yarn >= 1.22.4
|
||||
|
||||
## Build the doc site
|
||||
|
||||
First, make sure the Docker daemon is running on your machine. Then, follow these steps:
|
||||
|
||||
1. On the command line, first change to the docs folder: `cd docs`.
|
||||
1. Run `make docs`. This launches a preview of the website with the current grafana docs at `http://localhost:3002/docs/grafana/latest/` which will refresh automatically when changes are made to content in the `sources` directory.
|
||||
1. Run `make docs`. This launches a preview of the website with the current grafana docs at `http://localhost:3002/docs/grafana/next/` which will refresh automatically when changes are made to content in the `sources` directory.
|
||||
|
||||
If you have the grafana/website repo checked out in the same directory as the grafana repo, then you can run `make docs-local-static` to use local assets (such as images).
|
||||
|
||||
@@ -57,7 +52,7 @@ To specify different menu text from the page title, use the front matter paramet
|
||||
|
||||
### Add images
|
||||
|
||||
Please see our help documentation on [Image, diagram, and screenshot guidelines](https://grafana.com/docs/writers-toolkit/writing-guide/image-guidelines/) for comprehensive information.
|
||||
Images are currently hosted in the grafana/website repo.
|
||||
|
||||
---
|
||||
|
||||
|
||||
117
docs/docs.mk
117
docs/docs.mk
@@ -1,117 +0,0 @@
|
||||
# The source of this file is https://raw.githubusercontent.com/grafana/writers-toolkit/main/docs/docs.mk.
|
||||
# 4.0.0 (2023-06-06)
|
||||
include variables.mk
|
||||
-include variables.mk.local
|
||||
|
||||
.ONESHELL:
|
||||
.DELETE_ON_ERROR:
|
||||
export SHELL := bash
|
||||
export SHELLOPTS := pipefail:errexit
|
||||
MAKEFLAGS += --warn-undefined-variables
|
||||
MAKEFLAGS += --no-builtin-rule
|
||||
|
||||
.DEFAULT_GOAL: help
|
||||
|
||||
# Adapted from https://www.thapaliya.com/en/writings/well-documented-makefiles/
|
||||
.PHONY: help
|
||||
help: ## Display this help.
|
||||
help:
|
||||
@awk 'BEGIN { \
|
||||
FS = ": ##"; \
|
||||
printf "Usage:\n make <target>\n\nTargets:\n" \
|
||||
} \
|
||||
/^[a-zA-Z0-9_\.\-\/%]+: ##/ { printf " %-15s %s\n", $$1, $$2 }' \
|
||||
$(MAKEFILE_LIST)
|
||||
|
||||
GIT_ROOT := $(shell git rev-parse --show-toplevel)
|
||||
|
||||
PODMAN := $(shell if command -v podman >/dev/null 2>&1; then echo podman; else echo docker; fi)
|
||||
|
||||
ifeq ($(PROJECTS),)
|
||||
$(error "PROJECTS variable must be defined in variables.mk")
|
||||
endif
|
||||
|
||||
# First project is considered the primary one used for doc-validator.
|
||||
PRIMARY_PROJECT := $(subst /,-,$(firstword $(subst :, ,$(firstword $(PROJECTS)))))
|
||||
|
||||
# Name for the container.
|
||||
ifeq ($(origin DOCS_CONTAINER), undefined)
|
||||
export DOCS_CONTAINER := $(PRIMARY_PROJECT)-docs
|
||||
endif
|
||||
|
||||
# Host port to publish container port to.
|
||||
ifeq ($(origin DOCS_HOST_PORT), undefined)
|
||||
export DOCS_HOST_PORT := 3002
|
||||
endif
|
||||
|
||||
# Container image used to perform Hugo build.
|
||||
ifeq ($(origin DOCS_IMAGE), undefined)
|
||||
export DOCS_IMAGE := grafana/docs-base:latest
|
||||
endif
|
||||
|
||||
# Container image used for doc-validator linting.
|
||||
ifeq ($(origin DOC_VALIDATOR_IMAGE), undefined)
|
||||
export DOC_VALIDATOR_IMAGE := grafana/doc-validator:latest
|
||||
endif
|
||||
|
||||
# Container image used for vale linting.
|
||||
ifeq ($(origin VALE_IMAGE), undefined)
|
||||
export VALE_IMAGE := grafana/vale:latest
|
||||
endif
|
||||
|
||||
# PATH-like list of directories within which to find projects.
|
||||
# If all projects are checked out into the same directory, ~/repos/ for example, then the default should work.
|
||||
ifeq ($(origin REPOS_PATH), undefined)
|
||||
export REPOS_PATH := $(realpath $(GIT_ROOT)/..)
|
||||
endif
|
||||
|
||||
# How to treat Hugo relref errors.
|
||||
ifeq ($(origin HUGO_REFLINKSERRORLEVEL), undefined)
|
||||
export HUGO_REFLINKSERRORLEVEL := WARNING
|
||||
endif
|
||||
|
||||
.PHONY: docs-rm
|
||||
docs-rm: ## Remove the docs container.
|
||||
$(PODMAN) rm -f $(DOCS_CONTAINER)
|
||||
|
||||
.PHONY: docs-pull
|
||||
docs-pull: ## Pull documentation base image.
|
||||
$(PODMAN) pull -q $(DOCS_IMAGE)
|
||||
|
||||
make-docs: ## Fetch the latest make-docs script.
|
||||
make-docs:
|
||||
if [[ ! -f "$(PWD)/make-docs" ]]; then
|
||||
echo 'WARN: No make-docs script found in the working directory. Run `make update` to download it.' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
.PHONY: docs
|
||||
docs: ## Serve documentation locally, which includes pulling the latest `DOCS_IMAGE` (default: `grafana/docs-base:latest`) container image. See also `docs-no-pull`.
|
||||
docs: docs-pull make-docs
|
||||
$(PWD)/make-docs $(PROJECTS)
|
||||
|
||||
.PHONY: docs-no-pull
|
||||
docs-no-pull: ## Serve documentation locally without pulling the `DOCS_IMAGE` (default: `grafana/docs-base:latest`) container image.
|
||||
docs-no-pull: make-docs
|
||||
$(PWD)/make-docs $(PROJECTS)
|
||||
|
||||
.PHONY: docs-debug
|
||||
docs-debug: ## Run Hugo web server with debugging enabled. TODO: support all SERVER_FLAGS defined in website Makefile.
|
||||
docs-debug: make-docs
|
||||
WEBSITE_EXEC='hugo server --bind 0.0.0.0 --port 3002 --debug' $(PWD)/make-docs $(PROJECTS)
|
||||
|
||||
.PHONY: doc-validator
|
||||
doc-validator: ## Run doc-validator on the entire docs folder.
|
||||
doc-validator: make-docs
|
||||
DOCS_IMAGE=$(DOC_VALIDATOR_IMAGE) $(PWD)/make-docs $(PROJECTS)
|
||||
|
||||
.PHONY: vale
|
||||
vale: ## Run vale on the entire docs folder.
|
||||
vale: make-docs
|
||||
DOCS_IMAGE=$(VALE_IMAGE) $(PWD)/make-docs $(PROJECTS)
|
||||
|
||||
.PHONY: update
|
||||
update: ## Fetch the latest version of this Makefile and the `make-docs` script from Writers' Toolkit.
|
||||
curl -s -LO https://raw.githubusercontent.com/grafana/writers-toolkit/main/docs/docs.mk
|
||||
curl -s -LO https://raw.githubusercontent.com/grafana/writers-toolkit/main/docs/make-docs
|
||||
chmod +x make-docs
|
||||
515
docs/make-docs
515
docs/make-docs
@@ -1,515 +0,0 @@
|
||||
#!/bin/sh
|
||||
# The source of this file is https://raw.githubusercontent.com/grafana/writers-toolkit/main/docs/make-docs.
|
||||
# 4.1.0 (2023-06-16)
|
||||
|
||||
set -ef
|
||||
|
||||
readonly DOCS_CONTAINER="${DOCS_CONTAINER:-make-docs}"
|
||||
readonly DOCS_HOST_PORT="${DOCS_HOST_PORT:-3002}"
|
||||
readonly DOCS_IMAGE="${DOCS_IMAGE:-grafana/docs-base:latest}"
|
||||
|
||||
readonly DOC_VALIDATOR_INCLUDE="${DOC_VALIDATOR_INCLUDE:-.+\.md$}"
|
||||
readonly DOC_VALIDATOR_SKIP_CHECKS="${DOC_VALIDATOR_SKIP_CHECKS:-^image-}"
|
||||
|
||||
readonly HUGO_REFLINKSERRORLEVEL="${HUGO_REFLINKSERRORLEVEL:-WARNING}"
|
||||
readonly VALE_MINALERTLEVEL="${VALE_MINALERTLEVEL:-error}"
|
||||
readonly WEBSITE_EXEC="${WEBSITE_EXEC:-make server-docs}"
|
||||
# If set, the docs-base image will run a prebuild script that sets up Hugo mounts.
|
||||
readonly WEBSITE_MOUNTS="${WEBSITE_MOUNTS:-}"
|
||||
|
||||
PODMAN="$(if command -v podman >/dev/null 2>&1; then echo podman; else echo docker; fi)"
|
||||
|
||||
if ! command -v curl >/dev/null 2>&1; then
|
||||
if ! command -v wget >/dev/null 2>&1; then
|
||||
errr 'either `curl` or `wget` must be installed for this script to work.'
|
||||
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! command -v "${PODMAN}" >/dev/null 2>&1; then
|
||||
errr 'either `podman` or `docker` must be installed for this script to work.'
|
||||
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
about() {
|
||||
cat <<EOF
|
||||
Test documentation locally with multiple source repositories.
|
||||
|
||||
The REPOS_PATH environment variable is a colon (:) separated list of paths in which to look for project repositories.
|
||||
EOF
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage:
|
||||
REPOS_PATH=<PATH[:<PATH>...]> $0 [<PROJECT>[:<VERSION>[:<REPO>[:<DIR>]]]...]
|
||||
|
||||
Examples:
|
||||
REPOS_PATH=~/ext/grafana/ $0 writers-toolkit tempo:latest helm-charts/mimir-distributed:latest:mimir:docs/sources/mimir-distributed
|
||||
EOF
|
||||
}
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
cat <<EOF >&2
|
||||
ERRR: arguments required but not supplied.
|
||||
|
||||
$(about)
|
||||
|
||||
$(usage)
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
readonly REPOS_PATH="${REPOS_PATH:-$(realpath "$(git rev-parse --show-toplevel)/..")}"
|
||||
|
||||
if [ -z "${REPOS_PATH}" ]; then
|
||||
cat <<EOF >&2
|
||||
ERRR: REPOS_PATH environment variable is required but has not been provided.
|
||||
|
||||
$(usage)
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOURCES_as_code='as-code-docs'
|
||||
SOURCES_enterprise_metrics='backend-enterprise'
|
||||
SOURCES_enterprise_metrics_='backend-enterprise'
|
||||
SOURCES_grafana_cloud='website'
|
||||
SOURCES_grafana_cloud_k6='k6-docs'
|
||||
SOURCES_grafana_cloud_data_configuration_integrations='cloud-onboarding'
|
||||
SOURCES_grafana_cloud_frontend_observability_faro_web_sdk='faro-web-sdk'
|
||||
SOURCES_grafana_cloud_machine_learning='machine-learning'
|
||||
SOURCES_helm_charts_mimir_distributed='mimir'
|
||||
SOURCES_helm_charts_tempo_distributed='tempo'
|
||||
SOURCES_opentelemetry='opentelemetry-docs'
|
||||
|
||||
VERSIONS_as_code='UNVERSIONED'
|
||||
VERSIONS_grafana_cloud='UNVERSIONED'
|
||||
VERSIONS_grafana_cloud_k6='UNVERSIONED'
|
||||
VERSIONS_grafana_cloud_data_configuration_integrations='UNVERSIONED'
|
||||
VERSIONS_grafana_cloud_frontend_observability_faro_web_sdk='UNVERSIONED'
|
||||
VERSIONS_grafana_cloud_machine_learning='UNVERSIONED'
|
||||
VERSIONS_opentelemetry='UNVERSIONED'
|
||||
VERSIONS_technical_documentation='UNVERSIONED'
|
||||
VERSIONS_website='UNVERSIONED'
|
||||
VERSIONS_writers_toolkit='UNVERSIONED'
|
||||
|
||||
PATHS_grafana_cloud='content/docs/grafana-cloud'
|
||||
PATHS_helm_charts_mimir_distributed='docs/sources/helm-charts/mimir-distributed'
|
||||
PATHS_helm_charts_tempo_distributed='docs/sources/helm-charts/tempo-distributed'
|
||||
PATHS_mimir='docs/sources/mimir'
|
||||
PATHS_tempo='docs/sources/tempo'
|
||||
PATHS_website='content/docs'
|
||||
|
||||
# identifier STR
|
||||
# Replace characters that are not valid in an identifier with underscores.
|
||||
identifier() {
|
||||
echo "$1" | tr -C '[:alnum:]_\n' '_'
|
||||
}
|
||||
|
||||
# aget ARRAY KEY
|
||||
# Get the value of KEY from associative array ARRAY.
|
||||
# Characters that are not valid in an identifier are replaced with underscores.
|
||||
aget() {
|
||||
eval echo '$'"$(identifier "$1")_$(identifier "$2")"
|
||||
}
|
||||
|
||||
# new_proj populates a new project structure.
|
||||
new_proj() {
|
||||
_project="$1"
|
||||
_version="$2"
|
||||
_repo="$3"
|
||||
_path="$4"
|
||||
|
||||
# If version is not set, use the script mapping of project to default versions if it exists.
|
||||
# Fallback to 'latest'.
|
||||
if [ -z "${_version}" ]; then
|
||||
if [ -z "$(aget VERSIONS "${_project}")" ]; then
|
||||
_version=latest
|
||||
else
|
||||
_version="$(aget VERSIONS "${_project}")"
|
||||
fi
|
||||
fi
|
||||
|
||||
# If repo is not set, use the script mapping of project to repo name if it exists.
|
||||
# Fallback to using the project name.
|
||||
if [ -z "${_repo}" ]; then
|
||||
if [ -z "$(aget SOURCES "${_project}")" ]; then
|
||||
_repo="${_project}"
|
||||
else
|
||||
_repo="$(aget SOURCES "${_project}")"
|
||||
fi
|
||||
fi
|
||||
|
||||
# If path is not set, use the script mapping of project to docs sources path if it exists.
|
||||
# Fallback to using 'docs/sources'.
|
||||
if [ -z "${_path}" ]; then
|
||||
if [ -z "$(aget PATHS "${_project}")" ]; then
|
||||
_path="docs/sources"
|
||||
else
|
||||
_path="$(aget PATHS "${_project}")"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "${_project}:${_version}:${_repo}:${_path}"
|
||||
unset _project _version _repo _path
|
||||
}
|
||||
|
||||
# proj_url returns the webserver URL for a project.
|
||||
# It expects a complete project structure as input.
|
||||
proj_url() {
|
||||
IFS=: read -r _project _version _ _ <<POSIX_HERESTRING
|
||||
$1
|
||||
POSIX_HERESTRING
|
||||
|
||||
if [ "${_project}" = 'website' ]; then
|
||||
echo "http://localhost:${DOCS_HOST_PORT}/docs/"
|
||||
|
||||
unset _project _version
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -z "${_version}" ] || [ "${_version}" = 'UNVERSIONED' ]; then
|
||||
echo "http://localhost:${DOCS_HOST_PORT}/docs/${_project}/"
|
||||
else
|
||||
echo "http://localhost:${DOCS_HOST_PORT}/docs/${_project}/${_version}/"
|
||||
fi
|
||||
|
||||
unset _project _version
|
||||
}
|
||||
|
||||
# proj_ver returns the version for a project.
|
||||
# It expects a complete project structure as input.
|
||||
proj_ver() {
|
||||
IFS=: read -r _ _ver _ _ <<POSIX_HERESTRING
|
||||
$1
|
||||
POSIX_HERESTRING
|
||||
|
||||
echo "${_ver}"
|
||||
unset _ver
|
||||
}
|
||||
|
||||
# proj_dst returns the container path to content source for a project.
|
||||
# It expects a complete project structure as input.
|
||||
proj_dst() {
|
||||
IFS=: read -r _project _version _ _ <<POSIX_HERESTRING
|
||||
$1
|
||||
POSIX_HERESTRING
|
||||
|
||||
if [ "${_project}" = 'website' ]; then
|
||||
echo '/hugo/content/docs'
|
||||
|
||||
unset _project _version
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -z "${_version}" ] || [ "${_version}" = 'UNVERSIONED' ]; then
|
||||
echo "/hugo/content/docs/${_project}"
|
||||
else
|
||||
echo "/hugo/content/docs/${_project}/${_version}"
|
||||
fi
|
||||
|
||||
unset _project _version
|
||||
}
|
||||
|
||||
# repo_path returns the host path to the project repository.
|
||||
# It looks for the provided repository name in each of the paths specified in the REPOS_PATH environment variable.
|
||||
repo_path() {
|
||||
_repo="$1"
|
||||
IFS=:
|
||||
for lookup in ${REPOS_PATH}; do
|
||||
if [ -d "${lookup}/${_repo}" ]; then
|
||||
echo "${lookup}/${_repo}"
|
||||
unset _path _repo
|
||||
return
|
||||
fi
|
||||
done
|
||||
unset IFS
|
||||
|
||||
errr "could not find project '${_repo}' in any of the paths in REPOS_PATH '${REPOS_PATH}'."
|
||||
note "you must have a checkout of the project '${_repo}' at '${REPOS_PATH##:*}/${_repo}'."
|
||||
note "if you have cloned the repository into a directory with a different name, consider changing it to ${_repo}."
|
||||
|
||||
unset _repo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# proj_src returns the host path to content source for a project.
|
||||
# It expects a complete project structure as input.
|
||||
# It looks for the provided repository name in each of the paths specified in the REPOS_PATH environment variable.
|
||||
proj_src() {
|
||||
IFS=: read -r _ _ _repo _path <<POSIX_HERESTRING
|
||||
$1
|
||||
POSIX_HERESTRING
|
||||
|
||||
_repo="$(repo_path "${_repo}")"
|
||||
echo "${_repo}/${_path}"
|
||||
|
||||
unset _path _repo
|
||||
}
|
||||
|
||||
# proj_canonical returns the canonical absolute path partial URI for a project.
|
||||
# It expects a complete project structure as input.
|
||||
proj_canonical() {
|
||||
IFS=: read -r _project _version _ _ <<POSIX_HERESTRING
|
||||
$1
|
||||
POSIX_HERESTRING
|
||||
|
||||
if [ "${_project}" = 'website' ]; then
|
||||
echo '/docs'
|
||||
|
||||
unset _project _version
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -z "${_version}" ] || [ "${_version}" = 'UNVERSIONED' ]; then
|
||||
echo "/docs/${_project}"
|
||||
else
|
||||
echo "/docs/${_project}/${_version}"
|
||||
fi
|
||||
|
||||
unset _project _version
|
||||
}
|
||||
|
||||
proj_to_url_src_dst_ver() {
|
||||
_url="$(proj_url "$1")"
|
||||
_src="$(proj_src "$1")"
|
||||
_dst="$(proj_dst "$1")"
|
||||
_ver="$(proj_ver "$1")"
|
||||
|
||||
echo "${_url}^${_src}^${_dst}^${_ver}"
|
||||
unset _url _src _dst _ver
|
||||
}
|
||||
|
||||
url_src_dst_vers() {
|
||||
for arg in "$@"; do
|
||||
IFS=: read -r _project _version _repo _path <<POSIX_HERESTRING
|
||||
$arg
|
||||
POSIX_HERESTRING
|
||||
|
||||
case "${_project}" in
|
||||
# Workaround for arbitrary mounts where the version field is expected to be the local directory
|
||||
# and the repo field is expected to be the container directory.
|
||||
arbitrary)
|
||||
echo "${_project}^${_version}^${_repo}^" # TODO
|
||||
;;
|
||||
logs)
|
||||
proj_to_url_src_dst_ver "$(new_proj loki "${_version}")"
|
||||
proj_to_url_src_dst_ver "$(new_proj enterprise-logs "${_version}")"
|
||||
;;
|
||||
metrics)
|
||||
proj_to_url_src_dst_ver "$(new_proj mimir "${_version}")"
|
||||
proj_to_url_src_dst_ver "$(new_proj helm-charts/mimir-distributed "${_version}")"
|
||||
proj_to_url_src_dst_ver "$(new_proj enterprise-metrics "${_version}")"
|
||||
;;
|
||||
traces)
|
||||
proj_to_url_src_dst_ver "$(new_proj tempo "${_version}")"
|
||||
proj_to_url_src_dst_ver "$(new_proj enterprise-traces "${_version}")"
|
||||
;;
|
||||
*)
|
||||
proj_to_url_src_dst_ver "$(new_proj "${_project}" "${_version}" "${_repo}" "${_path}")"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
unset _project _version _repo _path
|
||||
}
|
||||
|
||||
await_build() {
|
||||
url="$1"
|
||||
req="$(if command -v curl >/dev/null 2>&1; then echo 'curl -s -o /dev/null'; else echo 'wget -q'; fi)"
|
||||
|
||||
sleep 2
|
||||
|
||||
if ${req} "${url}"; then
|
||||
echo
|
||||
echo "View documentation locally:"
|
||||
for x in ${url_src_dst_vers}; do
|
||||
IFS='^' read -r url _ _ <<POSIX_HERESTRING
|
||||
$x
|
||||
POSIX_HERESTRING
|
||||
|
||||
if [ -n "${url}" ]; then
|
||||
if [ "${_url}" != "arbitrary" ]; then
|
||||
echo " ${url}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo
|
||||
echo 'Press Ctrl+C to stop the server'
|
||||
else
|
||||
echo
|
||||
errr 'The build was interrupted or a build error occurred, check the previous logs for possible causes.'
|
||||
fi
|
||||
|
||||
unset url req
|
||||
}
|
||||
|
||||
debg() {
|
||||
if [ -n "${DEBUG}" ]; then
|
||||
echo "DEBG: $1" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
errr() {
|
||||
echo "ERRR: $1" >&2
|
||||
}
|
||||
|
||||
note() {
|
||||
echo "NOTE: $1" >&2
|
||||
}
|
||||
|
||||
url_src_dst_vers="$(url_src_dst_vers "$@")"
|
||||
|
||||
volumes=""
|
||||
redirects=""
|
||||
|
||||
for arg in "$@"; do
|
||||
IFS=: read -r _project _ _repo _ <<POSIX_HERESTRING
|
||||
${arg}
|
||||
POSIX_HERESTRING
|
||||
if [ "${_project}" = website ]; then
|
||||
_repo="$(repo_path website)"
|
||||
volumes="--volume=${_repo}/config:/hugo/config"
|
||||
volumes="${volumes} --volume=${_repo}/layouts/partials:/hugo/layouts/partials"
|
||||
volumes="${volumes} --volume=${_repo}/layouts/shortcodes:/hugo/layouts/shortcodes"
|
||||
fi
|
||||
unset _project _repo
|
||||
done
|
||||
|
||||
for x in ${url_src_dst_vers}; do
|
||||
IFS='^' read -r _url _src _dst _ver <<POSIX_HERESTRING
|
||||
$x
|
||||
POSIX_HERESTRING
|
||||
|
||||
if [ "${_url}" != "arbitrary" ]; then
|
||||
if [ ! -f "${_src}/_index.md" ]; then
|
||||
errr "Index file '${_src}/_index.md' does not exist."
|
||||
note "Is '${_src}' the correct source directory?"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
debg "DEBG: Mounting '${_src}' at container path '${_dst}'"
|
||||
|
||||
if [ -z "${volumes}" ]; then
|
||||
volumes="--volume=${_src}:${_dst}"
|
||||
else
|
||||
volumes="${volumes} --volume=${_src}:${_dst}"
|
||||
fi
|
||||
|
||||
if [ -n "${_ver}" ] && [ "${_ver}" != 'UNVERSIONED' ]; then
|
||||
if [ -z "${redirects}" ]; then
|
||||
redirects="${_dst}^${_ver}"
|
||||
else
|
||||
redirects="${redirects} ${_dst}^${_ver}"
|
||||
fi
|
||||
fi
|
||||
unset _url _src _dst _ver
|
||||
done
|
||||
|
||||
IFS=':' read -r image _ <<POSIX_HERESTRING
|
||||
${DOCS_IMAGE}
|
||||
POSIX_HERESTRING
|
||||
|
||||
case "${image}" in
|
||||
'grafana/doc-validator')
|
||||
proj="$(new_proj "$1")"
|
||||
echo
|
||||
"${PODMAN}" run \
|
||||
--init \
|
||||
--interactive \
|
||||
--name "${DOCS_CONTAINER}" \
|
||||
--platform linux/amd64 \
|
||||
--rm \
|
||||
--tty \
|
||||
${volumes} \
|
||||
"${DOCS_IMAGE}" \
|
||||
"--include=${DOC_VALIDATOR_INCLUDE}" \
|
||||
"--skip-checks=${DOC_VALIDATOR_SKIP_CHECKS}" \
|
||||
/hugo/content/docs \
|
||||
"$(proj_canonical "${proj}")" | sed "s#$(proj_dst "${proj}")#sources#"
|
||||
;;
|
||||
'grafana/vale')
|
||||
proj="$(new_proj "$1")"
|
||||
echo
|
||||
"${PODMAN}" run \
|
||||
--init \
|
||||
--interactive \
|
||||
--name "${DOCS_CONTAINER}" \
|
||||
--platform linux/amd64 \
|
||||
--rm \
|
||||
--tty \
|
||||
${volumes} \
|
||||
"${DOCS_IMAGE}" \
|
||||
"--minAlertLevel=${VALE_MINALERTLEVEL}" \
|
||||
--config=/etc/vale/.vale.ini \
|
||||
--output=line \
|
||||
/hugo/content/docs | sed "s#$(proj_dst "${proj}")#sources#"
|
||||
;;
|
||||
*)
|
||||
tempfile="$(mktemp -t make-docs.XXX)"
|
||||
cat <<EOF >"${tempfile}"
|
||||
#!/usr/bin/env bash
|
||||
for redirect in ${redirects}; do
|
||||
IFS='^' read -r path ver <<<"\${redirect}"
|
||||
echo -e "---\\nredirectURL: \"\${path/\/hugo\/content/}\"\\ntype: redirect\\nversioned: true\\n---\\n" > "\${path/\${ver}/_index.md}"
|
||||
done
|
||||
|
||||
for x in "${url_src_dst_vers}"; do
|
||||
IFS='^' read -r _ _ dst _ <<<"\${x}"
|
||||
|
||||
while [[ -n "\${dst}" ]]; do
|
||||
touch "\${dst}/_index.md"
|
||||
dst="\${dst%/*}"
|
||||
done
|
||||
done
|
||||
|
||||
if [[ -n "${WEBSITE_MOUNTS}" ]]; then
|
||||
unset WEBSITE_SKIP_MOUNTS
|
||||
fi
|
||||
|
||||
${WEBSITE_EXEC}
|
||||
EOF
|
||||
chmod +x "${tempfile}"
|
||||
volumes="${volumes} --volume=$(realpath "${tempfile}"):/entrypoint"
|
||||
readonly volumes
|
||||
|
||||
IFS='' read -r cmd <<EOF
|
||||
${PODMAN} run \
|
||||
--env=HUGO_REFLINKSERRORLEVEL=${HUGO_REFLINKSERRORLEVEL} \
|
||||
--init \
|
||||
--interactive \
|
||||
--name=${DOCS_CONTAINER} \
|
||||
--platform=linux/amd64 \
|
||||
--publish=${DOCS_HOST_PORT}:3002 \
|
||||
--publish=3003:3003 \
|
||||
--rm \
|
||||
--tty \
|
||||
${volumes} \
|
||||
${DOCS_IMAGE} \
|
||||
/entrypoint
|
||||
EOF
|
||||
await_build http://localhost:3002 &
|
||||
|
||||
if [ -n "${DEBUG}" ]; then
|
||||
${cmd}
|
||||
else
|
||||
${cmd} 2>&1| sed \
|
||||
-e '/Web Server is available at http:\/\/localhost:3003\/ (bind address 0.0.0.0)/ d' \
|
||||
-e '/^hugo server/ d' \
|
||||
-e '/fatal: not a git repository (or any parent up to mount point \/)/ d' \
|
||||
-e '/Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)./ d' \
|
||||
-e "/Makefile:[0-9]*: warning: overriding recipe for target 'docs'/ d" \
|
||||
-e "/docs.mk:[0-9]*: warning: ignoring old recipe for target 'docs'/ d" \
|
||||
-e '/\/usr\/bin\/make -j 2 proxy hserver-docs HUGO_PORT=3003/ d' \
|
||||
-e '/website-proxy/ d' \
|
||||
-e '/rm -rf dist*/ d' \
|
||||
-e '/Press Ctrl+C to stop/ d' \
|
||||
-e '/make/ d' || echo
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
@@ -103,7 +103,7 @@ GF_SERVER_ROOT_URL=https://grafana.example.com/
|
||||
|
||||
### Step 4. Restart Grafana
|
||||
|
||||
To finalize the installation of Grafana Enterprise, restart Grafana to enable all Grafana Enterprise features. Refer to [restart Grafana]({{< relref "../../setup-grafana/start-restart-grafana/" >}}) for more information.
|
||||
To finalize the installation of Grafana Enterprise, restart Grafana to enable all Grafana Enterprise features. Refer to [restart Grafana]({{< relref "../../setup-grafana/restart-grafana/" >}}) for more information.
|
||||
|
||||
## License expiration
|
||||
|
||||
@@ -125,7 +125,7 @@ If your license has expired, most of Grafana keeps working as normal. Some enter
|
||||
2. Log in to your [Grafana Cloud Account](/login) and make sure you're in the correct organization in the dropdown at the top of the page.
|
||||
3. Under the **Grafana Enterprise** section in the menu bar to the left, choose licenses and download the currently valid license with which you want to run Grafana. If you cannot see a valid license on Grafana.com, please contact your account manager at Grafana Labs to renew your subscription.
|
||||
4. Replace the current `license.jwt`-file with the one you've just downloaded.
|
||||
5. [Restart Grafana]({{< relref "../../setup-grafana/start-restart-grafana/" >}}).
|
||||
5. [Restart Grafana]({{< relref "../../setup-grafana/restart-grafana/" >}}).
|
||||
|
||||
### If your license expires
|
||||
|
||||
|
||||
@@ -121,6 +121,6 @@ To restart Grafana on a Kubernetes cluster,
|
||||
|
||||
1. After you update the service, navigate to your Grafana instance, sign in with Grafana Admin credentials, and navigate to the Statistics and Licensing page to validate that your license is active.
|
||||
|
||||
For more information about restarting Grafana, refer to [Restart Grafana]({{< relref "../../../../setup-grafana/start-restart-grafana/" >}}).
|
||||
For more information about restarting Grafana, refer to [Restart Grafana]({{< relref "../../../../setup-grafana/restart-grafana/" >}}).
|
||||
|
||||
> If you experience issues when you update the EKS cluster, refer to [Amazon EKS troubleshooting](https://docs.aws.amazon.com/eks/latest/userguide/troubleshooting.html).
|
||||
|
||||
@@ -127,4 +127,4 @@ Choose one of the following options to update the [license_validation_type]({{<
|
||||
|
||||
To activate Grafana Enterprise features, start (or restart) Grafana.
|
||||
|
||||
For information about restarting Grafana, refer to [Restart Grafana]({{< relref "../../../../setup-grafana/start-restart-grafana/" >}}).
|
||||
For information about restarting Grafana, refer to [Restart Grafana]({{< relref "../../../../setup-grafana/restart-grafana/" >}}).
|
||||
|
||||
@@ -61,7 +61,7 @@ Currently we do not provide any scripts/manifests for configuring Grafana. Rathe
|
||||
| --------- | -------------------------------------------------------------------------------------------------------------- |
|
||||
| Puppet | [https://forge.puppet.com/puppet/grafana](https://forge.puppet.com/puppet/grafana) |
|
||||
| Ansible | [https://github.com/cloudalchemy/ansible-grafana](https://github.com/cloudalchemy/ansible-grafana) |
|
||||
| Chef | [https://github.com/sous-chefs/chef-grafana](https://github.com/sous-chefs/chef-grafana) |
|
||||
| Chef | [https://github.com/JonathanTron/chef-grafana](https://github.com/JonathanTron/chef-grafana) |
|
||||
| Saltstack | [https://github.com/salt-formulas/salt-formula-grafana](https://github.com/salt-formulas/salt-formula-grafana) |
|
||||
| Jsonnet | [https://github.com/grafana/grafonnet-lib/](https://github.com/grafana/grafonnet-lib/) |
|
||||
|
||||
|
||||
@@ -10,9 +10,7 @@ weight: 80
|
||||
|
||||
# RBAC permissions, actions, and scopes
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud Advanced](/docs/grafana-cloud).
|
||||
{{% /admonition %}}
|
||||
> **Note:** Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud Advanced](/docs/grafana-cloud).
|
||||
|
||||
A permission is comprised of an action and a scope. When creating a custom role, consider the actions the user can perform and the resource(s) on which they can perform those actions.
|
||||
|
||||
@@ -25,129 +23,128 @@ To learn more about the Grafana resources to which you can apply RBAC, refer to
|
||||
|
||||
The following list contains role-based access control actions.
|
||||
|
||||
| Action | Applicable scope | Description |
|
||||
| ------------------------------------ | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `alert.instances.external:read` | `datasources:*`<br>`datasources:uid:*` | Read alerts and silences in data sources that support alerting. |
|
||||
| `alert.instances.external:write` | `datasources:*`<br>`datasources:uid:*` | Manage alerts and silences in data sources that support alerting. |
|
||||
| `alert.instances:create` | n/a | Create silences in the current organization. |
|
||||
| `alert.instances:read` | n/a | Read alerts and silences in the current organization. |
|
||||
| `alert.instances:write` | n/a | Update and expire silences in the current organization. |
|
||||
| `alert.notifications.external:read` | `datasources:*`<br>`datasources:uid:*` | Read templates, contact points, notification policies, and mute timings in data sources that support alerting. |
|
||||
| `alert.notifications.external:write` | `datasources:*`<br>`datasources:uid:*` | Manage templates, contact points, notification policies, and mute timings in data sources that support alerting. |
|
||||
| `alert.notifications:write` | n/a | Manage templates, contact points, notification policies, and mute timings in the current organization. |
|
||||
| `alert.notifications:read` | n/a | Read all templates, contact points, notification policies, and mute timings in the current organization. |
|
||||
| `alert.rules.external:read` | `datasources:*`<br>`datasources:uid:*` | Read alert rules in data sources that support alerting (Prometheus, Mimir, and Loki) |
|
||||
| `alert.rules.external:write` | `datasources:*`<br>`datasources:uid:*` | Create, update, and delete alert rules in data sources that support alerting (Mimir and Loki). |
|
||||
| `alert.rules:create` | `folders:*`<br>`folders:uid:*` | Create Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.rules:delete` | `folders:*`<br>`folders:uid:*` | Delete Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.rules:read` | `folders:*`<br>`folders:uid:*` | Read Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.rules:write` | `folders:*`<br>`folders:uid:*` | Update Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.provisioning:read` | n/a | Read all Grafana alert rules, notification policies, etc via provisioning API. Permissions to folders and datasource are not required. |
|
||||
| `alert.provisioning:write` | n/a | Update all Grafana alert rules, notification policies, etc via provisioning API. Permissions to folders and datasource are not required. |
|
||||
| `annotations:create` | `annotations:*`<br>`annotations:type:*` | Create annotations. |
|
||||
| `annotations:delete` | `annotations:*`<br>`annotations:type:*` | Delete annotations. |
|
||||
| `annotations:read` | `annotations:*`<br>`annotations:type:*` | Read annotations and annotation tags. |
|
||||
| `annotations:write` | `annotations:*`<br>`annotations:type:*` | Update annotations. |
|
||||
| `apikeys:create` | n/a | Create API keys. |
|
||||
| `apikeys:read` | `apikeys:*`<br>`apikeys:id:*` | Read API keys. |
|
||||
| `apikeys:delete` | `apikeys:*`<br>`apikeys:id:*` | Delete API keys. |
|
||||
| `dashboards:create` | `folders:*`<br>`folders:uid:*` | Create dashboards in one or more folders and their subfolders. |
|
||||
| `dashboards:delete` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Delete one or more dashboards. |
|
||||
| `dashboards.insights:read` | n/a | Read dashboard insights data and see presence indicators. |
|
||||
| `dashboards.permissions:read` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Read permissions for one or more dashboards. |
|
||||
| `dashboards.permissions:write` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Update permissions for one or more dashboards. |
|
||||
| `dashboards:read` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Read one or more dashboards. |
|
||||
| `dashboards:write` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Update one or more dashboards. |
|
||||
| `dashboards.public:write` | `dashboards:*`<br>`dashboards:uid:*` | Write public dashboard configuration. |
|
||||
| `datasources.caching:read` | `datasources:*`<br>`datasources:uid:*` | Read data source query caching settings. |
|
||||
| `datasources.caching:write` | `datasources:*`<br>`datasources:uid:*` | Update data source query caching settings. |
|
||||
| `datasources:create` | n/a | Create data sources. |
|
||||
| `datasources:delete` | `datasources:*`<br>`datasources:uid:*` | Delete data sources. |
|
||||
| `datasources:explore` | n/a | Enable access to the **Explore** tab. |
|
||||
| `datasources.id:read` | `datasources:*`<br>`datasources:uid:*` | Read data source IDs. |
|
||||
| `datasources.insights:read` | n/a | Read data sources insights data. |
|
||||
| `datasources.permissions:read` | `datasources:*`<br>`datasources:uid:*` | List data source permissions. |
|
||||
| `datasources.permissions:write` | `datasources:*`<br>`datasources:uid:*` | Update data source permissions. |
|
||||
| `datasources:query` | `datasources:*`<br>`datasources:uid:*` | Query data sources. |
|
||||
| `datasources:read` | `datasources:*`<br>`datasources:uid:*` | List data sources. |
|
||||
| `datasources:write` | `datasources:*`<br>`datasources:uid:*` | Update data sources. |
|
||||
| `folders.permissions:read` | `folders:*`<br>`folders:uid:*` | Read permissions for one or more folders and their subfolders. |
|
||||
| `folders.permissions:write` | `folders:*`<br>`folders:uid:*` | Update permissions for one or more folders and their subfolders. |
|
||||
| `folders:create` | n/a | Create folders in the root level. If granted together with `folders:write`, also allows creating subfolders under all folders that the user can update. |
|
||||
| `folders:delete` | `folders:*`<br>`folders:uid:*` | Delete one or more folders and their subfolders. |
|
||||
| `folders:read` | `folders:*`<br>`folders:uid:*` | Read one or more folders and their subfolders. |
|
||||
| `folders:write` | `folders:*`<br>`folders:uid:*` | Update one or more folders and their subfolders. If granted together with `folders:create` permission, also allows creating subfolders under these folders. |
|
||||
| `ldap.config:reload` | n/a | Reload the LDAP configuration. |
|
||||
| `ldap.status:read` | n/a | Verify the availability of the LDAP server or servers. |
|
||||
| `ldap.user:read` | n/a | Read users via LDAP. |
|
||||
| `ldap.user:sync` | n/a | Sync users via LDAP. |
|
||||
| `licensing.reports:read` | n/a | Get custom permission reports. |
|
||||
| `licensing:delete` | n/a | Delete the license token. |
|
||||
| `licensing:read` | n/a | Read licensing information. |
|
||||
| `licensing:write` | n/a | Update the license token. |
|
||||
| `org.users:write` | `users:*` <br> `users:id:*` | Update the organization role (`Viewer`, `Editor`, or `Admin`) of a user. |
|
||||
| `org.users:add` | `users:*` | Add a user to an organization or invite a new user to an organization. |
|
||||
| `org.users:read` | `users:*` <br> `users:id:*` | Get user profiles within an organization. |
|
||||
| `org.users:remove` | `users:*` <br> `users:id:*` | Remove a user from an organization. |
|
||||
| `org:create` | n/a | Create an organization. |
|
||||
| `orgs.preferences:read` | `orgs:*` <br> `orgs:id:*` | Read organization preferences. |
|
||||
| `orgs.preferences:write` | `orgs:*` <br> `orgs:id:*` | Update organization preferences. |
|
||||
| `orgs.quotas:read` | `orgs:*` <br> `orgs:id:*` | Read organization quotas. |
|
||||
| `orgs.quotas:write` | `orgs:*` <br> `orgs:id:*` | Update organization quotas. |
|
||||
| `orgs:delete` | `orgs:*` <br> `orgs:id:*` | Delete one or more organizations. |
|
||||
| `orgs:read` | `orgs:*` <br> `orgs:id:*` | Read one or more organizations. |
|
||||
| `orgs:write` | `orgs:*` <br> `orgs:id:*` | Update one or more organizations. |
|
||||
| `plugins.app:access` | `plugins:*` <br> `plugins:id:*` | Access one or more application plugins (still enforcing the organization role) |
|
||||
| `plugins:install` | n/a | Install and uninstall plugins. |
|
||||
| `plugins:write` | `plugins:*` <br> `plugins:id:*` | Edit settings for one or more plugins. |
|
||||
| `provisioning:reload` | `provisioners:*` | Reload provisioning files. To find the exact scope for specific provisioner, see [Scope definitions]({{< relref "#scope-definitions" >}}). |
|
||||
| `reports:create` | n/a | Create reports. |
|
||||
| `reports:write` | `reports:*` <br> `reports:id:*` | Update reports. |
|
||||
| `reports.settings:read` | n/a | Read report settings. |
|
||||
| `reports.settings:write` | n/a | Update report settings. |
|
||||
| `reports:delete` | `reports:*` <br> `reports:id:*` | Delete reports. |
|
||||
| `reports:read` | `reports:*` | List all available reports or get a specific report. |
|
||||
| `reports:send` | `reports:*` | Send a report email. |
|
||||
| `roles:delete` | `permissions:type:delegate` | Delete a custom role. |
|
||||
| `roles:read` | `roles:*` <br> `roles:uid:*` | List roles and read a specific with its permissions. |
|
||||
| `roles:write` | `permissions:type:delegate` | Create or update a custom role. |
|
||||
| `roles:write` | `permissions:type:escalate` | Reset basic roles to their default permissions. |
|
||||
| `server.stats:read` | n/a | Read Grafana instance statistics. |
|
||||
| `serviceaccounts:write` | `serviceaccounts:*` | Create Grafana service accounts. |
|
||||
| `serviceaccounts:create` | n/a | Update Grafana service accounts. |
|
||||
| `serviceaccounts:delete` | `serviceaccounts:*` | Delete Grafana service accounts. |
|
||||
| `serviceaccounts:read` | `serviceaccounts:*` | Read Grafana service accounts. |
|
||||
| `serviceaccounts.permissions:write` | `serviceaccounts:*` | Update Grafana service account permissions to control who can do what with the service account. |
|
||||
| `serviceaccounts.permissions:read` | `serviceaccounts:*` | Read Grafana service account permissions to see who can do what with the service account. |
|
||||
| `settings:read` | `settings:*`<br>`settings:auth.saml:*`<br>`settings:auth.saml:enabled` (property level) | Read the [Grafana configuration settings]({{< relref "../../../../setup-grafana/configure-grafana/" >}}) |
|
||||
| `settings:write` | `settings:*`<br>`settings:auth.saml:*`<br>`settings:auth.saml:enabled` (property level) | Update any Grafana configuration settings that can be [updated at runtime]({{< relref "../../../../setup-grafana/configure-grafana/settings-updates-at-runtime" >}}). |
|
||||
| `status:accesscontrol` | `services:accesscontrol` | Get access-control enabled status. |
|
||||
| `teams.permissions:read` | `teams:*`<br>`teams:id:*` | Read members and Team Sync setup for teams. |
|
||||
| `teams.permissions:write` | `teams:*`<br>`teams:id:*` | Add, remove and update members and manage Team Sync setup for teams. |
|
||||
| `teams.roles:add` | `permissions:type:delegate` | Assign a role to a team. |
|
||||
| `teams.roles:read` | `teams:*` | List roles assigned directly to a team. |
|
||||
| `teams.roles:remove` | `permissions:type:delegate` | Unassign a role from a team. |
|
||||
| `teams:create` | n/a | Create teams. |
|
||||
| `teams:delete` | `teams:*`<br>`teams:id:*` | Delete one or more teams. |
|
||||
| `teams:read` | `teams:*`<br>`teams:id:*` | Read one or more teams and team preferences. |
|
||||
| `teams:write` | `teams:*`<br>`teams:id:*` | Update one or more teams and team preferences. |
|
||||
| `users.authtoken:read` | `global.users:*` <br> `global.users:id:*` | List authentication tokens that are assigned to a user. |
|
||||
| `users.authtoken:write` | `global.users:*` <br> `global.users:id:*` | Update authentication tokens that are assigned to a user. |
|
||||
| `users.password:write` | `global.users:*` <br> `global.users:id:*` | Update a user’s password. |
|
||||
| `users.permissions:read` | `users:*` | List permissions of a user. |
|
||||
| `users.permissions:write` | `global.users:*` <br> `global.users:id:*` | Update a user’s organization-level permissions. |
|
||||
| `users.quotas:read` | `global.users:*` <br> `global.users:id:*` | List a user’s quotas. |
|
||||
| `users.quotas:write` | `global.users:*` <br> `global.users:id:*` | Update a user’s quotas. |
|
||||
| `users.roles:add` | `permissions:type:delegate` | Assign a role to a user or a service account. |
|
||||
| `users.roles:read` | `users:*` | List roles assigned directly to a user or a service account. |
|
||||
| `users.roles:remove` | `permissions:type:delegate` | Unassign a role from a user or a service account. |
|
||||
| `users:create` | n/a | Create a user. |
|
||||
| `users:delete` | `global.users:*` <br> `global.users:id:*` | Delete a user. |
|
||||
| `users:disable` | `global.users:*` <br> `global.users:id:*` | Disable a user. |
|
||||
| `users:enable` | `global.users:*` <br> `global.users:id:*` | Enable a user. |
|
||||
| `users:logout` | `global.users:*` <br> `global.users:id:*` | Sign out a user. |
|
||||
| `users:read` | `global.users:*` | Read or search user profiles. |
|
||||
| `users:write` | `global.users:*` <br> `global.users:id:*` | Update a user’s profile. |
|
||||
| Action | Applicable scope | Description |
|
||||
| ------------------------------------ | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `alert.instances.external:read` | `datasources:*`<br>`datasources:uid:*` | Read alerts and silences in data sources that support alerting. |
|
||||
| `alert.instances.external:write` | `datasources:*`<br>`datasources:uid:*` | Manage alerts and silences in data sources that support alerting. |
|
||||
| `alert.instances:create` | n/a | Create silences in the current organization. |
|
||||
| `alert.instances:read` | n/a | Read alerts and silences in the current organization. |
|
||||
| `alert.instances:write` | n/a | Update and expire silences in the current organization. |
|
||||
| `alert.notifications.external:read` | `datasources:*`<br>`datasources:uid:*` | Read templates, contact points, notification policies, and mute timings in data sources that support alerting. |
|
||||
| `alert.notifications.external:write` | `datasources:*`<br>`datasources:uid:*` | Manage templates, contact points, notification policies, and mute timings in data sources that support alerting. |
|
||||
| `alert.notifications:write` | n/a | Manage templates, contact points, notification policies, and mute timings in the current organization. |
|
||||
| `alert.notifications:read` | n/a | Read all templates, contact points, notification policies, and mute timings in the current organization. |
|
||||
| `alert.rules.external:read` | `datasources:*`<br>`datasources:uid:*` | Read alert rules in data sources that support alerting (Prometheus, Mimir, and Loki) |
|
||||
| `alert.rules.external:write` | `datasources:*`<br>`datasources:uid:*` | Create, update, and delete alert rules in data sources that support alerting (Mimir and Loki). |
|
||||
| `alert.rules:create` | `folders:*`<br>`folders:uid:*` | Create Grafana alert rules in a folder. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.rules:delete` | `folders:*`<br>`folders:uid:*` | Delete Grafana alert rules in a folder. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.rules:read` | `folders:*`<br>`folders:uid:*` | Read Grafana alert rules in a folder. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.rules:write` | `folders:*`<br>`folders:uid:*` | Update Grafana alert rules in a folder. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.provisioning:read` | n/a | Read all Grafana alert rules, notification policies, etc via provisioning API. Permissions to folders and datasource are not required. |
|
||||
| `alert.provisioning:write` | n/a | Update all Grafana alert rules, notification policies, etc via provisioning API. Permissions to folders and datasource are not required. |
|
||||
| `annotations:create` | `annotations:*`<br>`annotations:type:*` | Create annotations. |
|
||||
| `annotations:delete` | `annotations:*`<br>`annotations:type:*` | Delete annotations. |
|
||||
| `annotations:read` | `annotations:*`<br>`annotations:type:*` | Read annotations and annotation tags. |
|
||||
| `annotations:write` | `annotations:*`<br>`annotations:type:*` | Update annotations. |
|
||||
| `apikeys:create` | n/a | Create API keys. |
|
||||
| `apikeys:read` | `apikeys:*`<br>`apikeys:id:*` | Read API keys. |
|
||||
| `apikeys:delete` | `apikeys:*`<br>`apikeys:id:*` | Delete API keys. |
|
||||
| `dashboards:create` | `folders:*`<br>`folders:uid:*` | Create dashboards in one or more folders. |
|
||||
| `dashboards:delete` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Delete one or more dashboards. |
|
||||
| `dashboards.insights:read` | n/a | Read dashboard insights data and see presence indicators. |
|
||||
| `dashboards.permissions:read` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Read permissions for one or more dashboards. |
|
||||
| `dashboards.permissions:write` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Update permissions for one or more dashboards. |
|
||||
| `dashboards:read` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Read one or more dashboards. |
|
||||
| `dashboards:write` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Update one or more dashboards. |
|
||||
| `datasources.caching:read` | `datasources:*`<br>`datasources:uid:*` | Read data source query caching settings. |
|
||||
| `datasources.caching:write` | `datasources:*`<br>`datasources:uid:*` | Update data source query caching settings. |
|
||||
| `datasources:create` | n/a | Create data sources. |
|
||||
| `datasources:delete` | `datasources:*`<br>`datasources:uid:*` | Delete data sources. |
|
||||
| `datasources:explore` | n/a | Enable access to the **Explore** tab. |
|
||||
| `datasources.id:read` | `datasources:*`<br>`datasources:uid:*` | Read data source IDs. |
|
||||
| `datasources.insights:read` | n/a | Read data sources insights data. |
|
||||
| `datasources.permissions:read` | `datasources:*`<br>`datasources:uid:*` | List data source permissions. |
|
||||
| `datasources.permissions:write` | `datasources:*`<br>`datasources:uid:*` | Update data source permissions. |
|
||||
| `datasources:query` | `datasources:*`<br>`datasources:uid:*` | Query data sources. |
|
||||
| `datasources:read` | `datasources:*`<br>`datasources:uid:*` | List data sources. |
|
||||
| `datasources:write` | `datasources:*`<br>`datasources:uid:*` | Update data sources. |
|
||||
| `folders.permissions:read` | `folders:*`<br>`folders:uid:*` | Read permissions for one or more folders. |
|
||||
| `folders.permissions:write` | `folders:*`<br>`folders:uid:*` | Update permissions for one or more folders. |
|
||||
| `folders:create` | n/a | Create folders. |
|
||||
| `folders:delete` | `folders:*`<br>`folders:uid:*` | Delete one or more folders. |
|
||||
| `folders:read` | `folders:*`<br>`folders:uid:*` | Read one or more folders. |
|
||||
| `folders:write` | `folders:*`<br>`folders:uid:*` | Update one or more folders. |
|
||||
| `ldap.config:reload` | n/a | Reload the LDAP configuration. |
|
||||
| `ldap.status:read` | n/a | Verify the availability of the LDAP server or servers. |
|
||||
| `ldap.user:read` | n/a | Read users via LDAP. |
|
||||
| `ldap.user:sync` | n/a | Sync users via LDAP. |
|
||||
| `licensing.reports:read` | n/a | Get custom permission reports. |
|
||||
| `licensing:delete` | n/a | Delete the license token. |
|
||||
| `licensing:read` | n/a | Read licensing information. |
|
||||
| `licensing:write` | n/a | Update the license token. |
|
||||
| `org.users:write` | `users:*` <br> `users:id:*` | Update the organization role (`Viewer`, `Editor`, or `Admin`) of a user. |
|
||||
| `org.users:add` | `users:*` | Add a user to an organization or invite a new user to an organization. |
|
||||
| `org.users:read` | `users:*` <br> `users:id:*` | Get user profiles within an organization. |
|
||||
| `org.users:remove` | `users:*` <br> `users:id:*` | Remove a user from an organization. |
|
||||
| `org:create` | n/a | Create an organization. |
|
||||
| `orgs.preferences:read` | `orgs:*` <br> `orgs:id:*` | Read organization preferences. |
|
||||
| `orgs.preferences:write` | `orgs:*` <br> `orgs:id:*` | Update organization preferences. |
|
||||
| `orgs.quotas:read` | `orgs:*` <br> `orgs:id:*` | Read organization quotas. |
|
||||
| `orgs.quotas:write` | `orgs:*` <br> `orgs:id:*` | Update organization quotas. |
|
||||
| `orgs:delete` | `orgs:*` <br> `orgs:id:*` | Delete one or more organizations. |
|
||||
| `orgs:read` | `orgs:*` <br> `orgs:id:*` | Read one or more organizations. |
|
||||
| `orgs:write` | `orgs:*` <br> `orgs:id:*` | Update one or more organizations. |
|
||||
| `plugins.app:access` | `plugins:*` <br> `plugins:id:*` | Access one or more application plugins (still enforcing the organization role) |
|
||||
| `plugins:install` | n/a | Install and uninstall plugins. |
|
||||
| `plugins:write` | `plugins:*` <br> `plugins:id:*` | Edit settings for one or more plugins. |
|
||||
| `provisioning:reload` | `provisioners:*` | Reload provisioning files. To find the exact scope for specific provisioner, see [Scope definitions]({{< relref "#scope-definitions" >}}). |
|
||||
| `reports:create` | n/a | Create reports. |
|
||||
| `reports:write` | `reports:*` <br> `reports:id:*` | Update reports. |
|
||||
| `reports.settings:read` | n/a | Read report settings. |
|
||||
| `reports.settings:write` | n/a | Update report settings. |
|
||||
| `reports:delete` | `reports:*` <br> `reports:id:*` | Delete reports. |
|
||||
| `reports:read` | `reports:*` | List all available reports or get a specific report. |
|
||||
| `reports:send` | `reports:*` | Send a report email. |
|
||||
| `roles:delete` | `permissions:type:delegate` | Delete a custom role. |
|
||||
| `roles:read` | `roles:*` <br> `roles:uid:*` | List roles and read a specific with its permissions. |
|
||||
| `roles:write` | `permissions:type:delegate` | Create or update a custom role. |
|
||||
| `roles:write` | `permissions:type:escalate` | Reset basic roles to their default permissions. |
|
||||
| `server.stats:read` | n/a | Read Grafana instance statistics. |
|
||||
| `serviceaccounts:write` | `serviceaccounts:*` | Create Grafana service accounts. |
|
||||
| `serviceaccounts:create` | n/a | Update Grafana service accounts. |
|
||||
| `serviceaccounts:delete` | `serviceaccounts:*` | Delete Grafana service accounts. |
|
||||
| `serviceaccounts:read` | `serviceaccounts:*` | Read Grafana service accounts. |
|
||||
| `serviceaccounts.permissions:write` | `serviceaccounts:*` | Update Grafana service account permissions to control who can do what with the service account. |
|
||||
| `serviceaccounts.permissions:read` | `serviceaccounts:*` | Read Grafana service account permissions to see who can do what with the service account. |
|
||||
| `settings:read` | `settings:*`<br>`settings:auth.saml:*`<br>`settings:auth.saml:enabled` (property level) | Read the [Grafana configuration settings]({{< relref "../../../../setup-grafana/configure-grafana/" >}}) |
|
||||
| `settings:write` | `settings:*`<br>`settings:auth.saml:*`<br>`settings:auth.saml:enabled` (property level) | Update any Grafana configuration settings that can be [updated at runtime]({{< relref "../../../../setup-grafana/configure-grafana/settings-updates-at-runtime" >}}). |
|
||||
| `status:accesscontrol` | `services:accesscontrol` | Get access-control enabled status. |
|
||||
| `teams.permissions:read` | `teams:*`<br>`teams:id:*` | Read members and External Group Synchronization setup for teams. |
|
||||
| `teams.permissions:write` | `teams:*`<br>`teams:id:*` | Add, remove and update members and manage External Group Synchronization setup for teams. |
|
||||
| `teams.roles:add` | `permissions:type:delegate` | Assign a role to a team. |
|
||||
| `teams.roles:read` | `teams:*` | List roles assigned directly to a team. |
|
||||
| `teams.roles:remove` | `permissions:type:delegate` | Unassign a role from a team. |
|
||||
| `teams:create` | n/a | Create teams. |
|
||||
| `teams:delete` | `teams:*`<br>`teams:id:*` | Delete one or more teams. |
|
||||
| `teams:read` | `teams:*`<br>`teams:id:*` | Read one or more teams and team preferences. |
|
||||
| `teams:write` | `teams:*`<br>`teams:id:*` | Update one or more teams and team preferences. |
|
||||
| `users.authtoken:read` | `global.users:*` <br> `global.users:id:*` | List authentication tokens that are assigned to a user. |
|
||||
| `users.authtoken:write` | `global.users:*` <br> `global.users:id:*` | Update authentication tokens that are assigned to a user. |
|
||||
| `users.password:write` | `global.users:*` <br> `global.users:id:*` | Update a user’s password. |
|
||||
| `users.permissions:read` | `users:*` | List permissions of a user. |
|
||||
| `users.permissions:write` | `global.users:*` <br> `global.users:id:*` | Update a user’s organization-level permissions. |
|
||||
| `users.quotas:read` | `global.users:*` <br> `global.users:id:*` | List a user’s quotas. |
|
||||
| `users.quotas:write` | `global.users:*` <br> `global.users:id:*` | Update a user’s quotas. |
|
||||
| `users.roles:add` | `permissions:type:delegate` | Assign a role to a user or a service account. |
|
||||
| `users.roles:read` | `users:*` | List roles assigned directly to a user or a service account. |
|
||||
| `users.roles:remove` | `permissions:type:delegate` | Unassign a role from a user or a service account. |
|
||||
| `users:create` | n/a | Create a user. |
|
||||
| `users:delete` | `global.users:*` <br> `global.users:id:*` | Delete a user. |
|
||||
| `users:disable` | `global.users:*` <br> `global.users:id:*` | Disable a user. |
|
||||
| `users:enable` | `global.users:*` <br> `global.users:id:*` | Enable a user. |
|
||||
| `users:logout` | `global.users:*` <br> `global.users:id:*` | Sign out a user. |
|
||||
| `users:read` | `global.users:*` | Read or search user profiles. |
|
||||
| `users:write` | `global.users:*` <br> `global.users:id:*` | Update a user’s profile. |
|
||||
|
||||
### Grafana OnCall action definitions (beta)
|
||||
|
||||
@@ -196,7 +193,7 @@ The following list contains role-based access control scopes.
|
||||
| `apikeys:*`<br>`apikeys:id:*` | Restrict an action to a set of API keys. For example, `apikeys:*` matches any API key, `apikey:id:1` matches the API key whose id is `1`. |
|
||||
| `dashboards:*`<br>`dashboards:uid:*` | Restrict an action to a set of dashboards. For example, `dashboards:*` matches any dashboard, and `dashboards:uid:1` matches the dashboard whose UID is `1`. |
|
||||
| `datasources:*`<br>`datasources:uid:*` | Restrict an action to a set of data sources. For example, `datasources:*` matches any data source, and `datasources:uid:1` matches the data source whose UID is `1`. |
|
||||
| `folders:*`<br>`folders:uid:*` | Restrict an action to a set of folders. For example, `folders:*` matches any folder, and `folders:uid:1` matches the folder whose UID is `1`. Note that permissions granted to a folder cascade down to subfolders located under it |
|
||||
| `folders:*`<br>`folders:uid:*` | Restrict an action to a set of folders. For example, `folders:*` matches any folder, and `folders:uid:1` matches the folder whose UID is `1`. |
|
||||
| `global.users:*` <br> `global.users:id:*` | Restrict an action to a set of global users. For example, `global.users:*` matches any user and `global.users:id:1` matches the user whose ID is `1`. |
|
||||
| `orgs:*` <br> `orgs:id:*` | Restrict an action to a set of organizations. For example, `orgs:*` matches any organization and `orgs:id:1` matches the organization whose ID is `1`. |
|
||||
| `permissions:type:delegate` | The scope is only applicable for roles associated with the Access Control itself and indicates that you can delegate your permissions only, or a subset of it, by creating a new role or making an assignment. |
|
||||
@@ -210,4 +207,3 @@ The following list contains role-based access control scopes.
|
||||
| `settings:*` | Restrict an action to a subset of settings. For example, `settings:*` matches all settings, `settings:auth.saml:*` matches all SAML settings, and `settings:auth.saml:enabled` matches the enable property on the SAML settings. |
|
||||
| `teams:*` <br> `teams:id:*` | Restrict an action to a set of teams from an organization. For example, `teams:*` matches any team and `teams:id:1` matches the team whose ID is `1`. |
|
||||
| `users:*` <br> `users:id:*` | Restrict an action to a set of users from an organization. For example, `users:*` matches any user and `users:id:1` matches the user whose ID is `1`. |
|
||||
| `n/a` | `n/a` means not applicable. If an action has `n/a` specified for the scope, then the action does not require a scope. For example, the `teams:create` action does not require a scope and allows users to create teams. |
|
||||
|
||||
@@ -15,7 +15,7 @@ labels:
|
||||
products:
|
||||
- enterprise
|
||||
- oss
|
||||
title: View server statistics and license
|
||||
title: Stats and license
|
||||
weight: 400
|
||||
---
|
||||
|
||||
@@ -25,11 +25,11 @@ This setting contains information about tools that Grafana Server Admins can use
|
||||
|
||||
## View Grafana server settings
|
||||
|
||||
> Refer to [Role-based access control]({{< relref "../roles-and-permissions/access-control" >}}) in Grafana Enterprise to understand how you can control access with RBAC permissions.
|
||||
> Refer to [Role-based access control]({{< relref "../roles-and-permissions/access-control/" >}}) in Grafana Enterprise to understand how you can control access with RBAC permissions.
|
||||
|
||||
If you are a Grafana server administrator, use the Settings tab to view the settings that are applied to your Grafana server via the [Configuration]({{< relref "../../setup-grafana/configure-grafana#configuration-file-location" >}}) file and any environmental variables.
|
||||
If you are a Grafana server administrator, use the Settings tab to view the settings that are applied to your Grafana server via the [Configuration]({{< relref "../../setup-grafana/configure-grafana/#config-file-locations" >}}) file and any environmental variables.
|
||||
|
||||
> **Note:** Only Grafana server administrators can access the **Server Admin** menu. For more information about about administrative permissions, refer to [Roles and permissions]({{< relref "../roles-and-permissions#grafana-server-administrators" >}}).
|
||||
> **Note:** Only Grafana server administrators can access the **Server Admin** menu. For more information about about administrative permissions, refer to [Roles and permissions]({{< relref "../roles-and-permissions/#grafana-server-administrators" >}}).
|
||||
|
||||
### View server settings
|
||||
|
||||
@@ -38,15 +38,15 @@ If you are a Grafana server administrator, use the Settings tab to view the sett
|
||||
|
||||
### Available settings
|
||||
|
||||
For a full list of server settings, refer to [Configuration]({{< relref "../../setup-grafana/configure-grafana#server" >}}).
|
||||
For a full list of server settings, refer to [Configuration]({{< relref "../../setup-grafana/configure-grafana/" >}}).
|
||||
|
||||
## View Grafana server stats
|
||||
|
||||
> Refer to [Role-based access control]({{< relref "../roles-and-permissions/access-control" >}}) in Grafana Enterprise to understand how you can control access with RBAC permissions.
|
||||
> Refer to [Role-based access control]({{< relref "../roles-and-permissions/access-control/" >}}) in Grafana Enterprise to understand how you can control access with RBAC permissions.
|
||||
|
||||
If you are a Grafana server admin, then you can view useful statistics about your Grafana server in the Stats & Licensing tab.
|
||||
|
||||
> **Note:** Only Grafana server administrators can access the **Server Admin** menu. For more information about about administrative permissions, refer to [Roles and permissions]({{< relref "../roles-and-permissions#grafana-server-administrators" >}}).
|
||||
> **Note:** Only Grafana server administrators can access the **Server Admin** menu. For more information about about administrative permissions, refer to [Roles and permissions]({{< relref "../roles-and-permissions/#grafana-server-administrators" >}}).
|
||||
|
||||
### View server stats
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
aliases:
|
||||
- ../contact-points/
|
||||
- ../unified-alerting/contact-points/
|
||||
- contact-point-types/
|
||||
- /docs/grafana/latest/alerting/contact-points/
|
||||
- /docs/grafana/latest/alerting/unified-alerting/contact-points/
|
||||
- /docs/grafana/latest/alerting/fundamentals/contact-points/contact-point-types/
|
||||
description: Create or edit contact point
|
||||
keywords:
|
||||
- grafana
|
||||
|
||||
@@ -20,21 +20,16 @@ longer supported. We refer to these as [Differences]({{< relref "#differences" >
|
||||
|
||||
2. Read and write access to legacy dashboard alerts and Grafana alerts are governed by the permissions of the folders storing them. During migration, legacy dashboard alert permissions are matched to the new rules permissions as follows:
|
||||
|
||||
- If there are dashboard permissions, a folder named `Migrated {"dashboardUid": "UID", "panelId": 1, "alertId": 1}` is created to match the permissions of the dashboard (including the inherited permissions from the folder).
|
||||
- If there are no dashboard permissions and the dashboard is in a folder, then the rule is linked to this folder and inherits its permissions.
|
||||
- If there are no dashboard permissions and the dashboard is in the General folder, then the rule is linked to the `General Alerting` folder and the rule inherits the default permissions.
|
||||
- If alert's dashboard has permissions, it will create a folder named like `Migrated {"dashboardUid": "UID", "panelId": 1, "alertId": 1}` to match permissions of the dashboard (including the inherited permissions from the folder).
|
||||
- If there are no dashboard permissions and the dashboard is under a folder, then the rule is linked to this folder and inherits its permissions.
|
||||
- If there are no dashboard permissions and the dashboard is under the General folder, then the rule is linked to the `General Alerting` folder, and the rule inherits the default permissions.
|
||||
|
||||
3. `NoData` and `Error` settings are migrated as is to the corresponding settings in Grafana Alerting, except in two situations:
|
||||
|
||||
3.1. As there is no `Keep Last State` option for `No Data` in Grafana Alerting, this option becomes `NoData`. The `Keep Last State` option for `Error` is migrated to a new option `Error`. To match the behavior of the `Keep Last State`, in both cases, during the migration Grafana automatically creates a silence for each alert rule with a duration of 1 year.
|
||||
|
||||
3.2. Due to lack of validation, legacy alert rules imported via JSON or provisioned along with dashboards can contain arbitrary values for `NoData` and [`Error`](/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md#configure-no-data-and-error-handling). In this situation, Grafana will use the default setting: `NoData` for No data, and `Error` for Error.
|
||||
3. Since there is no `Keep Last State` option for [`No Data`]({{< relref "../alerting-rules/create-grafana-managed-rule/#no-data--error-handling" >}}) in Grafana Alerting, this option becomes `NoData` during the legacy rules migration. Option "Keep Last State" for [`Error handling`]({{< relref "../alerting-rules/create-grafana-managed-rule/#no-data--error-handling" >}}) is migrated to a new option `Error`. To match the behavior of the `Keep Last State`, in both cases, during the migration Grafana automatically creates a silence for each alert rule with a duration of 1 year.
|
||||
|
||||
4. Notification channels are migrated to an Alertmanager configuration with the appropriate routes and receivers. Default notification channels are added as contact points to the default route. Notification channels not associated with any Dashboard alert go to the `autogen-unlinked-channel-recv` route.
|
||||
|
||||
5. Unlike legacy dashboard alerts where images in notifications are enabled per contact point, images in notifications for Grafana Alerting must be enabled in the Grafana configuration, either in the configuration file or environment variables, and are enabled for either all or no contact points. Refer to [images in notifications]({{< relref "../manage-notifications/images-in-notifications" >}}).
|
||||
|
||||
6. The JSON format for webhook notifications has changed in Grafana Alerting and uses the format from [Prometheus Alertmanager](https://prometheus.io/docs/alerting/latest/configuration/#webhook_config).
|
||||
5. Unlike legacy dashboard alerts where images in notifications are enabled per contact point, images in notifications for Grafana Alerting must be enabled in the Grafana configuration, either in the configuration file or environment variables, and are enabled for either all or no contact points. Refer to [images in notifications](https://grafana.com/docs/grafana/latest/alerting/manage-notifications/images-in-notifications/).
|
||||
6. Grafana Alerting does not support pausing the evaluation of alert rules. After migration, all paused alert rules will become active, which may cause unexpected notifications to be sent.
|
||||
|
||||
## Limitations
|
||||
|
||||
|
||||
7
docs/sources/copyright/_index.md
Normal file
7
docs/sources/copyright/_index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Copyright notice
|
||||
---
|
||||
|
||||
# Copyright notice
|
||||
|
||||
Copyright © 2021 Raintank, Inc. dba Grafana Labs. All Rights Reserved.
|
||||
@@ -14,124 +14,85 @@ weight: 600
|
||||
|
||||
# Annotate visualizations
|
||||
|
||||
Annotations provide a way to mark points on a visualization with rich events. They are visualized as vertical lines and icons on all graph panels. When you hover over an annotation, you can get event description and event tags. The text field can include links to other systems with more detail.
|
||||
Annotations provide a way to mark points on the graph with rich events. When you hover over an annotation
|
||||
you can get event description and event tags. The text field can include links to other systems with more detail.
|
||||
|
||||
{{< figure src="/static/img/docs/v46/annotations.png" max-width="800px" >}}
|
||||
|
||||
You can annotate visualizations in three ways:
|
||||
## Native annotations
|
||||
|
||||
- Directly in the panel, using the [built-in annotations query](#built-in-query)
|
||||
- Using the HTTP API
|
||||
- Configuring annotation queries in the dashboard settings
|
||||
Grafana comes with a native annotation store and the ability to add annotation events directly from the graph panel or via the [HTTP API]({{< relref "../../../developers/http_api/annotations/" >}}).
|
||||
|
||||
In the first two cases, you're creating new annotations, while in the last you're querying existing annotations from data sources. The built-in annotation query also supports this.
|
||||
### Add annotation
|
||||
|
||||
This page explains the first and third options; for information about using the HTTP API, refer to [Annotations API]({{< relref "../../../developers/http_api/annotations/" >}}).
|
||||
|
||||
Annotations are supported for the following visualization types:
|
||||
|
||||
- Time series
|
||||
- State timeline
|
||||
- Candlestick
|
||||
|
||||
## Create annotations in panels
|
||||
|
||||
Grafana comes with the ability to add annotation events directly from a panel using the [built-in annotation query](#built-in-query) that exists on all dashboards. Annotations that you create this way are stored in Grafana.
|
||||
|
||||
To add annotations directly in the panel, the built-in query must be enabled. Learn more in [Built-in query](#built-in-query)
|
||||
|
||||
### Add an annotation
|
||||
|
||||
To add an annotation, complete the following steps:
|
||||
|
||||
1. In the dashboard click the panel to which you're adding the annotation. A context menu will appear.
|
||||
1. In the context menu, click **Add annotation**.
|
||||
1. In the dashboard click on the Time series panel. A context menu will appear.
|
||||
1. In the context menu click on **Add annotation**.
|
||||

|
||||
1. Add an annotation description and tags (optional).
|
||||
1. Click **Save**.
|
||||
1. Add an annotation description and tags(optional).
|
||||

|
||||
1. Click save.
|
||||
|
||||
Alternatively, to add an annotation, press Ctrl/Cmd and click the panel, and the **Add annotation** popover will appear.
|
||||
Alternatively, to add an annotation, Ctrl/Cmd+Click on the Time series panel and the Add annotation popover will appear
|
||||
|
||||
### Add a region annotation
|
||||
### Add region annotation
|
||||
|
||||
1. In the dashboard press Ctrl/Cmd and click and drag on the panel.
|
||||
1. In the dashboard Ctrl/Cmd+click and drag on the Time series panel.
|
||||

|
||||
1. Add an annotation description and tags (optional).
|
||||
1. Click **Save**.
|
||||
1. Add an annotation description and tags(optional).
|
||||
1. Click save.
|
||||
|
||||
### Edit an annotation
|
||||
### Edit annotation
|
||||
|
||||
1. In the dashboard, hover over an annotation indicator on the Time series panel.
|
||||
1. In the dashboard hover over an annotation indicator on the Time series panel.
|
||||
<!---->
|
||||
1. Click on the pencil icon in the annotation tooltip.
|
||||
1. Modify the description and/or tags.
|
||||
1. Click save.
|
||||
|
||||
### Delete an annotation
|
||||
### Delete annotation
|
||||
|
||||
1. In the dashboard hover over an annotation indicator on a panel.
|
||||
1. In the dashboard hover over an annotation indicator on the Time series panel.
|
||||
<!---->
|
||||
1. Click on the trash icon in the annotation tooltip.
|
||||
|
||||
## Fetch annotations through dashboard settings
|
||||
### Built-in query
|
||||
|
||||
In the dashboard settings, under **Annotations**, you can add new queries to fetch annotations using any data source, including the built-in data annotation data source. Annotation queries return events that can be visualized as event markers in graphs across the dashboard.
|
||||
After you added an annotation they will still be visible. This is due to the built in annotation query that exists on all dashboards. This annotation query will
|
||||
fetch all annotation events that originate from the current dashboard and show them on the panel where they were created. This includes alert state history annotations. You can
|
||||
stop annotations from being fetched and drawn by opening the **Annotations** settings (via Dashboard cogs menu) and modifying the query named `Annotations & Alerts (Built-in)`.
|
||||
|
||||
### Add new annotation queries
|
||||
When you copy a dashboard using the **Save As** feature it will get a new dashboard id so annotations created on source dashboard will no longer be visible on the copy. You
|
||||
can still show them if you add a new **Annotation Query** and filter by tags. But this only works if the annotations on the source dashboard had tags to filter by.
|
||||
|
||||
To add a new annotation query to a dashboard, take the following steps:
|
||||
### Query by tag
|
||||
|
||||
1. Click the dashboard settings (gear) icon in the dashboard header to open the settings menu.
|
||||
1. Select **Annotations**.
|
||||
1. Click **Add annotation query**.
|
||||
|
||||
If you've added a query before, the **+ New query** button is displayed.
|
||||
|
||||
1. Enter a name for the annotation query.
|
||||
|
||||
This name is given to the toggle (checkbox) that will allow you to enable/disable showing annotation events from this query.
|
||||
|
||||
1. Select the data source for the annotations.
|
||||
1. If you don't want to use the annotation query right away, clear the **Enabled** checkbox.
|
||||
1. If you don't want the annotation query toggle to be displayed in the dashboard, select the **Hidden** checkbox.
|
||||
1. Select a color for the event markers.
|
||||
1. Configure the query.
|
||||
|
||||
The annotation query options are different for each data source. For information about annotations in a specific data source, refer to the specific [data source]({{< relref "../../../datasources/" >}}) topic.
|
||||
|
||||
## Built-in query
|
||||
|
||||
After you add an annotation, they will still be visible. This is due to the built-in annotation query that exists on all dashboards. This annotation query will fetch all annotation events that originate from the current dashboard, which are stored in Grafana, and show them on the panel where they were created. This includes alert state history annotations.
|
||||
|
||||
To add annotations directly to the dashboard, this query must be enabled.
|
||||
|
||||
To confirm if the built-in query is enabled, take the following steps:
|
||||
|
||||
1. Click the dashboard settings (gear) icon in the dashboard header to open the dashboard settings menu.
|
||||
1. Click **Annotations**.
|
||||
1. Find the **Annotations & Alerts (Built-in)** query.
|
||||
|
||||
If it says **Disabled** before the name of the query, then you'll need to click the query name to open it and update the setting.
|
||||
|
||||
You can stop annotations from being fetched and drawn by taking the following steps:
|
||||
|
||||
1. Click the dashboard settings (gear) icon in the dashboard header to open the settings menu.
|
||||
1. Click **Annotations**.
|
||||
1. Find and click the **Annotations & Alerts (Built-in)** query to open it.
|
||||
1. Click the **Enabled** toggle to turn it off.
|
||||
|
||||
When you copy a dashboard using the **Save As** feature it will get a new dashboard id, so annotations created on source dashboard will no longer be visible on the copy. You can still show them if you add a new **Annotation Query** and filter by tags. However, this only works if the annotations on the source dashboard had tags to filter by.
|
||||
|
||||
### Filter queries by tag
|
||||
|
||||
You can create new queries to fetch annotations from the built-in annotation query using the `-- Grafana --` data source by setting _Filter by_ to `Tags`.
|
||||
You can create new queries to fetch annotations from the native annotation store via the `-- Grafana --` data source by setting _Filter by_ to `Tags`.
|
||||
|
||||
Grafana v8.1 and later versions also support typeahead of existing tags, provide at least one tag.
|
||||
|
||||
For example, create an annotation query name `outages` and specify a tag `outage`. This query will show all annotations (from any dashboard or via API) with the `outage` tag. If multiple tags are defined in an annotation query, then Grafana will only show annotations matching all the tags. To modify the behavior, enable `Match any`, and Grafana will show annotations that contain any one of the tags you provided.
|
||||
|
||||
{{< figure src="/media/docs/grafana/dashboards/screenshot-annotations-typeahead-support-10.0.png" max-width="600px" >}}
|
||||
{{< figure src="/static/img/docs/annotations/annotations_typeahead_support-8-1-0.png" max-width="600px" >}}
|
||||
|
||||
You can also use template variables in the tag query. This means if you have a dashboard showing stats for different services and a template variable that dictates which services to show, you can use the same template variable in your annotation query to only show annotations for those services.
|
||||
In Grafana v5.3+ it's possible to use template variables in the tag query. So if you have a dashboard showing stats for different services and a template variable that dictates which services to show, you can now use the same template variable in your annotation query to only show annotations for those services.
|
||||
|
||||
{{< figure src="/media/docs/grafana/dashboards/screenshot-annotation-tag-filter-variable-10.0.png" max-width="600px" >}}
|
||||
{{< figure src="/static/img/docs/annotations/annotation_tag_filter_variable-8-1-0.png" max-width="600px" >}}
|
||||
|
||||
## Querying other data sources
|
||||
|
||||
Annotation events are fetched via annotation queries. To add a new annotation query to a dashboard
|
||||
open the dashboard settings menu, then select `Annotations`. This will open the dashboard annotations
|
||||
settings view. To create a new annotation query hit the `New` button.
|
||||
|
||||
<!---->
|
||||
|
||||
{{< figure src="/static/img/docs/v50/annotation_new_query.png" max-width="600px" >}}
|
||||
|
||||
Specify a name for the annotation query. This name is given to the toggle (checkbox) that will allow
|
||||
you to enable/disable showing annotation events from this query. For example you might have two
|
||||
annotation queries named `Deploys` and `Outages`. The toggle will allow you to decide what annotations
|
||||
to show.
|
||||
|
||||
### Annotation query details
|
||||
|
||||
The annotation query options are different for each data source. For information about annotations in a specific data source, refer to the specific [data source]({{< relref "../../../datasources/" >}}) topic.
|
||||
|
||||
@@ -65,7 +65,7 @@ The query parameter `var-adhoc=key|=|value` applies the ad hoc filter configured
|
||||
|
||||
### Example
|
||||
|
||||
[This example in Grafana Play](https://play.grafana.org/d/000000002/influxdb-templated?orgId=1&var-datacenter=America&var-host=All&var-summarize=1m&var-adhoc=datacenter%7C%3D%7CAmerica) passes the ad hoc filter variable `adhoc` with the filter value `datacenter = America`.
|
||||
See [https://play.grafana.org/d/000000002/influxdb-templated?orgId=1&var-datacenter=America&var-host=All&var-summarize=1m&var-adhoc=datacenter%7C%3D%7CAmerica] - this passes the ad hoc filter variable `adhoc` with the filter value `datacenter = America`.
|
||||
|
||||
## Controlling time range using the URL
|
||||
|
||||
|
||||
@@ -30,13 +30,7 @@ Dashboards and panels allow you to show your data in visual form. Each panel nee
|
||||
|
||||
For more information about data sources, refer to [Data sources]({{< relref "../../../datasources/" >}}) for specific guidelines.
|
||||
|
||||
1. Click the Refresh dashboard icon to query the data source.
|
||||
|
||||

|
||||
|
||||
1. In the visualization list, select a visualization type.
|
||||
|
||||

|
||||
1. In the Visualization list, select a visualization type.
|
||||
|
||||
Grafana displays a preview of your query results with the visualization applied.
|
||||
|
||||
@@ -54,12 +48,9 @@ Dashboards and panels allow you to show your data in visual form. Each panel nee
|
||||
- [Configure thresholds]({{< relref "../../../panels-visualizations/configure-thresholds/" >}})
|
||||
- [Configure standard options]({{< relref "../../../panels-visualizations/configure-standard-options/" >}})
|
||||
|
||||
1. When you've finished editing your panel, click **Save** to save the dashboard.
|
||||
1. Add a note to describe the visualization (or describe your changes) and then click **Save** in the upper-right corner of the page.
|
||||
|
||||
Alternatively, click **Apply** if you want to see your changes applied to the dashboard first. Then click the save icon in the dashboard header.
|
||||
|
||||
1. Enter a name for your dashboard and select a folder, if applicable.
|
||||
1. Click **Save**.
|
||||
Notes can be helpful if you need to revert the dashboard to a previous version.
|
||||
|
||||
## Configure repeating rows
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Modify dashboard settings
|
||||
menuTitle: Modify dashboard settings
|
||||
menuTitle: Dashboard settings
|
||||
weight: 8
|
||||
keywords:
|
||||
- time settings
|
||||
@@ -12,7 +12,7 @@ keywords:
|
||||
|
||||
# Modify dashboard settings
|
||||
|
||||
The dashboard settings page allows you to:
|
||||
The dashboard settings page enables you to:
|
||||
|
||||
- Edit general dashboard properties, including time settings
|
||||
- Add annotation queries
|
||||
@@ -31,7 +31,7 @@ Adjust dashboard time settings when you want to change the dashboard timezone, t
|
||||
|
||||
1. On the **Dashboard settings** page, click **General**.
|
||||
1. Navigate to the **Time Options** section.
|
||||
1. Specify time settings as follows.
|
||||
1. Specify time settings according to the following descriptions.
|
||||
|
||||
- **Timezone:** Specify the local time zone of the service or system that you are monitoring. This can be helpful when monitoring a system or service that operates across several time zones.
|
||||
- **Default:** Grafana uses the default selected time zone for the user profile, team, or organization. If no time zone is specified for the user profile, a team the user is a member of, or the organization, then Grafana uses the local browser time.
|
||||
@@ -62,7 +62,7 @@ the dashboard. These dropdowns make it easy to change the data being displayed i
|
||||
For more information about variables, refer to [Variables]({{< relref "../../variables/" >}}).
|
||||
|
||||
1. On the **Dashboard settings** page, click **Variable** in the left side section menu and then the **Add variable** button.
|
||||
1. In the **General** section, the name of the variable. This is the name that you will later use in queries.
|
||||
1. In the **General** section, the the name of the variable. This is the name that you will later use in queries.
|
||||
1. Select a variable **Type**.
|
||||
|
||||
> **Note:** The variable type you select impacts which fields you populate on the page.
|
||||
@@ -74,7 +74,7 @@ For more information about variables, refer to [Variables]({{< relref "../../var
|
||||
Dashboard links enable you to place links to other dashboards and web sites directly below the dashboard header. Links provide for easy navigation to other, related dashboards and content.
|
||||
|
||||
1. On the **Dashboard settings** page, click **Links** in the left side section menu and then the **Add link** button.
|
||||
1. Enter title and in the **Type** field, select **Dashboard** or **Link**.
|
||||
1. Enter title and and in the **Type** field, select **Dashboard** or **Link**.
|
||||
1. To add a dashboard link:
|
||||
a. Add an optional tag. Tags are useful creating a dynamic dropdown of dashboards that all have a specific tag.
|
||||
b. Select any of the dashboard link **Options**.
|
||||
|
||||
@@ -10,10 +10,6 @@ keywords:
|
||||
- reporting
|
||||
- export
|
||||
- pdf
|
||||
labels:
|
||||
products:
|
||||
- cloud
|
||||
- enterprise
|
||||
menuTitle: Reporting
|
||||
title: Create and manage reports
|
||||
weight: 85
|
||||
@@ -30,7 +26,7 @@ Reporting enables you to automatically generate PDFs from any of your dashboards
|
||||
{{< figure src="/static/img/docs/enterprise/reports_list_8.1.png" max-width="500px" >}}
|
||||
-->
|
||||
|
||||
Any changes you make to a dashboard used in a report are reflected the next time the report is sent. For example, if you change the time range in the dashboard, then the time range in the report also changes, unless you've configured a custom time range.
|
||||
Any changes you make to a dashboard used in a report are reflected the next time the report is sent. For example, if you change the time range in the dashboard, then the time range in the report also changes.
|
||||
|
||||
For information about recent improvements to the reporting UI, refer to [Grafana reporting: How we improved the UX in Grafana](https://grafana.com/blog/2022/06/29/grafana-reporting-how-we-improved-the-ux-in-grafana/).
|
||||
|
||||
@@ -72,14 +68,6 @@ Only organization administrators can create reports by default. You can customiz
|
||||
- **Send test email:** To verify that the configuration works as expected. You can choose to send this email to the recipients configured for the report, or to a different set of email addresses only used for testing.
|
||||
1. Preview and save the report.
|
||||
|
||||
### Save as draft
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 9.1.0 and later and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
|
||||
{{% /admonition %}}
|
||||
|
||||
You can save a report as a draft at any point during the report creation or update process. You can save a report as a draft even if it's missing required fields. Also, the report won't be sent according to its schedule while it's a draft.
|
||||
|
||||
### Choose template variables
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 7.5 and later behind the `reportVariables` feature flag, Grafana Enterprise version 8.0 and later without a feature flag, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
|
||||
|
||||
@@ -25,13 +25,13 @@ This topic provides an overview of dashboard features and shortcuts, and describ
|
||||
|
||||
The dashboard user interface provides a number of features that you can use to customize the presentation of your data.
|
||||
|
||||
The following image and descriptions highlight all dashboard features.
|
||||
The following image and descriptions highlights all dashboards features.
|
||||
|
||||
{{< figure src="/static/img/docs/v91/dashboard-features/dashboard-features.png" width="700px" >}}
|
||||
|
||||
- (1) **Grafana home**: Click the Grafana home icon to be redirected to the home page configured in the Grafana instance.
|
||||
- (2) **Dashboard title**: When you click the dashboard title, you can search for dashboards contained in the current folder.
|
||||
- (3) **Share dashboard**: Use this option to share the current dashboard using a link or snapshot. You can also export the dashboard definition from the share modal.
|
||||
- (2) **Dashboard title**: When you click the dashboard title you can search for dashboard contained in the current folder.
|
||||
- (3) **Share dashboard**: Use this option to share the current dashboard by link or snapshot. You can also export the dashboard definition from the share modal.
|
||||
- (4) **Add a new panel**: Use this option to add a panel, dashboard row, or library panel to the current dashboard.
|
||||
- (5) **Dashboard settings**: Use this option to change dashboard name, folder, and tags and manage variables and annotation queries. For more information about dashboard settings, refer to [Modify dashboard settings]({{< relref "../build-dashboards/modify-dashboard-settings/" >}}).
|
||||
- (6) **Time picker dropdown**: Click to select relative time range options and set custom absolute time ranges.
|
||||
@@ -85,7 +85,7 @@ This section describes supported time units and relative ranges, the common time
|
||||
|
||||
Grafana supports the following time units: `s (seconds)`, `m (minutes)`, `h (hours)`, `d (days)`, `w (weeks)`, `M (months)`, `Q (quarters)` and `y (years)`.
|
||||
|
||||
The minus operator enables you to step back in time, relative to the current date and time, or `now`. If you want to display the full period of the unit (day, week, month, etc...), append `/<time unit>` to the end. To view fiscal periods, use `fQ (fiscal quarter)` and `fy (fiscal year)` time units.
|
||||
The minus operator enables you to step back in time, relative to now. If you want to display the full period of the unit (day, week, month, etc...), append `/<time unit>` to the end. To view fiscal periods, use `fQ (fiscal quarter)` and `fy (fiscal year)` time units.
|
||||
|
||||
The plus operator enables you to step forward in time, relative to now. For example, you can use this feature to look at predicted data in the future.
|
||||
|
||||
@@ -104,15 +104,13 @@ The following table provides example relative ranges:
|
||||
| This Year | `now/Y` | `now/Y` |
|
||||
| Previous fiscal year | `now-1y/fy` | `now-1y/fy` |
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
#### Note about Grafana Alerting
|
||||
|
||||
Grafana Alerting does not support the following syntaxes at this time:
|
||||
For Grafana Alerting, we do not support the following syntaxes at this time.
|
||||
|
||||
- now+n for future timestamps.
|
||||
- now-1n/n for "start of n until end of n" because this is an absolute timestamp.
|
||||
|
||||
{{% /admonition %}}
|
||||
|
||||
### Common time range controls
|
||||
|
||||
The dashboard and panel time controls have a common UI.
|
||||
@@ -157,32 +155,6 @@ You can set an absolute time range in the following ways:
|
||||
|
||||
This section also displays recently used absolute ranges.
|
||||
|
||||
#### Semi-relative time range
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
|
||||
Grafana Alerting does not support semi-relative time ranges.
|
||||
|
||||
{{% /admonition %}}
|
||||
|
||||
You can also use the absolute time range settings to set a semi-relative time range. Semi-relative time range dashboards are useful when you need to monitor the progress of something over time, but you also want to see the entire history from a starting point.
|
||||
|
||||
Set a semi-relative time range by setting the start time to an absolute timestamp and the end time to a “now” that is relative to the current time. For example:
|
||||
|
||||
**Start time:** `2023-05-01 00:00:00`
|
||||
|
||||
**End time:** `now`
|
||||
|
||||
If you wanted to track the progress of something during business hours, you could set a time range that covers the current day, but starting at 8am, like so:
|
||||
|
||||
**Start time:** `now/d+8h`
|
||||
|
||||
**End time:** `now`
|
||||
|
||||
This is equivalent to the **Today so far** time range preset, but it starts at 8:00am instead of 12:00am by appending +8h to the periodic start time.
|
||||
|
||||
Using a semi-relative time range, as time progresses, your dashboard will automatically and progressively zoom out to show more history and fewer details. At the same rate, as high data resolution decreases, historical trends over the entire time period will become more clear.
|
||||
|
||||
#### Zoom out (Cmd+Z or Ctrl+Z)
|
||||
|
||||
Click the **Zoom out** icon to view a larger time range in the dashboard or panel visualization.
|
||||
|
||||
@@ -45,19 +45,20 @@ To see variable settings, navigate to **Dashboard Settings > Variables**. Click
|
||||
|
||||
Variables can be used in titles, descriptions, text panels, and queries. Queries with text that starts with `$` are templates. Not all panels will have template queries.
|
||||
|
||||
The following dashboards in Grafana Play provide examples of template variables:
|
||||
The following dashboards in Grafana Play provide examples of template variables.
|
||||
|
||||
- [Graphite Templated Nested](https://play.grafana.org/d/000000056/templated-dynamic-dashboard?orgId=1&var-app=backend&var-server=backend_01&var-server=backend_02&var-server=backend_03&var-server=backend_04&var-interval=1h) - Uses query variables, chained query variables, an interval variable, and a repeated panel.
|
||||
- [Global variables and interpolation](https://play.grafana.org/d/HYaGDGIMk/templating-global-variables-and-interpolation?orgId=1&var-Server=A%27A%22A&var-Server=BB%5CB)
|
||||
- [Elasticsearch Dummy Flight Data](https://play.grafana.org/d/z8OZC66nk/elasticsearch-8-2-0-sample-flight-data?orgId=1&var-Filters=Carrier%7C%3D%7CLogstash%20Airways&var-query0=) - Uses ad hoc filters.
|
||||
- [Elasticsearch Metrics](https://play.grafana.org/d/z8OZC66nk/elasticsearch-8-2-0-sample-flight-data?orgId=1) - Uses ad hoc filters, global variables, and a custom variable.
|
||||
- [Graphite Templated Nested](https://play.grafana.org/d/000000056/graphite-templated-nested?orgId=1) - Uses query variables, chained query variables, an interval variable, and a repeated panel.
|
||||
- [Influx DB Group By Variable](https://play.grafana.org/d/000000137/influxdb-group-by-variable?orgId=1) - Query variable, panel uses the variable results to group the metric data.
|
||||
- [InfluxDB Raw Query Template Var](https://play.grafana.org/d/000000083/influxdb-raw-query-template-var?orgId=1) - Uses query variables, chained query variables, and an interval variable.
|
||||
- [InfluxDB Server Monitoring](https://play.grafana.org/d/AAy9r_bmk/influxdb-server-monitoring?orgId=1) - Uses query variables, chained query variables, an interval variable, and an ad hoc filter.
|
||||
- [Prometheus templating](https://play.grafana.org/d/000000063/prometheus-templating?orgId=1) - Uses chained query variables.
|
||||
- [Template Redux](https://play.grafana.org/d/p-k6QtkGz/template-redux?orgId=1) - Uses query variables, chained query variables, ad hoc filters, an interval variable, a text box variable, a custom variable, and a data source variable.
|
||||
- [Templating, repeated panels](https://play.grafana.org/d/000000025/templating-repeated-panels?orgId=1) - Two sets of repeated panels use query variables.
|
||||
- [Template Redux](https://play.grafana.org/d/p-k6QtkGz/template-redux?orgId=1) - Uses query variables, chained query variables, an interval variable, a text box variable, a custom variable, and a data source variable.
|
||||
- [Nested Variables Drilldown](https://play.grafana.org/d/testdata-nested-variables-drilldown/templating-nested-variables-drilldown?orgId=1&var-datacenter=A&var-server=AA&var-server=AC&var-pod=All)
|
||||
- [Templating showcase](https://play.grafana.org/d/000000091/templating-showcase?orgId=1) - Uses custom, query, chained query, and data source variables.
|
||||
- [Templating value groups](https://play.grafana.org/d/000000024/templating-value-groups?orgId=1) - Uses query variable with value groups.
|
||||
|
||||
## Variable best practices
|
||||
|
||||
- Variable drop-down lists are displayed in the order they are listed in the variable list in Dashboard settings.
|
||||
- Put the variables that you will change often at the top, so they will be shown first (far left on the dashboard).
|
||||
- By default, variables don't have a default value. This means that the topmost value in the drop-down is always preselected. If you want to pre-populate a variable with an empty value, you can use the following workaround in the variable settings:
|
||||
1. Select the **Include All Option** checkbox.
|
||||
2. In the **Custom all value** field, enter a value like `+`.
|
||||
|
||||
@@ -247,13 +247,13 @@ Grafana has two built-in time range variables: `$__from` and `$__to`. They are c
|
||||
|
||||
> **Note:** This special formatting syntax is only available in Grafana 7.1.2+
|
||||
|
||||
| Syntax | Example result | Description |
|
||||
| ------------------------ | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `${__from}` | 1594671549254 | Unix millisecond epoch |
|
||||
| `${__from:date}` | 2020-07-13T20:19:09.254Z | No args, defaults to ISO 8601/RFC 3339 |
|
||||
| `${__from:date:iso}` | 2020-07-13T20:19:09.254Z | ISO 8601/RFC 3339 |
|
||||
| `${__from:date:seconds}` | 1594671549 | Unix seconds epoch |
|
||||
| `${__from:date:YYYY-MM}` | 2020-07 | Any custom [date format](https://momentjs.com/docs/#/displaying/) that does not include the `:` character. Uses browser time. Use `:date` or `:date:iso` for UTC |
|
||||
| Syntax | Example result | Description |
|
||||
| ------------------------ | ------------------------ | --------------------------------------------------------------------------------------------------------- |
|
||||
| `${__from}` | 1594671549254 | Unix millisecond epoch |
|
||||
| `${__from:date}` | 2020-07-13T20:19:09.254Z | No args, defaults to ISO 8601/RFC 3339 |
|
||||
| `${__from:date:iso}` | 2020-07-13T20:19:09.254Z | ISO 8601/RFC 3339 |
|
||||
| `${__from:date:seconds}` | 1594671549 | Unix seconds epoch |
|
||||
| `${__from:date:YYYY-MM}` | 2020-07 | Any custom [date format](https://momentjs.com/docs/#/displaying/) that does not include the `:` character |
|
||||
|
||||
The syntax above also works with `${__to}`.
|
||||
|
||||
@@ -569,7 +569,7 @@ demo.robustperception.io:9100
|
||||
|
||||
Using named capture groups, you can capture separate 'text' and 'value' parts from the options returned by the variable query. This allows the variable drop-down list to contain a friendly name for each value that can be selected.
|
||||
|
||||
For example, when querying the `node_hwmon_chip_names` Prometheus metric, the `chip_name` is a lot friendlier than the `chip` value. So the following variable query result:
|
||||
For example, when querying the `node_hwmon_chip_names` Prometheus metric, the `chip_name` is a lot friendlier that the `chip` value. So the following variable query result:
|
||||
|
||||
```text
|
||||
node_hwmon_chip_names{chip="0000:d7:00_0_0000:d8:00_0",chip_name="enp216s0f0np0"} 1
|
||||
|
||||
@@ -22,7 +22,7 @@ Panel titles and metric queries can refer to variables using two different synta
|
||||
This syntax is easy to read, but it does not allow you to use a variable in the middle of a word.
|
||||
**Example:** apps.frontend.$server.requests.count
|
||||
- `${var_name}` Use this syntax when you want to interpolate a variable in the middle of an expression.
|
||||
- `${var_name:<format>}` This format gives you more control over how Grafana interpolates values. Refer to [Advanced variable format options]({{< relref "#advanced-variable-format-options" >}}) for more detail on all the formatting types.
|
||||
- `${var_name:<format>}` This format gives you more control over how Grafana interpolates values. Refer to [Advanced variable format options]({{< relref "#advanced-variable-format-options/" >}}) for more detail on all the formatting types.
|
||||
- `[[varname]]` Do not use. Deprecated old syntax, will be removed in a future release.
|
||||
|
||||
Before queries are sent to your data source the query is _interpolated_, meaning the variable is replaced with its current value. During
|
||||
@@ -30,7 +30,7 @@ interpolation, the variable value might be _escaped_ in order to conform to the
|
||||
For example, a variable used in a regex expression in an InfluxDB or Prometheus query will be regex escaped. Read the data source specific
|
||||
documentation topic for details on value escaping during interpolation.
|
||||
|
||||
For advanced syntax to override data source default formatting, refer to [Advanced variable format options]({{< relref "#advanced-variable-format-options" >}}).
|
||||
For advanced syntax to override data source default formatting, refer to [Advanced variable format options]({{< relref "#advanced-variable-format-options/" >}}).
|
||||
|
||||
## Advanced variable format options
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
aliases:
|
||||
- data-sources/
|
||||
- overview/
|
||||
- ./features/datasources/
|
||||
cascade:
|
||||
labels:
|
||||
products:
|
||||
|
||||
@@ -129,11 +129,6 @@ The Azure documentation includes resources to help you learn KQL:
|
||||
- [Tutorial: Use Kusto queries in Azure Monitor](https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/tutorial?pivots=azuremonitor)
|
||||
- [SQL to Kusto cheat sheet](https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/sqlcheatsheet)
|
||||
|
||||
> **Implicit dashboard time range usage:** As of Grafana v9.4.12 and v10.0, all Azure Monitor Logs queries
|
||||
> will use the specified dashboard or Explore time range by default.
|
||||
> Any query making use of a time range explicitly specified in the query body will have their query
|
||||
> executed against the intersection of the two time ranges. For more details on this change, refer to the [Azure Monitor Logs API documentation](https://learn.microsoft.com/en-us/rest/api/loganalytics/dataaccess/query/get?tabs=HTTP#uri-parameters).
|
||||
|
||||
This example query returns a virtual machine's CPU performance, averaged over 5ms time grains:
|
||||
|
||||
```kusto
|
||||
|
||||
@@ -47,10 +47,10 @@ Set the data source's basic configuration options carefully:
|
||||
|
||||
You can also configure settings specific to the Graphite data source:
|
||||
|
||||
| Name | Description |
|
||||
| ----------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| **Version** | Select your version of Graphite. If you are using Grafana Cloud Graphite, this should be set to `1.1.x`. |
|
||||
| **Type** | Select your type of Graphite. If you are using Grafana Cloud Graphite, this should be set to `Default`. |
|
||||
| Name | Description |
|
||||
| ----------- | -------------------------------- |
|
||||
| **Version** | Select your version of Graphite. |
|
||||
| **Type** | Select your type of Graphite. |
|
||||
|
||||
### Integrate with Loki
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ weight: 700
|
||||
|
||||
# InfluxDB data source
|
||||
|
||||
{{< docs/shared lookup="influxdb/intro.md" source="grafana" version="<GRAFANA VERSION>" >}}
|
||||
{{< docs/shared "influxdb/intro.md" >}}
|
||||
|
||||
Grafana includes built-in support for InfluxDB.
|
||||
This topic explains options, variables, querying, and other features specific to the InfluxDB data source, which include its [feature-rich code editor for queries and visual query builder]({{< relref "./query-editor/" >}}).
|
||||
|
||||
@@ -24,26 +24,17 @@ Administrators can also [configure the data source via YAML]({{< relref "#provis
|
||||
|
||||
## OpenTSDB settings
|
||||
|
||||
To configure basic settings for the data source, complete the following steps:
|
||||
To access OpenTSDB settings, hover your mouse over the **Configuration** (gear) icon, then click **Data Sources**, and then click the OpenTSDB data source.
|
||||
|
||||
1. Click **Connections** in the left-side menu.
|
||||
1. Under Your connections, click **Data sources**.
|
||||
1. Enter `OpenTSDB` in the search bar.
|
||||
1. Select **OpenTSDB**.
|
||||
|
||||
The **Settings** tab of the data source is displayed.
|
||||
|
||||
1. Set the data source's basic configuration options:
|
||||
|
||||
| Name | Description |
|
||||
| ------------------- | ---------------------------------------------------------------------------------------- |
|
||||
| **Name** | The data source name. This is how you refer to the data source in panels and queries. |
|
||||
| **Default** | Default data source that will be be pre-selected for new panels. |
|
||||
| **URL** | The HTTP protocol, IP, and port of your OpenTSDB server (default port is usually 4242). |
|
||||
| **Allowed cookies** | Listing of cookies to forward to the data source. |
|
||||
| **Version** | The OpenTSDB version. |
|
||||
| **Resolution** | Metrics from OpenTSDB may have data points with either second or millisecond resolution. |
|
||||
| **Lookup limit** | Default is 1000. |
|
||||
| Name | Description |
|
||||
| ------------------- | --------------------------------------------------------------------------------------- |
|
||||
| **Name** | The data source name. This is how you refer to the data source in panels and queries. |
|
||||
| **Default** | Default data source means that it will be pre-selected for new panels. |
|
||||
| **URL** | The HTTP protocol, IP, and port of your OpenTSDB server (default port is usually 4242) |
|
||||
| **Allowed cookies** | List the names of cookies to forward to the data source. |
|
||||
| **Version** | Version = opentsdb version, either <=2.1 or 2.2 |
|
||||
| **Resolution** | Metrics from opentsdb may have datapoints with either second or millisecond resolution. |
|
||||
| **Lookup limit** | Default is 1000. |
|
||||
|
||||
### Provision the data source
|
||||
|
||||
@@ -56,7 +47,7 @@ For more information about provisioning, and for available configuration options
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: OpenTSDB
|
||||
- name: OpenTsdb
|
||||
type: opentsdb
|
||||
access: proxy
|
||||
url: http://localhost:4242
|
||||
@@ -69,13 +60,11 @@ datasources:
|
||||
|
||||
Open a graph in edit mode by click the title. Query editor will differ if the data source has version <=2.1 or = 2.2.
|
||||
In the former version, only tags can be used to query OpenTSDB. But in the latter version, filters as well as tags
|
||||
can be used to query OpenTSDB. Fill Policy is also introduced in OpenTSDB 2.2.
|
||||
can be used to query opentsdb. Fill Policy is also introduced in OpenTSDB 2.2.
|
||||
|
||||

|
||||
|
||||
{{% admonition type="note" %}}
|
||||
While using OpenTSDB 2.2 data source, make sure you use either Filters or Tags as they are mutually exclusive. If used together, might give you weird results.
|
||||
{{% /admonition %}}
|
||||
> **Note:** While using OpenTSDB 2.2 data source, make sure you use either Filters or Tags as they are mutually exclusive. If used together, might give you weird results.
|
||||
|
||||
### Auto complete suggestions
|
||||
|
||||
|
||||
@@ -14,56 +14,49 @@ weight: 300
|
||||
|
||||
# Prometheus query editor
|
||||
|
||||
Grafana provides a query editor for the Prometheus data source to create queries in PromQL. For more information about PromQL, see [Querying Prometheus](http://prometheus.io/docs/querying/basics/).
|
||||
|
||||
This topic explains querying specific to the Prometheus data source.
|
||||
For general documentation on querying data sources in Grafana, see [Query and transform data]({{< relref "../../../panels-visualizations/query-transform-data" >}}).
|
||||
|
||||
For options and functions common to all query editors, see [Query editors]({{< relref "../../../panels-visualizations/query-transform-data" >}}).
|
||||
|
||||
## Choose a query editing mode
|
||||
|
||||
The Prometheus query editor has two modes:
|
||||
You can switch the Prometheus query editor between two modes:
|
||||
|
||||
- [Builder mode](#builder-mode)
|
||||
- [Code mode](#code-mode)
|
||||
- [Code mode](#code-mode), which provides a feature-rich editor for writing queries
|
||||
- [Builder mode](#builder-mode), which provides a visual query designer
|
||||
|
||||
Each mode is explained in greater detail below.
|
||||
{{< figure src="/static/img/docs/prometheus/header-9-1.png" max-width="500px" class="docs-image--no-shadow" caption="Editor toolbar" >}}
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/editing-mode.png" max-width="500px" class="docs-image--no-shadow" caption="Query editor mode" >}}
|
||||
To switch between the editor modes, select the corresponding **Builder** and **Code** tabs.
|
||||
|
||||
Both modes are synchronized, so you can switch between them. However, if there is an issue with the query while switching modes, a warning message will appear.
|
||||
To run a query, select **Run queries** located at the top of the editor.
|
||||
|
||||
## Toolbar elements
|
||||
> **Note:** To run Prometheus queries in [Explore]({{< relref "../../../explore" >}}), select **Run query**.
|
||||
|
||||
The query editor toolbar contains the following elements:
|
||||
Each mode is synchronized with the other modes, so you can switch between them without losing your work, although there are some limitations.
|
||||
|
||||
- **Kick start your query** - Click to see a list of operation patterns that help you quickly get started adding multiple operations to your query. These include:
|
||||
Builder mode doesn't yet support some complex queries.
|
||||
When you switch from Code mode to Builder mode with such a query, the editor displays a popup that explains how you might lose parts of the query if you continue.
|
||||
You can then decide whether you still want to switch to Builder mode.
|
||||
|
||||
- Rate query starters
|
||||
- Histogram query starters
|
||||
- Binary query starters
|
||||
You can also use the [Explain feature]({{< relref "#use-explain-mode-to-understand-queries" >}}) to help understand how a query works, and augment queries by using [template variables]({{< relref "./template-variables/" >}}).
|
||||
|
||||
Click the arrow next to each to see available options to add to your query.
|
||||
|
||||
- **Explain** - Toggle to display a step-by-step explanation of all query components and operations.
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/explain-results.png" max-width="500px" class="docs-image--no-shadow" caption="Explain results" >}}
|
||||
|
||||
- **Builder/Code** - Click the corresponding **Builder** or **Code** tab on the toolbar to select a editor mode.
|
||||
For options and functions common to all query editors, refer to [Query and transform data]({{< relref "../../../panels-visualizations/query-transform-data" >}}).
|
||||
|
||||
## Configure common options
|
||||
|
||||
You can configure Prometheus-specific options in the query editor by setting several options regardless of mode.
|
||||
You can configure Prometheus-specific options in the query editor by setting several options regardless of its mode.
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/options.png" max-width="500px" class="docs-image--no-shadow" caption="Options" >}}
|
||||
{{< figure src="/static/img/docs/prometheus/options-9-1.png" max-width="500px" class="docs-image--no-shadow" caption="Options" >}}
|
||||
|
||||
### Legend
|
||||
|
||||
The **Legend** setting defines the time series's name. You can use a predefined or custom format.
|
||||
|
||||
- **Auto** - Displays unique labels. Also displays all overlapping labels if a series has multiple labels.
|
||||
- **Verbose** - Displays all label names.
|
||||
- **Custom** - Uses templating to select which labels will be included. For example, `{{hostname}}` is replaced by the label value for the label `hostname`. Clear the input and click outside of it to select another mode.
|
||||
| Option | Description |
|
||||
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Auto** | Shows the value of a single label for each series with only one label, or displays all labels if a series has multiple labels. |
|
||||
| **Verbose** | Displays all labels. |
|
||||
| **Custom** | Uses templating to select which labels will be included.<br/>For example, `{{hostname}}` is replaced by the label value for the label `hostname`.<br/>Clear the input and click outside of it to select another mode. |
|
||||
|
||||
### Min step
|
||||
|
||||
@@ -73,134 +66,155 @@ This setting supports the `$__interval` and `$__rate_interval` macros.
|
||||
|
||||
### Format
|
||||
|
||||
Switch between the following format options:
|
||||
You can switch between **Table**, **Time series**, and **Heatmap** options by configuring the query's **Format**.
|
||||
|
||||
- **Time series** - The default time series format. See [Time series kind formats](https://grafana.github.io/dataplane/timeseries/) for information on time series data frames and how time and value fields are structured.
|
||||
- **Table** - This works only in a [Table panel]({{< relref "../../../panels-visualizations/visualizations/table" >}}).
|
||||
- **Heatmap** - Displays metrics of the Histogram type on a [Heatmap panel]({{< relref "../../../panels-visualizations/visualizations/heatmap" >}}) by converting cumulative histograms to regular ones and sorting the series by the bucket bound.
|
||||
| Option | Description |
|
||||
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Table** | This works only in a [Table panel]{{< relref "../../../panels-visualizations/visualizations/table" >}}. |
|
||||
| **Time series** | Uses the default time series format. |
|
||||
| **Heatmap** | Displays metrics of the Histogram type on a [Heatmap panel]{{< relref "../../../panels-visualizations/visualizations/heatmap" >}} by converting cumulative histograms to regular ones and sorting the series by the bucket bound. |
|
||||
|
||||
### Type
|
||||
|
||||
The **Type** setting sets the query type. These include:
|
||||
The **Type** setting selects the query type.
|
||||
|
||||
- **Both** - The default option. Returns results for both a **Range** query and an **Instant** query.
|
||||
- **Range** - Returns a range vector consisting of a set of time series data containing a range of data points over time for each time series. You can choose lines, bars, points, stacked lines or stacked bars
|
||||
- **Instant** - Returns one data point per query and only the most recent point in the time range provided. The results can be shown in table format or as raw data. To depict instant query results in the time series panel, first add a field override, next add a property to the override named `Transform`, and finally select `Constant` from the **Transform** dropdown.
|
||||
- A **Range** query returns a Range vector, comprised of a set of time series containing a range of data points over time for each time series.
|
||||
- An **Instant** query returns only the latest value that Prometheus has scraped for the requested time series. Instant queries can return results much faster than normal range queries and are well suited to look up label sets.
|
||||
|
||||
For more information, refer to the [Time Series Transform option documentation]({{< relref "../../../panels-visualizations/visualizations/time-series#transform" >}}).
|
||||
Instant query results are comprised of only one data point per series and can be shown in the time series panel by adding a field override, adding a property to the override named `Transform`, and selecting `Constant` from the **Transform** dropdown.
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
Grafana modifies the request dates for queries to align them with the dynamically calculated step.
|
||||
This ensures a consistent display of metrics data, but it can result in a small gap of data at the right edge of a graph.
|
||||
{{% /admonition %}}
|
||||
For more information, refer to the [Time Series Transform option documentation]({{< relref "../../../panels-visualizations/visualizations/time-series#transform" >}}).
|
||||
|
||||
### Exemplars
|
||||
- An **Exemplars** query runs with the regular query and shows exemplars in the graph.
|
||||
|
||||
Toggle **Exemplars** to run a query that includes exemplars in the graph. Exemplars are unique to Prometheus. For more information see [Introduction to exemplars](https://grafana.com/docs/grafana/latest/fundamentals/exemplars/).
|
||||
> **Note:** Grafana modifies the request dates for queries to align them with the dynamically calculated step.
|
||||
> This ensures a consistent display of metrics data, but it can result in a small gap of data at the right edge of a graph.
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
There is no option to add exemplars with an **Instant** query type.
|
||||
{{% /admonition %}}
|
||||
## Code mode
|
||||
|
||||
### Inspector
|
||||
{{< figure src="/static/img/docs/prometheus/code-mode-9-1.png" max-width="500px" class="docs-image--no-shadow" caption="Code mode" >}}
|
||||
|
||||
Click **Inspector** to get detailed statistics regarding your query. Inspector functions as a kind of debugging tool that "inspects" your query. It provides query statistics under **Stats**, request response time under **Query**, data frame details under **{} JSON**, and the shape of your data under **Data**.
|
||||
In **Code mode**, you can write complex queries using a text editor with autocompletion features and syntax highlighting.
|
||||
It also contains a [Metrics browser]({{< relref "#metrics-browser" >}}) to further help you write queries.
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/insepctor-9-5.png" max-width="500px" class="docs-image--no-shadow" caption="Inspector" >}}
|
||||
For more information about Prometheus's query language, refer to the [Prometheus documentation](http://prometheus.io/docs/querying/basics/).
|
||||
|
||||
### Use autocompletion
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/autocomplete-9-1.png" max-width="500px" class="docs-image--no-shadow" caption="Autocomplete" >}}
|
||||
|
||||
Code mode's autocompletion feature works automatically while typing.
|
||||
To manually trigger autocompletion, use the keyboard shortcut <key>Ctrl</key>/<key>Cmd</key> + <key>Space</key>.
|
||||
|
||||
The query editor can autocomplete static functions, aggregations, and keywords, and also dynamic items like metrics and labels.
|
||||
The autocompletion dropdown includes documentation for the suggested items where available.
|
||||
|
||||
To run a query in [Explore]({{< relref "../../../explore/" >}}), use the keyboard shortcut <key>Shift</key> + <key>Enter</key>.
|
||||
|
||||
### Metrics browser
|
||||
|
||||
The metrics browser locates metrics and selects relevant labels to help you build basic queries.
|
||||
When you open the browser, it displays all available metrics and labels.
|
||||
If supported by your Prometheus instance, each metric also displays its HELP and TYPE as a tooltip.
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/metric-browser-9-1.png" max-width="500px" class="docs-image--no-shadow" caption="Metrics browser" >}}
|
||||
|
||||
When you select a metric, the browser narrows down the available labels to show only the ones applicable to the metric.
|
||||
You can then select one or more labels for which the available label values are shown in lists in the bottom section.
|
||||
Select one or more values for each label to tighten your query scope.
|
||||
|
||||
> **Note:** If you do not remember a metric name to start with, you can also select a few labels to narrow down the list, then find relevant label values.
|
||||
|
||||
All lists in the metrics browser have a search field above them to quickly filter for metrics or labels that match a certain string.
|
||||
The values section has only one search field, and its filtering applies to all labels to help you find values across labels once selected.
|
||||
|
||||
For example, among your labels `app`, `job`, `job_name` only one might with the value you are looking for.
|
||||
|
||||
Once you are satisfied with your query, click "Use query" to run the query. The button "Use as rate query" adds a `rate(...)[$__interval]` around your query to help write queries for counter metrics.
|
||||
The "Validate selector" button will check with Prometheus how many time series are available for that selector.
|
||||
|
||||
## Builder mode
|
||||
|
||||
**Builder mode** helps you build queries using a visual interface. This option is best for users who have limited or no previous experience working with Prometheus and PromQL.
|
||||
In **Builder mode**, you can build queries using a visual interface.
|
||||
|
||||
This video demonstrates how to use the visual Prometheus query builder available in Grafana v9.0:
|
||||
This video demonstrates how to use the visual Prometheus query builder available since Grafana v9.0:
|
||||
|
||||
{{< vimeo 720004179 >}}
|
||||
|
||||
</br>
|
||||
|
||||
### Metrics
|
||||
### Toolbar
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/metrics-and-labels.png" max-width="500px" class="docs-image--no-shadow" caption="Metric and label filters" >}}
|
||||
In addition to the **Run query** button and mode switcher, Builder mode includes additional elements:
|
||||
|
||||
When you are ready to create a query, you can choose the specific metric name from the dropdown list under **Metric**.
|
||||
| Name | Description |
|
||||
| ------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| **Kick start your query** | A list of operation patterns that help you quickly add multiple operations to your query. |
|
||||
| **Explain** | Displays a step-by-step explanation of all query parts and its operations. |
|
||||
|
||||
### Metric and labels
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/metric-select-9-1.png" max-width="500px" class="docs-image--no-shadow" caption="Metric and labels" >}}
|
||||
|
||||
Select a specific metric name from the dropdown list.
|
||||
The data source requests the list of available metrics from the Prometheus server based on the selected time rage.
|
||||
You can also enter text into the selector when the dropdown is open to search and filter the list.
|
||||
|
||||
### Label filters
|
||||
|
||||
Select desired labels and their values from the dropdown list.
|
||||
When a metric is selected, the data source requests available labels and their values from the server.
|
||||
Use the `+` button to add a label, and the `x` button to remove a label.
|
||||
|
||||
### Operations
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/operations.png" max-width="500px" class="docs-image--no-shadow" caption="Operations" >}}
|
||||
{{< figure src="/static/img/docs/prometheus/operations-9-1.png" max-width="500px" class="docs-image--no-shadow" caption="Operations" >}}
|
||||
|
||||
Select the **+ Operations** button to add operations to your query.
|
||||
Select the `+ Operations` button to add operations to your query.
|
||||
The query editor groups operations into related sections, and you can type while the operations dropdown is open to search and filter the list.
|
||||
|
||||
The query editor groups operations into the following sections:
|
||||
The query editor displays a query's operations as boxes in the operations section.
|
||||
Each operation's header displays its name, and additional action buttons appear when you hover your cursor over the header:
|
||||
|
||||
- Aggregations - for additional information see [Aggregation operators](https://prometheus.io/docs/prometheus/latest/querying/operators/#aggregation-operators).
|
||||
- Range functions - for additional information see [Functions](https://prometheus.io/docs/prometheus/latest/querying/functions/#functions).
|
||||
- Functions - for additional information see [Functions](https://prometheus.io/docs/prometheus/latest/querying/functions/#functions).
|
||||
- Binary operations - for additional information see [Binary operators](https://prometheus.io/docs/prometheus/latest/querying/operators/#binary-operators).
|
||||
- Trigonometric - for additional information see [Trigonometric functions](https://prometheus.io/docs/prometheus/latest/querying/functions/#trigonometric-functions).
|
||||
- Time functions - for additional information see [Functions](https://prometheus.io/docs/prometheus/latest/querying/functions/#functions).
|
||||
| Button | Action |
|
||||
| ------ | ----------------------------------------------------------------- |
|
||||
| `v` | Replaces the operation with different operation of the same type. |
|
||||
| `info` | Opens the operation's description tooltip. |
|
||||
| `x` | Removes the operation. |
|
||||
|
||||
All operations have function parameters under the operation header. Click the `operator` to see a full list of supported functions. Some operations allow you to apply specific labels to functions.
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/use-function-by-label-9-5.png" max-width="500px" class="docs-image--no-shadow" caption="Functions and labels" >}}
|
||||
Some operations have additional parameters under the operation header.
|
||||
For details about each operation, use the `info` button to view the operation's description, or refer to the Prometheus documentation on [query functions](https://prometheus.io/docs/prometheus/latest/querying/functions/).
|
||||
|
||||
Some operations make sense only when used in a specific order.
|
||||
If adding an operation would result in nonsensical query, the query editor adds the operation to the correct place.
|
||||
To re-order operations manually, drag the operation box by its name and drop it into the desired place.
|
||||
|
||||
#### Hints
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/hint-example.png" max-width="500px" class="docs-image--no-shadow" caption="Hint" >}}
|
||||
{{< figure src="/static/img/docs/prometheus/hint-8-5.png" max-width="500px" class="docs-image--no-shadow" caption="Hint" >}}
|
||||
|
||||
The query editor can detect which operations are most appropriate for some selected metrics.
|
||||
If it does, it displays a hint next to the **+ Operations** button.
|
||||
If it does, it displays a hint next to the `+ Operations` button.
|
||||
|
||||
To add the operation to your query, click the **Hint**.
|
||||
To add the operations to your query, click the hint.
|
||||
|
||||
Once you are satisfied with your query, click **Run query**.
|
||||
## Use Explain mode to understand queries
|
||||
|
||||
## Code mode
|
||||
{{< figure src="/static/img/docs/prometheus/explain-8-5.png" max-width="500px" class="docs-image--no-shadow" caption="Explain mode" >}}
|
||||
|
||||
**Code mode** is for the experienced Prometheus user with prior expertise in PromQL, Prometheus' query language. The Code mode editor allows you to create queries just as you would in Prometheus. For more information about PromQL see [Querying Prometheus](http://prometheus.io/docs/querying/basics/).
|
||||
Explain mode helps you understand a query by displaying a step-by-step explanation of all query components and operations.
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/code-mode.png" max-width="500px" class="docs-image--no-shadow" caption="Code mode" >}}
|
||||
### Additional options
|
||||
|
||||
The user interface (UI) also lets you select metrics, labels, filters and operations.
|
||||
In addition to these Builder mode-specific options, the query editor also displays the options it shares in common with Code mode.
|
||||
For details, refer to the [common options]({{< relref "#configure-common-options" >}}).
|
||||
|
||||
You can write complex queries using the text editor with autocompletion features and syntax highlighting.
|
||||
It also contains a [Metrics browser]({{< relref "#metrics-browser" >}}) to further help you write queries.
|
||||
## Apply annotations
|
||||
|
||||
### Use autocomplete
|
||||
[Annotations]({{< relref "../../../dashboards/build-dashboards/annotate-visualizations" >}}) overlay rich event information on top of graphs.
|
||||
You can add annotation queries in the Dashboard menu's Annotations view.
|
||||
|
||||
Code mode's autocomplete feature works automatically while typing. The query editor can autocomplete static functions, aggregations, keywords, and also dynamic items like metrics and labels.
|
||||
The autocompletion dropdown includes documentation for the suggested items where available.
|
||||
Prometheus supports two ways to query annotations.
|
||||
|
||||
### Metrics browser
|
||||
- A regular metric query
|
||||
- A Prometheus query for pending and firing alerts (for details see [Inspecting alerts during runtime](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/#inspecting-alerts-during-runtime))
|
||||
|
||||
The metrics browser locates metrics and selects relevant labels to help you build basic queries.
|
||||
When you click **Metrics browser**, it displays all available metrics and labels.
|
||||
If supported by your Prometheus instance, each metric also displays its `HELP` and `TYPE` as a tooltip.
|
||||
|
||||
{{< figure src="/static/img/docs/prometheus/metric-browser.png" max-width="500px" class="docs-image--no-shadow" caption="Metrics browser" >}}
|
||||
|
||||
When you select a metric under Step 1, the browser narrows down the available labels to show only the ones applicable to the metric.
|
||||
You can then select one or more labels shown in Step 2.
|
||||
Select one or more values in Step 3 for each label to tighten your query scope.
|
||||
In Step 4, you can select **Use query** to run the query, **Use as rate query** to add the rate operation to your query (`$__rate_interval`), **Validate selector** to verify the selector is valid and show the number of series found, or **Clear** to clear your selections and start over.
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
If you do not remember a metric name, you can also select a few labels to narrow down the list, then find relevant label values.
|
||||
{{% /admonition %}}
|
||||
|
||||
All lists in the metrics browser have a search field above them to quickly filter for metrics or labels that match a certain string.
|
||||
The values section has only one search field, and its filtering applies to all labels to help you find values across labels once selected.
|
||||
|
||||
For example, among your labels `app`, `job`, `job_name` only one might have the value you are looking for.
|
||||
|
||||
Once you are satisfied with your query, click **Run query**.
|
||||
The step option is useful to limit the number of events returned from your query.
|
||||
|
||||
4
docs/sources/datasources/testdata/_index.md
vendored
4
docs/sources/datasources/testdata/_index.md
vendored
@@ -39,7 +39,7 @@ The data source doesn't provide any settings beyond the most basic options commo
|
||||
|
||||
## Create mock data
|
||||
|
||||
{{< figure src="/media/docs/grafana/data-sources/screenshot-testdata-add-10.0.png" class="docs-image--no-shadow" caption="Adding test data" >}}
|
||||
{{< figure src="/static/img/docs/v41/test_data_add.png" class="docs-image--no-shadow" caption="Adding test data" >}}
|
||||
|
||||
Once you've added the TestData data source, your Grafana instance's users can use it as a data source in any metric panel.
|
||||
|
||||
@@ -49,7 +49,7 @@ Instead of providing a query editor, the TestData data source helps you select a
|
||||
|
||||
You can assign an **Alias** to each scenario, and many have their own options that appear when selected.
|
||||
|
||||
{{< figure src="/media/docs/grafana/data-sources/screenshot-testdata-csv-example-10.0.png" class="docs-image--no-shadow" caption="Using CSV Metric Values" >}}
|
||||
{{< figure src="/static/img/docs/v41/test_data_csv_example.png" class="docs-image--no-shadow" caption="Using CSV Metric Values" >}}
|
||||
|
||||
**Available scenarios:**
|
||||
|
||||
|
||||
@@ -56,6 +56,6 @@ Grafana Enterprise includes all of the Grafana OSS APIs as well as those that fo
|
||||
|
||||
- [Role-based access control API]({{< relref "access_control/" >}})
|
||||
- [Data source permissions API]({{< relref "datasource_permissions/" >}})
|
||||
- [Team sync API]({{< relref "team_sync/" >}})
|
||||
- [External group sync API]({{< relref "external_group_sync/" >}})
|
||||
- [License API]({{< relref "licensing/" >}})
|
||||
- [Reporting API]({{< relref "reporting/" >}})
|
||||
|
||||
@@ -57,8 +57,10 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
- **dashboard.id** – id = null to create a new dashboard.
|
||||
- **dashboard.uid** – Optional unique identifier when creating a dashboard. uid = null will generate a new uid.
|
||||
- **folderId** – The id of the folder to save the dashboard in.
|
||||
- **folderUid** – The UID of the folder to save the dashboard in. Overrides the `folderId`.
|
||||
- **overwrite** – Set to true if you want to overwrite existing dashboard with newer version, same dashboard title in folder or same dashboard uid.
|
||||
- **message** - Set a commit message for the version history.
|
||||
- **refresh** - Set the dashboard refresh interval. If this is lower than [the minimum refresh interval]({{< relref "/docs/grafana/latest/setup-grafana/configure-grafana#min_refresh_interval" >}}), then Grafana will ignore it and will enforce the minimum refresh interval.
|
||||
|
||||
For adding or updating an alert rule for a dashboard panel the user should declare a
|
||||
`dashboard.panels.alert` block.
|
||||
@@ -67,36 +69,169 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 78
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 78
|
||||
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
|
||||
- **200** – Created
|
||||
- **400** – Errors (invalid json, missing or invalid fields, etc)
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
- **412** – Precondition failed
|
||||
|
||||
The **412** status code is used for explaining that you cannot create the dashboard and why.
|
||||
There can be different reasons for this:
|
||||
|
||||
- The dashboard has been changed by someone else, `status=version-mismatch`
|
||||
- A dashboard with the same name in the folder already exists, `status=name-exists`
|
||||
- A dashboard with the same uid already exists, `status=name-exists`
|
||||
- The dashboard belongs to plugin `<plugin title>`, `status=plugin-dashboard`
|
||||
|
||||
- **412** – Precondition failed
|
||||
|
||||
The **412** status code is used for explaining that you cannot create the dashboard and why.
|
||||
There can be different reasons for this:
|
||||
|
||||
- The dashboard has been changed by someone else, `status=version-mismatch`
|
||||
- A dashboard with the same name in the folder already exists, `status=name-exists`
|
||||
- A dashboard with the same uid already exists, `status=name-exists`
|
||||
- The dashboard belongs to plugin `<plugin title>`, `status=plugin-dashboard`
|
||||
|
||||
The response body will have the following properties:
|
||||
|
||||
```http
|
||||
HTTP/1.1 412 Precondition Failed
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 97
|
||||
|
||||
```
|
||||
|
||||
In case of title already exists the `status` property will be `name-exists`.
|
||||
|
||||
## Get dashboard by uid
|
||||
|
||||
`GET /api/dashboards/uid/:uid`
|
||||
|
||||
Will return the dashboard given the dashboard unique identifier (uid). Information about the unique identifier of a folder containing the requested dashboard might be found in the metadata.
|
||||
|
||||
**Required permissions**
|
||||
|
||||
See note in the [introduction]({{< ref "#dashboard-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| ----------------- | -------------- |
|
||||
| `dashboards:read` | `dashboards:*` |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/dashboards/uid/cIBgcSjkk HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Found
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
- **404** – Not found
|
||||
|
||||
## Delete dashboard by uid
|
||||
|
||||
`DELETE /api/dashboards/uid/:uid`
|
||||
|
||||
Will delete the dashboard given the specified unique identifier (uid).
|
||||
|
||||
**Required permissions**
|
||||
|
||||
See note in the [introduction]({{< ref "#dashboard-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| ------------------- | ----------------------------- |
|
||||
| `dashboards:delete` | `dashboards:*`<br>`folders:*` |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
DELETE /api/dashboards/uid/cIBgcSjkk HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Deleted
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
- **404** – Not found
|
||||
|
||||
## Gets the home dashboard
|
||||
|
||||
`GET /api/dashboards/home`
|
||||
|
||||
Will return the home dashboard.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/dashboards/home HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
## Tags for Dashboard
|
||||
|
||||
`GET /api/dashboards/tags`
|
||||
|
||||
Get all tags of dashboards
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/dashboards/tags HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
## Dashboard Search
|
||||
|
||||
See [Folder/Dashboard Search API]({{< relref "folder_dashboard_search/" >}}).
|
||||
@@ -108,12 +243,12 @@ Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 78
|
||||
|
||||
{
|
||||
## Get dashboard by uid
|
||||
|
||||
`GET /api/dashboards/uid/:uid`
|
||||
|
||||
Will return the dashboard given the dashboard unique identifier (uid). Information about the unique identifier of a folder containing the requested dashboard might be found in the metadata.
|
||||
|
||||
"id": 1,
|
||||
"uid": "cIBgcSjkk",
|
||||
"url": "/d/cIBgcSjkk/production-overview",
|
||||
"status": "success",
|
||||
"version": 1,
|
||||
"slug": "production-overview" //deprecated in Grafana v5.0
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
---
|
||||
aliases:
|
||||
- ../../http_api/external_group_sync/
|
||||
- ./external_group_sync/
|
||||
canonical: /docs/grafana/latest/developers/http_api/team_sync/
|
||||
description: Grafana Team Sync HTTP API
|
||||
canonical: /docs/grafana/latest/developers/http_api/external_group_sync/
|
||||
description: Grafana External Group Sync HTTP API
|
||||
keywords:
|
||||
- grafana
|
||||
- http
|
||||
@@ -14,12 +13,12 @@ keywords:
|
||||
- group
|
||||
- member
|
||||
- enterprise
|
||||
title: Team Sync HTTP API
|
||||
title: External Group Sync HTTP API
|
||||
---
|
||||
|
||||
# Team Sync API
|
||||
# External Group Synchronization API
|
||||
|
||||
> Team Sync is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "/docs/grafana/latest/introduction/grafana-enterprise" >}}).
|
||||
> External Group Synchronization is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "/docs/grafana/latest/introduction/grafana-enterprise" >}}).
|
||||
|
||||
> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
|
||||
|
||||
@@ -30,14 +30,14 @@ Returns a list of all library elements the authenticated user has permission to
|
||||
|
||||
Query parameters:
|
||||
|
||||
- `searchString`: Part of the name or description searched for.
|
||||
- `kind`: Kind of element to search for. Use `1` for library panels or `2` for library variables.
|
||||
- `sortDirection`: Sort order of elements. Use `alpha-asc` for ascending and `alpha-desc` for descending sort order.
|
||||
- `typeFilter`: A comma separated list of types to filter the elements by.
|
||||
- `excludeUid`: Element UID to exclude from search results.
|
||||
- `folderFilter`: A comma separated list of folder IDs to filter the elements by.
|
||||
- `perPage`: The number of results per page; default is 100.
|
||||
- `page`: The page for a set of records, given that only `perPage` records are returned at a time. Numbering starts at `1`.
|
||||
- **searchString** – Part of the name or description searched for.
|
||||
- **kind** – Kind of element to search for. Use `1` for library panels or `2` for library variables.
|
||||
- **sortDirection** – Sort order of elements. Use `alpha-asc` for ascending and `alpha-desc` for descending sort order.
|
||||
- **typeFilter** – A comma separated list of types to filter the elements by.
|
||||
- **excludeUid** – Element UID to exclude from search results.
|
||||
- **folderFilter** – A comma separated list of folder ID(s) to filter the elements by.
|
||||
- **perPage** – The number of results per page; default is 100.
|
||||
- **page** – The page for a set of records, given that only `perPage` records are returned at a time. Numbering starts at `1`.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
@@ -98,8 +98,8 @@ Content-Type: application/json
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/library-elements/name/API docs Example HTTP/1.1
|
||||
```http
|
||||
GET /api/library-elements/name/API docs Example HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
@@ -157,9 +157,9 @@ Content-Type: application/json
|
||||
JSON Body schema:
|
||||
|
||||
- **folderId** – ID of the folder where the library element is stored. It is deprecated since Grafana v9
|
||||
- `folderUid`: Optional, the UID of the folder where the library element is stored, empty string when it is General folder
|
||||
- `name`: Optional, the name of the library element.
|
||||
- `model`: The JSON model for the library element.
|
||||
- **folderUid** – Optional, the UID of the folder where the library element is stored, empty string when it is General folder
|
||||
- **name** – Optional, the name of the library element.
|
||||
- **model** – The JSON model for the library element.
|
||||
- **kind** – Kind of element to create, Use `1` for library panels or `2` for library variables.
|
||||
- **uid** – Optional, the [unique identifier](/http_api/library_element/#identifier-id-vs-unique-identifier-uid).
|
||||
|
||||
@@ -219,9 +219,9 @@ Content-Type: application/json
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Updated
|
||||
@@ -265,9 +265,9 @@ Content-Type: application/json
|
||||
- **403** – Access denied
|
||||
- **404** – Library element not found
|
||||
|
||||
- `200`: Found
|
||||
- `401`: Unauthorized
|
||||
- `404`: Library element not found
|
||||
- **200** – Found
|
||||
- **401** – Unauthorized
|
||||
- **404** – Library element not found
|
||||
|
||||
## Create library element
|
||||
|
||||
@@ -277,12 +277,12 @@ Creates a new library element.
|
||||
|
||||
JSON Body schema:
|
||||
|
||||
- `folderId`: ID of the folder where the library element is stored. It is deprecated since Grafana v9
|
||||
- `folderUid`: Optional, the UID of the folder where the library element is stored, empty string when it is General folder
|
||||
- `name`: Optional, the name of the library element.
|
||||
- `model`: The JSON model for the library element.
|
||||
- `kind`: Kind of element to create, Use `1` for library panels or `2` for library variables.
|
||||
- `uid`: Optional, the [unique identifier](/http_api/library_element/#identifier-id-vs-unique-identifier-uid).
|
||||
- **folderId** – ID of the folder where the library element is stored. It is deprecated since Grafana v9
|
||||
- **folderUid** – Optional, the UID of the folder where the library element is stored, empty string when it is General folder
|
||||
- **name** – Optional, the name of the library element.
|
||||
- **model** – The JSON model for the library element.
|
||||
- **kind** – Kind of element to create, Use `1` for library panels or `2` for library variables.
|
||||
- **uid** – Optional, the [unique identifier](/http_api/library_element/#identifier-id-vs-unique-identifier-uid).
|
||||
|
||||
**Example Request**:
|
||||
|
||||
@@ -343,10 +343,10 @@ Content-Type: application/json
|
||||
|
||||
Status Codes:
|
||||
|
||||
- `200`: Created
|
||||
- `400`: Errors (for example, name or UID already exists, invalid JSON, missing or invalid fields, and so on).
|
||||
- `401`: Unauthorized
|
||||
- `403`: Access denied
|
||||
- **200** – Created
|
||||
- **400** – Errors (for example, name or UID already exists, invalid JSON, missing or invalid fields, and so on).
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
|
||||
## Update library element
|
||||
|
||||
@@ -356,13 +356,13 @@ Updates an existing library element identified by uid.
|
||||
|
||||
JSON Body schema:
|
||||
|
||||
- `folderId`: ID of the folder where the library element is stored. It is deprecated since Grafana v9
|
||||
- `folderUid`: UID of the folder where the library element is stored, empty string when it is General folder.
|
||||
- `name`: Name of the library element.
|
||||
- `model`: The JSON model for the library element.
|
||||
- `kind`: Kind of element to create. Use `1` for library panels or `2` for library variables.
|
||||
- `version`: Version of the library element you are updating.
|
||||
- `uid`: Optional, the [unique identifier](/http_api/library_element/#identifier-id-vs-unique-identifier-uid).
|
||||
- **folderId** – ID of the folder where the library element is stored. It is deprecated since Grafana v9
|
||||
- **folderUid** – UID of the folder where the library element is stored, empty string when it is General folder.
|
||||
- **name** – Name of the library element.
|
||||
- **model** – The JSON model for the library element.
|
||||
- **kind** – Kind of element to create. Use `1` for library panels or `2` for library variables.
|
||||
- **version** – Version of the library element you are updating.
|
||||
- **uid** – Optional, the [unique identifier](/http_api/library_element/#identifier-id-vs-unique-identifier-uid).
|
||||
|
||||
**Example Request**:
|
||||
|
||||
@@ -424,12 +424,12 @@ Content-Type: application/json
|
||||
|
||||
Status Codes:
|
||||
|
||||
- `200`: Updated
|
||||
- `400`: Errors (for example, name or UID already exists, invalid JSON, missing or invalid fields, and so on).
|
||||
- `401`: Unauthorized
|
||||
- `403`: Access denied
|
||||
- `404`: Library element not found
|
||||
- `412`: Version mismatch
|
||||
- **200** – Updated
|
||||
- **400** – Errors (for example, name or UID already exists, invalid JSON, missing or invalid fields, and so on).
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
- **404** – Library element not found
|
||||
- **412** – Version mismatch
|
||||
|
||||
## Delete library element
|
||||
|
||||
@@ -463,8 +463,8 @@ Content-Type: application/json
|
||||
|
||||
Status Codes:
|
||||
|
||||
- `200`: Deleted
|
||||
- `401`: Unauthorized
|
||||
- `400`: Bad request
|
||||
- `403`: Access denied
|
||||
- `404`: Library element not found
|
||||
- **200** – Deleted
|
||||
- **401** – Unauthorized
|
||||
- **400** – Bad request
|
||||
- **403** – Access denied
|
||||
- **404** – Library element not found
|
||||
|
||||
@@ -217,168 +217,8 @@ Content-Type: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
## Get API key to service account migration status
|
||||
|
||||
`GET /api/serviceaccounts/migrationstatus`
|
||||
|
||||
**Required permissions**
|
||||
|
||||
See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| -------------------- | ------------------ |
|
||||
| serviceaccounts:read | serviceaccounts:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
POST /api/serviceaccounts/migrationstatus HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```
|
||||
|
||||
## Hide the API keys tab
|
||||
|
||||
`GET /api/serviceaccounts/hideApiKeys`
|
||||
|
||||
**Required permissions**
|
||||
|
||||
See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| --------------------- | ------------------ |
|
||||
| serviceaccounts:write | serviceaccounts:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
POST /api/serviceaccounts/hideApiKeys HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
## Get service account tokens
|
||||
|
||||
`GET /api/serviceaccounts/:id/tokens`
|
||||
|
||||
**Required permissions**
|
||||
|
||||
See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| -------------------- | --------------------- |
|
||||
| serviceaccounts:read | serviceaccounts:id:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/serviceaccounts/2/tokens HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
## Create service account tokens
|
||||
|
||||
`POST /api/serviceaccounts/:id/tokens`
|
||||
|
||||
**Required permissions**
|
||||
|
||||
See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| --------------------- | --------------------- |
|
||||
| serviceaccounts:write | serviceaccounts:id:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
POST /api/serviceaccounts/2/tokens HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
## Delete service account tokens
|
||||
|
||||
`DELETE /api/serviceaccounts/:id/tokens/:tokenId`
|
||||
|
||||
**Required permissions**
|
||||
|
||||
See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| --------------------- | --------------------- |
|
||||
| serviceaccounts:write | serviceaccounts:id:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
DELETE /api/serviceaccounts/2/tokens/1 HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
## Revert service account token to API key
|
||||
|
||||
`DELETE /api/serviceaccounts/:serviceAccountId/revert/:keyId`
|
||||
|
||||
This operation will delete the service account and create a legacy API Key for the given `keyId`.
|
||||
|
||||
**Required permissions**
|
||||
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
|
||||
@@ -2,51 +2,80 @@
|
||||
aliases:
|
||||
- ../plugins/developing/
|
||||
description: Resources for creating Grafana plugins
|
||||
title: Plugin developer's guide
|
||||
title: Build a plugin
|
||||
weight: 200
|
||||
---
|
||||
|
||||
# Grafana plugin developer's guide
|
||||
# Build a plugin
|
||||
|
||||
You can extend Grafana's built-in capabilities with plugins. Plugins enable Grafana to accomplish specialized tasks, custom-tailored to your requirements. By making a plugin for your organization, you can connect Grafana to other data sources, ticketing tools, and CI/CD tooling.
|
||||
For more information on the types of plugins you can build, refer to the [Plugin Overview]({{< relref "../../administration/plugin-management/" >}}).
|
||||
|
||||
You can create plugins for private use or contribute them to the open source community by publishing to the [Grafana plugin catalog](https://grafana.com/grafana/plugins/). This catalog has hundreds of other community and commercial plugins.
|
||||
## Get started
|
||||
|
||||
If you are a Grafana plugin developer or want to become one, this plugin developer's guide contains the tutorials and reference materials to help you get started.
|
||||
The easiest way to start developing Grafana plugins is to use the Grafana [create-plugin tool](https://www.npmjs.com/package/@grafana/create-plugin).
|
||||
|
||||
## Plugin basics
|
||||
Open the terminal, and run the following command in your [plugin directory]({{< relref "../../setup-grafana/configure-grafana/#plugins" >}}):
|
||||
|
||||
You can create several types of plugins, including:
|
||||
```bash
|
||||
npx @grafana/create-plugin@latest
|
||||
```
|
||||
|
||||
- **Panel plugins** - Visualize data and navigate between dashboards.
|
||||
- **Data source plugins** - Link to new databases or other sources of data.
|
||||
- **App plugins** - Create rich applications for custom out-of-the-box experiences.
|
||||
Follow the questions and you will have a starter plugin ready to develop.
|
||||
|
||||
> **Note:** To learn more about the types of plugins you can build, refer to the [Plugin management]({{< relref "../../administration/plugin-management" >}}) documentation.
|
||||
If you want a more guided introduction to plugin development, check out our tutorials:
|
||||
|
||||
## Contents of this developer's guide
|
||||
|
||||
The following topics are covered in this guide:
|
||||
|
||||
- **[Get started with plugins]({{< relref "./get-started-with-plugins" >}})** - Start developing Grafana plugins with the [Create-plugin](https://www.npmjs.com/package/@grafana/create-plugin) tool.
|
||||
- **[Introduction to plugin development]({{< relref "./introduction-to-plugin-development" >}})** - Learn the fundamentals of Grafana plugin development: frontend and backend development processes, data frames, error handling, and more.
|
||||
- **[Create a Grafana plugin]({{< relref "./create-a-grafana-plugin" >}})** - If you're familiar with plugin creation, use the tutorials for creating panel plugins, data source plugins, and more to deepen your knowledge.
|
||||
- **[Migrate a plugin]({{< relref "./migration-guide" >}})** - Learn how to upgrade from a previous version of a Grafana plugin, rewrite an old Angular plugin in React, or update to a newer version.
|
||||
- **[Publish a Grafana plugin]({{< relref "./publish-a-plugin" >}})** - Learn about publishing a plugin to the Grafana plugin catalog, including publishing criteria, packaging, and deployment.
|
||||
- **[Reference]({{< relref "metadata.md" >}})** - Description of the `plugin.json` schema and plugin metadata.
|
||||
- [Build a panel plugin](/tutorials/build-a-panel-plugin/)
|
||||
- [Build a data source plugin](/tutorials/build-a-data-source-plugin/)
|
||||
|
||||
## Go further
|
||||
|
||||
Learn more about additional tools and see plugin type examples.
|
||||
Learn more about specific areas of plugin development.
|
||||
|
||||
### User interface creation
|
||||
### Tutorials
|
||||
|
||||
If you're looking to build your first plugin, check out these introductory tutorials:
|
||||
|
||||
- [Build a panel plugin](/tutorials/build-a-panel-plugin/)
|
||||
- [Build a data source plugin](/tutorials/build-a-data-source-plugin/)
|
||||
- [Build a data source backend plugin](/tutorials/build-a-data-source-backend-plugin/)
|
||||
|
||||
Ready to learn more? Check out our other tutorials:
|
||||
|
||||
- [Build a panel plugin with D3.js](/tutorials/build-a-panel-plugin-with-d3/)
|
||||
|
||||
### Guides
|
||||
|
||||
Improve an existing plugin with one of our guides:
|
||||
|
||||
- [Add authentication for data source plugins]({{< relref "add-authentication-for-data-source-plugins.md" >}})
|
||||
- [Add support for annotations]({{< relref "add-support-for-annotations.md" >}})
|
||||
- [Add support for Explore queries]({{< relref "add-support-for-explore-queries.md" >}})
|
||||
- [Add support for variables]({{< relref "add-support-for-variables.md" >}})
|
||||
- [Add a query editor help component]({{< relref "add-query-editor-help.md" >}})
|
||||
- [Build a logs data source plugin]({{< relref "build-a-logs-data-source-plugin.md" >}})
|
||||
- [Build a streaming data source plugin]({{< relref "build-a-streaming-data-source-plugin.md" >}}/)
|
||||
- [Error handling]({{< relref "error-handling.md" >}})
|
||||
- [Working with data frames]({{< relref "working-with-data-frames.md" >}})
|
||||
- [Development with local Grafana]({{< relref "development-with-local-grafana.md" >}})
|
||||
|
||||
### Concepts
|
||||
|
||||
Deepen your knowledge through a series of high-level overviews of plugin concepts:
|
||||
|
||||
- [Data frames]({{< relref "data-frames.md" >}})
|
||||
|
||||
### UI library
|
||||
|
||||
Explore the many UI components in our [Grafana UI library](/ui).
|
||||
|
||||
### Plugin examples
|
||||
### Examples
|
||||
|
||||
Grafana Labs provides a number of best practice example plugins for different use cases to help you quickly get started. Browse our [plugin examples](https://github.com/grafana/grafana-plugin-examples).
|
||||
For inspiration, check out our [plugin examples](https://github.com/grafana/grafana-plugin-examples).
|
||||
|
||||
### Metadata
|
||||
|
||||
- [Plugin metadata]({{< relref "metadata.md" >}})
|
||||
|
||||
### SDK
|
||||
|
||||
Learn more about [Grafana Plugin SDK for Go]({{< relref "./backend/grafana-plugin-sdk-for-go" >}}).
|
||||
- [Grafana Plugin SDK for Go]({{< relref "backend/grafana-plugin-sdk-for-go.md" >}})
|
||||
|
||||
@@ -2,17 +2,13 @@
|
||||
title: Add anonymous usage reporting
|
||||
---
|
||||
|
||||
# Add anonymous usage reporting
|
||||
# Add anonymous usage reporting to you plugin
|
||||
|
||||
Add anonymous usage tracking to your plugin to send [reporting events]({{< relref "../../setup-grafana/configure-grafana/#reporting_enabled" >}}) that describe how your plugin is being used to a tracking system configured by your Grafana server administrator.
|
||||
The Grafana server administrator has the possibility to configure [anonymous usage tracking]({{< relref "../../setup-grafana/configure-grafana/#reporting_enabled" >}}).
|
||||
|
||||
## Event reporting
|
||||
By adding usage tracking to your plugin you will send events of how your plugin is being used to the configured tracking system.
|
||||
|
||||
In this section, we show an example of tracking usage data from a query editor and receiving a report back from the analytics service.
|
||||
|
||||
### Sample query editor
|
||||
|
||||
Let's say you have a `QueryEditor` that looks similar to the example below. It has a `CodeEditor` field where you can write your query and a query type selector so you can select the kind of query result that you expect to return:
|
||||
Lets say we have a QueryEditor that looks something like the example below. It has an editor field where you can write your query and a query type selector so you can select what kind of query result you are expecting that query to return.
|
||||
|
||||
```ts
|
||||
import React, { ReactElement } from 'react';
|
||||
@@ -21,11 +17,11 @@ import type { EditorProps } from './types';
|
||||
|
||||
export function QueryEditor(props: EditorProps): ReactElement {
|
||||
const { datasource, query, onChange, onRunQuery } = props;
|
||||
const queryType = { value: query.value ?? 'timeseries' };
|
||||
const queryType = { value: query.value ?? 'timeserie' };
|
||||
const queryTypes = [
|
||||
{
|
||||
label: 'Timeseries',
|
||||
value: 'timeseries',
|
||||
label: 'Timeserie',
|
||||
value: 'timeserie',
|
||||
},
|
||||
{
|
||||
label: 'Table',
|
||||
@@ -70,14 +66,7 @@ export function QueryEditor(props: EditorProps): ReactElement {
|
||||
}
|
||||
```
|
||||
|
||||
### Track usage with `usePluginInteractionReporter`
|
||||
|
||||
Let's say that you want to track how the usage looks between time series and table queries.
|
||||
|
||||
What you want to do is to add the `usePluginInteractionReporter` to fetch a report function that takes two arguments:
|
||||
|
||||
- Required: An event name that begins with `grafana_plugin_`. It is used to identify the interaction being made.
|
||||
- Optional: Attached contextual data. In our example, that is the query type.
|
||||
Lets say that we would like to track how the usage looks between time series and table queries. All you need to do is to add the `usePluginInteractionReporter` to fetch a report function which takes two arguments. The first one is the event name which is used to identify the interaction being made. It need to start with `grafana_plugin_` which makes it easier to differentiate plugin events from Grafana core events. The second argument is optional and should be used to attach contextual data to the event. In our example, that would be the query type. It is optional because it does not make sense to pass contextual data for all user interactions.
|
||||
|
||||
```ts
|
||||
import React, { ReactElement } from 'react';
|
||||
@@ -89,11 +78,11 @@ export function QueryEditor(props: EditorProps): ReactElement {
|
||||
const { datasource, query, onChange, onRunQuery } = props;
|
||||
const report = usePluginInteractionReporter();
|
||||
|
||||
const queryType = { value: query.value ?? 'timeseries' };
|
||||
const queryType = { value: query.value ?? 'timeserie' };
|
||||
const queryTypes = [
|
||||
{
|
||||
label: 'Timeseries',
|
||||
value: 'timeseries',
|
||||
label: 'Timeserie',
|
||||
value: 'timeserie',
|
||||
},
|
||||
{
|
||||
label: 'Table',
|
||||
@@ -143,11 +132,7 @@ export function QueryEditor(props: EditorProps): ReactElement {
|
||||
}
|
||||
```
|
||||
|
||||
### Data returned from the analytics service
|
||||
|
||||
When you use `usePluginInteractionReporter`, the report function that is handed back to you automatically attaches contextual data about the plugin you are tracking to the events.
|
||||
|
||||
In our example, the following information is sent to the analytics service configured by the Grafana server administrator:
|
||||
Another benefit of using the `usePluginInteractionReporter` is that the report function that is handed back to you will automatically attach contextual data about the plugin you are tracking to every event. In our example the following information will be sent to the analytics service configured by the Grafana server administrator.
|
||||
|
||||
```ts
|
||||
{
|
||||
@@ -160,7 +145,7 @@ In our example, the following information is sent to the analytics service confi
|
||||
plugin_id: 'grafana-example-datasource',
|
||||
plugin_name: 'Example',
|
||||
datasource_uid: 'qeSI8VV7z', // will only be added for datasources
|
||||
query_type: 'timeseries'
|
||||
query_type: 'timeserie'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -7,121 +7,112 @@ title: Add authentication for data source plugins
|
||||
|
||||
# Add authentication for data source plugins
|
||||
|
||||
Grafana plugins can perform authenticated requests against a third-party API by using the _data source proxy_ or through a custom a _backend plugin_.
|
||||
This page explains how to configure your data source plugin to authenticate against a third-party API.
|
||||
|
||||
## Choose an authentication method
|
||||
There are two ways you can perform authenticated requests from your plugin—using the [_data source proxy_](#authenticate-using-the-data-source-proxy), or by building a [_backend plugin_](#authenticate-using-a-backend-plugin). The one you choose depends on how your plugin authenticates against the third-party API.
|
||||
|
||||
Configure your data source plugin to authenticate against a third-party API in one of either of two ways:
|
||||
- Use the data source proxy if you need to authenticate using Basic Auth or API keys
|
||||
- Use the data source proxy if the API supports OAuth 2.0 using client credentials
|
||||
- Use a backend plugin if the API uses a custom authentication method that isn't supported by the data source proxy, or if your API communicates over a different protocol than HTTP
|
||||
|
||||
- Use the [_data source proxy_](#authenticate-using-the-data-source-proxy) method, or
|
||||
- Build a [_backend plugin_](#authenticate-using-a-backend-plugin).
|
||||
|
||||
| Case | Use |
|
||||
| ----------------------------------------------------------------------------------------------- | ------------------------------- |
|
||||
| Do you need to authenticate your plugin using Basic Auth or API keys? | Use the data source proxy. |
|
||||
| Does your API support OAuth 2.0 using client credentials? | Use the data source proxy. |
|
||||
| Does your API use a custom authentication method that isn't supported by the data source proxy? | Use a backend plugin. |
|
||||
| Does your API communicate over a protocol other than HTTP? | Build and use a backend plugin. |
|
||||
| Does your plugin require alerting support? | Build and use a backend plugin. |
|
||||
Regardless of which approach you use, you first need to encrypt any sensitive information that the plugin needs to store.
|
||||
|
||||
## Encrypt data source configuration
|
||||
|
||||
Data source plugins have two ways of storing custom configuration: `jsonData` and `secureJsonData`.
|
||||
|
||||
Users with the Viewer role can access data source configuration such as the contents of `jsonData` in cleartext. If you've enabled anonymous access, anyone who can access Grafana in their browser can see the contents of `jsonData`.
|
||||
|
||||
Users of [Grafana Enterprise](https://grafana.com/products/enterprise/grafana/) can restrict access to data sources to specific users and teams. For more information, refer to [Data source permissions](https://grafana.com/docs/grafana/latest/enterprise/datasource_permissions).
|
||||
|
||||
> **Important:** Do not use `jsonData` with sensitive data such as password, tokens, and API keys. If you need to store sensitive information, use `secureJsonData` instead.
|
||||
Users with the _Viewer_ role can access data source configuration—such as the contents of `jsonData`—in cleartext. If you've enabled anonymous access, anyone that can access Grafana in their browser can see the contents of `jsonData`. **Only use `jsonData` to store non-sensitive configuration.**
|
||||
|
||||
> **Note:** You can see the settings that the current user has access to by entering `window.grafanaBootData` in the developer console of your browser.
|
||||
|
||||
### Store configuration in `secureJsonData`
|
||||
> **Note:** Users of [Grafana Enterprise](https://grafana.com/products/enterprise/grafana/) can restrict access to data sources to specific users and teams. For more information, refer to [Data source permissions](https://grafana.com/docs/grafana/latest/enterprise/datasource_permissions).
|
||||
|
||||
If you need to store sensitive information, use `secureJsonData` instead of `jsonData`. Whenever the user saves the data source configuration, the secrets in `secureJsonData` are sent to the Grafana server and encrypted before they're stored.
|
||||
If you need to store sensitive information, such as passwords, tokens and API keys, use `secureJsonData` instead. Whenever the user saves the data source configuration, the secrets in `secureJsonData` are sent to the Grafana server and encrypted before they're stored.
|
||||
|
||||
Once you have encrypted the secure configuration, it can no longer be accessed from the browser. The only way to access secrets after they've been saved is by using the [_data source proxy_](#authenticate-using-the-data-source-proxy).
|
||||
Once the secure configuration has been encrypted, it can no longer be accessed from the browser. The only way to access secrets after they've been saved is by using the [_data source proxy_](#authenticate-using-the-data-source-proxy).
|
||||
|
||||
### Add secret configuration to your data source plugin
|
||||
#### Add secret configuration to your data source plugin
|
||||
|
||||
To demonstrate how you can add secrets to a data source plugin, let's add support for configuring an API key.
|
||||
|
||||
1. Create a new interface in `types.ts` to hold the API key:
|
||||
```ts
|
||||
export interface MySecureJsonData {
|
||||
apiKey?: string;
|
||||
}
|
||||
```
|
||||
1. Add type information to your `secureJsonData` object by updating the props for your `ConfigEditor` to accept the interface as a second type parameter. Access the value of the secret from the `options` prop inside your `ConfigEditor`:
|
||||
Create a new interface in `types.ts` to hold the API key.
|
||||
|
||||
```ts
|
||||
interface Props extends DataSourcePluginOptionsEditorProps<MyDataSourceOptions, MySecureJsonData> {}
|
||||
```
|
||||
```ts
|
||||
export interface MySecureJsonData {
|
||||
apiKey?: string;
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
const { secureJsonData, secureJsonFields } = options;
|
||||
const { apiKey } = secureJsonData;
|
||||
```
|
||||
Add type information to your `secureJsonData` object by updating the props for your `ConfigEditor` to accept the interface as a second type parameter.
|
||||
|
||||
> **Note:** You can do this until the user saves the configuration; when the user saves the configuration, Grafana clears the value. After that, you can use `secureJsonFields` to determine whether the property has been configured.
|
||||
```ts
|
||||
interface Props extends DataSourcePluginOptionsEditorProps<MyDataSourceOptions, MySecureJsonData> {}
|
||||
```
|
||||
|
||||
1. To securely update the secret in your plugin's configuration editor, update the `secureJsonData` object using the `onOptionsChange` prop:
|
||||
You can access the value of the secret from the `options` prop inside your `ConfigEditor` until the user saves the configuration. When the user saves the configuration, Grafana clears the value. After that, you can use the `secureJsonFields` to determine whether the property has been configured.
|
||||
|
||||
```ts
|
||||
const onAPIKeyChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
onOptionsChange({
|
||||
...options,
|
||||
secureJsonData: {
|
||||
apiKey: event.target.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
```
|
||||
```ts
|
||||
const { secureJsonData, secureJsonFields } = options;
|
||||
const { apiKey } = secureJsonData;
|
||||
```
|
||||
|
||||
1. Define a component that can accept user input:
|
||||
To securely update the secret in your plugin's configuration editor, update the `secureJsonData` object using the `onOptionsChange` prop.
|
||||
|
||||
```ts
|
||||
<Input
|
||||
type="password"
|
||||
placeholder={secureJsonFields?.apiKey ? 'configured' : ''}
|
||||
value={secureJsonData.apiKey ?? ''}
|
||||
onChange={onAPIKeyChange}
|
||||
/>
|
||||
```
|
||||
```ts
|
||||
const onAPIKeyChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
onOptionsChange({
|
||||
...options,
|
||||
secureJsonData: {
|
||||
apiKey: event.target.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
1. Optional: If you want the user to be able to reset the API key, then you need to set the property to `false` in the `secureJsonFields` object:
|
||||
Next, define a component that can accept user input.
|
||||
|
||||
```ts
|
||||
const onResetAPIKey = () => {
|
||||
onOptionsChange({
|
||||
...options,
|
||||
secureJsonFields: {
|
||||
...options.secureJsonFields,
|
||||
apiKey: false,
|
||||
},
|
||||
secureJsonData: {
|
||||
...options.secureJsonData,
|
||||
apiKey: '',
|
||||
},
|
||||
});
|
||||
};
|
||||
```
|
||||
```ts
|
||||
<Input
|
||||
type="password"
|
||||
placeholder={secureJsonFields?.apiKey ? 'configured' : ''}
|
||||
value={secureJsonData.apiKey ?? ''}
|
||||
onChange={onAPIKeyChange}
|
||||
/>
|
||||
```
|
||||
|
||||
Finally, if you want the user to be able to reset the API key, then you need to set the property to `false` in the `secureJsonFields` object.
|
||||
|
||||
```ts
|
||||
const onResetAPIKey = () => {
|
||||
onOptionsChange({
|
||||
...options,
|
||||
secureJsonFields: {
|
||||
...options.secureJsonFields,
|
||||
apiKey: false,
|
||||
},
|
||||
secureJsonData: {
|
||||
...options.secureJsonData,
|
||||
apiKey: '',
|
||||
},
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
Now that users can configure secrets, the next step is to see how we can add them to our requests.
|
||||
|
||||
## Authenticate using the data source proxy
|
||||
|
||||
Once the user has saved the configuration for a data source, the secret data source configuration will no longer be available in the browser. Encrypted secrets can only be accessed on the server. So how do you add them to your request?
|
||||
Once the user has saved the configuration for a data source, any secret data source configuration will no longer be available in the browser. Encrypted secrets can only be accessed on the server. So how do you add them to you request?
|
||||
|
||||
The Grafana server comes with a proxy that lets you define templates for your requests: _proxy routes_. Grafana sends the proxy route to the server, decrypts the secrets along with other configuration, and adds them to the request before sending it.
|
||||
The Grafana server comes with a proxy that lets you define templates for your requests. We call them _proxy routes_. Grafana sends the proxy route to the server, decrypts the secrets along with other configuration, and adds them to the request before sending it off.
|
||||
|
||||
> **Note:** Be sure not to confuse the data source proxy with the [auth proxy]({{< relref "../../setup-grafana/configure-security/configure-authentication/auth-proxy/" >}}). The data source proxy is used to authenticate a data source, while the auth proxy is used to log into Grafana itself.
|
||||
|
||||
### Add a proxy route to your plugin
|
||||
|
||||
To forward requests through the Grafana proxy, you need to configure one or more _proxy routes_. A proxy route is a template for any outgoing request that is handled by the proxy. You can configure proxy routes in the [plugin.json](https://grafana.com/docs/grafana/latest/developers/plugins/metadata/) file.
|
||||
To forward requests through the Grafana proxy, you need to configure one or more proxy routes. A proxy route is a template for any outgoing request that is handled by the proxy. You can configure proxy routes in the [plugin.json](https://grafana.com/docs/grafana/latest/developers/plugins/metadata/) file.
|
||||
|
||||
1. Add the route to `plugin.json`:
|
||||
1. Add the route to plugin.json. Note that you need to restart the Grafana server every time you make a change to your plugin.json file.
|
||||
|
||||
```json
|
||||
"routes": [
|
||||
@@ -132,9 +123,7 @@ To forward requests through the Grafana proxy, you need to configure one or more
|
||||
]
|
||||
```
|
||||
|
||||
> **Note:** You need to restart the Grafana server every time you make a change to your `plugin.json` file.
|
||||
|
||||
1. In the `DataSource`, extract the proxy URL from `instanceSettings` to a class property called `url`:
|
||||
1. In the `DataSource`, extract the proxy URL from `instanceSettings` to a class property called `url`.
|
||||
|
||||
```ts
|
||||
export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
|
||||
@@ -150,7 +139,7 @@ To forward requests through the Grafana proxy, you need to configure one or more
|
||||
}
|
||||
```
|
||||
|
||||
1. In the `query` method, make a request using `BackendSrv`. The first section of the URL path needs to match the `path` of your proxy route. The data source proxy replaces `this.url + routePath` with the `url` of the route. Based on our example, the URL for the request would be `https://api.example.com/v1/users`:
|
||||
1. In the `query` method, make a request using `BackendSrv`. The first section of the URL path needs to match the `path` of your proxy route. The data source proxy replaces `this.url + routePath` with the `url` of the route. The following request will be made to `https://api.example.com/v1/users`.
|
||||
|
||||
```ts
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
@@ -169,36 +158,32 @@ To forward requests through the Grafana proxy, you need to configure one or more
|
||||
|
||||
Grafana sends the proxy route to the server, where the data source proxy decrypts any sensitive data and interpolates the template variables with the decrypted data before making the request.
|
||||
|
||||
To add user-defined configuration to your routes:
|
||||
To add user-defined configuration to your routes, for example, add `{{ .JsonData.projectId }}` to the route, where `projectId` is the name of a property in the `jsonData` object.
|
||||
|
||||
- Use `.JsonData` for configuration stored in `jsonData`. For example, where `projectId` is the name of a property in the `jsonData` object:
|
||||
```json
|
||||
"routes": [
|
||||
{
|
||||
"path": "example",
|
||||
"url": "https://api.example.com/projects/{{ .JsonData.projectId }}"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json
|
||||
"routes": [
|
||||
{
|
||||
"path": "example",
|
||||
"url": "https://api.example.com/projects/{{ .JsonData.projectId }}"
|
||||
}
|
||||
]
|
||||
```
|
||||
You can also configure your route to use sensitive data by using `.SecureJsonData`.
|
||||
|
||||
- Use `.SecureJsonData` for sensitive data stored in `secureJsonData`. For example, where `password` is the name of a property in the `secureJsonData` object:
|
||||
```json
|
||||
"routes": [
|
||||
{
|
||||
"path": "example",
|
||||
"url": "https://{{ .JsonData.username }}:{{ .SecureJsonData.password }}@api.example.com"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json
|
||||
"routes": [
|
||||
{
|
||||
"path": "example",
|
||||
"url": "https://{{ .JsonData.username }}:{{ .SecureJsonData.password }}@api.example.com"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
In addition to adding the URL to the proxy route, you can also add headers, URL parameters, and a request body.
|
||||
In addition to the URL, you can also add headers, URL parameters, and a request body, to a proxy route.
|
||||
|
||||
#### Add HTTP headers to a proxy route
|
||||
|
||||
Here's an example of adding `name` and `content` as HTTP headers:
|
||||
|
||||
```json
|
||||
"routes": [
|
||||
{
|
||||
@@ -216,8 +201,6 @@ Here's an example of adding `name` and `content` as HTTP headers:
|
||||
|
||||
#### Add URL parameters to a proxy route
|
||||
|
||||
Here's an example of adding `name` and `content` as URL parameters:
|
||||
|
||||
```json
|
||||
"routes": [
|
||||
{
|
||||
@@ -235,8 +218,6 @@ Here's an example of adding `name` and `content` as URL parameters:
|
||||
|
||||
#### Add a request body to a proxy route
|
||||
|
||||
Here's an example of adding `username` and `password` to the request body:
|
||||
|
||||
```json
|
||||
"routes": [
|
||||
{
|
||||
@@ -250,9 +231,11 @@ Here's an example of adding `username` and `password` to the request body:
|
||||
]
|
||||
```
|
||||
|
||||
### Add an OAuth 2.0 proxy route to your plugin
|
||||
### Add a OAuth 2.0 proxy route to your plugin
|
||||
|
||||
Since your request to each route is made server-side with OAuth 2.0 authentication, only machine-to-machine requests are supported. In order words, if you need to use a different grant than client credentials, you need to implement it yourself.
|
||||
The data source proxy supports OAuth 2.0 authentication.
|
||||
|
||||
Since the request to each route is made server-side, only machine-to-machine authentication is supported. In order words, if you need to use a different grant than client credentials, you need to implement it yourself.
|
||||
|
||||
To authenticate using OAuth 2.0, add a `tokenAuth` object to the proxy route definition. If necessary, Grafana performs a request to the URL defined in `tokenAuth` to retrieve a token before making the request to the URL in your proxy route. Grafana automatically renews the token when it expires.
|
||||
|
||||
@@ -281,10 +264,10 @@ Any parameters defined in `tokenAuth.params` are encoded as `application/x-www-f
|
||||
|
||||
While the data source proxy supports the most common authentication methods for HTTP APIs, using proxy routes has a few limitations:
|
||||
|
||||
- Proxy routes only support HTTP or HTTPS.
|
||||
- Proxy routes don't support custom token authentication.
|
||||
- Proxy routes only support HTTP or HTTPS
|
||||
- Proxy routes don't support custom token authentication
|
||||
|
||||
If any of these limitations apply to your plugin, you need to add a [backend plugin]({{< relref "backend/" >}}). Because backend plugins run on the server, they can access decrypted secrets, which makes it easier to implement custom authentication methods.
|
||||
If any of these limitations apply to your plugin, you need to add a [backend plugin]({{< relref "backend/" >}}). Since backend plugins run on the server they can access decrypted secrets, which makes it easier to implement custom authentication methods.
|
||||
|
||||
The decrypted secrets are available from the `DecryptedSecureJSONData` field in the instance settings.
|
||||
|
||||
@@ -302,99 +285,72 @@ func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataReque
|
||||
|
||||
## Forward OAuth identity for the logged-in user
|
||||
|
||||
If your data source uses the same OAuth provider as Grafana itself, for example using [Generic OAuth Authentication]({{< relref "../../setup-grafana/configure-security/configure-authentication/generic-oauth/" >}}), then your data source plugin can reuse the access token for the logged-in Grafana user.
|
||||
If your data source uses the same OAuth provider as Grafana itself, for example using [Generic OAuth Authentication]({{< relref "../../setup-grafana/configure-security/configure-authentication/generic-oauth/" >}}), your data source plugin can reuse the access token for the logged-in Grafana user.
|
||||
|
||||
To allow Grafana to pass the access token to the plugin, update the data source configuration and set the `jsonData.oauthPassThru` property to `true`. The [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) settings provide a toggle, the **Forward OAuth Identity** option, for this. You can also build an appropriate toggle to set `jsonData.oauthPassThru` in your data source configuration page UI.
|
||||
To allow Grafana to pass the access token to the plugin, update the data source configuration and set the` jsonData.oauthPassThru` property to `true`. The [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) provides a toggle, the **Forward OAuth Identity** option, for this. You can also build an appropriate toggle to set `jsonData.oauthPassThru` in your data source configuration page UI.
|
||||
|
||||
When configured, Grafana can forward authorization HTTP headers such as `Authorization` or `X-ID-Token` to a backend data source. This information is available across the `QueryData`, `CallResource` and `CheckHealth` requests.
|
||||
|
||||
To get Grafana to forward the headers, create a HTTP client using the [Grafana plugin SDK for Go](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go/backend/httpclient) and set the `ForwardHTTPHeaders` option to `true` (by default, it's set to `false`). This package exposes request information which can be subsequently forwarded downstream and/or used directly within the plugin.
|
||||
|
||||
```go
|
||||
func NewDatasource(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
||||
opts, err := settings.HTTPClientOptions()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("http client options: %w", err)
|
||||
}
|
||||
|
||||
// Important: Reuse the same client for each query to avoid using all available connections on a host.
|
||||
|
||||
opts.ForwardHTTPHeaders = true
|
||||
|
||||
cl, err := httpclient.New(opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("httpclient new: %w", err)
|
||||
}
|
||||
return &Datasource{
|
||||
httpClient: cl,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
// Necessary to keep the Context, since the injected middleware is configured there
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://some-url", nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new request with context: %w", err)
|
||||
}
|
||||
// Authorization header will be automatically injected if oauthPassThru is configured
|
||||
resp, err := ds.httpClient.Do(req)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
You can see a full working plugin example here: [datasource-http-backend](https://github.com/grafana/grafana-plugin-examples/tree/main/examples/datasource-http-backend).
|
||||
|
||||
### Extract a header from an HTTP request
|
||||
|
||||
If you need to access the HTTP header information directly, you can also extract that information from the request:
|
||||
When configured, Grafana will pass the user's token to the plugin in an Authorization header, available on the `QueryDataRequest` object on the `QueryData` request in your backend data source.
|
||||
|
||||
```go
|
||||
func (ds *dataSource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||
token := strings.Fields(req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName))
|
||||
var (
|
||||
tokenType = token[0]
|
||||
accessToken = token[1]
|
||||
)
|
||||
|
||||
// ...
|
||||
return &backend.CheckHealthResult{Status: backend.HealthStatusOk}, nil
|
||||
}
|
||||
|
||||
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
token := strings.Fields(req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName))
|
||||
var (
|
||||
tokenType = token[0]
|
||||
accessToken = token[1]
|
||||
)
|
||||
var (
|
||||
tokenType = token[0]
|
||||
accessToken = token[1]
|
||||
)
|
||||
|
||||
for _, q := range req.Queries {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In addition, if the user's token includes an ID token, Grafana will pass the user's ID token to the plugin in an `X-ID-Token` header, available on the `QueryDataRequest` object on the `QueryData` request in your backend data source.
|
||||
|
||||
```go
|
||||
func (ds *dataSource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||
idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName)
|
||||
|
||||
// ...
|
||||
return &backend.CheckHealthResult{Status: backend.HealthStatusOk}, nil
|
||||
}
|
||||
|
||||
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName)
|
||||
|
||||
for _, q := range req.Queries {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `Authorization` and `X-ID-Token` headers will also be available on the `CallResourceRequest` object on the `CallResource` request in your backend data source when `jsonData.oauthPassThru` is `true`.
|
||||
|
||||
```go
|
||||
func (ds *dataSource) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||
token := req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName)
|
||||
idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName) // present if user's token includes an ID token
|
||||
|
||||
// ...
|
||||
return &backend.CheckHealthResult{Status: backend.HealthStatusOk}, nil
|
||||
}
|
||||
|
||||
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
token := strings.Fields(req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName))
|
||||
var (
|
||||
tokenType = token[0]
|
||||
accessToken = token[1]
|
||||
)
|
||||
idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName)
|
||||
|
||||
for _, q := range req.Queries {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
func (ds *dataSource) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||
token := req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName)
|
||||
idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName)
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Work with cookies
|
||||
## Forward cookies for the logged-in user
|
||||
|
||||
### Forward cookies for the logged-in user
|
||||
Your data source plugin can forward certain cookies for the logged-in Grafana user to the data source. Use the [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) component on the data source's configuration page. It provides the **Allowed cookies** option, where the names of cookies to pass to the plugin can be specified.
|
||||
|
||||
Your data source plugin can forward cookies for the logged-in Grafana user to the data source. Use the [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) component on the data source's configuration page. It provides the **Allowed cookies** option, where you can specify the cookie names.
|
||||
|
||||
When configured, as with [authorization headers](#forward-oauth-identity-for-the-logged-in-user), these cookies are automatically injected if you use the SDK HTTP client.
|
||||
|
||||
### Extract cookies for the logged-in user
|
||||
|
||||
You can also extract the cookies in the `QueryData`, `CallResource` and `CheckHealth` requests if required.
|
||||
|
||||
**`QueryData`**
|
||||
When configured, Grafana will pass these cookies to the plugin in the `Cookie` header, available in the `QueryData`, `CallResource` and `CheckHealth` requests in your backend data source.
|
||||
|
||||
```go
|
||||
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
@@ -402,21 +358,13 @@ func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataReque
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**`CallResource`**
|
||||
|
||||
```go
|
||||
func (ds *dataSource) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||
cookies:= req.GetHTTPHeader(backend.CookiesHeaderName)
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**`CheckHealth`**
|
||||
|
||||
```go
|
||||
func (ds *dataSource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||
cookies:= req.GetHTTPHeader(backend.CookiesHeaderName)
|
||||
|
||||
@@ -426,9 +374,7 @@ func (ds *dataSource) CheckHealth(ctx context.Context, req *backend.CheckHealthR
|
||||
|
||||
## Forward user header for the logged-in user
|
||||
|
||||
When [send_user_header]({{< relref "../../setup-grafana/configure-grafana/_index.md#send_user_header" >}}) is enabled, Grafana passes the user header to the plugin using the `X-Grafana-User` header. You can forward this header as well as [authorization headers](#forward-oauth-identity-for-the-logged-in-user) or [configured cookies](#forward-cookies-for-the-logged-in-user).
|
||||
|
||||
**`QueryData`**
|
||||
When [send_user_header]({{< relref "../../setup-grafana/configure-grafana/_index.md#send_user_header" >}}) is enabled, Grafana will pass the user header to the plugin in the `X-Grafana-User` header, available in the `QueryData`, `CallResource` and `CheckHealth` requests in your backend data source.
|
||||
|
||||
```go
|
||||
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
@@ -436,21 +382,13 @@ func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataReque
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**`CallResource`**
|
||||
|
||||
```go
|
||||
func (ds *dataSource) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||
u := req.GetHTTPHeader("X-Grafana-User")
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**`CheckHealth`**
|
||||
|
||||
```go
|
||||
func (ds *dataSource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||
u := req.GetHTTPHeader("X-Grafana-User")
|
||||
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
---
|
||||
title: Add distributed tracing for backend plugins
|
||||
---
|
||||
|
||||
# Add distributed tracing for backend plugins
|
||||
|
||||
> **Note:** This feature requires at least Grafana 9.5.0, and your plugin needs to be built at least with grafana-plugins-sdk-go v0.157.0. If you run a plugin with tracing features on an older version of Grafana, tracing is disabled.
|
||||
|
||||
Distributed tracing allows backend plugin developers to create custom spans in their plugins, and send them to the same endpoint and with the same propagation format as the main Grafana instance. The tracing context is also propagated from the Grafana instance to the plugin, so the plugin's spans will be correlated to the correct trace.
|
||||
|
||||
## Plugin configuration
|
||||
|
||||
Plugin tracing must be enabled manually on a per-plugin basis, by specifying `tracing = true` in the plugin's config section:
|
||||
|
||||
```ini
|
||||
[plugin.myorg-myplugin-datasource]
|
||||
tracing = true
|
||||
```
|
||||
|
||||
## OpenTelemetry configuration in Grafana
|
||||
|
||||
Grafana supports [OpenTelemetry](https://opentelemetry.io/) for distributed tracing. If Grafana is configured to use a deprecated tracing system (Jaeger or OpenTracing), then tracing is disabled in the plugin provided by the SDK and configured when calling `datasource.Manage | app.Manage`.
|
||||
|
||||
OpenTelemetry must be enabled and configured for the Grafana instance. Please refer to the [Grafana configuration documentation](
|
||||
{{< relref "../../setup-grafana/configure-grafana/#tracingopentelemetry" >}}) for more information.
|
||||
|
||||
Refer to the [OpenTelemetry Go SDK](https://pkg.go.dev/go.opentelemetry.io/otel) for in-depth documentation about all the features provided by OpenTelemetry.
|
||||
|
||||
> **Note:** If tracing is disabled in Grafana, `backend.DefaultTracer()` returns a no-op tracer.
|
||||
|
||||
## Implement tracing in your plugin
|
||||
|
||||
> **Note:** Make sure you are using at least grafana-plugin-sdk-go v0.157.0. You can update with `go get -u github.com/grafana/grafana-plugin-sdk-go`.
|
||||
|
||||
### Configure a global tracer
|
||||
|
||||
When OpenTelemetry tracing is enabled on the main Grafana instance and tracing is enabled for a plugin, the OpenTelemetry endpoint address and propagation format is passed to the plugin during startup. These parameters are used to configure a global tracer.
|
||||
|
||||
1. Use `datasource.Manage` or `app.Manage` to run your plugin to automatically configure the global tracer. Specify any custom attributes for the default tracer using `CustomAttributes`:
|
||||
|
||||
```go
|
||||
func main() {
|
||||
if err := datasource.Manage("MY_PLUGIN_ID", plugin.NewDatasource, datasource.ManageOpts{
|
||||
TracingOpts: tracing.Opts{
|
||||
// Optional custom attributes attached to the tracer's resource.
|
||||
// The tracer will already have some SDK and runtime ones pre-populated.
|
||||
CustomAttributes: []attribute.KeyValue{
|
||||
attribute.String("my_plugin.my_attribute", "custom value"),
|
||||
},
|
||||
},
|
||||
}); err != nil {
|
||||
log.DefaultLogger.Error(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Once you have configured tracing, use the global tracer like this:
|
||||
|
||||
```go
|
||||
tracing.DefaultTracer()
|
||||
```
|
||||
|
||||
This returns an [OpenTelemetry `trace.Tracer`](https://pkg.go.dev/go.opentelemetry.io/otel/trace#Tracer) for creating spans.
|
||||
|
||||
**Example:**
|
||||
|
||||
```go
|
||||
func (d *Datasource) query(ctx context.Context, pCtx backend.PluginContext, query backend.DataQuery) (backend.DataResponse, error) {
|
||||
ctx, span := tracing.DefaultTracer().Start(
|
||||
ctx,
|
||||
"query processing",
|
||||
trace.WithAttributes(
|
||||
attribute.String("query.ref_id", query.RefID),
|
||||
attribute.String("query.type", query.QueryType),
|
||||
attribute.Int64("query.max_data_points", query.MaxDataPoints),
|
||||
attribute.Int64("query.interval_ms", query.Interval.Milliseconds()),
|
||||
attribute.Int64("query.time_range.from", query.TimeRange.From.Unix()),
|
||||
attribute.Int64("query.time_range.to", query.TimeRange.To.Unix()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
log.DefaultLogger.Debug("query", "traceID", trace.SpanContextFromContext(ctx).TraceID())
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Tracing gRPC calls
|
||||
|
||||
When tracing is enabled, a new span is created automatically for each gRPC call (`QueryData`, `CheckHealth`, etc.), both on Grafana's side and on the plugin's side. The plugin SDK also injects the trace context into the `context.Context` that is passed to those methods.
|
||||
|
||||
You can retrieve the [trace.SpanContext](https://pkg.go.dev/go.opentelemetry.io/otel/trace#SpanContext) with `tracing.SpanContextFromContext` by passing the original `context.Context` to it:
|
||||
|
||||
```go
|
||||
func (d *Datasource) query(ctx context.Context, pCtx backend.PluginContext, query backend.DataQuery) (backend.DataResponse, error) {
|
||||
spanCtx := trace.SpanContextFromContext(ctx)
|
||||
traceID := spanCtx.TraceID()
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Tracing HTTP requests
|
||||
|
||||
When tracing is enabled, a `TracingMiddleware` is also added to the default middleware stack to all HTTP clients created using the `httpclient.New` or `httpclient.NewProvider`, unless you specify custom middleware. This middleware creates spans for each outgoing HTTP request and provides some useful attributes and events related to the request's lifecycle.
|
||||
|
||||
## Plugin example
|
||||
|
||||
Refer to the [datasource-http-backend plugin example](https://github.com/grafana/grafana-plugin-examples/tree/main/examples/datasource-http-backend) for a complete example of a plugin with full distributed tracing support.
|
||||
@@ -2,11 +2,11 @@
|
||||
title: Add query editor help
|
||||
---
|
||||
|
||||
# Add query editor help
|
||||
# Add a query editor help component
|
||||
|
||||
Query editors support the addition of a help component to display examples of potential queries. When the user clicks on one of the examples, the query editor is automatically updated. This helps the user to make faster queries.
|
||||
By adding a help component to your plugin, you can for example create "cheat sheets" with commonly used queries. When the user clicks on one of the examples, it automatically updates the query editor. It's a great way to increase productivity for your users.
|
||||
|
||||
1. In the `src` directory of your plugin, create a file `QueryEditorHelp.tsx` with the following content:
|
||||
1. Create a file `QueryEditorHelp.tsx` in the `src` directory of your plugin, with the following content:
|
||||
|
||||
```ts
|
||||
import React from 'react';
|
||||
@@ -17,7 +17,7 @@ Query editors support the addition of a help component to display examples of po
|
||||
};
|
||||
```
|
||||
|
||||
1. Configure the plugin to use `QueryEditorHelp`:
|
||||
1. Configure the plugin to use the `QueryEditorHelp`.
|
||||
|
||||
```ts
|
||||
import QueryEditorHelp from './QueryEditorHelp';
|
||||
@@ -30,7 +30,7 @@ Query editors support the addition of a help component to display examples of po
|
||||
.setQueryEditorHelp(QueryEditorHelp);
|
||||
```
|
||||
|
||||
1. Create a few examples of potential queries:
|
||||
1. Create a few examples.
|
||||
|
||||
```ts
|
||||
import React from 'react';
|
||||
|
||||
@@ -4,15 +4,19 @@ title: Add support for annotations
|
||||
|
||||
# Add support for annotations
|
||||
|
||||
You can add support to your plugin for annotations that will insert information into Grafana alerts. This guide explains how to add support for [annotations]({{< relref "../../dashboards/build-dashboards/annotate-visualizations/#querying-other-data-sources " >}}) to a data source plugin.
|
||||
This guide explains how to add support for [annotations]({{< relref "../../dashboards/build-dashboards/annotate-visualizations" >}}) to an existing data source plugin.
|
||||
|
||||
## Support annotations in your data source plugin
|
||||
This guide assumes that you're already familiar with how to [Build a data source plugin](/tutorials/build-a-data-source-plugin/).
|
||||
|
||||
To enable annotations, simply add two lines of code to your plugin. Grafana uses your default query editor for editing annotation queries.
|
||||
> **Note:** Annotation support for React plugins was released in Grafana 7.2. To support earlier versions, refer to [Add support for annotation for Grafana 7.1](https://grafana.com/docs/grafana/v7.1/developers/plugins/add-support-for-annotations/).
|
||||
|
||||
## Add annotations support to your data source
|
||||
|
||||
To enable annotation support for your data source, add the following two lines of code. Grafana uses your default query editor for editing annotation queries.
|
||||
|
||||
1. Add `"annotations": true` to the [plugin.json]({{< relref "metadata/" >}}) file to let Grafana know that your plugin supports annotations.
|
||||
|
||||
**In `plugin.json`:**
|
||||
**plugin.json**
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -20,9 +24,9 @@ To enable annotations, simply add two lines of code to your plugin. Grafana uses
|
||||
}
|
||||
```
|
||||
|
||||
2. In `datasource.ts`, override the `annotations` property from `DataSourceApi` (or `DataSourceWithBackend` for backend data sources). For the default behavior, set `annotations` to an empty object.
|
||||
2. In `datasource.ts`, override the `annotations` property from `DataSourceApi` (or `DataSourceWithBackend` for backend data sources). For the default behavior, you can set `annotations` to an empty object.
|
||||
|
||||
**In `datasource.ts`:**
|
||||
**datasource.ts**
|
||||
|
||||
```ts
|
||||
annotations: {
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
---
|
||||
title: Add features to Explore queries
|
||||
title: Add support for Explore queries
|
||||
---
|
||||
|
||||
# Add features for Explore queries
|
||||
# Add support for Explore queries
|
||||
|
||||
[Explore]({{< relref "../../explore/" >}}) allows users can make ad-hoc queries without the use of a dashboard. This is useful when they want to troubleshoot or learn more about the data.
|
||||
This guide explains how to improve support for [Explore]({{< relref "../../explore/" >}}) in an existing data source plugin.
|
||||
|
||||
Your data source supports Explore by default and uses the existing query editor for the data source. This guide explains how to extend functionality for Explore queries in a data source plugin.
|
||||
This guide assumes that you're already familiar with how to [Build a data source plugin](/tutorials/build-a-data-source-plugin/).
|
||||
|
||||
With Explore, users can make ad-hoc queries without the use of a dashboard. This is useful when users want to troubleshoot or to learn more about the data.
|
||||
|
||||
Your data source supports Explore by default and uses the existing query editor for the data source.
|
||||
|
||||
## Add an Explore-specific query editor
|
||||
|
||||
To extend Explore functionality for your data source, define an Explore-specific query editor.
|
||||
To extend Explore functionality for your data source, you can define an Explore-specific query editor.
|
||||
|
||||
1. Create a file `ExploreQueryEditor.tsx` in the `src` directory of your plugin, with content similar to this:
|
||||
1. Create a file `ExploreQueryEditor.tsx` in the `src` directory of your plugin, with the following content:
|
||||
|
||||
```ts
|
||||
import React from 'react';
|
||||
@@ -50,13 +54,13 @@ To extend Explore functionality for your data source, define an Explore-specific
|
||||
};
|
||||
```
|
||||
|
||||
## Select a preferred visualization type
|
||||
## Selecting preferred visualisation
|
||||
|
||||
By default, Explore should select an appropriate and useful visualization for your data. It can figure out whether the returned data is time series data or logs or something else, and creates the right type of visualization.
|
||||
Explore should by default select a reasonable visualization for your data so users do not have to tweak and play with the visualizations and just focus on querying. This usually works fairly well and Explore can figure out whether the returned data is time series data or logs or something else.
|
||||
|
||||
However, if you want a custom visualization, you can add a hint to your returned data frame by setting the `meta' attribute to `preferredVisualisationType`.
|
||||
If this does not work for you or you want to show some data in a specific visualization, add a hint to your returned data frame using the `preferredVisualisationType` meta attribute.
|
||||
|
||||
Construct a data frame with specific metadata like this:
|
||||
You can construct a data frame with specific metadata:
|
||||
|
||||
```
|
||||
const firstResult = new MutableDataFrame({
|
||||
|
||||
@@ -4,9 +4,11 @@ title: Add support for variables in plugins
|
||||
|
||||
# Add support for variables in plugins
|
||||
|
||||
Variables are placeholders for values, and you can use them to create templated queries, and dashboard or panel links. For more information on variables, refer to [Templates and variables]({{< relref "../../dashboards/variables/" >}}).
|
||||
Variables are placeholders for values, and can be used to create things like templated queries and dashboard or panel links. For more information on variables, refer to [Templates and variables]({{< relref "../../dashboards/variables/" >}}).
|
||||
|
||||
In this guide, you'll see how you can turn a query string like this:
|
||||
This guide explains how to leverage template variables in your panel plugins and data source plugins.
|
||||
|
||||
We'll see how you can turn a string like this:
|
||||
|
||||
```sql
|
||||
SELECT * FROM services WHERE id = "$service"
|
||||
@@ -22,9 +24,9 @@ Grafana provides a couple of helper functions to interpolate variables in a stri
|
||||
|
||||
## Interpolate variables in panel plugins
|
||||
|
||||
For panels, the `replaceVariables` function is available in the `PanelProps`.
|
||||
For panels, the `replaceVariables` function is available in the PanelProps.
|
||||
|
||||
Add `replaceVariables` to the argument list, and pass a user-defined template string to it:
|
||||
Add `replaceVariables` to the argument list, and pass it a user-defined template string.
|
||||
|
||||
```ts
|
||||
export function SimplePanel({ options, data, width, height, replaceVariables }: Props) {
|
||||
@@ -36,15 +38,15 @@ export function SimplePanel({ options, data, width, height, replaceVariables }:
|
||||
|
||||
## Interpolate variables in data source plugins
|
||||
|
||||
For data sources, you need to use the `getTemplateSrv`, which returns an instance of `TemplateSrv`.
|
||||
For data sources, you need to use the getTemplateSrv, which returns an instance of TemplateSrv.
|
||||
|
||||
1. Import `getTemplateSrv` from the `runtime` package:
|
||||
1. Import `getTemplateSrv` from the `runtime` package.
|
||||
|
||||
```ts
|
||||
import { getTemplateSrv } from '@grafana/runtime';
|
||||
```
|
||||
|
||||
1. In your `query` method, call the `replace` method with a user-defined template string:
|
||||
1. In your `query` method, call the `replace` method with a user-defined template string.
|
||||
|
||||
```ts
|
||||
async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse> {
|
||||
@@ -58,9 +60,9 @@ For data sources, you need to use the `getTemplateSrv`, which returns an instanc
|
||||
|
||||
## Format multi-value variables
|
||||
|
||||
When a user selects multiple values for a variable, the value of the interpolated variable depends on the [variable format]({{< relref "../../dashboards/variables/variable-syntax/#advanced-variable-format-options" >}}).
|
||||
When a user selects multiple values for variable, the value of the interpolated variable depends on the [variable format]({{< relref "../../dashboards/variables/variable-syntax/#advanced-variable-format-options" >}}).
|
||||
|
||||
A data source plugin can define the default format option when no format is specified by adding a third argument to the interpolation function.
|
||||
A data source can define the default format option when no format is specified by adding a third argument to the interpolation function.
|
||||
|
||||
Let's change the SQL query to use CSV format by default:
|
||||
|
||||
@@ -82,8 +84,8 @@ Not only can you read the value of a variable, you can also update the variable
|
||||
|
||||
The following example shows how to update a variable called `service`.
|
||||
|
||||
- `query` contains the query parameters you want to update. The query parameters that control variables are prefixed with `var-`.
|
||||
- `replace: true` tells Grafana to update the current URL state rather than creating a new history entry.
|
||||
- `query` contains the query parameters you want to update. Query parameters controlling variables are prefixed with `var-`.
|
||||
- `replace: true` tells Grafana to update the current URL state, rather than creating a new history entry.
|
||||
|
||||
```ts
|
||||
import { locationService } from '@grafana/runtime';
|
||||
@@ -97,9 +99,9 @@ locationService.partial({ 'var-service': 'billing' }, true);
|
||||
|
||||
## Add support for query variables to your data source
|
||||
|
||||
A [query variable]({{< relref "../../dashboards/variables/add-template-variables/#add-a-query-variable" >}}) is a type of variable that allows you to query a data source for the values. By adding support for query variables to your data source plugin, users can create dynamic dashboards based on data from your data source.
|
||||
[Query variables]({{< relref "../../dashboards/variables/add-template-variables/#add-a-query-variable" >}}) is a type of variable that allows you to query a data source for the values. By adding support for query variables to your data source plugin, users can create dynamic dashboards based on data from your data source.
|
||||
|
||||
Let's start by defining a query model for the variable query:
|
||||
Let's start by defining a query model for the variable query.
|
||||
|
||||
```ts
|
||||
export interface MyVariableQuery {
|
||||
@@ -108,7 +110,7 @@ export interface MyVariableQuery {
|
||||
}
|
||||
```
|
||||
|
||||
For a data source to support query variables, override the `metricFindQuery` in your `DataSourceApi` class. The `metricFindQuery` function returns an array of `MetricFindValue` which has a single property, `text`:
|
||||
For a data source to support query variables, you must override the `metricFindQuery` in your `DataSourceApi` class. `metricFindQuery` returns an array of `MetricFindValue` which has a single property, `text`:
|
||||
|
||||
```ts
|
||||
async metricFindQuery(query: MyVariableQuery, options?: any) {
|
||||
@@ -122,15 +124,15 @@ async metricFindQuery(query: MyVariableQuery, options?: any) {
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** By default, Grafana provides a basic query model and editor for simple text queries. If that's all you need, then leave the query type as `string`:
|
||||
|
||||
```ts
|
||||
async metricFindQuery(query: string, options?: any)
|
||||
```
|
||||
> **Note:** By default, Grafana provides a default query model and editor for simple text queries. If that's all you need, then you can leave the query type as `string`.
|
||||
>
|
||||
> ```ts
|
||||
> async metricFindQuery(query: string, options?: any)
|
||||
> ```
|
||||
|
||||
Let's create a custom query editor to allow the user to edit the query model.
|
||||
|
||||
1. Create a `VariableQueryEditor` component:
|
||||
1. Create a `VariableQueryEditor` component.
|
||||
|
||||
```ts
|
||||
import React, { useState } from 'react';
|
||||
@@ -183,9 +185,9 @@ Let's create a custom query editor to allow the user to edit the query model.
|
||||
|
||||
Grafana saves the query model whenever one of the text fields loses focus (`onBlur`) and then previews the values returned by `metricFindQuery`.
|
||||
|
||||
The second argument to `onChange` allows you to set a text representation of the query that will appear next to the name of the variable in the variables list.
|
||||
The second argument to `onChange` allows you to set a text representation of the query which will appear next to the name of the variable in the variables list.
|
||||
|
||||
1. Configure your plugin to use the query editor:
|
||||
1. Finally, configure your plugin to use the query editor.
|
||||
|
||||
```ts
|
||||
import { VariableQueryEditor } from './VariableQueryEditor';
|
||||
|
||||
@@ -13,85 +13,63 @@ title: Backend plugins
|
||||
|
||||
# Backend plugins
|
||||
|
||||
The Grafana plugin system for backend development allows you to integrate Grafana with virtually anything and offer custom visualizations. This document explains the system's background, use cases, and key features.
|
||||
Grafana added support for plugins in version 3.0 and this enabled the Grafana community to create panel plugins and data source plugins. It was wildly successful and has made Grafana much more useful as you can integrate it with anything and do any type of custom visualization that you want.
|
||||
|
||||
## Background
|
||||
However, one limitation with these plugins are that they execute on the client-side (in the browser) which makes it hard to support certain use cases/features, e.g. enable Grafana Alerting for data sources. Grafana v7.0 adds official support for backend plugins which removes this limitation. At the same time it gives plugin developers the possibility to extend Grafana in new and interesting ways, with code running in the backend (server side).
|
||||
|
||||
Grafana added support for _frontend plugins_ in version 3.0 so that the Grafana community could create custom panels and data sources. It was wildly successful and has made Grafana much more useful for our user community.
|
||||
We use the term _backend plugin_ to denote that a plugin has a backend component. Still, normally a backend plugin requires frontend components as well. This is for example true for backend data source plugins which normally need configuration and query editor components implemented for the frontend.
|
||||
|
||||
However, one limitation of these plugins is that they run on the client side, in the browser. Therefore, they can't support use cases that require server-side features.
|
||||
|
||||
Since Grafana v7.0, we have supported server-side plugins that remove this limitation. We use the term _backend plugin_ to denote that a plugin has a backend component. A backend plugin usually requires frontend components as well. For example, some backend data source plugins need query editor components on the frontend.
|
||||
Data source plugins can be extended with a backend component. In the future we plan to support additional types and possibly new kinds of plugins, such as notifiers for Grafana Alerting and custom authentication to name a few.
|
||||
|
||||
## Use cases for implementing a backend plugin
|
||||
|
||||
The following examples give some common use cases for backend plugins:
|
||||
The following examples gives you an idea of why you'd consider implementing a backend plugin:
|
||||
|
||||
- Enable [Grafana Alerting]({{< relref "../../../alerting/" >}}) for data sources.
|
||||
- Connect to SQL database servers and other non-HTTP services that normally can't be connected to from a browser.
|
||||
- Keep state between users, for example, by query caching for data sources.
|
||||
- Connect to non-HTTP services that normally can't be connected to from a web browser, e.g. SQL database servers.
|
||||
- Keep state between users, e.g. query caching for data sources.
|
||||
- Use custom authentication methods and/or authorization checks that aren't supported in Grafana.
|
||||
- Use a custom data source request proxy (refer to [Resources]({{< relref "#resources" >}}) for more information).
|
||||
- Use a custom data source request proxy, see [Resources]({{< relref "#resources" >}}).
|
||||
|
||||
## Grafana backend plugin system
|
||||
## Grafana’s backend plugin system
|
||||
|
||||
The Grafana backend plugin system is based on HashiCorp's [Go Plugin System over RPC](https://github.com/hashicorp/go-plugin). Our implementation of the Grafana server launches each backend plugin as a subprocess and communicates with it over [gRPC](https://grpc.io/).
|
||||
The Grafana backend plugin system is based on the [go-plugin library by HashiCorp](https://github.com/hashicorp/go-plugin). The Grafana server launches each backend plugin as a subprocess and communicates with it over [gRPC](https://grpc.io/). This approach has a number of benefits:
|
||||
|
||||
### Benefits for plugin development
|
||||
- Plugins can’t crash your grafana process: a panic in a plugin doesn’t panic the server.
|
||||
- Plugins are easy to develop: just write a Go application and run `go build` (or use any other language which supports gRPC).
|
||||
- Plugins can be relatively secure: The plugin only has access to the interfaces and arguments that are given to it, not to the entire memory space of the process.
|
||||
|
||||
Grafana's approach has benefits for developers:
|
||||
|
||||
- **Stability:** Plugins can't crash your Grafana process: a panic in a plugin doesn't panic the server.
|
||||
- **Ease of development:** Plugins can be written in any language that supports gRPC (for example, write a Go application and run `go build`).
|
||||
- **Security:** Plugins only have access to the interfaces and arguments given to them, not to the entire memory space of the process.
|
||||
|
||||
### Capabilities of the backend plugin system
|
||||
|
||||
Grafana's backend plugin system exposes several key capabilities, or building blocks, that your backend plugin can implement:
|
||||
Grafana's backend plugin system exposes a couple of different capabilities, or building blocks, that a backend plugin can implement:
|
||||
|
||||
- Query data
|
||||
- Resources
|
||||
- Health checks
|
||||
- Collect metrics
|
||||
- Streaming
|
||||
|
||||
#### Query data
|
||||
### Query data
|
||||
|
||||
The query data capability allows a backend plugin to handle data source queries that are submitted from a [dashboard]({{< relref "../../../dashboards/" >}}), [Explore]({{< relref "../../../explore/" >}}) or [Grafana Alerting]({{< relref "../../../alerting/" >}}). The response contains [data frames]({{< relref "../data-frames/" >}}), which are used to visualize metrics, logs, and traces.
|
||||
The query data capability allows a backend plugin to handle data source queries that are submitted from a [dashboard]({{< relref "../../../dashboards/" >}}), [Explore]({{< relref "../../../explore/" >}}) or [Grafana Alerting]({{< relref "../../../alerting/" >}}). The response contains [data frames]({{< relref "../data-frames/" >}}), which are used to visualize metrics, logs, and traces. The query data capability is required to implement for a backend data source plugin.
|
||||
|
||||
{{% admonition type="note" %}} Backend data source plugins are required to implement the query data capability.{{%
|
||||
/admonition %}}
|
||||
### Resources
|
||||
|
||||
#### Resources
|
||||
|
||||
The resources capability allows a backend plugin to handle custom HTTP requests sent to the Grafana HTTP API and respond with custom HTTP responses. Here, the request and response formats can vary. For example, you can use JSON, plain text, HTML, or static resources such as images and files, and so on.
|
||||
|
||||
Compared to the query data capability, where the response contains data frames, the resources capability gives the plugin developer more flexibility for extending and opening up Grafana for new and interesting use cases.
|
||||
|
||||
### Use cases
|
||||
The resources capability allows a backend plugin to handle custom HTTP requests sent to the Grafana HTTP API and respond with custom HTTP responses. Here, the request and response formats can vary, e.g. JSON, plain text, HTML or static resources (files, images) etc. Compared to the query data capability where the response contains data frames, resources give the plugin developer a lot of flexibility for extending and open up Grafana for new and interesting use cases.
|
||||
|
||||
Examples of use cases for implementing resources:
|
||||
|
||||
- Implement a custom data source proxy to provide certain authentication, authorization, or other requirements that are not supported in Grafana's [built-in data proxy]({{< relref "../../http_api/data_source/#data-source-proxy-calls" >}}).
|
||||
- Return data or information in a format suitable for use within a data source query editor to provide auto-complete functionality.
|
||||
- Return static resources such as images or files.
|
||||
- Send a command to a device, such as a microcontroller or IoT device.
|
||||
- Request information from a device, such as a microcontroller or IoT device.
|
||||
- Implement a custom data source proxy in case certain authentication/authorization or other requirements are required/needed that are not supported in Grafana's [built-in data proxy]({{< relref "../../http_api/data_source/#data-source-proxy-calls" >}}).
|
||||
- Return data or information in a format suitable to use within a data source query editor to provide auto-complete functionality.
|
||||
- Return static resources, such as images or files.
|
||||
- Send a command to a device, such as a micro controller or IOT device.
|
||||
- Request information from a device, such as a micro controller or IOT device.
|
||||
- Extend Grafana's HTTP API with custom resources, methods and actions.
|
||||
- Use [chunked transfer encoding](https://en.wikipedia.org/wiki/Chunked_transfer_encoding) to return large data responses in chunks or to enable certain streaming capabilities.
|
||||
- Use [chunked transfer encoding](https://en.wikipedia.org/wiki/Chunked_transfer_encoding) to return large data responses in chunks or to enable "basic" streaming capabilities.
|
||||
|
||||
#### Health checks
|
||||
### Health checks
|
||||
|
||||
The health checks capability allows a backend plugin to return the status of the plugin. For data source backend plugins, the health check is automatically called when a user edits a data source and selects _Save & Test_ in the UI.
|
||||
The health checks capability allows a backend plugin to return the status of the plugin. For data source backend plugins the health check will automatically be called when you do _Save & Test_ in the UI when editing a data source. A plugin's health check endpoint is exposed in the Grafana HTTP API and allows external systems to continuously poll the plugin's health to make sure it's running and working as expected.
|
||||
|
||||
A plugin's health check endpoint is exposed in the Grafana HTTP API and allows external systems to continuously poll the plugin's health to make sure that it's running and working as expected.
|
||||
### Collect metrics
|
||||
|
||||
#### Collect metrics
|
||||
A backend plugin can collect and return runtime, process and custom metrics using the text-based Prometheus [exposition format](https://prometheus.io/docs/instrumenting/exposition_formats/). If you’re using the [Grafana Plugin SDK for Go]({{< relref "grafana-plugin-sdk-for-go/" >}}) to implement your backend plugin, then the [Prometheus instrumentation library for Go applications](https://github.com/prometheus/client_golang) is built-in, and gives you Go runtime metrics and process metrics out of the box. By using the [Prometheus instrumentation library](https://github.com/prometheus/client_golang) you can add custom metrics to instrument your backend plugin.
|
||||
|
||||
A backend plugin can collect and return runtime, process, and custom metrics using the text-based Prometheus [exposition format](https://prometheus.io/docs/instrumenting/exposition_formats/). If you're using the [Grafana Plugin SDK for Go]({{< relref "grafana-plugin-sdk-for-go/" >}}) to implement your backend plugin, then the [Prometheus instrumentation library for Go applications](https://github.com/prometheus/client_golang) is built-in. This SDK gives you Go runtime metrics and process metrics out of the box. You can use the [Prometheus instrumentation library](https://github.com/prometheus/client_golang) to add custom metrics to instrument your backend plugin.
|
||||
|
||||
The Grafana HTTP API offers an endpoint (`/api/plugins/<plugin id>/metrics`) that allows you to configure a Prometheus instance to scrape the metrics.
|
||||
|
||||
#### Streaming
|
||||
|
||||
The streaming capability allows a backend plugin to handle data source queries that are streaming. For more information, refer to [Build a streaming data source plugin]({{<relref "../build-a-streaming-data-source-plugin.md">}})
|
||||
A metrics endpoint (`/api/plugins/<plugin id>/metrics`) for a plugin is available in the Grafana HTTP API and allows a Prometheus instance to be configured to scrape the metrics.
|
||||
|
||||
@@ -12,17 +12,15 @@ title: Grafana Plugin SDK for Go
|
||||
|
||||
# Grafana plugin SDK for Go
|
||||
|
||||
The [Grafana plugin SDK for Go](https://pkg.go.dev/mod/github.com/grafana/grafana-plugin-sdk-go?tab=overview) is a [Go](https://golang.org/) module that provides a set of [packages](https://pkg.go.dev/mod/github.com/grafana/grafana-plugin-sdk-go?tab=packages) that you can use to implement a backend plugin.
|
||||
The Grafana plugin SDK for Go enables building Grafana backend plugins using [Go](https://golang.org/). The SDK provides a high-level framework with APIs, utilities and tooling that abstract away the details of the [plugin protocol]({{< relref "plugin-protocol/" >}}) and RPC communication so plugin developers do not need to manage either.
|
||||
|
||||
The plugin SDK provides a high-level framework with APIs, utilities, and tooling. By using the SDK, you can avoid the need to learn the details of the [plugin protocol]({{< relref "plugin-protocol/" >}}) and RPC communication protocol, so you don't have to manage either one.
|
||||
The [github.com/grafana/grafana-plugin-sdk-go](https://pkg.go.dev/mod/github.com/grafana/grafana-plugin-sdk-go?tab=overview) is a Go module that provides a set of [Go packages](https://pkg.go.dev/mod/github.com/grafana/grafana-plugin-sdk-go?tab=packages) that can be used to implement a backend plugin.
|
||||
|
||||
## Versioning
|
||||
|
||||
The Grafana plugin Go SDK is still in development. It is based on the [plugin protocol]({{< relref "plugin-protocol/" >}}), which is versioned separately and is considered stable. However, from time to time, we might introduce breaking changes in the SDK.
|
||||
|
||||
When we update the plugin SDK, those plugins that use an older version of the SDK should still work with Grafana. However, these older plugins may be unable to use the new features and capabilities we introduce in updated SDK versions.
|
||||
The SDK is still in development. The [plugin protocol]({{< relref "plugin-protocol/" >}}) between Grafana and the plugin SDK is versioned separately and considered stable. However, there might be breaking changes introduced in the SDK. This means that plugins using an older version of the SDK should still work with Grafana, but might lose out on new features and capabilities introduced in the SDK.
|
||||
|
||||
## See also
|
||||
|
||||
- [SDK source code](https://github.com/grafana/grafana-plugin-sdk-go)
|
||||
- [Source code](https://github.com/grafana/grafana-plugin-sdk-go)
|
||||
- [Go reference documentation](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go)
|
||||
|
||||
@@ -11,35 +11,24 @@ title: Plugin protocol
|
||||
|
||||
# Plugin protocol
|
||||
|
||||
The Grafana server uses a physical wire protocol to communicate with backend plugins. This protocol establishes a contract between Grafana and backend plugins to allow them to communicate with each other.
|
||||
There’s a physical wire protocol that Grafana server uses to communicate with backend plugins. This is the contract between Grafana and backend plugins, that must be agreed upon for Grafana and a backend plugin to be able to communicate with each other. The plugin protocol is built on [gRPC](https://grpc.io/) and is defined in [Protocol Buffers (a.k.a., protobuf)](https://developers.google.com/protocol-buffers).
|
||||
|
||||
## Developing with the plugin protocol
|
||||
We advise for backend plugins to not be implemented directly against this protocol. Instead, prefer to use the [Grafana Plugin SDK for Go]({{< relref "grafana-plugin-sdk-for-go/" >}}) that implements this protocol and provides higher level APIs.
|
||||
|
||||
{{% admonition type="caution" %}} We strongly recommend that backend plugin development not be implemented directly against the protocol. Instead, we prefer that you use the [Grafana Plugin SDK for Go]({{< relref "grafana-plugin-sdk-for-go/" >}}) that implements this protocol and provides higher-level APIs. {{%
|
||||
/admonition %}}
|
||||
|
||||
If you choose to develop against the plugin protocol directly, you can do so using [Protocol Buffers](https://developers.google.com/protocol-buffers) (that is, protobufs) with [gRPC](https://grpc.io/).
|
||||
|
||||
Grafana's plugin protocol protobufs are available in the [GitHub repository](https://github.com/grafana/grafana-plugin-sdk-go/blob/master/proto/backend.proto).
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
The plugin protocol lives in the [Grafana Plugin SDK for Go]({{< relref "grafana-plugin-sdk-for-go/" >}}) because Grafana itself uses parts of the SDK as a dependency.
|
||||
{{% /admonition %}}
|
||||
The plugin protocol is available in the [GitHub repository](https://github.com/grafana/grafana-plugin-sdk-go/blob/master/proto/backend.proto). The plugin protocol lives in the [Grafana Plugin SDK for Go]({{< relref "grafana-plugin-sdk-for-go/" >}}) since Grafana itself uses parts of the SDK as a dependency.
|
||||
|
||||
## Versioning
|
||||
|
||||
From time to time, Grafana will offer additions of services, messages, and fields in the latest version of the plugin protocol. We don't expect these updates to introduce any breaking changes. However, if we must introduce breaking changes to the plugin protocol, we'll create a new major version of the plugin protocol.
|
||||
Additions of services, messages and fields in the latest version of the plugin protocol are expected to happen, but should not introduce any breaking changes. If breaking changes to the plugin protocol is needed, a new major version of the plugin protocol will be created and released together with a new major Grafana release. Grafana will then support both the old and the new plugin protocol for some time to make sure existing backend plugins continue to work.
|
||||
|
||||
Grafana will release new major versions of the plugin protocol alongside new major Grafana releases. When this happens, we'll support both the old and the new plugin protocol for some time to make sure existing backend plugins continue to work.
|
||||
|
||||
The plugin protocol attempts to follow Grafana's versioning. However, that doesn't mean we will automatically create a new major version of the plugin protocol when a new major release of Grafana is released.
|
||||
Because Grafana maintains the plugin protocol, the plugin protocol attempts to follow Grafana's versioning, However, that doesn't automatically mean that a new major version of the plugin protocol is created when a new major release of Grafana is released.
|
||||
|
||||
## Writing plugins without Go
|
||||
|
||||
If you want to write a backend plugin in a language other than Go, then it's possible as long as the language supports gRPC. However, we recommend that you develop your plugin in Go for several reasons:
|
||||
If you want to write a backend plugin in another language than Go, then it’s possible as long as the language supports [gRPC](https://grpc.io/). However, writing a plugin in Go is recommended and has several advantages that should be carefully taken into account before proceeding:
|
||||
|
||||
- We offer an official plugin SDK.
|
||||
- The compiled output is a single binary.
|
||||
- Writing for multiple platforms is easy. Typically, no additional dependencies must be installed on the target platform.
|
||||
- Small footprint for binary size.
|
||||
- Small footprint for resource usage.
|
||||
- There's an official [SDK]({{< relref "grafana-plugin-sdk-for-go/" >}}) available.
|
||||
- Single binary as the compiled output.
|
||||
- Building and compiling for multiple platforms is easy.
|
||||
- A statically compiled binary (in most cases) doesn't require any additional dependencies installed on the target platform enabling it to run “everywhere”.
|
||||
- Small footprint in regards to binary size and resource usage.
|
||||
|
||||
@@ -4,22 +4,19 @@ title: Build a logs data source plugin
|
||||
|
||||
# Build a logs data source plugin
|
||||
|
||||
Grafana data source plugins support metrics, logs, and other data types. The steps to build a logs data source plugin are largely the same as for a metrics data source, but there are a few differences which we will explain in this guide.
|
||||
This guide explains how to build a logs data source plugin.
|
||||
|
||||
## Before you begin
|
||||
|
||||
This guide assumes that you're already familiar with how to [Build a data source plugin](/tutorials/build-a-data-source-plugin/) for metrics. We recommend that you review this material before continuing.
|
||||
Data sources in Grafana supports both metrics and log data. The steps to build a logs data source plugin are largely the same as for a metrics data source. This guide assumes that you're already familiar with how to [Build a data source plugin](/tutorials/build-a-data-source-plugin/) for metrics.
|
||||
|
||||
## Add logs support to your data source
|
||||
|
||||
To add logs support to an existing data source, you need to:
|
||||
|
||||
1. Enable logs support
|
||||
1. Construct the log data
|
||||
- Enable logs support
|
||||
- Construct the log data
|
||||
- (Optional) Add preferred visualisation type hint to the data frame
|
||||
|
||||
When these steps are done, then you can improve the user experience with one or more [optional features](#enhance-your-logs-data-source-plugin-with-optional-features).
|
||||
|
||||
### Step 1: Enable logs support
|
||||
### Enable logs support
|
||||
|
||||
Tell Grafana that your data source plugin can return log data, by adding `"logs": true` to the [plugin.json]({{< relref "metadata/" >}}) file.
|
||||
|
||||
@@ -29,9 +26,9 @@ Tell Grafana that your data source plugin can return log data, by adding `"logs"
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Construct the log data
|
||||
### Construct the log data
|
||||
|
||||
As it does with metrics data, Grafana expects your plugin to return log data as a [data frame]({{< relref "data-frames/" >}}).
|
||||
Just like for metrics data, Grafana expects your plugin to return log data as a [data frame]({{< relref "data-frames/" >}}).
|
||||
|
||||
To return log data, return a data frame with at least one time field and one text field from the data source's `query` method.
|
||||
|
||||
@@ -54,13 +51,9 @@ That's all you need to start returning log data from your data source. Go ahead
|
||||
|
||||
Congratulations, you just wrote your first logs data source plugin! Next, let's look at a couple of features that can further improve the experience for the user.
|
||||
|
||||
## Enhance your logs data source plugin with optional features
|
||||
### (Optional) Add preferred visualisation type hint to the data frame
|
||||
|
||||
Add visualization type hints, labels, and other optional features to logs.
|
||||
|
||||
### Add a preferred visualization type hint to the data frame
|
||||
|
||||
To make sure Grafana recognizes data as logs and shows logs visualization automatically in Explore, set `meta.preferredVisualisationType` to `'logs'` in the returned data frame. See [Selecting preferred visualisation section]({{< relref "add-support-for-explore-queries/#selecting-preferred-visualisation" >}})
|
||||
To make sure Grafana recognizes data as logs and shows logs visualization automatically in Explore you have do set `meta.preferredVisualisationType` to `'logs'` in the returned data frame. See [Selecting preferred visualisation section]({{< relref "add-support-for-explore-queries/#selecting-preferred-visualisation" >}})
|
||||
|
||||
**Example:**
|
||||
|
||||
@@ -77,11 +70,11 @@ const frame = new MutableDataFrame({
|
||||
});
|
||||
```
|
||||
|
||||
### Add labels to your logs
|
||||
## Add labels to your logs
|
||||
|
||||
Many log systems let you query logs based on metadata, or _labels_, to help filter log lines.
|
||||
To help filter log lines, many log systems let you query logs based on metadata, or _labels_.
|
||||
|
||||
Add labels to a stream of logs by setting the `labels` property on the Field.
|
||||
You can add labels to a stream of logs by setting the labels property on the Field.
|
||||
|
||||
**Example**:
|
||||
|
||||
@@ -98,15 +91,15 @@ frame.add({ time: 1589189388597, content: 'user registered' });
|
||||
frame.add({ time: 1589189406480, content: 'user logged in' });
|
||||
```
|
||||
|
||||
### Extract detected fields from your logs
|
||||
## Extract detected fields from your logs
|
||||
|
||||
Add additional information about each log line by supplying more data frame fields.
|
||||
You can add additional information about each log line by adding more data frame fields.
|
||||
|
||||
If a data frame has more than one text field, then Grafana assumes the first field in the data frame to be the actual log line. Grafana treats subsequent text fields as [detected fields]({{< relref "../../explore/#labels-and-detected-fields" >}}).
|
||||
If a data frame has more than one text field, then Grafana assumes the first field in the data frame to be the actual log line. Any subsequent text fields are treated as [detected fields]({{< relref "../../explore/#labels-and-detected-fields" >}}).
|
||||
|
||||
Any number of custom fields can be added to your data frame; Grafana comes with two dedicated fields: `levels` and `id`.
|
||||
While you can add any number of custom fields to your data frame, Grafana comes with a couple of dedicated fields: `levels` and `id`. Let's have a closer look at each one.
|
||||
|
||||
#### Levels
|
||||
### Levels
|
||||
|
||||
To set the level for each log line, add a `level` field.
|
||||
|
||||
@@ -126,7 +119,7 @@ frame.add({ time: 1589189388597, content: 'user registered', level: 'info' });
|
||||
frame.add({ time: 1589189406480, content: 'unknown error', level: 'error' });
|
||||
```
|
||||
|
||||
#### 'id' for assigning unique identifiers to log lines
|
||||
### Unique log lines
|
||||
|
||||
By default, Grafana offers basic support for deduplicating log lines. You can improve the support by adding an `id` field to explicitly assign identifiers to each log line.
|
||||
|
||||
|
||||
@@ -4,112 +4,100 @@ title: Build a streaming data source plugin
|
||||
|
||||
# Build a streaming data source plugin
|
||||
|
||||
In Grafana, you can set your dashboards to automatically refresh at a certain interval, no matter what data source you use. Unfortunately, this means that your queries are requesting all the data to be sent again, regardless of whether the data has actually changed. Adding streaming to a plugin helps reduce queries so your dashboard is only updated when new data becomes available.
|
||||
|
||||
## Before you begin
|
||||
This guide explains how to build a streaming data source plugin.
|
||||
|
||||
This guide assumes that you're already familiar with how to [Build a data source plugin](/tutorials/build-a-data-source-plugin/).
|
||||
|
||||
Grafana uses [RxJS](https://rxjs.dev/) to continuously send data from a data source to a panel visualization.
|
||||
When monitoring critical applications, you want your dashboard to refresh as soon as your data does. In Grafana, you can set your dashboards to automatically refresh at a certain interval, no matter what data source you use. Unfortunately, this means that your queries are requesting all the data to be sent again, regardless of whether the data has actually changed.
|
||||
|
||||
> **Note:** To learn more about RxJs, refer to the [RxJS documentation](https://rxjs.dev/guide/overview).
|
||||
|
||||
## Add streaming to your data source
|
||||
|
||||
Enable streaming for your data source plugin to update your dashboard when new data becomes available.
|
||||
By enabling _streaming_ for your data source plugin, you can update your dashboard as soon as new data becomes available.
|
||||
|
||||
For example, a streaming data source plugin can connect to a websocket, or subscribe to a message bus, and update the visualization whenever a new message is available.
|
||||
|
||||
### Step 1: Edit the `plugin.json` file
|
||||
Let's see how you can add streaming to an existing data source!
|
||||
|
||||
Enable streaming for your data source in the `plugin.json` file.
|
||||
Grafana uses [RxJS](https://rxjs.dev/) to continuously send data from a data source to a panel visualization. There's a lot more to RxJS than what's covered in this guide. If you want to learn more, check out the [RxJS documentation](https://rxjs.dev/guide/overview).
|
||||
|
||||
```json
|
||||
{
|
||||
"streaming": true
|
||||
}
|
||||
```
|
||||
1. Enable streaming for your data source in the `plugin.json` file.
|
||||
|
||||
### Step 2: Change the signature of the `query` method
|
||||
```json
|
||||
{
|
||||
"streaming": true
|
||||
}
|
||||
```
|
||||
|
||||
Modify the signature of the `query` method to return an `Observable` from the `rxjs` package. Make sure you remove the `async` keyword.
|
||||
1. Change the signature of the `query` method to return an `Observable` from the `rxjs` package. Make sure you remove the `async` keyword.
|
||||
|
||||
```ts
|
||||
import { Observable } from 'rxjs';
|
||||
```
|
||||
```ts
|
||||
import { Observable } from 'rxjs';
|
||||
```
|
||||
|
||||
```ts
|
||||
query(options: DataQueryRequest<MyQuery>): Observable<DataQueryResponse> {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
```ts
|
||||
query(options: DataQueryRequest<MyQuery>): Observable<DataQueryResponse> {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Create an `Observable` instance for each query
|
||||
1. Create an `Observable` for each query, and then combine them all using the `merge` function from the `rxjs` package.
|
||||
|
||||
Create an `Observable` instance for each query, and then combine them all using the `merge` function from the `rxjs` package.
|
||||
```ts
|
||||
import { Observable, merge } from 'rxjs';
|
||||
```
|
||||
|
||||
```ts
|
||||
import { Observable, merge } from 'rxjs';
|
||||
```
|
||||
```ts
|
||||
const observables = options.targets.map((target) => {
|
||||
return new Observable<DataQueryResponse>((subscriber) => {
|
||||
// ...
|
||||
});
|
||||
});
|
||||
|
||||
```ts
|
||||
const observables = options.targets.map((target) => {
|
||||
return new Observable<DataQueryResponse>((subscriber) => {
|
||||
// ...
|
||||
});
|
||||
});
|
||||
return merge(...observables);
|
||||
```
|
||||
|
||||
return merge(...observables);
|
||||
```
|
||||
1. In the `subscribe` function, create a `CircularDataFrame`.
|
||||
|
||||
### Step 4: Create a `CircularDataFrame` instance
|
||||
```ts
|
||||
import { CircularDataFrame } from '@grafana/data';
|
||||
```
|
||||
|
||||
In the `subscribe` function, create a `CircularDataFrame` instance.
|
||||
```ts
|
||||
const frame = new CircularDataFrame({
|
||||
append: 'tail',
|
||||
capacity: 1000,
|
||||
});
|
||||
|
||||
```ts
|
||||
import { CircularDataFrame } from '@grafana/data';
|
||||
```
|
||||
frame.refId = query.refId;
|
||||
frame.addField({ name: 'time', type: FieldType.time });
|
||||
frame.addField({ name: 'value', type: FieldType.number });
|
||||
```
|
||||
|
||||
```ts
|
||||
const frame = new CircularDataFrame({
|
||||
append: 'tail',
|
||||
capacity: 1000,
|
||||
});
|
||||
Circular data frames have a limited capacity. When a circular data frame reaches its capacity, the oldest data point is removed.
|
||||
|
||||
frame.refId = query.refId;
|
||||
frame.addField({ name: 'time', type: FieldType.time });
|
||||
frame.addField({ name: 'value', type: FieldType.number });
|
||||
```
|
||||
1. Use `subscriber.next()` to send the updated data frame whenever you receive new updates.
|
||||
|
||||
Circular data frames have a limited capacity. When a circular data frame reaches its capacity, the oldest data point is removed.
|
||||
```ts
|
||||
import { LoadingState } from '@grafana/data';
|
||||
```
|
||||
|
||||
### Step 5: Send the updated data frame
|
||||
```ts
|
||||
const intervalId = setInterval(() => {
|
||||
frame.add({ time: Date.now(), value: Math.random() });
|
||||
|
||||
Use `subscriber.next()` to send the updated data frame whenever you receive new updates.
|
||||
subscriber.next({
|
||||
data: [frame],
|
||||
key: query.refId,
|
||||
state: LoadingState.Streaming,
|
||||
});
|
||||
}, 500);
|
||||
|
||||
```ts
|
||||
import { LoadingState } from '@grafana/data';
|
||||
```
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
```
|
||||
|
||||
```ts
|
||||
const intervalId = setInterval(() => {
|
||||
frame.add({ time: Date.now(), value: Math.random() });
|
||||
> **Note:** In practice, you'd call `subscriber.next` as soon as you receive new data from a websocket or a message bus. The example above simulates data being received every 500 milliseconds.
|
||||
|
||||
subscriber.next({
|
||||
data: [frame],
|
||||
key: query.refId,
|
||||
state: LoadingState.Streaming,
|
||||
});
|
||||
}, 500);
|
||||
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
```
|
||||
|
||||
> **Note:** In practice, you'd call `subscriber.next` as soon as you receive new data from a websocket or a message bus. In the example above, data is being received every 500 milliseconds.
|
||||
|
||||
### Example code for final `query` method
|
||||
Here's the final `query` method.
|
||||
|
||||
```ts
|
||||
query(options: DataQueryRequest<MyQuery>): Observable<DataQueryResponse> {
|
||||
@@ -146,6 +134,4 @@ query(options: DataQueryRequest<MyQuery>): Observable<DataQueryResponse> {
|
||||
}
|
||||
```
|
||||
|
||||
One limitation with this example is that the panel visualization is cleared every time you update the dashboard. If you have access to historical data, you can add it, or _backfill_ it, to the data frame before the first call to `subscriber.next()`.
|
||||
|
||||
For another example of a streaming plugin, refer to the [streaming websocket example](https://github.com/grafana/grafana-plugin-examples/tree/main/examples/datasource-streaming-websocket) on GitHub.
|
||||
One limitation with this example is that the panel visualization is cleared every time you update the dashboard. If you have access to historical data, you can add, or _backfill_, it to the data frame before the first call to `subscriber.next()`.
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
---
|
||||
description: How-to topics for plugin development
|
||||
title: Create a plugin
|
||||
---
|
||||
|
||||
# Create a Grafana plugin
|
||||
|
||||
This section contains how-to topics for developing Grafana plugins.
|
||||
|
||||
- [Build a Grafana plugin](https://grafana.github.io/plugin-tools/docs/creating-a-plugin)
|
||||
- [Build a panel plugin](https://grafana.com/tutorials/build-a-panel-plugin/)
|
||||
- [Build a data source plugin](https://grafana.com/tutorials/build-a-data-source-plugin/)
|
||||
- [Build a data source backend plugin](https://grafana.com/tutorials/build-a-data-source-backend-plugin/)
|
||||
- [Build a logs data source plugin]({{< relref "../build-a-logs-data-source-plugin.md">}})
|
||||
- [Build a streaming data source plugin]({{< relref "../build-a-streaming-data-source-plugin.md">}})
|
||||
- Extend a Grafana plugin
|
||||
- [Add annotations]({{< relref "add-support-for-annotations.md">}})
|
||||
- [Add anonymous usage reporting]({{< relref "add-anonymous-usage-reporting.md">}})
|
||||
- [Add authentication for a data source plugin]({{< relref "add-authentication-for-data-source-plugins.md">}})
|
||||
- [Add Explore queries]({{< relref "add-support-for-explore-queries.md">}})
|
||||
- [Add query editor help]({{< relref "add-query-editor-help.md">}})
|
||||
- [Add variables]({{< relref "add-support-for-variables.md">}})
|
||||
- [Create panel option editors]({{< relref "custom-panel-option-editors.md">}})
|
||||
- [Sign a plugin]({{< relref "sign-a-plugin.md">}})
|
||||
- [Automate development with CI](https://grafana.github.io/plugin-tools/docs/ci)
|
||||
- [Create nested plugins](https://grafana.github.io/plugin-tools/docs/nested-plugins)
|
||||
- [Extend configurations](https://grafana.github.io/plugin-tools/docs/advanced-configuration)
|
||||
@@ -1,74 +0,0 @@
|
||||
---
|
||||
title: Work with cross-plugin links
|
||||
description: Learn how to add plugin links to a Grafana app plugin
|
||||
---
|
||||
|
||||
# Work with cross-plugin links
|
||||
|
||||
With the Plugins extension API, app plugins can register extension points of their own to display other plugins links. This is called _cross-plugin linking_, and you can use it to create more immersive user experiences with installed plugins.
|
||||
|
||||
## Available extension points within plugins
|
||||
|
||||
An extension point is a location in another plugin's UI where your plugin can insert links. All extension point IDs within plugins should follow the naming convention `plugins/<plugin-id>/<extension-point-id>`.
|
||||
|
||||
## How to create an extension point within a plugin
|
||||
|
||||
Use the `getPluginExtensions` method in `@grafana/runtime` to create an extension point within your plugin. An extension point is a way to specify where in the plugin UI other plugins links are rendered.
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
Creating an extension point in a plugin creates a public interface for other plugins to interact with. Changes to the extension point ID or its context could break any plugin that attempts to register a link inside your plugin.
|
||||
{{% /admonition %}}
|
||||
|
||||
The `getPluginExtensions` method takes an object consisting of the `extensionPointId`, which must begin `plugin/<pluginId>`, and any contextual information that you want to provide. The `getPluginExtensions` method returns a list of `extensionLinks` that your program can loop over:
|
||||
|
||||
```typescript
|
||||
import { getPluginExtensions } from '@grafana/runtime';
|
||||
import { isPluginExtensionLink } from '@grafana/data';
|
||||
import { LinkButton } from '@grafana/ui';
|
||||
|
||||
function AppExtensionPointExample() {
|
||||
const { extensions } = getPluginExtensions({
|
||||
extensionPointId: 'plugin/another-app-plugin/menu',
|
||||
context: {
|
||||
pluginId: 'another-app-plugin',
|
||||
},
|
||||
});
|
||||
|
||||
if (extensions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{extensions.map((extension) => {
|
||||
if (isPluginExtensionLink(extension)) {
|
||||
return (
|
||||
<LinkButton href={extension.path} title={extension.description} key={extension.key}>
|
||||
{extension.title}
|
||||
</LinkButton>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
The preceding example shows a component that renders `<LinkButton />` components for all link extensions that other plugins registered for the `plugin/another-app-plugin/menu` extension point ID. The context is passed as the second parameter to `getPluginExtensions`, which uses `Object.freeze` to make the context immutable before passing it to other plugins.
|
||||
|
||||
## Insert links into another plugin
|
||||
|
||||
Create links for other plugins in the same way you [extend the Grafana application UI]({{< relref "./extend-the-grafana-ui-with-links" >}}) with a link. Don't specify a `grafana/...` extension point. Instead, specify the plugin extension point `plugin/<pluginId>/<extensionPointId>`.
|
||||
|
||||
Given the preceding example, use a plugin link such as the following:
|
||||
|
||||
```typescript
|
||||
new AppPlugin().configureExtensionLink({
|
||||
title: 'Go to basic app',
|
||||
description: 'Will navigate the user to the basic app',
|
||||
extensionPointId: 'plugin/another-app-plugin/menu',
|
||||
path: '/a/myorg-basic-app/one',
|
||||
});
|
||||
```
|
||||
@@ -1,17 +1,12 @@
|
||||
---
|
||||
title: Build a custom panel option editor
|
||||
title: Custom panel option editors
|
||||
---
|
||||
|
||||
# Build a custom panel option editor
|
||||
# Custom panel option editors
|
||||
|
||||
The Grafana plugin platform comes with a range of editors that allow your users to customize a panel. The standard editors cover the most common types of options, such as text input and boolean switches. If you don't find the editor you're looking for, you can build your own.
|
||||
The Grafana plugin platform comes with a range of editors that allow your users to customize a panel. The standard editors cover the most common types of options, such as text input and boolean switches. If you don't find the editor you're looking for, you can build your own. In this guide, you'll learn how to build your own panel option editor.
|
||||
|
||||
## Panel option editor basics
|
||||
|
||||
The simplest editor is a React component that accepts two props:
|
||||
|
||||
- **`value`**: the current value of the option
|
||||
- **`onChange`**: updates the option's value
|
||||
The simplest editor is a React component that accepts two props: `value` and `onChange`. `value` contains the current value of the option, and `onChange` updates it.
|
||||
|
||||
The editor in the example below lets the user toggle a boolean value by clicking a button:
|
||||
|
||||
@@ -27,7 +22,7 @@ export const SimpleEditor: React.FC<StandardEditorProps<boolean>> = ({ value, on
|
||||
};
|
||||
```
|
||||
|
||||
To use a custom panel option editor, use the `addCustomEditor` on the `OptionsUIBuilder` object in your `module.ts` file and set the `editor` property to the name of your custom editor component.
|
||||
To use a custom panel option editor, use the `addCustomEditor` on the `OptionsUIBuilder` object in your `module.ts` file. Configure the editor to use by setting the `editor` property to the `SimpleEditor` component.
|
||||
|
||||
**module.ts**
|
||||
|
||||
@@ -44,9 +39,9 @@ export const plugin = new PanelPlugin<SimpleOptions>(SimplePanel).setPanelOption
|
||||
|
||||
## Add settings to your panel option editor
|
||||
|
||||
You can use your custom editor to customize multiple possible settings. To add settings to your editor, set the second template variable of `StandardEditorProps` to an interface that contains the settings you want to configure. Access the editor settings through the `item` prop.
|
||||
If you're using your custom editor to configure multiple options, you might want to be able to customize it. Add settings to your editor by setting the second template variable of `StandardEditorProps` to an interface that contains the settings you want to be able to configure.
|
||||
|
||||
Here's an example of an editor that populates a drop-down with a range of numbers. The `Settings` interface defines the range of the `from` and `to` properties.
|
||||
You can access the editor settings through the `item` prop. Here's an example of an editor that populates a drop-down with a range of numbers. The range is defined by the `from` and `to` properties in the `Settings` interface.
|
||||
|
||||
**SimpleEditor.tsx**
|
||||
|
||||
@@ -74,7 +69,7 @@ export const SimpleEditor: React.FC<StandardEditorProps<number, Settings>> = ({
|
||||
};
|
||||
```
|
||||
|
||||
You can now configure the editor for each option by configuring the `settings` property to call `addCustomEditor`:
|
||||
You can now configure the editor for each option, by configuring the `settings` property in the call to `addCustomEditor`.
|
||||
|
||||
```ts
|
||||
export const plugin = new PanelPlugin<SimpleOptions>(SimplePanel).setPanelOptions((builder) => {
|
||||
@@ -93,7 +88,9 @@ export const plugin = new PanelPlugin<SimpleOptions>(SimplePanel).setPanelOption
|
||||
|
||||
## Use query results in your panel option editor
|
||||
|
||||
Option editors can access the results from the last query. This lets you update your editor dynamically based on the data returned by the data source.
|
||||
Option editors can access the results from the last query. This lets you update your editor dynamically, based on the data returned by the data source.
|
||||
|
||||
> **Note:** This feature was introduced in 7.0.3. Anyone using an older version of Grafana will see an error when using your plugin.
|
||||
|
||||
The editor context is available through the `context` prop. The data frames returned by the data source are available under `context.data`.
|
||||
|
||||
@@ -117,3 +114,5 @@ export const SimpleEditor: React.FC<StandardEditorProps<string>> = ({ item, valu
|
||||
return <Select options={options} value={value} onChange={(selectableValue) => onChange(selectableValue.value)} />;
|
||||
};
|
||||
```
|
||||
|
||||
Have you built a custom editor that you think would be useful to other plugin developers? Consider contributing it as a standard editor!
|
||||
|
||||
@@ -6,65 +6,45 @@ title: Data frames
|
||||
|
||||
Grafana supports a variety of different data sources, each with its own data model. To make this possible, Grafana consolidates the query results from each of these data sources into one unified data structure called a _data frame_.
|
||||
|
||||
The data frame structure is a concept that's borrowed from data analysis tools like the [R programming language](https://www.r-project.org) and [Pandas](https://pandas.pydata.org/).
|
||||
The data frame structure is a concept that's borrowed from data analysis tools like the [R programming language](https://www.r-project.org), and [Pandas](https://pandas.pydata.org/).
|
||||
|
||||
> Data frames are available in Grafana 7.0+, and replaced the Time series and Table structures with a more generic data structure that can support a wider range of data types.
|
||||
|
||||
This document gives an overview of the data frame structure, and of how data is handled within Grafana.
|
||||
|
||||
### Data frame fields
|
||||
## The data frame
|
||||
|
||||
A data frame is a collection of _fields_, where each field corresponds to a column. Each field, in turn, consists of a collection of values and metadata, such as the data type of those values.
|
||||
A data frame is a columnar-oriented table structure, which means it stores data by column and not by row. To understand what this means, let’s look at the TypeScript definition used by Grafana:
|
||||
|
||||
```ts
|
||||
export interface Field<T = any, V = Vector<T>> {
|
||||
/**
|
||||
* Name of the field (column)
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Field value type (string, number, and so on)
|
||||
*/
|
||||
type: FieldType;
|
||||
/**
|
||||
* Meta info about how field and how to display it
|
||||
*/
|
||||
config: FieldConfig;
|
||||
interface DataFrame {
|
||||
name?: string;
|
||||
// reference to query that create the frame
|
||||
refId?: string;
|
||||
|
||||
/**
|
||||
* The raw field values
|
||||
* In Grafana 10, this accepts both simple arrays and the Vector interface
|
||||
* In Grafana 11, the Vector interface will be removed
|
||||
*/
|
||||
values: V | T[];
|
||||
|
||||
/**
|
||||
* When type === FieldType.Time, this can optionally store
|
||||
* the nanosecond-precison fractions as integers between
|
||||
* 0 and 999999.
|
||||
*/
|
||||
nanos?: number[];
|
||||
|
||||
labels?: Labels;
|
||||
|
||||
/**
|
||||
* Cached values with appropriate display and id values
|
||||
*/
|
||||
state?: FieldState | null;
|
||||
|
||||
/**
|
||||
* Convert a value for display
|
||||
*/
|
||||
display?: DisplayProcessor;
|
||||
|
||||
/**
|
||||
* Get value data links with variables interpolated
|
||||
*/
|
||||
getLinks?: (config: ValueLinkConfig) => Array<LinkModel<Field>>;
|
||||
fields: []Field;
|
||||
}
|
||||
```
|
||||
|
||||
Let's look at an example. The following table demonstrates a data frame with two fields, _time_ and _temperature_:
|
||||
In essence, a data frame is a collection of _fields_, where each field corresponds to a column. Each field, in turn, consists of a collection of values, along with meta information, such as the data type of those values.
|
||||
|
||||
```ts
|
||||
interface Field {
|
||||
name: string;
|
||||
// Prometheus like Labels / Tags
|
||||
labels?: Record<string, string>;
|
||||
|
||||
// For example string, number, time (or more specific primitives in the backend)
|
||||
type: FieldType;
|
||||
// Array of values all of the same type
|
||||
values: Vector<T>;
|
||||
|
||||
// Optional display data for the field (e.g. unit, name over-ride, etc)
|
||||
config: FieldConfig;
|
||||
}
|
||||
```
|
||||
|
||||
Let's look at an example. The table below demonstrates a data frame with two fields, _time_ and _temperature_.
|
||||
|
||||
| time | temperature |
|
||||
| ------------------- | ----------- |
|
||||
@@ -72,24 +52,22 @@ Let's look at an example. The following table demonstrates a data frame with two
|
||||
| 2020-01-02 03:05:00 | 47.0 |
|
||||
| 2020-01-02 03:06:00 | 48.0 |
|
||||
|
||||
Each field has three values, and each value in a field must share the same type. In this case, all values in the `time` field are timestamps, and all values in the `temperature` field are numbers.
|
||||
Each field has three values, and each value in a field must share the same type. In this case, all values in the time field are timestamps, and all values in the temperature field are numbers.
|
||||
|
||||
One restriction on data frames is that all fields in the frame must be of the same length to be a valid data frame.
|
||||
|
||||
### Field configurations
|
||||
### Field configuration
|
||||
|
||||
Each field in a data frame contains optional information about the values in the field, such as units, scaling, and so on.
|
||||
|
||||
By adding field configurations to a data frame, Grafana can configure visualizations automatically. For example, you could configure Grafana to automatically set the unit provided by the data source.
|
||||
|
||||
## Data transformations
|
||||
## Transformations
|
||||
|
||||
We have seen how field configs contain type information, and they also have another role. Data frame fields enable _data transformations_ within Grafana.
|
||||
Along with the type information, field configs enable _data transformations_ within Grafana.
|
||||
|
||||
A data transformation is any function that accepts a data frame as input, and returns another data frame as output. By using data frames in your plugin, you get a range of transformations for free.
|
||||
|
||||
To learn more about data transformations in Grafana, refer to [Transform data](https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/transform-data/).
|
||||
|
||||
## Data frames as time series
|
||||
|
||||
A data frame with at least one time field is considered a _time series_.
|
||||
@@ -98,9 +76,9 @@ For more information on time series, refer to our [Introduction to time series](
|
||||
|
||||
### Wide format
|
||||
|
||||
When a collection of time series shares the same _time index_—the time fields in each time series are identical—they can be stored together, in a _wide_ format. By reusing the time field, less data is sent to the browser.
|
||||
When a collection of time series shares the same _time index_—the time fields in each time series are identical—they can be stored together, in a _wide_ format. By reusing the time field, we can reduce the amount of data being sent to the browser.
|
||||
|
||||
In this example, the `cpu` usage from each host shares the time index, so we can store them in the same data frame:
|
||||
In this example, the `cpu` usage from each host share the time index, so we can store them in the same data frame.
|
||||
|
||||
```text
|
||||
Name: Wide
|
||||
@@ -115,7 +93,7 @@ Dimensions: 3 fields by 2 rows
|
||||
+---------------------+-----------------+-----------------+
|
||||
```
|
||||
|
||||
However, if the two time series don't share the same time values, they are represented as two distinct data frames:
|
||||
However, if the two time series don't share the same time values, they are represented as two distinct data frames.
|
||||
|
||||
```text
|
||||
Name: cpu
|
||||
@@ -141,17 +119,19 @@ Dimensions: 2 fields by 2 rows
|
||||
+---------------------+-----------------+
|
||||
```
|
||||
|
||||
A typical use for the wide format is when multiple time series are collected by the same process. In this case, every measurement is made at the same interval and therefore shares the same time values.
|
||||
The wide format can typically be used when multiple time series are collected by the same process. In this case, every measurement is made at the same interval and will therefore share the same time values.
|
||||
|
||||
### Long format
|
||||
|
||||
Some data sources return data in a _long_ format (also called _narrow_ format). This is a common format returned by, for example, SQL databases.
|
||||
Some data sources return data in a _long_ format (also called _narrow_ format). This is common format returned by, for example, SQL databases.
|
||||
|
||||
In the long format, string values are represented as separate fields rather than as labels. As a result, a data form in long form may have duplicated time values.
|
||||
In long format, string values are represented as separate fields rather than as labels. As a result, a data form in long form may have duplicated time values.
|
||||
|
||||
Grafana can detect and convert data frames in long format into wide format.
|
||||
|
||||
For example, the following data frame appears in long format:
|
||||
> **Note:** Long format is currently only supported in the backend: [Grafana Issue #22219](https://github.com/grafana/grafana/issues/22219).
|
||||
|
||||
For example, the following data frame in long format:
|
||||
|
||||
```text
|
||||
Name: Long
|
||||
@@ -168,7 +148,7 @@ Dimensions: 4 fields by 4 rows
|
||||
+---------------------+-----------------+-----------------+----------------+
|
||||
```
|
||||
|
||||
The above table can be converted into a data frame in wide format like this:
|
||||
can be converted into a data frame in wide format:
|
||||
|
||||
```text
|
||||
Name: Wide
|
||||
@@ -183,11 +163,11 @@ Dimensions: 5 fields by 2 rows
|
||||
+---------------------+------------------+------------------+------------------+------------------+
|
||||
```
|
||||
|
||||
> **Note:** Not all panels support the wide time series data frame format. To keep full backward compatibility Grafana has introduced a transformation that you can use to convert from the wide to the long format. For usage information, refer to the [Prepare time series-transformation]({{< relref "../../panels-visualizations/query-transform-data/transform-data/#prepare-time-series" >}}).
|
||||
> **Note:** Not all panels support the wide time series data frame format. To keep full backward compatibility we have introduced a transformation that can be used to convert from the wide to the long format. For usage information, refer to the [Prepare time series-transformation]({{< relref "../../panels-visualizations/query-transform-data/transform-data/#prepare-time-series" >}}).
|
||||
|
||||
## Technical references
|
||||
|
||||
The concept of a data frame in Grafana is borrowed from data analysis tools like the [R programming language](https://www.r-project.org), and [Pandas](https://pandas.pydata.org/). Other technical references are provided below.
|
||||
This section contains links to technical reference and implementations of data frames.
|
||||
|
||||
### Apache Arrow
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
---
|
||||
title: Develop with a local environment
|
||||
title: Development with local Grafana
|
||||
---
|
||||
|
||||
# Develop with a local environment
|
||||
# Development with local Grafana
|
||||
|
||||
Follow the steps in this guide to set up a development environment where you run Grafana and your plugin locally. With this setup, you can see your changes as you add them.
|
||||
This guide allows you to setup a development environment where you run Grafana and your plugin locally. With this, you will be able to see your changes as you add them.
|
||||
|
||||
## Run Grafana in your host
|
||||
|
||||
To clone and run Grafana locally:
|
||||
If you have git, Go and the required version of NodeJS in your system, you can clone and run Grafana locally:
|
||||
|
||||
1. Download and set up Grafana. Refer to the [developer-guide](https://github.com/grafana/grafana/blob/HEAD/contribute/developer-guide.md).
|
||||
1. Download and set up Grafana. You can find instructions on how to do it in the [developer-guide](https://github.com/grafana/grafana/blob/HEAD/contribute/developer-guide.md).
|
||||
|
||||
2. Grafana looks for plugins, by default, in its `data/plugins` directory. You can create a symbolic link to your plugin repository to detect new changes:
|
||||
2. Grafana will look for plugins, by default, on its `data/plugins` directory. You can create a symbolic link to your plugin repository to detect new changes:
|
||||
|
||||
```bash
|
||||
ln -s <plugin-path>/dist data/plugins/<plugin-name>
|
||||
```
|
||||
|
||||
3. Optional: If the preceding step doesn't work for you (for example, if you are running on Windows), then modify the default path in the Grafana configuration. Find the default path at `conf/custom.ini`) and point it to your plugin's directory:
|
||||
3. (Optional) If the step above doesn't work for you (e.g. you are running on Windows), you can also modify the default path in the Grafana configuration (that can be found at `conf/custom.ini`) and point to the directory with your plugin:
|
||||
|
||||
```ini
|
||||
[paths]
|
||||
@@ -27,11 +27,9 @@ To clone and run Grafana locally:
|
||||
|
||||
## Run Grafana with docker-compose
|
||||
|
||||
Another option is to run Grafana with docker-compose so that it runs in a container. To do so, create the `docker-compose` file in your plugin directory.
|
||||
Another possibility is to run Grafana with docker-compose so it runs in a container. For doing so, create the docker-compose file in your plugin directory:
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
If your plugin already includes a docker-compose file, then skip this step.
|
||||
{{% /admonition %}}
|
||||
**NOTE**: Some plugins already include a docker-compose file so you can skip this step.
|
||||
|
||||
```yaml
|
||||
version: '3.7'
|
||||
@@ -43,7 +41,7 @@ services:
|
||||
ports:
|
||||
- 3000:3000/tcp
|
||||
volumes:
|
||||
# Use your plugin folder (for example, redshift-datasource)
|
||||
# Use your plugin folder (e.g. redshift-datasource)
|
||||
- ./dist:/var/lib/grafana/plugins/<plugin-folder>
|
||||
- ./provisioning:/etc/grafana/provisioning
|
||||
environment:
|
||||
@@ -53,9 +51,9 @@ services:
|
||||
- GF_DEFAULT_APP_MODE=development
|
||||
```
|
||||
|
||||
## Run your plugin in development mode
|
||||
## Run your plugin
|
||||
|
||||
Finally, start your plugin in development mode. Go to your plugin's root directory and follow these steps:
|
||||
Finally start your plugin in development mode. Go to your plugin root directory and follow these steps:
|
||||
|
||||
1. Build your plugin backend and start the frontend in watch mode:
|
||||
|
||||
@@ -64,9 +62,9 @@ Finally, start your plugin in development mode. Go to your plugin's root directo
|
||||
yarn watch
|
||||
```
|
||||
|
||||
2. Start the Grafana backend and frontend:
|
||||
2. Start Grafana backend and frontend:
|
||||
|
||||
1. For a local copy of Grafana, go to the directory with Grafana source code and run:
|
||||
2.1 For a local copy of Grafana, go to the directory with Grafana source code and run:
|
||||
|
||||
```bash
|
||||
make run
|
||||
@@ -76,29 +74,25 @@ Finally, start your plugin in development mode. Go to your plugin's root directo
|
||||
yarn start
|
||||
```
|
||||
|
||||
2. Or, with docker-compose, in your plugin directory, run:
|
||||
2.2 Or with docker-compose, in your plugin directory, run:
|
||||
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
After this, you should be able to see your plugin listed in Grafana, and then you can test your changes.
|
||||
|
||||
If you make a change in the frontend, you must refresh your browser. However, changes in the backend may require that you rebuild your plugin binaries and reload the plugin (`mage && mage reloadPlugin` for local development, or run `docker-compose up` again if you are using docker-compose).
|
||||
After this, you should be able to see your plugin listed in Grafana and test your changes. Note that any change in the fronted will require you to refresh your browser while changes in the backend may require to rebuild your plugin binaries and reload the plugin (`mage && mage reloadPlugin` for local development or `docker-compose up` again if you are using docker-compose).
|
||||
|
||||
## Run your backend plugin with a debugger
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
The following method only works with a local Grafana instance and currently doesn't work with Docker.
|
||||
{{% /admonition %}}
|
||||
> Note: The following method only works with a local Grafana instance and currently doesn't work with Docker.
|
||||
|
||||
Running a backend plugin with a debugger is supported in Visual Studio Code and GoLand out of the box, but it can also work with any other IDE or debugger.
|
||||
You can run a backend plugin and attach a debugger to it, which allows you to set breakpoints and debug your backend plugin directly from your IDE of choice.
|
||||
|
||||
You can run a backend plugin and attach a debugger to it, which allows you to set breakpoints and debug your backend plugin directly from your IDE of choice:
|
||||
We support Visual Studio Code and GoLand out of the box, but this feature can also work with any other IDE or debugger.
|
||||
|
||||
1. Go to your plugin's folder.
|
||||
|
||||
1. Check your `go.mod` to make sure `grafana-plugin-sdk-go` are at least on `v0.156.0`
|
||||
1. Check your `go.mod` and make sure `grafana-plugin-sdk-go` is at least on `v0.156.0`
|
||||
- If not, update it to the latest version:
|
||||
```
|
||||
go get -u github.com/grafana/grafana-plugin-sdk-go
|
||||
@@ -133,9 +127,9 @@ Now that your plugin is ready to run, follow the instructions bellow for your ID
|
||||
```
|
||||
|
||||
1. Press `F5` to run your plugin in debug mode.
|
||||
1. If Grafana isn't already running, run it.
|
||||
1. Start Grafana, if it's not already running.
|
||||
|
||||
> If you re-run the configuration, Grafana automatically reloads the plugin.
|
||||
> If you re-run the configuration, Grafana will automatically reload the plugin.
|
||||
|
||||
### GoLand
|
||||
|
||||
@@ -147,32 +141,30 @@ Now that your plugin is ready to run, follow the instructions bellow for your ID
|
||||
|
||||
1. Run the config (with or without the debugger).
|
||||
|
||||
1. If Grafana isn't already running, run it.
|
||||
1. Start Grafana, if it's not already running.
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
If you re-run the configuration, Grafana automatically reloads the plugin.
|
||||
{{% /admonition %}}
|
||||
> If you re-run the configuration, Grafana will automatically reload the plugin.
|
||||
|
||||
### Other IDEs
|
||||
|
||||
Configure your code editor to run the following steps:
|
||||
|
||||
1. Build the executable file with debug flags.
|
||||
1. Build the executable with debug flags.
|
||||
```
|
||||
mage build:debug
|
||||
```
|
||||
1. Run the plugin's executable file (inside `dist`) with `-standalone -debug` flags.
|
||||
1. Run the plugin's executable (inside `dist`) with `-standalone -debug` flags.
|
||||
```
|
||||
./gpx_xyz_linux_amd64 -standalone -debug
|
||||
```
|
||||
1. Attach a debugger to the process.
|
||||
|
||||
1. If Grafana isn't already running, run it.
|
||||
Then, you can start Grafana, if it's not already running.
|
||||
|
||||
> If you re-run the configuration, Grafana automatically reloads the plugin.
|
||||
> If you re-run the configuration, Grafana will automatically reload the plugin.
|
||||
|
||||
### Notes
|
||||
|
||||
- All logs are printed in the plugin's `stdout` rather than in Grafana logs.
|
||||
- If the backend plugin doesn't serve requests after you turn off debug mode, you can force a reset to the standalone mode. To do so, delete the files `dist/standalone.txt`, `dist/pid.txt`, and the executable file, and then restart Grafana.
|
||||
- Grafana doesn't support debugging backend plugins running inside Docker. But this is a [planned enhancement](https://github.com/grafana/grafana-plugin-sdk-go/issues/685).
|
||||
- If the backend plugin doesn't serve requests after turning off debug mode, you can force reset the standalone mode. To do so, delete the files `dist/standalone.txt` and `dist/pid.txt` alongside the executable file, and then restart Grafana.
|
||||
- We currently do not support debugging backend plugins running inside Docker.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
title: Work with error handling
|
||||
title: Error handling
|
||||
---
|
||||
|
||||
# Work with error handling
|
||||
# Error handling
|
||||
|
||||
This guide explains how to handle errors in plugins and provides suggestions for common scenarios.
|
||||
This guide explains how to handle errors in plugins.
|
||||
|
||||
## Provide usable defaults
|
||||
|
||||
@@ -33,7 +33,7 @@ Grafana displays the error message in the top-left corner of the panel.
|
||||
|
||||
{{< figure src="/static/img/docs/panel_error.png" class="docs-image--no-shadow" max-width="850px" >}}
|
||||
|
||||
We recommend that you avoid displaying overly technical error messages to the user. If you want to let technical users report an error, consider logging it to the console instead.
|
||||
Avoid displaying overly-technical error messages to the user. If you want to let technical users report an error, consider logging it instead.
|
||||
|
||||
```ts
|
||||
try {
|
||||
@@ -44,9 +44,7 @@ try {
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** Grafana displays the exception message in the UI as written, so use grammatically correct sentences. For more information, refer to the [Documentation style guide](https://github.com/grafana/grafana/blob/main/contribute/style-guides/documentation-style-guide.md).
|
||||
|
||||
## Common error scenarios
|
||||
> **Note:** Grafana displays the exception message in the UI as written, so we recommend using grammatically correct sentences. For more information, refer to the [Documentation style guide](https://github.com/grafana/grafana/blob/main/contribute/style-guides/documentation-style-guide.md).
|
||||
|
||||
Here are some examples of situations where you might want to display an error to the user.
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
description: Get started guide
|
||||
title: Get started with plugins
|
||||
---
|
||||
|
||||
# Get started with Grafana plugins
|
||||
|
||||
This section contains guidance for building plugins.
|
||||
|
||||
- [Get started with creating a plugin](https://grafana.github.io/plugin-tools/docs/getting-started)
|
||||
- [Types of Grafana plugins](https://grafana.com/docs/grafana/latest/administration/plugin-management/)
|
||||
- [Set up your development environment](https://grafana.github.io/plugin-tools/docs/docker)
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
description: Conceptual topics for plugin development
|
||||
title: Introduction to plugin development
|
||||
---
|
||||
|
||||
# Introduction to Grafana plugin development
|
||||
|
||||
This section contains topics related to the key concepts for Grafana plugin development.
|
||||
|
||||
- [Backend plugins]({{< relref "../backend/" >}})
|
||||
- [Grafana plugin SDK for Go]({{< relref "../backend/grafana-plugin-sdk-for-go.md" >}})
|
||||
- [Plugin protocol]({{< relref "../backend/plugin-protocol.md" >}})
|
||||
- [Data frames]({{< relref "data-frames.md">}})
|
||||
@@ -1,67 +0,0 @@
|
||||
---
|
||||
description: How to package a plugin
|
||||
title: Package a plugin
|
||||
---
|
||||
|
||||
By packaging a plugin, you can organize the plugin code and make it ready for use in your organization.
|
||||
|
||||
## Package a plugin for distribution
|
||||
|
||||
1. Build the plugin
|
||||
|
||||
```
|
||||
yarn install --pure-lockfile
|
||||
yarn build
|
||||
```
|
||||
|
||||
1. Optional: If your data source plugin has a backend plugin, build it as well.
|
||||
|
||||
```
|
||||
mage
|
||||
```
|
||||
|
||||
Make sure that all the binaries are executable and have a `0755` (`-rwxr-xr-x`) permission.
|
||||
|
||||
1. Sign the plugin. To learn more, refer to [Sign the plugin]({{< relref "./sign-a-plugin" >}}).
|
||||
|
||||
1. Rename the `dist` directory to match your plugin ID, and then create a ZIP archive.
|
||||
|
||||
```
|
||||
mv dist/ myorg-simple-panel
|
||||
zip myorg-simple-panel-1.0.0.zip myorg-simple-panel -r
|
||||
```
|
||||
|
||||
1. Optional: Verify that your plugin is packaged correctly using [zipinfo](https://linux.die.net/man/1/zipinfo).
|
||||
It should look like this:
|
||||
|
||||
```
|
||||
zipinfo grafana-clickhouse-datasource-1.1.2.zip
|
||||
|
||||
Archive: grafana-clickhouse-datasource-1.1.2.zip
|
||||
Zip file size: 34324077 bytes, number of entries: 22
|
||||
drwxr-xr-x 0 bx stor 22-Mar-24 23:23 grafana-clickhouse-datasource/
|
||||
-rw-r--r-- 1654 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/CHANGELOG.md
|
||||
-rw-r--r-- 11357 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/LICENSE
|
||||
-rw-r--r-- 2468 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/MANIFEST.txt
|
||||
-rw-r--r-- 8678 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/README.md
|
||||
drwxr-xr-x 0 bx stor 22-Mar-24 23:23 grafana-clickhouse-datasource/dashboards/
|
||||
-rw-r--r-- 42973 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/dashboards/cluster-analysis.json
|
||||
-rw-r--r-- 56759 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/dashboards/data-analysis.json
|
||||
-rw-r--r-- 39406 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/dashboards/query-analysis.json
|
||||
-rwxr-xr-x 16469136 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_darwin_amd64
|
||||
-rwxr-xr-x 16397666 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_darwin_arm64
|
||||
-rwxr-xr-x 14942208 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_linux_amd64
|
||||
-rwxr-xr-x 14155776 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_linux_arm
|
||||
-rwxr-xr-x 14548992 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_linux_arm64
|
||||
-rwxr-xr-x 15209472 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_windows_amd64.exe
|
||||
drwxr-xr-x 0 bx stor 22-Mar-24 23:23 grafana-clickhouse-datasource/img/
|
||||
-rw-r--r-- 304 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/img/logo.png
|
||||
-rw-r--r-- 1587 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/img/logo.svg
|
||||
-rw-r--r-- 138400 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/module.js
|
||||
-rw-r--r-- 808 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/module.js.LICENSE.txt
|
||||
-rw-r--r-- 487395 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/module.js.map
|
||||
-rw-r--r-- 1616 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/plugin.json
|
||||
22 files, 92516655 bytes uncompressed, 34319591 bytes compressed: 62.9%
|
||||
```
|
||||
|
||||
When you've packaged your plugin, you can proceed to [publishing a plugin]({{< relref "publish-a-plugin.md" >}}) or [installing a packaged plugin](https://grafana.com/docs/grafana/latest/administration/plugin-management/#install-a-packaged-plugin).
|
||||
185
docs/sources/developers/plugins/publish-a-plugin.md
Normal file
185
docs/sources/developers/plugins/publish-a-plugin.md
Normal file
@@ -0,0 +1,185 @@
|
||||
---
|
||||
aliases:
|
||||
- share-a-plugin/
|
||||
- package-a-plugin/
|
||||
description: Learn how to package and share your plugin.
|
||||
title: Publish a plugin
|
||||
type: docs
|
||||
---
|
||||
|
||||
# Publish a plugin
|
||||
|
||||
You've just built your first plugin, and now you want to share it with the world.
|
||||
In this guide, you'll learn how to package and share your plugin with others.
|
||||
|
||||
For Grafana to be able to load a plugin, it first needs to be built.
|
||||
When you build a plugin from source, a `dist` directory is created that contains the production build, or _plugin assets_, for your plugin.
|
||||
|
||||
When the Grafana server starts, it recursively looks in the plugin directory for any directory that contains a `plugin.json` file and tries to load the plugin assets in the same directory.
|
||||
|
||||
There are three steps needed to package a plugin:
|
||||
|
||||
- Building the plugin
|
||||
- Signing the plugin
|
||||
- Packaging the plugin
|
||||
|
||||
1. Build the plugin
|
||||
|
||||
```
|
||||
yarn install --pure-lockfile
|
||||
yarn build
|
||||
```
|
||||
|
||||
1. (Optional) If your data source plugin has a backend plugin, build it as well.
|
||||
|
||||
```
|
||||
mage
|
||||
```
|
||||
|
||||
make sure that all the binaries are executable and have a `0755` (`-rwxr-xr-x`) permission
|
||||
|
||||
1. [Sign the plugin]({{< relref "./sign-a-plugin" >}}).
|
||||
|
||||
1. Rename `dist` directory to match your plugin id and create a ZIP archive
|
||||
|
||||
```
|
||||
mv dist/ myorg-simple-panel
|
||||
zip myorg-simple-panel-1.0.0.zip myorg-simple-panel -r
|
||||
```
|
||||
|
||||
1. (Optional) Verify your plugin is packaged correctly using [zipinfo](https://linux.die.net/man/1/zipinfo).
|
||||
It should look like this:
|
||||
|
||||
```
|
||||
zipinfo grafana-clickhouse-datasource-1.1.2.zip
|
||||
|
||||
Archive: grafana-clickhouse-datasource-1.1.2.zip
|
||||
Zip file size: 34324077 bytes, number of entries: 22
|
||||
drwxr-xr-x 0 bx stor 22-Mar-24 23:23 grafana-clickhouse-datasource/
|
||||
-rw-r--r-- 1654 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/CHANGELOG.md
|
||||
-rw-r--r-- 11357 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/LICENSE
|
||||
-rw-r--r-- 2468 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/MANIFEST.txt
|
||||
-rw-r--r-- 8678 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/README.md
|
||||
drwxr-xr-x 0 bx stor 22-Mar-24 23:23 grafana-clickhouse-datasource/dashboards/
|
||||
-rw-r--r-- 42973 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/dashboards/cluster-analysis.json
|
||||
-rw-r--r-- 56759 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/dashboards/data-analysis.json
|
||||
-rw-r--r-- 39406 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/dashboards/query-analysis.json
|
||||
-rwxr-xr-x 16469136 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_darwin_amd64
|
||||
-rwxr-xr-x 16397666 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_darwin_arm64
|
||||
-rwxr-xr-x 14942208 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_linux_amd64
|
||||
-rwxr-xr-x 14155776 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_linux_arm
|
||||
-rwxr-xr-x 14548992 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_linux_arm64
|
||||
-rwxr-xr-x 15209472 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/gpx_clickhouse_windows_amd64.exe
|
||||
drwxr-xr-x 0 bx stor 22-Mar-24 23:23 grafana-clickhouse-datasource/img/
|
||||
-rw-r--r-- 304 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/img/logo.png
|
||||
-rw-r--r-- 1587 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/img/logo.svg
|
||||
-rw-r--r-- 138400 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/module.js
|
||||
-rw-r--r-- 808 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/module.js.LICENSE.txt
|
||||
-rw-r--r-- 487395 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/module.js.map
|
||||
-rw-r--r-- 1616 bX defN 22-Mar-24 23:23 grafana-clickhouse-datasource/plugin.json
|
||||
22 files, 92516655 bytes uncompressed, 34319591 bytes compressed: 62.9%
|
||||
```
|
||||
|
||||
## Publish your plugin on Grafana.com
|
||||
|
||||
The best way to share your plugin with the world is to publish it on [Grafana Plugins](/plugins).
|
||||
By having your plugin published on Grafana.com, more users will be able to discover your plugin.
|
||||
|
||||
Before you submit your plugin, we ask that you read our guidelines and frequently asked questions.
|
||||
|
||||
### Guidelines
|
||||
|
||||
To speed up the time it takes to review your plugin:
|
||||
|
||||
- Get familiar with our plugin [publishing and signing criteria]({{< relref "./publishing-and-signing-criteria" >}})
|
||||
- Check that your plugin is ready for review using the [plugin validator](https://github.com/grafana/plugin-validator).
|
||||
- Read our [6 tips for improving your Grafana plugin before you publish](/blog/2021/01/21/6-tips-for-improving-your-grafana-plugin-before-you-publish/).
|
||||
- Refer to [plugin-examples](https://github.com/grafana/grafana-plugin-examples) to review best practices for building your plugin.
|
||||
|
||||
### Frequently Asked Questions
|
||||
|
||||
**Do I need to submit a private plugin?**
|
||||
|
||||
- No. Please only submit plugins that you wish to make publicly available for the Grafana community.
|
||||
|
||||
**How long does it take to review my submission?**
|
||||
|
||||
- We're not able to give an estimate at this time, though we're constantly working on improving the time it takes to review a plugin.
|
||||
|
||||
**Can I decide a date when my plugin will be published?**
|
||||
|
||||
- No. We cannot guarantee specific publishing dates, as plugins are immediately published after a review based on our internal prioritization.
|
||||
|
||||
**Can I see metrics of my plugin installs, downloads or usage?**
|
||||
|
||||
- No. We don't offer this information at the moment to plugin authors.
|
||||
|
||||
**How can I update my plugin's catalog page?**
|
||||
|
||||
- The plugin's catalog page content is extracted from the plugin README file.
|
||||
To update the plugin's catalog page, it is necessary to submit an updated plugin with the new content included in the README file.
|
||||
|
||||
**Can I unlist my plugin from the Grafana Plugin's Catalog in case of a bug?**
|
||||
|
||||
- In the event of a bug, unlisting the plugin from the Grafana Plugin's Catalog may be possible in exceptional cases, such as security concerns.
|
||||
However, we do not have control over the specific instances where the plugin is installed.
|
||||
|
||||
**Can I distribute my plugin somewhere else than the Grafana Catalog?**
|
||||
|
||||
- The official method for distributing Grafana plugins is through the Grafana Catalog.
|
||||
Alternative methods, such as installing private or development plugins on local Grafana instances, are available as per the guidelines provided in [this guide]({{< relref "../../administration/plugin-management#install-plugin-on-local-grafana" >}}).
|
||||
|
||||
**Can I still use Angular for my plugin?**
|
||||
|
||||
- No. We will not accept any new plugin submissions written in angular.
|
||||
Please take a look at our [angular support deprecation documentation]({{< relref "../angular_deprecation" >}}).
|
||||
|
||||
### Publishing your plugin for the first time
|
||||
|
||||
**Do plugin signatures expire?**
|
||||
|
||||
- Plugin signatures do not currently expire.
|
||||
|
||||
{{< figure src="/static/img/docs/plugins/plugins-submission-create2.png" class="docs-image--no-shadow" max-width="650px" >}}
|
||||
|
||||
1. [Sign in](/auth/sign-in) to your Grafana Cloud account.
|
||||
1. In the left menu, under **Org settings**, click **My Plugins**.
|
||||
1. Click **Submit Plugin**.
|
||||
1. Enter the information requested by the form.
|
||||
- **OS & Architecture:**
|
||||
- Select **Single** if your plugin archive contains binaries for multiple architectures.
|
||||
- Select **Multiple** if you'd like to submit separate plugin archives for each architecture.
|
||||
This can lead to faster downloads since users can select the specific architecture on which they want to install the plugin.
|
||||
- **URL:** A URL that points to a ZIP archive of your packaged plugin.
|
||||
- **Source Code URL:** A URL that points to a public git repository or ZIP archive of your complete plugin source code.
|
||||
- **MD5:** The MD5 hash of the plugin specified by the **URL**.
|
||||
- The remaining questions help us determine the [signature level]({{< relref "./sign-a-plugin#plugin-signature-levels" >}}) for your plugin.
|
||||
1. Click **Submit**.
|
||||
After you have submitted your plugin, we run an automated validation to make sure it adheres to our guidelines.
|
||||
Once your submission passes the validation, it's placed in a review queue.
|
||||
|
||||
All submissions are manually inspected by a plugin reviewer.
|
||||
For every new plugin, we perform a manual review that includes the following checks:
|
||||
|
||||
- **Code review:** For quality and security purposes, we review the source code for the plugin.
|
||||
If you're unable to make the source code publicly available, let us know in a comment on your plugin submission.
|
||||
- **Tests:** We install your plugin on one of our Grafana instances to test it for basic use.
|
||||
For more advanced plugins, we may ask you to assist us in configuring a test environment for the plugin.
|
||||
This test environment will be used whenever you submit an plugin update.
|
||||
|
||||
### Submit a plugin update
|
||||
|
||||
To submit an **update** for an already published plugin:
|
||||
|
||||
1. [Sign in](/auth/sign-in) to your Grafana Cloud account.
|
||||
1. In the left menu, under **Org settings**, click **My Plugins**.
|
||||
1. Click **Submit Update** for the plugin you want to update.
|
||||
1. Enter the information requested by the form.
|
||||
- **OS & Architecture:**
|
||||
- Select **Single** if your plugin archive contains binaries for multiple architectures.
|
||||
- Select **Multiple** if you'd like to submit separate plugin archives for each architecture.
|
||||
This can lead to faster downloads since users can select the specific architecture they want to install the plugin on.
|
||||
- **URL:** A URL that points to a ZIP archive of your packaged plugin.
|
||||
- **Source Code URL:** A URL that points to a public git repository or ZIP archive of your complete plugin source code.
|
||||
- **MD5:** The MD5 hash of the plugin specified by the **URL**.
|
||||
1. Click **Submit**.
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
description: Topics related to plugin publishing
|
||||
title: Publish a plugin
|
||||
---
|
||||
|
||||
# Publish a plugin
|
||||
|
||||
This section contains topics related to publishing Grafana plugins.
|
||||
|
||||
- [Publishing and signing criteria]({{< relref "../publishing-and-signing-criteria.md">}})
|
||||
- [Publish or update a plugin]({{< relref "../publish-or-update-a-plugin.md">}})
|
||||
@@ -1,128 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- share-a-plugin/
|
||||
description: Learn how to package and share your plugin.
|
||||
title: Publish or update a plugin
|
||||
type: docs
|
||||
---
|
||||
|
||||
# Publish or update a plugin
|
||||
|
||||
You've just built your plugin; now you want to share it with the world.
|
||||
|
||||
In this guide, you'll learn how to package and share your plugin with others.
|
||||
|
||||
The best way to share your plugin with the world is to publish it in the [Grafana plugin catalog]{{< relref "/plugins" >}}).
|
||||
By having your plugin published on Grafana.com, more users will be able to discover your plugin.
|
||||
|
||||
## Before you begin
|
||||
|
||||
When you build a plugin from source, a `dist` folder is created. This folder contains the production build or _plugin assets_ for your plugin.
|
||||
|
||||
To package a plugin, refer to [Package a plugin]{{< relref "package-a-plugin.md" >}}).
|
||||
|
||||
### Follow our guidelines
|
||||
|
||||
Get familiar with our plugin [publishing and signing criteria]({{< relref "./publishing-and-signing-criteria" >}})
|
||||
|
||||
### Do this for best results
|
||||
|
||||
To speed up the time it takes to review your plugin:
|
||||
|
||||
- Check that your plugin is ready for review using the [plugin validator](https://github.com/grafana/plugin-validator).
|
||||
- Read our [6 tips for improving your Grafana plugin before you publish](/blog/2021/01/21/6-tips-for-improving-your-grafana-plugin-before-you-publish/).
|
||||
- Refer to [plugin-examples](https://github.com/grafana/grafana-plugin-examples) to review best practices for building your plugin.
|
||||
|
||||
## Publish your plugin
|
||||
|
||||
Follow these steps to publish your plugin for the first time.
|
||||
|
||||
1. [Sign in](/auth/sign-in) to your Grafana Cloud account.
|
||||
1. In the left menu, under **Org settings**, click **My Plugins**.
|
||||
1. Click **Submit Plugin**. The Create Plugin Submission dialog appears.
|
||||
|
||||
{{< figure src="/static/img/docs/plugins/plugins-submission-create2.png" class="docs-image--no-shadow" max-width="650px" >}}
|
||||
|
||||
1. Enter the information requested by the form.
|
||||
- **OS & Architecture:**
|
||||
- Select **Single** if your plugin archive contains binaries for multiple architectures.
|
||||
- Select **Multiple** if you'd like to submit separate plugin archives for each architecture.
|
||||
This can lead to faster downloads since users can select the specific architecture on which they want to install the plugin.
|
||||
- **URL:** A URL that points to a ZIP archive of your packaged plugin.
|
||||
- **Source Code URL:** A URL that points to a public Git repository or ZIP archive of your complete plugin source code.
|
||||
- **MD5:** The MD5 hash of the plugin specified by the **URL**.
|
||||
- The remaining questions help us determine the [signature level]({{< relref "./sign-a-plugin#plugin-signature-levels" >}}) for your plugin.
|
||||
1. Click **Submit**.
|
||||
After you submit your plugin, we run an automated validation to make sure it adheres to our guidelines.
|
||||
Once your submission passes the validation, it's placed in a review queue.
|
||||
All submissions are manually inspected by a plugin reviewer.
|
||||
For every new plugin, we perform a manual review that includes the following checks:
|
||||
|
||||
- **Code review:** For quality and security purposes, we review the source code for the plugin.
|
||||
If you're unable to make the source code publicly available, let us know in a comment on your plugin submission.
|
||||
- **Tests:** We install your plugin on one of our Grafana instances to test it for basic use.
|
||||
For more advanced plugins, we may ask you to assist us in configuring a test environment for the plugin.
|
||||
We use the test environment whenever you submit a plugin update.
|
||||
|
||||
## Update your plugin
|
||||
|
||||
To submit an **update** for an already published plugin:
|
||||
|
||||
1. [Sign in](/auth/sign-in) to your Grafana Cloud account.
|
||||
1. In the left menu, under **Org settings**, click **My Plugins**.
|
||||
1. Click **Submit Update** for the plugin you want to update. The Create Plugin Submission dialog appears.
|
||||
{{< figure src="/static/img/docs/plugins/plugins-submission-create2.png" class="docs-image--no-shadow" max-width="650px" >}}
|
||||
1. Enter the information requested by the form.
|
||||
- **OS & Architecture:**
|
||||
- Select **Single** if your plugin archive contains binaries for multiple architectures.
|
||||
- Select **Multiple** if you'd like to submit separate plugin archives for each architecture.
|
||||
This can lead to faster downloads since users can select the specific architecture they want to install the plugin on.
|
||||
- **URL:** A URL that points to a ZIP archive of your packaged plugin.
|
||||
- **Source Code URL:** A URL that points to a public Git repository or ZIP archive of your complete plugin source code. See [examples](#what-source-code-url-formats-are-supported).
|
||||
- **MD5:** The MD5 hash of the plugin specified by the **URL**.
|
||||
1. Click **Submit**.
|
||||
|
||||
## Frequently asked questions
|
||||
|
||||
### Do I need to submit a private plugin?
|
||||
|
||||
- No. Please only submit plugins that you wish to make publicly available for the Grafana community.
|
||||
|
||||
### How long does it take to review my submission?
|
||||
|
||||
- We're not able to give an estimate at this time, though we're constantly working on improving the time it takes to review a plugin.
|
||||
|
||||
### Can I decide a date when my plugin will be published?
|
||||
|
||||
- No. We cannot guarantee specific publishing dates, as plugins are immediately published after a review based on our internal prioritization.
|
||||
|
||||
### Can I see metrics of my plugin installs, downloads or usage?
|
||||
|
||||
- No. We don't offer this information at the moment to plugin authors.
|
||||
|
||||
### How can I update my plugin's catalog page?
|
||||
|
||||
- The plugin's catalog page content is extracted from the plugin README file.
|
||||
To update the plugin's catalog page, submit an updated plugin with the new content included in the README file.
|
||||
|
||||
### Can I unlist my plugin from the Grafana plugin catalog in case of a bug?
|
||||
|
||||
- In the event of a bug, unlisting the plugin from our catalog may be possible in exceptional cases, such as security concerns. However, we don't have control over the instances where the plugin is installed.
|
||||
|
||||
### Can I distribute my plugin somewhere else other than the Grafana plugin catalog?
|
||||
|
||||
- The official method for distributing Grafana plugins is through our catalog. Alternative methods, such as installing private or development plugins on local Grafana instances, are available as per the guidelines provided in [this guide]({{< relref "../../administration/plugin-management#install-plugin-on-local-grafana" >}}).
|
||||
|
||||
### Can I still use Angular for my plugin?
|
||||
|
||||
- No. We will not accept any new plugin submissions written in Angular. For more information, refer to our [Angular support deprecation documentation]({{< relref "../angular_deprecation" >}}).
|
||||
|
||||
### Do plugin signatures expire?
|
||||
|
||||
- Plugin signatures do not currently expire.
|
||||
|
||||
### What source code URL formats are supported?
|
||||
|
||||
- Using a tag or branch: `https://github.com/grafana/clock-panel/tree/v2.1.3`
|
||||
- Using a tag or branch and the code is in a subdirectory (important for mono repos): `https://github.com/grafana/clock-panel/tree/v2.1.3/plugin/` (here, the plugin contains the plugin code)
|
||||
- Using the latest main or master branch commit: `https://github.com/grafana/clock-panel/` (not recommended, it's better to pass a tag or branch)
|
||||
@@ -4,29 +4,27 @@ title: Plugin publishing and signing criteria
|
||||
|
||||
# Plugin publishing and signing criteria
|
||||
|
||||
Grafana plugins must adhere to the Grafana Labs [Plugin Policy](https://grafana.com/legal/plugins/). Our review process for publishing and signing will examine your compliance with this policy.
|
||||
Grafana plugins must adhere to the following criteria when being reviewed for publishing and signing.
|
||||
|
||||
> **Important:** Grafana Labs reserves the right to decline or remove any plugin at its discretion. Failure to comply with publishing and signing criteria may result in immediate removal from the Grafana plugin catalog.
|
||||
## Privacy and security
|
||||
|
||||
<<<<<<< HEAD
|
||||
- Plugins cannot collect usage or user information. Violations of this include but is not limited to:
|
||||
- Directly collecting installation and user statistics
|
||||
- Sending data to 3rd parties for analytics purposes
|
||||
- Embedding tracking code
|
||||
- Data at rest: sensitive data such as credentials and user information, must be encrypted using industry standards.
|
||||
- Use secureJsonData to store data source credentials
|
||||
- Secrets cannot be stored in panel options
|
||||
- Data transmission: secure methods that meet industry standard encryption levels should be used, such as Secure Sockets Layer (SSL) or Transport Layer Security (TLS)
|
||||
- Abuse: plugins should not perform actions beyond the scope of the intended use.
|
||||
- Do not include hidden files
|
||||
- Do not manipulate the underlying environment, privileges, or related processes
|
||||
- Security:
|
||||
- Should not access the filesystem
|
||||
- Should not access environment variables
|
||||
|
||||
## Commercial
|
||||
|
||||
- Usage of 3rd party software or dependencies within the plugin must be licensed for the intended use. For example, using open source dependencies must be credited/licensed; embedding logos or trademarks;
|
||||
|
||||
# Grafana Labs reserves the right to decline or remove any plugin at its discretion. Failure to comply with publishing and signing criteria may result in immediate removal from the Grafana plugin catalog.
|
||||
|
||||
## Plugin licensing
|
||||
|
||||
Plugins must be licensed under one of the following AGPL compliant licenses for publishing to the Grafana plugin catalog:
|
||||
|
||||
- AGPL-3.0
|
||||
- Apache-2.0
|
||||
- BSD
|
||||
- GPL-3.0
|
||||
- LGPL-3.0
|
||||
- MIT
|
||||
|
||||
If contributing a plugin on behalf of an organization, be sure to seek guidance from your legal team.
|
||||
|
||||
> > > > > > > 13be068919 (Docs: Plugin doc review for chunk 1-A (#67070))
|
||||
Grafana Labs reserves the right to decline or remove any plugin at its discretion. Failure to comply with publishing and signing criteria may result in immediate removal from the Grafana plugin catalog.
|
||||
|
||||
@@ -4,26 +4,19 @@ title: Sign a plugin
|
||||
|
||||
# Sign a plugin
|
||||
|
||||
<<<<<<< HEAD
|
||||
Signing a plugin allows Grafana to verify the authenticity of the plugin with [signature verification]({{< relref "../../administration/plugin-management#plugin-signatures" >}}). This gives users a way to make sure plugins haven't been tampered with. All Grafana Labs-authored backend plugins, including Enterprise plugins, are signed.
|
||||
|
||||
> # **Important:** Future versions of Grafana will require all plugins to be signed.
|
||||
>
|
||||
> Grafana requires all plugins to be signed so that we can verify their authenticity with [signature verification]({{< relref "../../administration/plugin-management#plugin-signatures" >}}).
|
||||
|
||||
All Grafana Labs-authored backend plugins, including Enterprise plugins, are signed. By [default]({{< relref "../../administration/plugin-management#allow-unsigned-plugins" >}}), Grafana **requires** all plugins to be signed in order for them to be loaded.
|
||||
|
||||
> > > > > > > 13be068919 (Docs: Plugin doc review for chunk 1-A (#67070))
|
||||
> **Important:** Future versions of Grafana will require all plugins to be signed.
|
||||
|
||||
Before you can sign your plugin, you need to decide whether you want to sign it as a _public_ or a _private_ plugin.
|
||||
|
||||
To make your plugin publicly available outside of your organization, sign your plugin under a _community_ or _commercial_ [signature level](#plugin-signature-levels). Public plugins are available from the [Grafana plugin catalog](https://grafana.com/plugins) and can be installed by anyone.
|
||||
If you want to make your plugin publicly available outside of your organization, you need to sign your plugin under a _community_ or _commercial_ [signature level](#plugin-signature-levels). Public plugins are available from [grafana.com/plugins](https://grafana.com/plugins) and can be installed by anyone.
|
||||
|
||||
If you intend to only use the plugin within your organization, sign it under a _private_ [signature level](#plugin-signature-levels).
|
||||
If you intend to only use the plugin within your organization, you can sign it under a _private_ [signature level](#plugin-signature-levels).
|
||||
|
||||
## Generate an API key
|
||||
|
||||
To verify ownership of your plugin, generate an API key that you'll use every time you need to sign a new version of your plugin.
|
||||
To verify ownership of your plugin, you need to generate an API key that you'll use every time you need to sign a new version of your plugin.
|
||||
|
||||
1. [Create a Grafana Cloud account](https://grafana.com/signup).
|
||||
|
||||
@@ -38,8 +31,8 @@ To verify ownership of your plugin, generate an API key that you'll use every ti
|
||||
Public plugins need to be reviewed by the Grafana team before you can sign them.
|
||||
|
||||
1. Submit your plugin for [review]({{< relref "publish-a-plugin/#publishing-your-plugin-for-the-first-time" >}})
|
||||
1. If we approve your plugin, you're granted a plugin signature level. You need this signature level to proceed.
|
||||
1. In your plugin directory, sign the plugin with the API key you just created. Grafana Sign Plugin creates a [MANIFEST.txt](#plugin-manifest) file in the `dist` directory of your plugin:
|
||||
2. When your plugin is approved, you're granted a plugin signature level. **Without a plugin signature level, you won't be able to sign your plugin**.
|
||||
3. In your plugin directory, sign the plugin with the API key you just created. Grafana Sign Plugin creates a [MANIFEST.txt](#plugin-manifest) file in the `dist` directory of your plugin.
|
||||
|
||||
```bash
|
||||
export GRAFANA_API_KEY=<YOUR_API_KEY>
|
||||
@@ -50,24 +43,24 @@ Public plugins need to be reviewed by the Grafana team before you can sign them.
|
||||
|
||||
1. In your plugin directory, sign the plugin with the API key you just created. Grafana Sign Plugin creates a [MANIFEST.txt](#plugin-manifest) file in the `dist` directory of your plugin.
|
||||
|
||||
The `rootUrls` flag accepts a comma-separated list of URLs to the Grafana instances where you intend to install the plugin.
|
||||
|
||||
```bash
|
||||
export GRAFANA_API_KEY=<YOUR_API_KEY>
|
||||
npx @grafana/sign-plugin@latest --rootUrls https://example.com/grafana
|
||||
```
|
||||
|
||||
1. After the `rootUrls` flag, enter a comma-separated list of URLs for the Grafana instances where you intend to install the plugin.
|
||||
|
||||
## Plugin signature levels
|
||||
|
||||
To sign a plugin, you need to select the _signature level_ that you want to sign it under. The signature level of your plugin determines how you can distribute it.
|
||||
To sign a plugin, you need to decide the _signature level_ you want to sign it under. The signature level of your plugin determines how you can distribute it.
|
||||
|
||||
You can sign your plugin under three different _signature levels_: _private_, _community_, and _commercial_.
|
||||
You can sign your plugin under three different _signature levels_.
|
||||
|
||||
| **Plugin Level** | **Paid Subscription Required?** | **Description** |
|
||||
| ---------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Private | No;<br>Free of charge | <p>You can create and sign a Private plugin for any technology at no charge.</p><p>Private plugins are intended for use on your own installation of Grafana. They may not be distributed to the Grafana community, and they are not published in the Grafana plugin catalog.</p> |
|
||||
| Community | No;<br>Free of charge | <p>You can create, sign, and distribute plugins at no charge, provided that all dependent technologies are open source and not for profit.</p><p>Community plugins are published in the official Grafana catalog, and are available to the entire Grafana community.</p> |
|
||||
| Commercial | Yes;<br>Commercial plugin subscription required | <p>You can create, sign, and distribute plugins with dependent technologies that are closed source or commercially backed. To do so, enter into a Commercial plugin subscription with Grafana Labs.</p><p>Commercial plugins are published on the Grafana plugin catalog, and are available to the entire Grafana community.</p> |
|
||||
| **Plugin Level** | **Paid Subscription Required?** | **Description** |
|
||||
| ---------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Private | No;<br>Free of charge | <p>You can create and sign a Private Plugin for any technology at no charge.</p><p>Private Plugins are for use on your own Grafana. They may not be distributed to the Grafana community, and are not published in the Grafana catalog.</p> |
|
||||
| Community | No;<br>Free of charge | <p>You can create, sign and distribute plugins at no charge, provided that all dependent technologies are open source and not for profit.</p><p>Community Plugins are published in the official Grafana catalog, and are available to the Grafana community.</p> |
|
||||
| Commercial | Yes;<br>Commercial Plugin Subscription required | <p>You can create, sign and distribute plugins with dependent technologies that are closed source or commercially backed, by entering into a Commercial Plugin Subscription with Grafana Labs.</p><p>Commercial Plugins are published on the official Grafana catalog, and are available to the Grafana community.</p> |
|
||||
|
||||
For instructions on how to sign a plugin under the Community and Commercial signature level, refer to [Sign a public plugin](#sign-a-public-plugin).
|
||||
|
||||
@@ -75,12 +68,12 @@ For instructions on how to sign a plugin under the Private signature level, refe
|
||||
|
||||
## Plugin manifest
|
||||
|
||||
For Grafana to verify the digital signature of a plugin, the plugin must include a signed manifest file, `MANIFEST.txt`. The signed manifest file contains two sections:
|
||||
For Grafana to verify the digital signature of a plugin, the plugin must include a signed manifest file, _MANIFEST.txt_. The signed manifest file contains two sections:
|
||||
|
||||
- **Signed message -** Contains plugin metadata and plugin files with their respective checksums (SHA256).
|
||||
- **Digital signature -** Created by encrypting the signed message using a private key. Grafana has a public key built-in that can be used to verify that the digital signature has been encrypted using the expected private key.
|
||||
- **Signed message -** The signed message contains plugin metadata and plugin files with their respective checksums (SHA256).
|
||||
- **Digital signature -** The digital signature is created by encrypting the signed message using a private key. Grafana has a public key built-in that can be used to verify that the digital signature have been encrypted using expected private key.
|
||||
|
||||
**Example**
|
||||
**Example manifest file:**
|
||||
|
||||
```txt
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
@@ -116,18 +109,16 @@ T6scfmuhWC/TOcm83EVoCzIV3R5dOTKHqkjIUg==
|
||||
-----END PGP SIGNATURE-----
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
## Troubleshooting issues while signing your plugin
|
||||
|
||||
### Why do I get a "Modified signature" error?
|
||||
### Why am I getting a "Modified signature" in Grafana?
|
||||
|
||||
In some cases an invalid `MANIFEST.txt` is generated because of an issue when signing the plugin on Windows. You can fix this by replacing all double backslashes, `\\`, with a forward slash, `/`, in the `MANIFEST.txt` file. You need to do this every time you sign your plugin.
|
||||
Due to an issue when signing the plugin on Windows, in some cases an invalid MANIFEST.txt is being generated. You can fix this by replacing all double backslashes, `\\`, with a forward slash, `/` in the MANIFEST.txt file. You need to do this every time you sign your plugin.
|
||||
|
||||
### Why do I get a "Field is required: `rootUrls`" error for my public plugin?
|
||||
### Error signing manifest: Field is required: rootUrls
|
||||
|
||||
With a **public** plugin, your plugin doesn't have a plugin signature level assigned to it yet. A Grafana team member will assign a signature level to your plugin once it has been reviewed and approved. For more information, refer to [Sign a public plugin](#sign-a-public-plugin).
|
||||
If you're trying to sign a **public** plugin, this means that your plugin doesn't have a plugin signature level assigned to it yet. A Grafana team member will assign a signature level to your plugin once it has been reviewed and approved. For more information, refer to [Sign a public plugin](#sign-a-public-plugin).
|
||||
|
||||
### Why do I get a "Field is required: `rootUrls`" error for my private plugin?
|
||||
|
||||
With a **private** plugin, you need to add a `rootUrls` flag to the `plugin:sign` command. The `rootUrls` must match the [root_url]({{< relref "../../setup-grafana/configure-grafana/#root_url" >}}) configuration. For more information, refer to [Sign a private plugin](#sign-a-private-plugin).
|
||||
If you're trying to sign a **private** plugin, this means that you need to add a `rootUrls` flag to the `plugin:sign` command. The `rootUrls` must match the [root_url]({{< relref "../../setup-grafana/configure-grafana/#root_url" >}}) configuration. For more information, refer to [Sign a private plugin](#sign-a-private-plugin).
|
||||
|
||||
If you still get this error, make sure that the API key was generated by a Grafana Cloud account that matches the first part of the plugin ID.
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
---
|
||||
title: Work with data frames
|
||||
title: Working with data frames
|
||||
---
|
||||
|
||||
# Work with data frames
|
||||
# Working with data frames
|
||||
|
||||
The [data frame]({{< relref "data-frames" >}}) is a columnar data structure that allows for efficient querying of large amounts of data. Since data frames are a central concept when developing plugins for Grafana, in this guide we'll look at some ways you can use them.
|
||||
The data frame is a columnar data structure which allows efficient querying of large amounts of data. Since data frames are a central concept when developing plugins for Grafana, in this guide we'll look at some ways you can use them.
|
||||
|
||||
The `DataFrame` interface contains a `name` and an array of `fields` where each field contains the name, type, and the values for the field.
|
||||
The DataFrame interface contains a `name` and an array of `fields` where each field contains the name, type, and the values for the field.
|
||||
|
||||
> **Note:** If you want to migrate an existing plugin to use the data frame format, refer to [Migrate to data frames]({{< relref "migration-guide/#migrate-to-data-frames" >}}).
|
||||
> **Note:** If you're looking to migrate an existing plugin to use the data frame format, refer to [Migrate to data frames]({{< relref "migration-guide/#migrate-to-data-frames" >}}).
|
||||
|
||||
## Create a data frame
|
||||
|
||||
If you build a data source plugin, then you'll most likely want to convert a response from an external API to a data frame. Let's look at how to do this.
|
||||
If you build a data source plugin, then you'll most likely want to convert a response from an external API to a data frame. Let's look at how to create a data frame.
|
||||
|
||||
Let's start with creating a simple data frame that represents a time series. The easiest way to create a data frame is to use the `toDataFrame` function.
|
||||
Let's start with creating a simple data frame that represents a time series. The easiest way to create a data frame is to use the toDataFrame function.
|
||||
|
||||
```ts
|
||||
// Need to be of the same length.
|
||||
@@ -31,9 +31,9 @@ const frame = toDataFrame({
|
||||
});
|
||||
```
|
||||
|
||||
> **Note:** Data frames representing time series contain at least a `time` field and a `number` field. By convention, built-in plugins use `Time` and `Value` as field names for data frames containing time series data.
|
||||
> **Note:** Data frames representing time series contain at least a `time` field, and a `number` field. By convention, built-in plugins use `Time` and `Value` as field names for data frames containing time series data.
|
||||
|
||||
As you can see from the example, to create data frames like this, your data must already be stored as columnar data. If you already have the records in the form of an array of objects, then you can pass it to `toDataFrame`. In this case, `toDataFrame` tries to guess the schema based on the types and names of the objects in the array. To create complex data frames this way, be sure to verify that you get the schema you expect.
|
||||
As you can see from the example, creating data frames like this requires that your data is already stored as columnar data. If you already have the records in the form of an array of objects, then you can pass it to `toDataFrame` which tries to guess the schema based on the types and names of the objects in the array. If you're creating complex data frames this way, then be sure to verify that you get the schema you expect.
|
||||
|
||||
```ts
|
||||
const series = [
|
||||
@@ -57,7 +57,7 @@ function SimplePanel({ data: Props }) {
|
||||
}
|
||||
```
|
||||
|
||||
Before you start reading the data, think about what data you expect. For example, to visualize a time series you need at least one time field and one number field.
|
||||
Before you start reading the data, think about what data you expect. For example, to visualize a time series we'd need at least one time field, and one number field.
|
||||
|
||||
```ts
|
||||
const timeField = frame.fields.find((field) => field.type === FieldType.time);
|
||||
@@ -78,7 +78,7 @@ for (let i = 0; i < frame.length; i++) {
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, you can use the `DataFrameView`, which gives you an array of objects that contain a property for each field in the frame.
|
||||
Alternatively, you can use the DataFrameView, which gives you an array of objects that contain a property for each field in the frame.
|
||||
|
||||
```ts
|
||||
const view = new DataFrameView(frame);
|
||||
@@ -113,7 +113,7 @@ return (
|
||||
);
|
||||
```
|
||||
|
||||
To apply field options to the name of a field, use `getFieldDisplayName`.
|
||||
To apply field options to the name of a field, use getFieldDisplayName.
|
||||
|
||||
```ts
|
||||
const valueField = frame.fields.find((field) => field.type === FieldType.number);
|
||||
|
||||
@@ -9,13 +9,17 @@ weight: 15
|
||||
|
||||
# Logs in Explore
|
||||
|
||||
Along with metrics, Explore allows you to investigate your logs across several data sources including:
|
||||
Along with metrics, Explore allows you to investigate your logs in the following data sources:
|
||||
|
||||
- [Elasticsearch]({{< relref "../datasources/elasticsearch/" >}})
|
||||
- [InfluxDB]({{< relref "../datasources/influxdb/" >}})
|
||||
- [Loki]({{< relref "../datasources/loki/" >}})
|
||||
|
||||
During monitoring, troubleshooting, and incident response, you can dig deeper into the metrics and logs to find the cause of the issue. Explore also allows you to correlate metrics and logs by viewing them side-by-side.
|
||||
During an infrastructure monitoring and incident response, you can dig deeper into the metrics and logs to find the cause. Explore also allows you to correlate metrics and logs by viewing them side-by-side. This creates a new debugging workflow:
|
||||
|
||||
1. Receive an alert.
|
||||
1. Drill down and examine metrics.
|
||||
1. Drill down again and search logs related to the metric and time interval (and in the future, distributed traces).
|
||||
|
||||
## Logs visualization
|
||||
|
||||
@@ -23,7 +27,7 @@ Results of log queries are shown as histograms in the graph and individual logs
|
||||
|
||||
If the data source supports a full range log volume histogram, the graph with log distribution for all entered log queries is shown automatically. This feature is currently supported by Elasticsearch and Loki data sources.
|
||||
|
||||
> **Note:** In Loki, this full range log volume histogram is rendered by metric query which can be expensive depending on time range queried. This query may be particularly challenging for smaller Loki installations to process. To mitigate this, we recommend using a proxy like [nginx](https://www.nginx.com/) in front of Loki to set a custom timeout (for example, 10 seconds) for these queries. Log volume histogram queries can be identified by looking for queries with the HTTP header `X-Query-Tags` with value `Source=logvolhist`; these headers are added by Grafana to all log volume histogram queries.
|
||||
**NOTE:** In Loki, this full range log volume histogram is rendered by metric query which can be expensive depending on time range queried. This query may be particularly challenging for smaller Loki installations to process. To mitigate this, we recommend using a proxy like [nginx](https://www.nginx.com/) in front of Loki to set a custom timeout (e.g. 10 seconds) for these queries. Log volume histogram queries can be identified by looking for queries with the HTTP header `X-Query-Tags` with value `Source=logvolhist`; these headers are added by Grafana to all log volume histogram queries.
|
||||
|
||||
If the data source does not support loading full range log volume histogram, the logs model computes a time series based on the log row counts bucketed by an automatically calculated time interval, and the first log row's timestamp then anchors the start of the histogram from the result. The end of the time series is anchored to the time picker's **To** range.
|
||||
|
||||
@@ -49,7 +53,6 @@ For logs where a level label is specified, we use the value of the label to dete
|
||||
| warning | warning | yellow |
|
||||
| info | info | green |
|
||||
| information | info | green |
|
||||
| informational | info | green |
|
||||
| notice | info | green |
|
||||
| dbug | debug | blue |
|
||||
| debug | debug | blue |
|
||||
@@ -58,7 +61,7 @@ For logs where a level label is specified, we use the value of the label to dete
|
||||
|
||||
## Logs navigation
|
||||
|
||||
Logs navigation, at the right side of the log lines, can be used to request more logs. You can do this by clicking the **Older logs** button at the bottom of the navigation. This is especially useful when you hit the line limit and you want to see more logs. Each request that's run from the navigation is then displayed in the navigation as separate page. Every page shows `from` and `to` timestamps of the incoming log lines. You can see previous results by clicking on the page. Explore caches the last five requests run from the logs navigation, so you're not re-running the same queries when clicking on the pages.
|
||||
Logs navigation next to the log lines can be used to request more logs. You can do this by clicking on Older logs button on the bottom of navigation. This is especially useful when you hit the line limit and you want to see more logs. Each request that is run from the navigation is then displayed in the navigation as separate page. Every page is showing from and to timestamp of the incoming log lines. You can see previous results by clicking on the page. Explore is caching last five requests run from the logs navigation, so you are not re-running the same queries when clicking on the pages.
|
||||
|
||||

|
||||
|
||||
@@ -90,14 +93,13 @@ Log data can be very repetitive and Explore can help by hiding duplicate log lin
|
||||
- **Numbers -** Matches on the line after stripping out numbers such as durations, IP addresses, and so on.
|
||||
- **Signature -** The most aggressive deduplication, this strips all letters and numbers and matches on the remaining whitespace and punctuation.
|
||||
|
||||
### Display results order
|
||||
### Flip results order
|
||||
|
||||
You can change the order of received logs from the default descending order (newest first) to ascending order (oldest first).
|
||||
|
||||
## Labels and detected fields
|
||||
|
||||
Each log line has an extendable area, with its labels and detected fields, for more robust interaction. You can filter for (positive filter) and filter out (negative filter) selected labels. Additionally, you can select a unique field to visualize instead of the whole log line by clicking on the eye icon.
|
||||
Finally, each field or label also has a stats icon to display ad-hoc statistics in relation to all displayed logs.
|
||||
Each log row has an extendable area with its labels and detected fields, for more robust interaction. For all labels we have added the ability to filter for (positive filter) and filter out (negative filter) selected labels. Each field or label also has a stats icon to display ad-hoc statistics in relation to all displayed logs.
|
||||
|
||||
## Escaping newlines
|
||||
|
||||
@@ -110,11 +112,17 @@ To automatically fix incorrectly escaped sequences that Explore has detected:
|
||||
|
||||
Explore replaces these sequences. When it does so, the option will change from "Escape newlines" to "Remove escaping". Evaluate the changes as the parsing may not be accurate based on the input received. You can revert the replacements by clicking "Remove escaping".
|
||||
|
||||
## Data links
|
||||
### Data links
|
||||
|
||||
By using data links, you can turn any part of a log message into an internal or external link. The created link is visible as a button in the **Links** section inside the **Log details** view.
|
||||
{{< figure src="/static/img/docs/explore/data-link-9-4.png" max-width="800px" caption="Data link in Explore" >}}
|
||||
|
||||
### Toggle field visibility
|
||||
|
||||
Expand a log line and click the eye icon to show or hide fields.
|
||||
|
||||
{{< figure src="/static/img/docs/explore/toggle-fields-9-4.gif" max-width="800px" caption="Toggling detected fields in Explore" >}}
|
||||
|
||||
## Loki-specific features
|
||||
|
||||
As mentioned, one of the log integrations is for the new open source log aggregation system from Grafana Labs - [Loki](https://github.com/grafana/loki). Loki is designed to be very cost effective, as it does not index the contents of the logs, but rather a set of labels for each log stream. The logs from Loki are queried in a similar way to querying with label selectors in Prometheus. It uses labels to group log streams which can be made to match up with your Prometheus labels. For more information about Grafana Loki, refer to [Grafana Loki](https://github.com/grafana/loki) or the Grafana Labs hosted variant: [Grafana Cloud Logs](https://grafana.com/loki).
|
||||
@@ -133,7 +141,7 @@ after switching to the Logs data source, the query changes to:
|
||||
|
||||
This will return a chunk of logs in the selected time range that can be grepped/text searched.
|
||||
|
||||
### Logs sample
|
||||
## Logs sample
|
||||
|
||||
If the selected data source implements logs sample, and supports both log and metric queries, then for metric queries you will be able to automatically see samples of log lines that contributed to visualized metrics. This feature is currently supported by Loki data sources.
|
||||
|
||||
@@ -145,4 +153,4 @@ Click the **Live** button in the Explore toolbar to switch to Live tail view.
|
||||
|
||||
While in Live tail view new logs will come from the bottom of the screen and will have fading contrasting background so you can keep track of what is new. Click the **Pause** button or scroll the logs view to pause the Live tailing and explore previous logs without interruption. Click **Resume** button to resume the Live tailing or click **Stop** button to exit Live tailing and go back to standard Explore view.
|
||||
|
||||
{{< figure src="/static/img/docs/v64/explore_live_tailing.gif" class="docs-image--no-shadow" caption="Explore Live tailing in action" >}}```
|
||||
{{< figure src="/static/img/docs/v64/explore_live_tailing.gif" class="docs-image--no-shadow" caption="Explore Live tailing in action" >}}
|
||||
|
||||
@@ -84,7 +84,7 @@ Click the document icon to open a split view in Explore with the configured data
|
||||
The Service Graph view visualizes the span metrics (traces data for rates, error rates, and durations (RED)) and service graphs.
|
||||
Once the requirements are set up, this pre-configured view is immediately available.
|
||||
|
||||
For more information, refer to the [Service Graph view section]({{< relref "../datasources/tempo/#open-the-service-graph-view" >}}) of the Tempo data source page and the [service graph view page](/docs/tempo/latest/metrics-generator/service-graph-view/) in the Tempo documentation.
|
||||
For more information, refer to the [Service Graph view table section](https://grafana.com/docs/grafana/latest/datasources/tempo/#service-graph-view-table) of the Tempo data source page and the [service graph view page](https://grafana.com/docs/tempo/latest/metrics-generator/service-graph-view/) in the Tempo documentation.
|
||||
|
||||
{{< figure src="/static/img/docs/grafana-cloud/apm-overview.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the Service Graph view" >}}
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ weight: 8
|
||||
|
||||
This section provides basic information about observability topics in general and Grafana in particular. These topics will help people who are just starting out with observability and monitoring.
|
||||
|
||||
{{< docs/shared lookup="basics/what-is-grafana.md" source="grafana" version="<GRAFANA VERSION>" >}}
|
||||
{{< docs/shared "basics/what-is-grafana.md" >}}
|
||||
|
||||
{{< docs/shared lookup="basics/grafana-cloud.md" source="grafana" version="<GRAFANA VERSION>" >}}
|
||||
{{< docs/shared "basics/grafana-cloud.md" >}}
|
||||
|
||||
{{< docs/shared lookup="basics/grafana-enterprise.md" source="grafana" version="<GRAFANA VERSION>" >}}
|
||||
{{< docs/shared "basics/grafana-enterprise.md" >}}
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
---
|
||||
description: Learn how Grafana dashboards are built.
|
||||
keywords:
|
||||
- grafana
|
||||
- dashboards
|
||||
- panel
|
||||
- data source
|
||||
- transform
|
||||
- query
|
||||
title: Grafana dashboards overview
|
||||
menuTitle: Dashboard overview
|
||||
weight: 390
|
||||
---
|
||||
|
||||
# Grafana dashboards overview
|
||||
|
||||
Have you ever wondered what a dashboard is? In the observability world, this term is frequently used, but what exactly does it mean? The concept is borrowed from automobiles, where a dashboard gives drivers access to the controls necessary to operate a vehicle. Similarly, digital dashboards help us comprehend and manage systems. This topic explains how Grafana dashboards function, enabling you to create your own with greater ease.
|
||||
|
||||
The following image illustrates a sample Grafana dashboard:
|
||||
|
||||
{{< figure src="/media/docs/grafana/dashboards-overview/complex-dashboard-example.png" max-width="750px" caption="Example Grafana dashboard" >}}
|
||||
|
||||
A Grafana dashboard consists of panels displaying data in beautiful graphs, charts, and other visualizations. These panels are created using components that transform raw data from a data source into visualizations. The process involves passing data through three gates: a plugin, a query, and an optional transformation.
|
||||
|
||||
The image below displays all the gates, followed by detailed explanations of their purpose, usage, and significance.
|
||||
|
||||
{{< figure src="/media/docs/grafana/dashboards-overview/dashboard-component-architecture.png" max-width="750px" caption="Dashboard component architecture" >}}
|
||||
|
||||
## Data sources
|
||||
|
||||
A data source refers to any entity that consists of data. It can be an SQL database, Grafana Loki, Grafana Mimir, or a JSON-based API. It can even be a basic CSV file. The first step in creating a dashboard visualization is selecting the data source that contains the data you need.
|
||||
|
||||
It can be difficult to understand the distinctions between different data sources as each possesses its own structure and requires different query methods. However, in dashboards, you can see different data sources visualized in one single view, making it easier to understand your data overall.
|
||||
|
||||
## Plugins
|
||||
|
||||
A Grafana plugin is software that adds new capabilities to Grafana. They come in many types, but right now we'll address _data source plugins_. The job of a Grafana data source plugin is to take a query you want answered, retrieve the data from the data source, and reconcile the differences between the data model of the data source and the data model of Grafana dashboards. It does this using a unified data structure called a [data frame][data-frames].
|
||||
|
||||
The data coming into the plugin from the data source might be in many different formats (such as JSON, rows and columns, or CSV), but when it leaves the plugin and moves through the rest of the gates toward a visualization, it's always in data frames.
|
||||
|
||||
Currently, Grafana offers a diverse range of 155 data sources that you can use. The most commonly used options are already pre-installed and accessible. Before exploring other options, look for an existing data source that matches your requirements. Grafana constantly updates the list, but if you don't find a suitable data source, you can browse through the [plugin catalog](/grafana/plugins/?type=datasource) or [create a plugin](/tutorials/build-a-data-source-plugin/).
|
||||
|
||||
## Queries
|
||||
|
||||
Queries allow you to reduce the entirety of your data to a specific dataset, providing a more manageable visualization. They help answer questions you have about system and operational processes. For instance, a company with an online store might want to determine the number of customers who add products to their shopping carts. This can be achieved through a query that aggregates access metrics for the shopping cart service, revealing the number of users accessing the service per second.
|
||||
|
||||
When working with data sources, it's crucial to recognize that each one has its own distinct query language. For example, Prometheus data sources utilize [PromQL](/blog/2020/02/04/introduction-to-promql-the-prometheus-query-language/), while [LogQL](/docs/loki/latest/logql/) is used for logs, and particular databases employ SQL. A query is the foundation of every visualization in Grafana, and a dashboard might use a range of query languages.
|
||||
|
||||
The following image shows the Query Editor associated with the Prometheus data source. The `node_cpu_seconds_total` query is written in PromQL and requests just one metric:
|
||||
|
||||
{{< figure src="/media/docs/grafana/dashboards-overview/example-query.png" max-width="750px" caption="Example query" >}}
|
||||
|
||||
## Transformations
|
||||
|
||||
When the data format in a visualization doesn’t meet your requirements, you can apply a [transformation][transform-data] that manipulates the data returned by a query.
|
||||
You might not need to transform data when you're first starting out, but they're powerful and worth mentioning.
|
||||
|
||||
Transforming data is useful in the following kinds of situations:
|
||||
|
||||
- You want to combine two fields together, for example, concatenating `Given Name` and `Family Name` into a `Full Name` field.
|
||||
- You have CSV data (all text), and you want to convert a field type (such as parsing a date or a number out of a string).
|
||||
- You want to filter, join, merge, or perform other SQL-like operations that might not be supported by the underlying data source or query language.
|
||||
|
||||
Transformations are located in the **Transform** tab in the edit dialog for a panel. Select the transformation you want, and define the transformation. The following image shows that you can have as many transformations as you want, just like queries. For example, you can chain together a series of transformations that make a change to a data type, filter results, organize columns, and sort the result into one data pipeline. Every time the dashboard is refreshed, the transformation applies to the latest data from the data source.
|
||||
|
||||
The following image shows the transformation dialog:
|
||||
|
||||
{{< figure src="/media/docs/grafana/dashboards-overview/example-transform-chain.png" max-width="750px" caption="Example chain of transformations" >}}
|
||||
|
||||
## Panels
|
||||
|
||||
After the data is sourced, queried, and transformed, it passes to a panel, which is the final gate in the journey to a Grafana visualization. A panel is a container that displays the visualization and provides you with various controls to manipulate it. The panel configuration is where you specify how you want to see the data. For example, you use a drop-down menu in the top-right of the panel to specify the type of visualization you want to see, such as a bar chart, pie chart, or histogram.
|
||||
|
||||
The panel options let you customize many aspects of the visualization and the options differ based on which visualization you select. Panels also contain queries that specify the data the panel is visualizing.
|
||||
|
||||
The following image shows a table panel being edited, the panel settings showing the query at the bottom, and the panel options on the right. In this image, you can see how the data source, plugin, query, and panel all come together.
|
||||
|
||||
{{< figure src="/media/docs/grafana/dashboards-overview/example-table-panel.png" max-width="750px" caption="Example table panel" >}}
|
||||
|
||||
Selecting the best visualization depends on the data and how you want it presented. To see examples of dashboards in one place that you can browse and inspect, refer to [Grafana Play](https://play.grafana.org/), which has feature showcases and a variety of examples.
|
||||
|
||||
## Conclusion
|
||||
|
||||
With the data source, plugin, query, transformation, and panel model in mind, you can now see right through any Grafana dashboard you encounter, and imagine how to build your own.
|
||||
|
||||
Building a Grafana dashboard is a process that starts with determining your dashboard requirements and identifying which data sources support those requirements. If you want to integrate a specialized database with a Grafana dashboard, you must ensure the correct plugin is installed so that you can add a data source to use with that plugin.
|
||||
|
||||
And with the data source identified and the plugin installed, you can write your query, transform the data, and format the visualization to meet your needs.
|
||||
|
||||
This component architecture is part of what makes Grafana so powerful and general. Given the data source plugin and data frame abstraction, any data source you can access can work with the same general approach.
|
||||
|
||||
{{% docs/reference %}}
|
||||
[data-frames]: "/docs/grafana/ -> /docs/grafana/<GRAFANA VERSION>/developers/plugins/data-frames"
|
||||
[data-frames]: "/docs/grafana-cloud/ -> /docs/grafana/<GRAFANA VERSION>/developers/plugins/data-frames"
|
||||
|
||||
[transform-data]: "/docs/grafana/ -> /docs/grafana/<GRAFANA VERSION>/panels-visualizations/query-transform-data/transform-data"
|
||||
[transform-data]: "/docs/grafana-cloud/ -> /docs/grafana/<GRAFANA VERSION>/panels-visualizations/query-transform-data/transform-data"
|
||||
{{% /docs/reference %}}
|
||||
@@ -8,9 +8,8 @@ keywords:
|
||||
- concepts
|
||||
- exemplars
|
||||
- prometheus
|
||||
menuTitle: Exemplars
|
||||
title: Introduction to exemplars
|
||||
weight: 800
|
||||
title: Exemplars
|
||||
weight: 400
|
||||
---
|
||||
|
||||
# Introduction to exemplars
|
||||
@@ -23,7 +22,7 @@ To identify the factors that are contributing to the latency, you must compare a
|
||||
|
||||
Use exemplars to help isolate problems within your data distribution by pinpointing query traces exhibiting high latency within a time interval. Once you localize the latency problem to a few exemplar traces, you can combine it with additional system based information or location properties to perform a root cause analysis faster, leading to quick resolutions to performance issues.
|
||||
|
||||
Support for exemplars is available for the Prometheus data source only. Once you enable the functionality, exemplar data is available by default. For more information on exemplar configuration and how to enable exemplars, refer to [configuring exemplars in the Prometheus data source]({{< relref "../../datasources/prometheus/#configure-exemplars" >}}).
|
||||
Support for exemplars is available for the Prometheus data source only. Once you enable the functionality, exemplars data is available by default. For more information on exemplar configuration and how to enable exemplars, refer to [configuring exemplars in Prometheus data source]({{< relref "../../datasources/prometheus/#configuring-exemplars" >}}).
|
||||
|
||||
Grafana shows exemplars alongside a metric in the Explore view and in dashboards. Each exemplar displays as a highlighted star. You can hover your cursor over an exemplar to view the unique traceID, which is a combination of a key value pair. To investigate further, click the blue button next to the `traceID` property.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ keywords:
|
||||
- glossary
|
||||
- dictionary
|
||||
title: Glossary
|
||||
weight: 850
|
||||
weight: 800
|
||||
---
|
||||
|
||||
# Glossary
|
||||
|
||||
@@ -9,9 +9,8 @@ keywords:
|
||||
- panel
|
||||
- documentation
|
||||
- histogram
|
||||
menuTitle: Histograms and heatmaps
|
||||
title: Introduction to histograms and heatmaps
|
||||
weight: 650
|
||||
title: Histograms and heatmaps
|
||||
weight: 700
|
||||
---
|
||||
|
||||
# Introduction to histograms and heatmaps
|
||||
@@ -33,7 +32,7 @@ Here is an example showing height distribution of people.
|
||||
|
||||
{{< figure src="/static/img/docs/histogram-panel/histogram-example-v8-0.png" max-width="625px" caption="Bar chart example" >}}
|
||||
|
||||
For more information about histogram visualization options, refer to [Histogram][histogram].
|
||||
For more information about histogram visualization options, refer to [Histogram]({{< relref "../../panels-visualizations/visualizations/histogram/" >}}).
|
||||
|
||||
Histograms only look at _value distributions_ over a specific time range. The problem with histograms is that you cannot see any trends or changes in the distribution over time. This is where heatmaps become useful.
|
||||
|
||||
@@ -45,7 +44,7 @@ In this example, you can clearly see what values are more common and how they tr
|
||||
|
||||

|
||||
|
||||
For more information about heatmap visualization options, refer to [Heatmap][heatmap].
|
||||
For more information about heatmap visualization options, refer to [Heatmap]({{< relref "../../panels-visualizations/visualizations/heatmap/" >}}).
|
||||
|
||||
## Pre-bucketed data
|
||||
|
||||
@@ -69,11 +68,3 @@ supports doing histogram bucketing on the raw data.
|
||||
If you remove or lower the group by time (or raise maxDataPoints) in your query to return more data points, your heatmap will be
|
||||
more accurate, but this can also be very CPU and memory taxing for your browser, possibly causing hangs or crashes if the number of
|
||||
data points becomes unreasonably large.
|
||||
|
||||
{{% docs/reference %}}
|
||||
[heatmap]: "/docs/grafana/ -> /docs/grafana/<GRAFANA VERSION>/panels-visualizations/visualizations/heatmap"
|
||||
[heatmap]: "/docs/grafana-cloud/ -> /docs/grafana/<GRAFANA VERSION>/panels-visualizations/visualizations/heatmap"
|
||||
|
||||
[histogram]: "/docs/grafana/ -> /docs/grafana/<GRAFANA VERSION>/panels-visualizations/visualizations/histogram"
|
||||
[histogram]: "/docs/grafana-cloud/ -> /docs/grafana/<GRAFANA VERSION>/panels-visualizations/visualizations/histogram"
|
||||
{{% /docs/reference %}}
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- ../basics/timeseries/
|
||||
description: Introduction to Prometheus
|
||||
keywords:
|
||||
- grafana
|
||||
- intro
|
||||
- Prometheus
|
||||
- metrics
|
||||
- time series
|
||||
title: What is Prometheus?
|
||||
weight: 300
|
||||
---
|
||||
|
||||
# What is Prometheus?
|
||||
|
||||
Observability focuses on understanding the internal state of your systems based on the data they produce, which helps determine if your infrastructure is healthy. Prometheus is a core technology for system observability, but the term "Prometheus" can be confusing because it is used in different contexts. Understanding Prometheus basics, why it’s valuable for system observability, and how people use it in practice will both help you better understand it and help you use Grafana.
|
||||
|
||||
Prometheus began in 2012 at SoundCloud because existing technologies were insufficient for their observability needs. Prometheus offers both a robust data model and a query language, which are discussed on this page. Prometheus is also simple and scalable. In 2018, Prometheus graduated from Cloud Native Computing Foundation (CNCF) incubation, and today has a thriving community.
|
||||
|
||||
## Prometheus as data
|
||||
|
||||
The following panel in a Grafana dashboard shows how much disk bandwidth on a Mac laptop is being used. The green line represents disk `reads`, and the yellow line represents `writes`.
|
||||
|
||||
{{< figure src="/media/docs/grafana/intro-prometheus/disk-io.png" max-width="750px" caption="Disk I/O dashboard" >}}
|
||||
|
||||
Data like these form _time series_. The X-axis is a moment in time and the Y-axis is a number or measurement; for example, 5 megabytes per second. This type of time series data appears everywhere in systems monitoring, as well as in places such as seasonal temperature charts and stock prices. This data is simply some measurement (such as a company stock price or Disk I/O) through a series of time instants.
|
||||
|
||||
Prometheus is a technology that collects and stores time series data. Time series are fundamental to Prometheus; its [data model](https://prometheus.io/docs/concepts/data_model/) is arranged into:
|
||||
|
||||
- _metrics_ that consist of a _timestamp_ and a _sample_, which is the numeric value, such as how many disk bytes have been read or a stock price
|
||||
- a set of labels called _dimensions_, for example, `job` and `device`
|
||||
|
||||
You can store time series data in any relational database, but these kinds of systems are not developed to store and query large volumes of time series data. Prometheus and similar software provide tools to compact and optimize time series data.
|
||||
|
||||
### Simple dashboard using PromQL
|
||||
|
||||
The following Grafana dashboard image shows a Disk I/O graph of raw data from Prometheus derived from a laptop.
|
||||
|
||||
The **Metrics browser** field contains the following query:
|
||||
|
||||
`node_disk_written_bytes_total{job="integrations/macos-node", device!=""}`
|
||||
|
||||
In this example, the Y-axis shows the total number of bytes written, and the X-axis shows dates and times. As the laptop runs, the number of bytes written increases over time. Below **Metrics browser** is a counter that counts the number of bytes written over time.
|
||||
|
||||
{{< figure src="/media/docs/grafana/intro-prometheus/dashboard-example.png" max-width="750px" caption="Metrics browser and counter" >}}
|
||||
|
||||
The query is a simple example of [PromQL](/blog/2020/02/04/introduction-to-promql-the-prometheus-query-language/), the Prometheus Query Language. The query identifies the metric of interest (`node_disk_written_bytes_total`) and provides two labels (`job` and `device`). The label selector `job="integrations/macos-node"` filters metrics. It both reduces the scope of the metrics to those coming from the MacOS integration job and specifies that the “device” label cannot be empty. The result of this query is the raw stream of numbers that the graph displays.
|
||||
|
||||
Although this view provides some insight into the performance of the system, it doesn’t provide the full story. A clearer picture of system performance requires understanding the rate of change that displays _how fast the data being written is changing_. To properly monitor disk performance, you need to also see spikes in activity that illustrate if and when the system is under load, and whether disk performance is at risk. PromQL includes a [rate()](https://prometheus.io/docs/prometheus/latest/querying/functions/#rate) function that shows the per-second average rate of increase over `5m` (5-minute) intervals. This view provides a much clearer picture of what’s happening with the system.
|
||||
|
||||
{{< figure src="/media/docs/grafana/intro-prometheus/rate-function.png" max-width="750px" caption="Prometheus rate function" >}}
|
||||
|
||||
A counter metric is just one type of metric; it is a number (such as total bytes written) that only increases. Prometheus [supports several others](https://prometheus.io/docs/concepts/metric_types/), such as the metric type `gauge`, which can increase or decrease.
|
||||
|
||||
The following gauge visualization displays the total RAM usage on a computer.
|
||||
|
||||
{{< figure src="/media/docs/grafana/intro-prometheus/gauge-example.png" max-width="750px" caption="Gauge visualization" >}}
|
||||
|
||||
The third metric type is called a `histogram`, which counts observations and organizes them into configurable groups. The following example displays floating-point numbers grouped into ranges that display how frequently each occurred.
|
||||
|
||||
{{< figure src="/media/docs/grafana/intro-prometheus/histogram-example.png" max-width="750px" caption="Historgram visualization" >}}
|
||||
|
||||
These core concepts of time series, metrics, labels, and aggregation functions are foundational to Grafana and observability.
|
||||
|
||||
## Why this is valuable
|
||||
|
||||
Software and systems are a difficult business. Sometimes things go wrong. Observability helps you understand a system’s state so that issues can be quickly identified and proactively addressed. And when problems do occur, you can be alerted to them to diagnose and solve them within your Service Level Objectives (SLOs).
|
||||
|
||||
The [three pillars of observability](https://www.oreilly.com/library/view/distributed-systems-observability/9781492033431/ch04.html) are metrics, logs, and traces. Prometheus supports the metrics pillar. When software on a computer runs slowly, observability can help you identify whether CPU is saturated, the system is out of memory, or if the disk is writing at maximum speed so you can proactively respond.
|
||||
|
||||
## Prometheus as software
|
||||
|
||||
Prometheus isn’t just a data format; it is also considered an [open source systems monitoring and alerting toolkit](https://prometheus.io/docs/introduction/overview/). That’s because Prometheus is software, not just data.
|
||||
|
||||
Prometheus can scrape metric data from software and infrastructure and store it. Scraping means that Prometheus software periodically revisits the same endpoint to check for new data. Prometheus scrapes data from a piece of software instrumented with a client library.
|
||||
|
||||
For example, a NodeJS application can configure the [prom-client](https://github.com/siimon/prom-client) to expose metrics easily at an endpoint, and Prometheus can regularly scrape that endpoint. Prometheus includes a number of other tools within the toolkit to instrument your applications.
|
||||
|
||||
## Prometheus as deployment
|
||||
|
||||
The first section of this document introduced the Prometheus as Data concept and how the Prometheus data model and metrics are organized. The second section introduced the concept of Prometheus as Software that is used to collect, process, and store metrics. This section describes how Prometheus as Data and Prometheus as Software come together.
|
||||
|
||||
Consider the following example. Suppose a 'MyApp' application uses a Prometheus client to expose metrics. One approach to collecting metrics data is to use a URL in the application that points to an endpoint `http://localhost:3000/metrics` that produces Prometheus metrics data.
|
||||
|
||||
The following image shows the two metrics associated with the endpoint. The HELP text explains what the metric means, and the TYPE text indicates what kind of metric it is (in this case, a gauge). `MyAppnodejs_active_request_total` indicates the number of requests (in this case, `1`). `MyAppnodejs_heap_size_total_bytes` indicates the heap size reported in bytes. There are only two numbers because this data shows the value at the moment the data was fetched.
|
||||
|
||||
{{< figure src="/media/docs/grafana/intro-prometheus/endpoint-data.png" max-width="750px" caption="Endpoint example" >}}
|
||||
|
||||
The 'MyApp' metrics are available in an HTTP endpoint, but how do they get to Grafana, and subsequently, into a dashboard? The process of recording and transmitting the readings of an application or piece of infrastructure is known as _telemetry_. Telemetry is critical to observability because it helps you understand exactly what's going on in your infrastructure. The metrics introduced previously, for example, `MyAppnodejs_active_requests_total`, are telemetry data.
|
||||
|
||||
To get metrics into Grafana, you can use either the Prometheus software or [Grafana Agent](/docs/agent/latest/) to scrape metrics. Grafana Agent collects and forwards the telemetry data to open-source deployments of the Grafana Stack, Grafana Cloud, or Grafana Enterprise, where your data can be analyzed. For example, you can configure Grafana Agent to pull the data from 'MyApp' every five seconds and send the results to Grafana Cloud.
|
||||
|
||||
Metrics data is only one type of telemetry data; the other kinds are logs and traces. Using Grafana Agent can be a great option to send telemetry data because as you scale your observability practices to include logs and traces, which Grafana Agent also supports, you've got a solution already in place.
|
||||
|
||||
The following image illustrates how Grafana Agent works as an intermediary between 'MyApp' and Grafana Cloud.
|
||||
|
||||
{{< figure src="/media/docs/grafana/intro-prometheus/grafana-agent.png" max-width="750px" caption="Grafana Agent" >}}
|
||||
|
||||
## Bringing it together
|
||||
|
||||
The combination of Prometheus and Grafana Agent gives you control over the metrics you want to report, where they come from, and where they’re going. Once the data is in Grafana, it can be stored in a Grafana Mimir database. Grafana dashboards consist of visualizations populated by data queried from the Prometheus data source. The PromQL query filters and aggregates the data to provide you the insight you need. With those steps, we’ve gone from raw numbers, generated by software, into Prometheus, delivered to Grafana, queried by PromQL, and visualized by Grafana.
|
||||
|
||||
## What’s next?
|
||||
|
||||
Now that you understand how Prometheus metrics work, what will you build?
|
||||
|
||||
- One great next step is to [build a dashboard][build-dashboards] in Grafana and start turning that raw Prometheus telemetry data into insights about what’s going with your services and infrastructure.
|
||||
- Another great step is to learn about [Grafana Mimir](/oss/mimir/), which is essentially a database for Prometheus data. If you’re wondering how to make this work for a large volumes of metrics with a lot of data and fast querying, check out Grafana Mimir.
|
||||
- If you’re interested in working with Prometheus data in Grafana directly, check out the [Prometheus data source][prometheus] documentation, or check out [PromQL basics](https://prometheus.io/docs/prometheus/latest/querying/basics/).
|
||||
|
||||
{{% docs/reference %}}
|
||||
[build-dashboards]: "/docs/grafana/ -> /docs/grafana/<GRAFANA VERSION>/dashboards/build-dashboards"
|
||||
[build-dashboards]: "/docs/grafana-cloud/ -> /docs/grafana/<GRAFANA VERSION>/dashboards/build-dashboards"
|
||||
|
||||
[prometheus]: "/docs/grafana/ -> /docs/grafana/<GRAFANA VERSION>/datasources/prometheus"
|
||||
[prometheus]: "/docs/grafana-cloud/ -> /docs/grafana/<GRAFANA VERSION>/datasources/prometheus"
|
||||
{{% /docs/reference %}}
|
||||
@@ -3,6 +3,7 @@ aliases:
|
||||
- ../basics/timeseries-dimensions/
|
||||
- ../getting-started/timeseries-dimensions/
|
||||
- ../guides/timeseries-dimensions/
|
||||
- /docs/rafana/latest/fundamentals/timeseries-dimensions/
|
||||
description: time series dimensions
|
||||
keywords:
|
||||
- grafana
|
||||
@@ -12,12 +13,12 @@ keywords:
|
||||
- timeseries
|
||||
- labels
|
||||
title: Time series dimensions
|
||||
weight: 500
|
||||
weight: 600
|
||||
---
|
||||
|
||||
# Time series dimensions
|
||||
|
||||
In [Introduction to time series][time-series-databases], the concept of _labels_, also called _tags_, is introduced:
|
||||
In [Introduction to time series]({{< relref "timeseries/#time-series-databases" >}}), the concept of _labels_, also called _tags_, is introduced:
|
||||
|
||||
> Another feature of a TSDB is the ability to filter measurements using _tags_. Each data point is labeled with a tag that adds context information, such as where the measurement was taken.
|
||||
|
||||
@@ -85,24 +86,10 @@ In this case the labels that represent the dimensions will have two keys based o
|
||||
|
||||
> **Note:** More than one dimension is currently only supported in the Logs queries within the Azure Monitor service as of version 7.1.
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
Multiple dimensions are not supported in a way that maps to multiple alerts in Grafana, but rather they are treated as multiple conditions to a single alert.
|
||||
For more information, see the documentation on [creating alerts with multiple series][create-grafana-managed-rule].
|
||||
{{% /admonition %}}
|
||||
> **Note:** Multiple dimensions are not supported in a way that maps to multiple alerts in Grafana, but rather they are treated as multiple conditions to a single alert. For more information, see See the documentation on [creating alerts with multiple series]({{< relref "../../alerting/alerting-rules/create-grafana-managed-rule/#single-and-multi-dimensional-rule" >}}).
|
||||
|
||||
### Multiple values
|
||||
|
||||
In the case of SQL-like data sources, more than one numeric column can be selected, with or without additional string columns to be used as dimensions. For example, `AVG(Temperature) AS AvgTemp, MAX(Temperature) AS MaxTemp`. This, if combined with multiple dimensions, can result in a lot of series. Selecting multiple values is currently only designed to be used with visualization.
|
||||
|
||||
Additional technical information on tabular time series formats and how dimensions are extracted can be found in [the developer documentation on data frames as time series][data-frames-as-time-series].
|
||||
|
||||
{{% docs/reference %}}
|
||||
[create-grafana-managed-rule]: "/docs/grafana/ -> /docs/grafana/<GRAFANA VERSION>/alerting/alerting-rules/create-grafana-managed-rule#single-and-multi-dimensional-rule"
|
||||
[create-grafana-managed-rule]: "/docs/grafana-cloud/ -> /docs/grafana/<GRAFANA VERSION>/alerting/alerting-rules/create-grafana-managed-rule#single-and-multi-dimensional-rule"
|
||||
|
||||
[data-frames-as-time-series]: "/docs/grafana/ -> docs/grafana/<GRAFANA VERSION>/developers/plugins/data-frames#data-frames-as-time-series"
|
||||
[data-frames-as-time-series]: "/docs/grafana-cloud/ -> docs/grafana/<GRAFANA VERSION>/developers/plugins/data-frames#data-frames-as-time-series"
|
||||
|
||||
[time-series-databases]: "/docs/grafana/ -> /docs/grafana/<GRAFANA VERSION>/fundamentals/timeseries#time-series-databases"
|
||||
[time-series-databases]: "/docs/grafana-cloud/ -> /docs/grafana/<GRAFANA VERSION>/fundamentals/timeseries#time-series-databases"
|
||||
{{% /docs/reference %}}
|
||||
Additional technical information on tabular time series formats and how dimensions are extracted can be found in [the developer documentation on data frames as time series]({{< relref "../../developers/plugins/data-frames/#data-frames-as-time-series" >}}).
|
||||
|
||||
@@ -10,7 +10,7 @@ weight: 200
|
||||
|
||||
# Build your first dashboard
|
||||
|
||||
This topic helps you get started with Grafana and build your first dashboard using the built-in `Grafana` data source. To learn more about Grafana, refer to [Introduction to Grafana]({{< relref "../introduction/" >}}).
|
||||
This topic helps you get started with Grafana and build your first dashboard. To learn more about Grafana, refer to [What is Grafana?]({{< relref "_index.md" >}}).
|
||||
|
||||
> **Note:** Grafana also offers a [free account with Grafana Cloud](https://grafana.com/signup/cloud/connect-account?pg=gsdocs) to help getting started even easier and faster. You can install Grafana to self-host or get a free Grafana Cloud account.
|
||||
|
||||
@@ -37,9 +37,7 @@ To sign in to Grafana for the first time:
|
||||
|
||||
#### Create a dashboard
|
||||
|
||||
If you've already set up a data source that you know how to query, refer to [Create a dashboard]({{< relref "../dashboards/build-dashboards/create-dashboard/" >}}) instead.
|
||||
|
||||
To create your first dashboard using the built-in `Grafana` data source:
|
||||
To create your first dashboard:
|
||||
|
||||
1. Click the **New dashboard** item under the **Dashboards** icon in the side menu.
|
||||
1. On the dashboard, click **Add a new panel**.
|
||||
@@ -48,15 +46,8 @@ To create your first dashboard using the built-in `Grafana` data source:
|
||||
|
||||
This generates the Random Walk dashboard.
|
||||
|
||||
1. Click the Refresh dashboard icon to query the data source.
|
||||
|
||||

|
||||
|
||||
1. When you've finished editing your panel, click **Save** to save the dashboard.
|
||||
|
||||
Alternatively, click **Apply** if you want to see your changes applied to the dashboard first. Then click the save icon in the dashboard header.
|
||||
|
||||
1. Add a descriptive name for the dashboard, and then click **Save**.
|
||||
1. Click the **Save** icon in the top right corner of your screen to save the dashboard.
|
||||
1. Add a descriptive name, and then click **Save**.
|
||||
|
||||
Congratulations, you have created your first dashboard and it is displaying results.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ weight: 400
|
||||
|
||||
# Get started with Grafana and InfluxDB
|
||||
|
||||
{{< docs/shared lookup="influxdb/intro.md" source="grafana" version="<GRAFANA VERSION>" >}}
|
||||
{{< docs/shared "influxdb/intro.md" >}}
|
||||
|
||||
#### Get InfluxDB
|
||||
|
||||
|
||||
@@ -9,5 +9,3 @@ weight: 300
|
||||
# Grafana Cloud
|
||||
|
||||
Grafana Cloud is a highly available, fast, fully-managed OpenSaaS logging and metrics platform. It is everything you love about Grafana, hosted by Grafana Labs.
|
||||
|
||||
Visit the [Grafana Cloud documentation](/docs/grafana-cloud) for more information.
|
||||
|
||||
@@ -13,13 +13,13 @@ weight: 200
|
||||
|
||||
Grafana Enterprise is a commercial edition of Grafana that includes additional features not found in the open source version.
|
||||
|
||||
Building on everything you already know and love about Grafana open source, Grafana Enterprise includes [exclusive datasource plugins]({{< relref "#enterprise-data-sources" >}}) and [additional features]({{< relref "#enterprise-features" >}}). You also get 24x7x365 support and training from the core Grafana team.
|
||||
Building on everything you already know and love about Grafana open source, Grafana Enterprise includes [exclusive datasource plugins]({{< relref "#enterprise-plugins">}}) and [additional features]({{< relref "#enterprise-features">}}). You also get 24x7x365 support and training from the core Grafana team.
|
||||
|
||||
To learn more about Grafana Enterprise, refer to [our product page](/enterprise).
|
||||
To learn more about Grafana Enterprise, refer to [our product page](https://grafana.com/enterprise).
|
||||
|
||||
## Enterprise features in Grafana Cloud
|
||||
|
||||
Many Grafana Enterprise features are also available in [Grafana Cloud](/docs/grafana-cloud) Free, Pro, and Advanced accounts. For details, refer to [the Grafana Cloud features table](/pricing/#featuresTable).
|
||||
Many Grafana Enterprise features are also available in [Grafana Cloud](/docs/grafana-cloud) Pro and Advanced accounts. For details, refer to [the Grafana Cloud features table](https://grafana.com/pricing/#featuresTable).
|
||||
|
||||
## Authentication
|
||||
|
||||
@@ -27,74 +27,69 @@ Grafana Enterprise includes integrations with more ways to authenticate your use
|
||||
|
||||
### Team sync
|
||||
|
||||
[Team sync]({{< relref "../setup-grafana/configure-security/configure-team-sync" >}}) allows you to set up synchronization between teams in Grafana and teams in your auth provider so that your users automatically end up in the right team.
|
||||
[Team sync]({{< relref "../setup-grafana/configure-security/configure-team-sync/" >}}) allows you to set up synchronization between teams in Grafana and teams in your auth provider so that your users automatically end up in the right team.
|
||||
|
||||
Supported auth providers:
|
||||
|
||||
- [Auth Proxy]({{< relref "../setup-grafana/configure-security/configure-authentication/auth-proxy#team-sync-enterprise-only" >}})
|
||||
- [Azure AD OAuth]({{< relref "../setup-grafana/configure-security/configure-authentication/azuread#team-sync-enterprise-only" >}})
|
||||
- [GitHub OAuth]({{< relref "../setup-grafana/configure-security/configure-authentication/github#configure-team-synchronization" >}})
|
||||
- [GitLab OAuth]({{< relref "../setup-grafana/configure-security/configure-authentication/gitlab#configure-team-synchronization" >}})
|
||||
- [LDAP]({{< relref "../setup-grafana/configure-security/configure-authentication/enhanced-ldap#ldap-group-synchronization-for-teams" >}})
|
||||
- [Okta]({{< relref "../setup-grafana/configure-security/configure-authentication/okta#configure-team-synchronization-enterprise-only" >}})
|
||||
- [SAML]({{< relref "../setup-grafana/configure-security/configure-authentication/saml#configure-team-sync" >}})
|
||||
- [Auth Proxy]({{< relref "../setup-grafana/configure-security/configure-authentication/auth-proxy/#team-sync-enterprise-only" >}})
|
||||
- [Azure AD OAuth]({{< relref "../setup-grafana/configure-security/configure-authentication/azuread/#team-sync-enterprise-only" >}})
|
||||
- [GitHub OAuth]({{< relref "../setup-grafana/configure-security/configure-authentication/github/#team-sync-enterprise-only" >}})
|
||||
- [GitLab OAuth]({{< relref "../setup-grafana/configure-security/configure-authentication/gitlab/#team-sync-enterprise-only" >}})
|
||||
- [LDAP]({{< relref "../setup-grafana/configure-security/configure-authentication/enhanced-ldap/#ldap-group-synchronization-for-teams" >}})
|
||||
- [Okta]({{< relref "../setup-grafana/configure-security/configure-authentication/okta/#team-sync-enterprise-only" >}})
|
||||
- [SAML]({{< relref "../setup-grafana/configure-security/configure-authentication/saml/#configure-team-sync" >}})
|
||||
|
||||
### Enhanced LDAP integration
|
||||
|
||||
With [enhanced LDAP integration]({{< relref "../setup-grafana/configure-security/configure-authentication/enhanced-ldap" >}}), you can set up active LDAP synchronization.
|
||||
With [enhanced LDAP integration]({{< relref "../setup-grafana/configure-security/configure-authentication/enhanced-ldap/" >}}), you can set up active LDAP synchronization.
|
||||
|
||||
### SAML authentication
|
||||
|
||||
[SAML authentication]({{< relref "../setup-grafana/configure-security/configure-authentication/saml" >}}) enables users to authenticate with single sign-on services that use Security Assertion Markup Language (SAML).
|
||||
[SAML authentication]({{< relref "../setup-grafana/configure-security/configure-authentication/saml/" >}}) enables users to authenticate with single sign-on services that use Security Assertion Markup Language (SAML).
|
||||
|
||||
### Protected roles
|
||||
|
||||
With [protected roles]({{< relref "../setup-grafana/configure-security/configure-authentication#protected-roles" >}}), you can define user roles that are exempt from being converted from one authentication type to another when changing auth providers.
|
||||
With [protected roles]({{< relref "../setup-grafana/configure-security/configure-authentication/#protected-roles" >}}), you can define user roles that are exempt from being converted from one authentication type to another when changing auth providers.
|
||||
|
||||
## Enterprise features
|
||||
|
||||
Grafana Enterprise adds the following features:
|
||||
|
||||
- [Role-based access control]({{< relref "../administration/roles-and-permissions/access-control" >}}) to control access with role-based permissions.
|
||||
- [Role-based access control]({{< relref "../administration/roles-and-permissions/access-control/" >}}) to control access with role-based permissions.
|
||||
- [Data source permissions]({{< relref "../administration/data-source-management#data-source-permissions" >}}) to restrict query access to specific teams and users.
|
||||
- [Data source query caching]({{< relref "../administration/data-source-management#query-caching" >}}) to temporarily store query results in Grafana to reduce data source load and rate limiting.
|
||||
- [Reporting]({{< relref "../dashboards/create-reports" >}}) to generate a PDF report from any dashboard and set up a schedule to have it emailed to whomever you choose.
|
||||
- [Export dashboard as PDF]({{< relref "../dashboards/share-dashboards-panels#export-dashboard-as-pdf" >}})
|
||||
- [Custom branding]({{< relref "../setup-grafana/configure-grafana/configure-custom-branding" >}}) to customize Grafana from the brand and logo to the footer links.
|
||||
- [Usage insights]({{< relref "../dashboards/assess-dashboard-usage" >}}) to understand how your Grafana instance is used.
|
||||
- [Data source query caching]({{< relref "../administration/data-source-management/#query-caching" >}}) to temporarily store query results in Grafana to reduce data source load and rate limiting.
|
||||
- [Reporting]({{< relref "../dashboards/create-reports/" >}}) to generate a PDF report from any dashboard and set up a schedule to have it emailed to whomever you choose.
|
||||
- [Export dashboard as PDF]({{< relref "../dashboards/share-dashboards-panels/#export-dashboard-as-pdf" >}})
|
||||
- [Custom branding]({{< relref "../setup-grafana/configure-grafana/configure-custom-branding/" >}}) to customize Grafana from the brand and logo to the footer links.
|
||||
- [Usage insights]({{< relref "../dashboards/assess-dashboard-usage/" >}}) to understand how your Grafana instance is used.
|
||||
- [Recorded queries]({{< relref "../administration/recorded-queries" >}}) to see trends over time for your data sources.
|
||||
- [Vault integration]({{< relref "../setup-grafana/configure-security/configure-database-encryption#encrypting-your-database-with-a-key-from-a-key-management-service-kms" >}}) to manage your configuration or provisioning secrets with Vault.
|
||||
- [Auditing]({{< relref "../setup-grafana/configure-security/audit-grafana" >}}) tracks important changes to your Grafana instance to help you manage and mitigate suspicious activity and meet compliance requirements.
|
||||
- [Request security]({{< relref "../setup-grafana/configure-security/configure-request-security" >}}) makes it possible to restrict outgoing requests from the Grafana server.
|
||||
- [Vault integration]({{< relref "../setup-grafana/configure-security/configure-database-encryption/#encrypting-your-database-with-a-key-from-a-key-management-service-kms" >}}) to manage your configuration or provisioning secrets with Vault.
|
||||
- [Auditing]({{< relref "../setup-grafana/configure-security/audit-grafana/" >}}) tracks important changes to your Grafana instance to help you manage and mitigate suspicious activity and meet compliance requirements.
|
||||
- [Request security]({{< relref "../setup-grafana/configure-security/configure-request-security/" >}}) makes it possible to restrict outgoing requests from the Grafana server.
|
||||
- [Settings updates at runtime]({{< relref "../setup-grafana/configure-grafana/settings-updates-at-runtime" >}}) allows you to update Grafana settings at runtime without requiring a restart.
|
||||
|
||||
## Enterprise data sources
|
||||
|
||||
With a Grafana Enterprise license, you also get access to premium data sources, including:
|
||||
|
||||
- [AppDynamics](/grafana/plugins/dlopes7-appdynamics-datasource)
|
||||
- [Azure Devops](/grafana/plugins/grafana-azuredevops-datasource)
|
||||
- [Databricks](/grafana/plugins/grafana-databricks-datasource)
|
||||
- [DataDog](/grafana/plugins/grafana-datadog-datasource)
|
||||
- [Databricks](/grafana/plugins/grafana-databricks-datasource/)
|
||||
- [Dynatrace](/grafana/plugins/grafana-dynatrace-datasource)
|
||||
- [Gitlab](/grafana/plugins/grafana-gitlab-datasource)
|
||||
- [Honeycomb](/grafana/plugins/grafana-honeycomb-datasource)
|
||||
- [Jira](/grafana/plugins/grafana-jira-datasource)
|
||||
- [k6 Cloud App](/grafana/plugins/grafana-k6-app)
|
||||
- [MongoDB](/grafana/plugins/grafana-mongodb-datasource)
|
||||
- [New Relic](/grafana/plugins/grafana-newrelic-datasource)
|
||||
- [Sqlyze Datasource](/grafana/plugins/grafana-odbc-datasource)
|
||||
- [Oracle Database](/grafana/plugins/grafana-oracle-datasource)
|
||||
- [Salesforce](/grafana/plugins/grafana-salesforce-datasource)
|
||||
- [SAP HANA®](/grafana/plugins/grafana-saphana-datasource)
|
||||
- [ServiceNow](/grafana/plugins/grafana-servicenow-datasource)
|
||||
- [Snowflake](/grafana/plugins/grafana-snowflake-datasource)
|
||||
- [Splunk](/grafana/plugins/grafana-splunk-datasource)
|
||||
- [Splunk Infrastructure monitoring (SignalFx)](/grafana/plugins/grafana-splunk-monitoring-datasource)
|
||||
- [Sqlyze](/grafana/plugins/grafana-odbc-datasource/)
|
||||
- [Wavefront](/grafana/plugins/grafana-wavefront-datasource)
|
||||
- [AppDynamics](https://grafana.com/grafana/plugins/dlopes7-appdynamics-datasource)
|
||||
- [Azure Devops](https://grafana.com/grafana/plugins/grafana-azuredevops-datasource)
|
||||
- [DataDog](https://grafana.com/grafana/plugins/grafana-datadog-datasource)
|
||||
- [Dynatrace](https://grafana.com/grafana/plugins/grafana-dynatrace-datasource)
|
||||
- [Gitlab](https://grafana.com/grafana/plugins/grafana-gitlab-datasource)
|
||||
- [Honeycomb](https://grafana.com/grafana/plugins/grafana-honeycomb-datasource)
|
||||
- [Jira](https://grafana.com/grafana/plugins/grafana-jira-datasource)
|
||||
- [MongoDB](https://grafana.com/grafana/plugins/grafana-mongodb-datasource)
|
||||
- [New Relic](https://grafana.com/grafana/plugins/grafana-newrelic-datasource)
|
||||
- [Oracle Database](https://grafana.com/grafana/plugins/grafana-oracle-datasource)
|
||||
- [Salesforce](https://grafana.com/grafana/plugins/grafana-salesforce-datasource)
|
||||
- [SAP HANA®](https://grafana.com/grafana/plugins/grafana-saphana-datasource)
|
||||
- [ServiceNow](https://grafana.com/grafana/plugins/grafana-servicenow-datasource)
|
||||
- [Snowflake](https://grafana.com/grafana/plugins/grafana-snowflake-datasource)
|
||||
- [Splunk](https://grafana.com/grafana/plugins/grafana-splunk-datasource)
|
||||
- [Splunk Infrastructure monitoring (SignalFx)](https://grafana.com/grafana/plugins/grafana-splunk-monitoring-datasource)
|
||||
- [Wavefront](https://grafana.com/grafana/plugins/grafana-wavefront-datasource)
|
||||
|
||||
## Try Grafana Enterprise
|
||||
|
||||
To purchase or obtain a trial license, contact the Grafana Labs [Sales Team](/contact?about=support&topic=Grafana%20Enterprise).
|
||||
To purchase or obtain a trial license, contact the Grafana Labs [Sales Team](https://grafana.com/contact?about=support&topic=Grafana%20Enterprise).
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user