Compare commits

..

3 Commits

Author SHA1 Message Date
Arve Knudsen
b72a0c81b9 CircleCI: Update grabpl
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
2020-04-28 14:19:05 +02:00
Arve Knudsen
37b9ad2efe Release 7.0.0-beta1
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
2020-04-28 11:20:21 +02:00
Arve Knudsen
29a3641147 Update changelogs
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
2020-04-28 11:07:07 +02:00
3743 changed files with 87131 additions and 152436 deletions

View File

@@ -2,12 +2,23 @@ version: 2.1
aliases:
# Workflow filters
- &filter-only-release
branches:
only: chore/test-release-pipeline
tags:
only: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/
- &filter-not-release-or-master
tags:
ignore: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/
branches:
ignore: master
- &filter-only-master
branches:
only: master
- &filter-release
- &filter-master-or-release
branches:
only:
- master
- chore/test-release-pipeline
tags:
only: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/
@@ -18,16 +29,13 @@ executors:
- image: cimg/base:stable
node:
docker:
- image: cimg/node:12.18
- image: cimg/node:12.16
go:
docker:
- image: cimg/go:1.14
e2e:
docker:
- image: srclosson/grafana-plugin-ci-e2e:latest
grafana-build:
docker:
- image: grafana/build-container:1.2.27
- image: grafana/build-container:1.2.15
grafana-publish:
docker:
- image: grafana/grafana-ci-deploy:1.2.5
@@ -42,7 +50,7 @@ commands:
- run:
name: "Install Grafana build pipeline tool"
command: |
VERSION=0.5.16
VERSION=0.3.0
curl -fLO https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v${VERSION}/grabpl
chmod +x grabpl
mv grabpl /tmp
@@ -60,7 +68,7 @@ jobs:
- run:
name: Exit if enterprise and forked PR
command: |
if [[ "<< parameters.edition >>" == "enterprise" && -n "$CIRCLE_PR_NUMBER" ]]; then
if [[ "<< parameters.edition >>" == "enterprise" && -n "$CIRCLE_PR_NUMBER" ]]; then
echo "Nothing to do for forked PRs, so marking this step successful"
circleci step halt
fi
@@ -74,12 +82,16 @@ jobs:
command: |
if [[ -n $CIRCLE_TAG ]]; then
# A release build
/tmp/grabpl build-backend --github-token "${GITHUB_GRAFANABOT_TOKEN}" --edition << parameters.edition >> \
/tmp/grabpl build-backend --edition << parameters.edition >> \
--variants << parameters.variant >> $CIRCLE_TAG
elif [[ $CIRCLE_BRANCH == "chore/test-release-pipeline" ]]; then
# We're testing the release pipeline
/tmp/grabpl build-backend --github-token "${GITHUB_GRAFANABOT_TOKEN}" --edition << parameters.edition >> \
--variants << parameters.variant >> v7.0.0-test
/tmp/grabpl build-backend --edition << parameters.edition >> \
--variants << parameters.variant >> v6.7.0-beta1
else
# A master or PR build
/tmp/grabpl build-backend --edition << parameters.edition >> \
--variants << parameters.variant >> --build-id $CIRCLE_WORKFLOW_ID
fi
- run:
name: Move artifacts
@@ -105,6 +117,13 @@ jobs:
resource_class: large
executor: grafana-build
steps:
- run:
name: Exit if enterprise and forked PR
command: |
if [[ "<< parameters.edition >>" == "enterprise" && -n "$CIRCLE_PR_NUMBER" ]]; then
echo "Nothing to do for forked PRs, so marking this step successful"
circleci step halt
fi
- checkout
- restore_cache:
keys:
@@ -130,14 +149,7 @@ jobs:
- node_modules
- run:
name: Build Grafana frontend
command: |
if [[ -n $CIRCLE_TAG ]]; then
# A release build
/tmp/grabpl build-frontend --github-token "${GITHUB_GRAFANABOT_TOKEN}" --edition << parameters.edition >> $CIRCLE_TAG
elif [[ $CIRCLE_BRANCH == "chore/test-release-pipeline" ]]; then
# We're testing the release pipeline
/tmp/grabpl build-frontend --github-token "${GITHUB_GRAFANABOT_TOKEN}" --edition << parameters.edition >> 7.0.0-test
fi
command: /tmp/grabpl build-frontend --edition << parameters.edition >>
- run:
name: Move artifacts
command: mkdir << parameters.edition >> && cp -r public << parameters.edition >>/
@@ -164,7 +176,7 @@ jobs:
- run:
name: Exit if enterprise and forked PR
command: |
if [[ "<< parameters.edition >>" == "enterprise" && -n "$CIRCLE_PR_NUMBER" ]]; then
if [[ "<< parameters.edition >>" == "enterprise" && -n "$CIRCLE_PR_NUMBER" ]]; then
echo "Nothing to do for forked PRs, so marking this step successful"
circleci step halt
fi
@@ -176,8 +188,7 @@ jobs:
- run:
name: Build internal Grafana plug-ins
command: |
export GRAFANA_API_KEY=$GRAFANA_COM_API_KEY
/tmp/grabpl build-plugins --jobs 2 --edition << parameters.edition >> --sign --signing-admin
/tmp/grabpl build-plugins --jobs 2 --edition << parameters.edition >>
- run:
name: Move artifacts
command: |
@@ -324,6 +335,38 @@ jobs:
command: "./scripts/ci-job-succeeded.sh"
when: on_success
release-next-packages:
executor: grafana-build
steps:
- run:
name: Exit if forked PR
command: |
if [[ -n "$CIRCLE_PR_NUMBER" ]]; then
echo "Nothing to do for forked PRs, so marking this step successful"
circleci step halt
fi
- checkout
- run:
name: CI job started
command: ./scripts/ci-job-started.sh
- run:
name: Bootstrap lerna
command: npx lerna bootstrap
- run:
name: npm - Prepare auth token
command: "echo //registry.npmjs.org/:_authToken=$NPM_TOKEN >> ~/.npmrc"
- run:
name: Release next packages
command: ./scripts/circle-release-next-packages.sh
- run:
name: CI job failed
command: ./scripts/ci-job-failed.sh
when: on_fail
- run:
name: CI job succeeded
command: ./scripts/ci-job-succeeded.sh
when: on_success
package-oss:
executor: grafana-build
steps:
@@ -340,14 +383,24 @@ jobs:
- run:
name: Package Grafana
command: |
# Necessary for signing bundled plugins
export GRAFANA_API_KEY=$GRAFANA_COM_API_KEY
if [[ -n "$CIRCLE_PR_NUMBER" ]]; then
echo Using test GPG key pair since building a forked PR
source scripts/build/gpg-test-vars.sh
fi
if [[ -n $CIRCLE_TAG ]]; then
# A release build
/tmp/grabpl package --github-token "${GITHUB_GRAFANABOT_TOKEN}" --jobs 2 --edition oss --sign $CIRCLE_TAG
/tmp/grabpl package --jobs 2 --edition oss $CIRCLE_TAG
elif [[ $CIRCLE_BRANCH == "chore/test-release-pipeline" ]]; then
# We're testing the release pipeline
/tmp/grabpl package --github-token "${GITHUB_GRAFANABOT_TOKEN}" --jobs 2 --edition oss --sign v7.0.0-test
/tmp/grabpl package --jobs 2 --edition oss v6.7.0-beta1
elif [[ $CIRCLE_BRANCH == "master" ]]; then
# A master build
/tmp/grabpl package --jobs 2 --edition oss --build-id $CIRCLE_WORKFLOW_ID
else
# A PR build
/tmp/grabpl package --jobs 2 --edition oss --build-id $CIRCLE_WORKFLOW_ID --variants \
linux-x64,linux-x64-musl,osx64,win64
fi
- run:
name: Move artifacts
@@ -390,15 +443,19 @@ jobs:
- run:
name: Package Grafana
command: |
# Necessary for signing bundled plugins
export GRAFANA_API_KEY=$GRAFANA_COM_API_KEY
if [[ -n $CIRCLE_TAG ]]; then
# A release build
/tmp/grabpl package --github-token "${GITHUB_GRAFANABOT_TOKEN}" --jobs 2 --edition enterprise --sign $CIRCLE_TAG
/tmp/grabpl package --jobs 2 --edition enterprise $CIRCLE_TAG
elif [[ $CIRCLE_BRANCH == "chore/test-release-pipeline" ]]; then
# We're testing the release pipeline
/tmp/grabpl package --github-token "${GITHUB_GRAFANABOT_TOKEN}" --jobs 2 --edition enterprise --sign v7.0.0-test
/tmp/grabpl package --jobs 2 --edition enterprise v6.7.0-beta1
elif [[ $CIRCLE_BRANCH == "master" ]]; then
# A master build
/tmp/grabpl package --jobs 2 --edition enterprise --build-id $CIRCLE_WORKFLOW_ID
else
# A PR build
/tmp/grabpl package --jobs 2 --edition enterprise --build-id $CIRCLE_WORKFLOW_ID --variants \
linux-x64,linux-x64-musl,osx64,win64
fi
- run:
name: Move artifacts
@@ -474,9 +531,18 @@ jobs:
yarn install --frozen-lockfile --no-progress
yarn storybook:build
if [[ -n "$CIRCLE_PR_NUMBER" ]]; then
echo "Nothing to do for forked PRs, so marking this step successful"
circleci step halt
fi
if [[ $CIRCLE_BRANCH == "chore/test-release-pipeline" ]]; then
# We're testing the release pipeline
echo Testing release
elif [[ $CIRCLE_BRANCH == "master" ]]; then
echo $GCP_GRAFANA_UPLOAD_KEY > /tmp/gcpkey.json
gcloud auth activate-service-account --key-file=/tmp/gcpkey.json
gsutil -m rsync -d -r ./packages/grafana-ui/dist/storybook gs://grafana-storybook/canary
elif [[ -n $CIRCLE_TAG ]]; then
echo $GCP_GRAFANA_UPLOAD_KEY > /tmp/gcpkey.json
gcloud auth activate-service-account --key-file=/tmp/gcpkey.json
@@ -507,7 +573,7 @@ jobs:
- run:
name: Exit if enterprise and forked PR
command: |
if [[ "<< parameters.edition >>" == "enterprise" && -n "$CIRCLE_PR_NUMBER" ]]; then
if [[ "<< parameters.edition >>" == "enterprise" && -n "$CIRCLE_PR_NUMBER" ]]; then
echo "Nothing to do for forked PRs, so marking this step successful"
circleci step halt
fi
@@ -521,15 +587,6 @@ jobs:
# This version is necessary for building cross-platform images
version: 18.09.3
- install-grabpl
- run:
name: Install gcloud SDK
command: |
VERSION=298.0.0
curl -fLO https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-${VERSION}-linux-x86_64.tar.gz
echo 0d58f451331abf43d080fa997c8e580d64897627e30be74f6d8f983ccfabef1e \
google-cloud-sdk-${VERSION}-linux-x86_64.tar.gz | sha256sum --check --strict --status
tar xf google-cloud-sdk-${VERSION}-linux-x86_64.tar.gz
./google-cloud-sdk/install.sh -q
# XXX: Is this necessary?
- run: docker run --privileged linuxkit/binfmt:v0.6
- run:
@@ -539,8 +596,7 @@ jobs:
- run:
name: Build Docker images
command: |
source google-cloud-sdk/path.bash.inc
if [[ -n $CIRCLE_TAG || $CIRCLE_BRANCH == "chore/test-release-pipeline" ]]; then
if [[ -n $CIRCLE_TAG || $CIRCLE_BRANCH == "chore/test-release-pipeline" || $CIRCLE_BRANCH == "master" ]]; then
# It's a full build
/tmp/grabpl build-docker --jobs 4 --edition << parameters.edition >> \
--ubuntu=<< parameters.ubuntu >>
@@ -552,7 +608,7 @@ jobs:
- run:
name: Exit if PR
command: |
if [[ -z $CIRCLE_TAG && $CIRCLE_BRANCH != "chore/test-release-pipeline" ]]; then
if [[ -z $CIRCLE_TAG && $CIRCLE_BRANCH != "chore/test-release-pipeline" && $CIRCLE_BRANCH != "master" ]]; then
echo "Nothing to do for PRs, so marking this step successful"
circleci step halt
fi
@@ -562,9 +618,6 @@ jobs:
if [[ $CIRCLE_BRANCH == "chore/test-release-pipeline" ]]; then
# We're testing the release pipeline
/tmp/grabpl publish-docker --jobs 4 --edition << parameters.edition >> --ubuntu=<< parameters.ubuntu >> --dry-run
elif [[ -n $CIRCLE_TAG ]]; then
# This is a release
/tmp/grabpl publish-docker --jobs 4 --edition << parameters.edition >> --ubuntu=<< parameters.ubuntu >>
else
/tmp/grabpl publish-docker --jobs 4 --edition << parameters.edition >> --ubuntu=<< parameters.ubuntu >>
fi
@@ -578,7 +631,8 @@ jobs:
when: on_success
end-to-end-tests:
executor: e2e
docker:
- image: circleci/node:12-browsers
steps:
- attach_workspace:
at: /tmp/workspace
@@ -605,9 +659,6 @@ jobs:
name: Start grafana-server
command: ./e2e/start-server
background: true
- run:
name: "Wait for Grafana to start"
command: './e2e/wait-for-grafana'
- run:
name: Run end-to-end tests
command: ./e2e/run-suite
@@ -692,7 +743,7 @@ jobs:
- run:
# Important: all words have to be in lowercase, and separated by "\n".
name: exclude known exceptions
command: 'echo -e "unknwon\nreferer\nerrorstring\neror\niam" > words_to_ignore.txt'
command: 'echo -e "unknwon\nreferer\nerrorstring\neror" > words_to_ignore.txt'
- run:
name: check documentation spelling errors
command: "codespell -I ./words_to_ignore.txt docs/"
@@ -710,38 +761,31 @@ jobs:
name: Install Go linters
command: |
pushd /tmp
VERSION=1.28.0
curl -fLO https://github.com/golangci/golangci-lint/releases/download/v${VERSION}/golangci-lint-${VERSION}-linux-amd64.tar.gz
echo 179d34edf4baf6454a7081fbaaf74dc99397a3be8e1a535dee04d835a977bf76 \
golangci-lint-${VERSION}-linux-amd64.tar.gz | sha256sum --check --strict --status
tar -xf golangci-lint-${VERSION}-linux-amd64.tar.gz
sudo mv golangci-lint-${VERSION}-linux-amd64/golangci-lint /usr/local/bin/
curl -fLO https://github.com/golangci/golangci-lint/releases/download/v1.24.0/golangci-lint-1.24.0-linux-amd64.tar.gz
echo 241ca454102e909de04957ff8a5754c757cefa255758b3e1fba8a4533d19d179 \
golangci-lint-1.24.0-linux-amd64.tar.gz | sha256sum --check --strict --status
tar -xf golangci-lint-1.24.0-linux-amd64.tar.gz
sudo mv golangci-lint-1.24.0-linux-amd64/golangci-lint /usr/local/bin/
popd
make scripts/go/bin/revive
make scripts/go/bin/revive scripts/go/bin/gosec
- run:
name: Lint Go
command: |
# To save memory, run in two batches
golangci-lint run -v -j 4 --config scripts/go/configs/ci/.golangci.toml -E deadcode -E depguard -E dogsled \
-E errcheck -E goconst -E golint -E gosec -E gosimple -E govet -E exportloopref -E whitespace \
-E goprintffuncname ./pkg/...
golangci-lint run -v -j 4 --config scripts/go/configs/ci/.golangci.toml -E ineffassign -E gocritic -E nakedret \
-E rowserrcheck -E staticcheck -E structcheck -E typecheck -E unconvert -E unused -E varcheck ./pkg/...
go vet ./pkg/...
golangci-lint run -v -j 4 --config scripts/go/configs/ci/.golangci.yml -E deadcode -E gofmt \
-E gosimple -E ineffassign -E structcheck -E typecheck ./pkg/...
golangci-lint run -v -j 4 --config scripts/go/configs/ci/.golangci.yml -E unconvert -E unused \
-E varcheck -E goconst -E errcheck -E staticcheck ./pkg/...
./scripts/go/bin/revive -formatter stylish -config ./scripts/go/configs/revive.toml ./pkg/...
./scripts/go/bin/revive -formatter stylish -config ./scripts/go/configs/revive-strict.toml \
-exclude ./pkg/plugins/backendplugin/pluginextensionv2/... \
./pkg/services/alerting/... \
./pkg/services/provisioning/datasources/... \
./pkg/services/provisioning/dashboards/... \
./pkg/services/provisioning/notifiers/... \
./pkg/services/provisioning/values/... \
./pkg/plugins/backendplugin/...
./scripts/tidy-check.sh
./pkg/services/provisioning/dashboards/...
./scripts/go/bin/gosec -quiet -exclude=G104,G107,G108,G201,G202,G204,G301,G304,G401,G402,G501 \
-conf=./scripts/go/configs/gosec.json ./pkg/...
test-frontend:
parameters:
edition:
type: string
executor: node
steps:
- checkout
@@ -761,17 +805,9 @@ jobs:
key: v2-yarn-{{ checksum "yarn.lock" }}
paths:
- node_modules
- install-grabpl
- run:
name: frontend tests
command: |
if [[ -n $CIRCLE_TAG ]]; then
# A release build
./scripts/circle-test-frontend.sh --edition << parameters.edition >> $CIRCLE_TAG
elif [[ $CIRCLE_BRANCH == "chore/test-release-pipeline" ]]; then
# We're testing the release pipeline
./scripts/circle-test-frontend.sh --edition << parameters.edition >> v7.0.0-test
fi
command: "./scripts/circle-test-frontend.sh"
- store_test_results:
path: reports/junit
- run:
@@ -785,27 +821,14 @@ jobs:
test-backend:
executor: go
parameters:
edition:
type: string
steps:
- checkout
- run:
name: CI job started
command: "./scripts/ci-job-started.sh"
- install-grabpl
- run:
name: back-end tests
command: |
if [[ -n $CIRCLE_TAG ]]; then
# A release build
/tmp/grabpl test-backend --github-token "${GITHUB_GRAFANABOT_TOKEN}" --edition << parameters.edition >> \
$CIRCLE_TAG
elif [[ $CIRCLE_BRANCH == "chore/test-release-pipeline" ]]; then
# We're testing the release pipeline
/tmp/grabpl test-backend --github-token "${GITHUB_GRAFANABOT_TOKEN}" --edition << parameters.edition >> \
v7.0.0-test
fi
name: build backend and run go tests
command: "./scripts/circle-test-backend.sh"
- run:
name: CI job failed
command: "./scripts/ci-job-failed.sh"
@@ -815,9 +838,59 @@ jobs:
command: "./scripts/ci-job-succeeded.sh"
when: on_success
build-docs-website:
executor: grafana-build
steps:
- checkout
- setup_remote_docker
- run:
name: CI job started
command: "./scripts/ci-job-started.sh"
- run:
name: Install docker
command: |
apt-get update
apt-get install -y docker.io
- run:
name: Build Grafana docs website
command: |
IMAGE=grafana/docs-base@sha256:63758b74e3990ab61e274f5e98da092d5c38378829dad0488aa97c59f0144f34
# In order to copy sources into the remote container, we need to employ a trick of creating a container
# with a volume, that we copy the sources into. Then, we launch the build container, with the volume
# from the other container
docker create -v /hugo/content/docs/grafana --name docs alpine:3.11 /bin/true
docker cp ${PWD}/docs/sources docs:/hugo/content/docs/grafana/latest
docker run --volumes-from docs $IMAGE /bin/bash -c 'make prod'
- run:
name: CI job failed
command: "./scripts/ci-job-failed.sh"
when: on_fail
- run:
name: CI job succeeded
command: "./scripts/ci-job-succeeded.sh"
when: on_success
deploy-to-kubernetes:
description: "Deploy Grafana master Docker image to Kubernetes"
executor: base
steps:
- install-grabpl
- run:
name: Deploy to Kubernetes
command: |
/tmp/grabpl deploy-to-k8s $CIRCLE_WORKFLOW_ID
release-packages:
executor: node
steps:
- run:
name: Exit if forked PR
command: |
if [[ -n "$CIRCLE_PR_NUMBER" ]]; then
echo "Nothing to do for forked PRs, so marking this step successful"
circleci step halt
fi
- checkout
- run:
name: CI job started
@@ -828,14 +901,6 @@ jobs:
- run:
name: npm - Prepare auth token
command: "echo //registry.npmjs.org/:_authToken=$NPM_TOKEN >> ~/.npmrc"
- run:
name: Exit if release pipeline test
command: |
if [[ $CIRCLE_BRANCH == "chore/test-release-pipeline" ]]; then
# We're testing the release pipeline
echo "We're testing the release pipeline, so stopping before publishing"
circleci step halt
fi
- run:
name: Release packages
command: ./scripts/build/release-packages.sh "${CIRCLE_TAG}"
@@ -848,13 +913,7 @@ jobs:
command: "./scripts/ci-job-succeeded.sh"
when: on_success
scan-docker-image:
description: "Scans a docker image for vulnerabilities using trivy"
parameters:
image:
type: string
tag:
type: string
scan-docker-images:
docker:
- image: circleci/buildpack-deps:stretch
steps:
@@ -877,11 +936,29 @@ jobs:
name: Clear trivy cache
command: trivy --clear-cache
- run:
name: Scan Docker image for unkown/low/medium vulnerabilities
command: trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM << parameters.image >>:<< parameters.tag >>
name: Scan grafana/grafana:master
command: trivy --exit-code 1 grafana/grafana:master
- run:
name: Scan Docker image for high/critical vulnerabilities
command: trivy --exit-code 1 --severity HIGH,CRITICAL << parameters.image >>:<< parameters.tag >>
name: Scan grafana/grafana:master-ubuntu
command: trivy --exit-code 1 grafana/grafana:master-ubuntu
- run:
name: Scan grafana/grafana-enterprise:master
command: trivy --exit-code 1 grafana/grafana-enterprise:master
- run:
name: Scan grafana/grafana-enterprise:master-ubuntu
command: trivy --exit-code 1 grafana/grafana-enterprise:master-ubuntu
- run:
name: Scan grafana/grafana:latest
command: trivy --exit-code 1 grafana/grafana:latest
- run:
name: Scan grafana/grafana:latest-ubuntu
command: trivy --exit-code 1 grafana/grafana:latest-ubuntu
- run:
name: Scan grafana/grafana-enterprise:latest
command: trivy --exit-code 1 grafana/grafana-enterprise:latest
- run:
name: Scan grafana/grafana-enterprise:latest-ubuntu
command: trivy --exit-code 1 grafana/grafana-enterprise:latest-ubuntu
- save_cache:
key: vulnerability-db
paths:
@@ -890,194 +967,207 @@ jobs:
workflows:
build-pipeline:
jobs:
# No filters, meaning this job runs for all branches
- build-backend:
filters: *filter-release
filters: *filter-master-or-release
edition: oss
variant: armv6
name: build-oss-backend-armv6
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
filters: *filter-master-or-release
edition: oss
variant: armv7
name: build-oss-backend-armv7
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
filters: *filter-master-or-release
edition: oss
variant: armv7-musl
name: build-oss-backend-armv7-musl
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
filters: *filter-master-or-release
edition: oss
variant: arm64
name: build-oss-backend-arm64
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
filters: *filter-master-or-release
edition: oss
variant: arm64-musl
name: build-oss-backend-arm64-musl
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
# No filters, meaning this job runs for all branches
edition: oss
variant: osx64
name: build-oss-backend-osx64
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
# No filters, meaning this job runs for all branches
edition: oss
variant: win64
name: build-oss-backend-win64
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
# No filters, meaning this job runs for all branches
edition: oss
variant: linux-x64
name: build-oss-backend-linux-x64
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
# No filters, meaning this job runs for all branches
edition: oss
variant: linux-x64-musl
name: build-oss-backend-linux-x64-musl
requires:
- lint-go
- test-backend
- test-frontend
- build-frontend:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-oss-frontend
edition: oss
requires:
- test-backend
- test-frontend
- build-plugins:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-oss-plugins
edition: oss
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
filters: *filter-master-or-release
name: build-enterprise-backend-armv6
edition: enterprise
variant: armv6
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
filters: *filter-master-or-release
name: build-enterprise-backend-armv7
edition: enterprise
variant: armv7
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
filters: *filter-master-or-release
name: build-enterprise-backend-armv7-musl
edition: enterprise
variant: armv7-musl
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
filters: *filter-master-or-release
name: build-enterprise-backend-arm64
edition: enterprise
variant: arm64
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
filters: *filter-master-or-release
name: build-enterprise-backend-arm64-musl
edition: enterprise
variant: arm64-musl
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-enterprise-backend-osx64
edition: enterprise
variant: osx64
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-enterprise-backend-win64
edition: enterprise
variant: win64
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-enterprise-backend-linux-x64
edition: enterprise
variant: linux-x64
requires:
- lint-go
- test-backend
- test-frontend
- build-backend:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-enterprise-backend-linux-x64-musl
edition: enterprise
variant: linux-x64-musl
requires:
- lint-go
- test-backend
- test-frontend
- build-frontend:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-enterprise-frontend
edition: enterprise
requires:
- test-backend
- test-frontend
- build-plugins:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-enterprise-plugins
edition: enterprise
requires:
- lint-go
- test-backend
- test-frontend
- build-release-publisher:
filters: *filter-release
- codespell:
filters: *filter-release
- lint-go:
filters: *filter-release
- shellcheck:
filters: *filter-release
filters: *filter-master-or-release
# No filters, meaning this job runs for all branches
- codespell
# No filters, meaning this job runs for all branches
- lint-go
# No filters, meaning this job runs for all branches
- shellcheck
# No filters, meaning this job runs for all branches
- test-backend:
filters: *filter-release
name: test-oss-backend
edition: oss
requires:
- lint-go
- test-backend:
filters: *filter-release
name: test-enterprise-backend
edition: enterprise
requires:
- lint-go
- test-frontend:
filters: *filter-release
name: test-oss-frontend
edition: oss
- test-frontend:
filters: *filter-release
name: test-enterprise-frontend
edition: enterprise
# No filters, meaning this job runs for all branches
- test-frontend
# No filters, meaning this job runs for all branches
- mysql-integration-test:
filters: *filter-release
requires:
- lint-go
- test-oss-backend
- test-oss-frontend
- test-backend
- test-frontend
- postgres-integration-test:
filters: *filter-release
# No filters, meaning this job runs for all branches
requires:
- lint-go
- test-oss-backend
- test-oss-frontend
- test-backend
- test-frontend
- package-oss:
filters: *filter-release
# No filters, meaning this job runs for all branches
requires:
- build-oss-backend-armv6
- build-oss-backend-armv7
@@ -1089,13 +1179,13 @@ workflows:
- build-oss-backend-linux-x64
- build-oss-backend-linux-x64-musl
- build-oss-frontend
- test-oss-backend
- test-oss-frontend
- test-backend
- test-frontend
- codespell
- shellcheck
- build-oss-plugins
- package-enterprise:
filters: *filter-release
# No filters, meaning this job runs for all branches
requires:
- build-enterprise-backend-armv6
- build-enterprise-backend-armv7
@@ -1107,27 +1197,31 @@ workflows:
- build-enterprise-backend-linux-x64
- build-enterprise-backend-linux-x64-musl
- build-enterprise-frontend
- test-enterprise-backend
- test-enterprise-frontend
- test-backend
- test-frontend
- codespell
- shellcheck
- build-enterprise-plugins
- build-oss-windows-installer:
filters: *filter-release
# No filters, meaning this job runs for all branches
requires:
- package-oss
- build-enterprise-windows-installer:
filters: *filter-release
# No filters, meaning this job runs for all branches
requires:
- package-enterprise
- release-next-packages:
filters: *filter-only-master
requires:
- end-to-end-tests
- release-packages:
filters: *filter-release
filters: *filter-only-release
requires:
- end-to-end-tests
- mysql-integration-test
- postgres-integration-test
- publish-packages:
filters: *filter-release
filters: *filter-master-or-release
name: publish-oss-packages
edition: oss
requires:
@@ -1138,7 +1232,7 @@ workflows:
- postgres-integration-test
- build-release-publisher
- publish-packages:
filters: *filter-release
filters: *filter-master-or-release
name: publish-enterprise-packages
edition: enterprise
requires:
@@ -1149,12 +1243,11 @@ workflows:
- postgres-integration-test
- build-release-publisher
- publish-storybook:
filters: *filter-release
requires:
- test-oss-backend
- test-oss-frontend
- test-backend
- test-frontend
- build-docker-images:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-oss-docker-images
edition: oss
ubuntu: false
@@ -1165,7 +1258,7 @@ workflows:
- package-oss
- build-oss-windows-installer
- build-docker-images:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-oss-ubuntu-docker-images
edition: oss
ubuntu: true
@@ -1176,7 +1269,7 @@ workflows:
- package-oss
- build-oss-windows-installer
- build-docker-images:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-enterprise-docker-images
edition: enterprise
ubuntu: false
@@ -1187,7 +1280,7 @@ workflows:
- package-enterprise
- build-enterprise-windows-installer
- build-docker-images:
filters: *filter-release
# No filters, meaning this job runs for all branches
name: build-enterprise-ubuntu-docker-images
edition: enterprise
ubuntu: true
@@ -1198,9 +1291,18 @@ workflows:
- package-enterprise
- build-enterprise-windows-installer
- end-to-end-tests:
filters: *filter-release
# No filters, meaning this job runs for all branches
requires:
- package-oss
- build-docs-website:
filters: *filter-not-release-or-master
requires:
- mysql-integration-test
- postgres-integration-test
- deploy-to-kubernetes:
filters: *filter-only-master
requires:
- build-enterprise-docker-images
nightly:
triggers:
@@ -1208,8 +1310,4 @@ workflows:
cron: "0 0 * * *"
filters: *filter-only-master
jobs:
- scan-docker-image:
matrix:
parameters:
image: [grafana/grafana, grafana/grafana-enterprise]
tag: [latest, master, latest-ubuntu, master-ubuntu]
- scan-docker-images

View File

@@ -1,8 +0,0 @@
load('scripts/pr.star', 'pr_pipelines')
load('scripts/master.star', 'master_pipelines')
load('scripts/release.star', 'release_pipelines', 'test_release_pipelines')
def main(ctx):
edition = 'oss'
return pr_pipelines(edition=edition) + master_pipelines(edition=edition) + release_pipelines() + \
test_release_pipelines()

2249
.drone.yml

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,3 @@ trim_trailing_whitespace = false
[Makefile]
indent_style = tab
indent_size = 2
[*.star]
indent_size = 4

View File

@@ -1,7 +0,0 @@
node_modules
compiled
build
vendor
devenv
data
dist

View File

@@ -1,13 +1,4 @@
{
"extends": ["@grafana/eslint-config"],
"root": true,
"overrides": [
{
"files": ["packages/grafana-ui/**/*/!(*.story).{ts,tsx}", "public/app/**/*.{ts,tsx}"],
"rules": {
"react-hooks/rules-of-hooks": "off",
"react-hooks/exhaustive-deps": "off"
}
}
]
"root": true
}

45
.github/CODEOWNERS vendored
View File

@@ -12,49 +12,12 @@
# This should make it easy to add new rules without breaking existing ones.
# Documentation owner: Diana Payton
/docs/ @oddlittlebird @achatterjee-grafana
/contribute/ @oddlittlebird @marcusolsson @achatterjee-grafana
/docs/sources/developers/plugins/ @marcusolsson
/docs/ @oddlittlebird
/contribute/ @oddlittlebird @marcusolsson
# @grafana/ui component documentation
*.mdx @marcusolsson @jessover9000
# Backend code
*.go @grafana/backend-platform
go.mod @grafana/backend-platform
go.sum @grafana/backend-platform
/e2e @grafana/grafana-frontend-platform
/packages @grafana/grafana-frontend-platform
/plugins-bundled @grafana/grafana-frontend-platform
/public @grafana/grafana-frontend-platform
/scripts/build/release-packages.sh @grafana/grafana-frontend-platform
/scripts/circle-release-next-packages.sh @grafana/grafana-frontend-platform
/scripts/ci-frontend-metrics.sh @grafana/grafana-frontend-platform
/scripts/grunt @grafana/grafana-frontend-platform
/scripts/webpack @grafana/grafana-frontend-platform
package.json @grafana/grafana-frontend-platform
tsconfig.json @grafana/grafana-frontend-platform
lerna.json @grafana/grafana-frontend-platform
.babelrc @grafana/grafana-frontend-platform
.prettierrc.js @grafana/grafana-frontend-platform
.eslintrc @grafana/grafana-frontend-platform
# @grafana/ui component documentation
*.mdx @marcusolsson @jessover9000 @grafana/grafana-frontend-platform
/public/app/features/explore/ @grafana/observability-squad
/packages/jaeger-ui-components/ @grafana/observability-squad
# Core datasources
/public/app/plugins/datasource/cloudwatch @grafana/backend-platform @grafana/observability-squad
/public/app/plugins/datasource/elasticsearch @grafana/observability-squad
/public/app/plugins/datasource/grafana-azure-monitor-datasource @grafana/backend-platform
/public/app/plugins/datasource/graphite @grafana/observability-squad
/public/app/plugins/datasource/influxdb @grafana/observability-squad
/public/app/plugins/datasource/jaeger @grafana/observability-squad
/public/app/plugins/datasource/loki @grafana/observability-squad
/public/app/plugins/datasource/mssql @grafana/backend-platform
/public/app/plugins/datasource/mysql @grafana/backend-platform
/public/app/plugins/datasource/opentsdb @grafana/backend-platform
/public/app/plugins/datasource/postgres @grafana/backend-platform
/public/app/plugins/datasource/prometheus @grafana/observability-squad
/public/app/plugins/datasource/cloud-monitoring @grafana/backend-platform
/public/app/plugins/datasource/zipkin @grafana/observability-squad

View File

@@ -5,13 +5,9 @@ labels: 'type: bug'
---
<!--
Please use this template to create your bug report. By providing as much info as possible you help us understand the issue, reproduce it and resolve it for you quicker. Therefor take a couple of extra minutes to make sure you have provided all info needed.
PROTIP: record your screen and attach it as a gif to showcase the issue.
- Questions should be posted to: https://community.grafana.com
- Use query inspector to troubleshoot issues: https://bit.ly/2XNF6YS
- How to record and attach gif: https://bit.ly/2Mi8T6K
Please use this template while reporting a bug and provide as much info as possible.
Questions should be posted to https://community.grafana.com
Use query inspector to troubleshoot issues: https://community.grafana.com/t/using-grafanas-query-inspector-to-troubleshoot-issues/2630
-->
**What happened**:

View File

@@ -1,39 +0,0 @@
---
name: '@grafana/ui component request'
about: Suggest a component for the @grafana/ui package
labels: 'area/grafana/ui'
---
<!--
By using this template you will make it easier for us to make sure that documentation and implementation stays up to date for every component in @grafana/ui
Thank you!
-->
**Why is this component needed**:
<!-- Explain your use case -->
___
- [ ] Is/could it be used in more than one place in Grafana?
**Where is/could it be used?**:
___
- [ ] Post screenshots possible.
- [ ] It has a single use case.
- [ ] It is/could be used in multiple places.
**Implementation** (Checklist meant for the person implementing the component)
- [ ] Component has a story in Storybook.
- [ ] Props and naming follows [our style guide](https://github.com/grafana/grafana/blob/master/contribute/style-guides/frontend.md).
- [ ] It is extendable (rest props are spread, styles with className work, and so on).
- [ ] Uses [theme for spacing, colors, and so on](https://github.com/grafana/grafana/blob/master/contribute/style-guides/themes.md).
- [ ] Works with both light and dark theme.
**Documentation**
- [ ] Properties are documented.
- [ ] Use cases are described.
- [ ] Code examples for the different use cases.
- [ ] Dos and don'ts.
- [ ] Styling guidelines, specific color usage (if applicable).

View File

@@ -22,7 +22,7 @@ Thank you for sending a pull request! Here are some tips:
<!--
- Automatically closes linked issue when the Pull Request is merged.
* Automatically closes linked issue when the Pull Request is merged.
Usage: "Fixes #<issue number>", or "Fixes (paste link of issue)"

View File

@@ -8,7 +8,7 @@ This can be especially useful for publishing static website, such as with
[GitHub Pages](https://pages.github.com/), from built files in other job
steps, such as [Doxygen](http://www.doxygen.nl/) generated HTML files.
> **Note:** GitHub currently requires the use of a Personal Access Token for
**NOTE**: GitHub currently requires the use of a Personal Access Token for
pushing to other repositories. Pushing to the current repository should work
with the always-available GitHub Token (available via
`{{ secrets.GITHUB_TOKEN }}`. If pushing to another repository, a Personal

27
.github/commands.json vendored
View File

@@ -1,27 +0,0 @@
[
{
"type": "label",
"name": "type/question",
"action": "close",
"comment": "Please ask your question on [community.grafana.com/](https://community.grafana.com/). To avoid having your issue closed in the future, please read our [CONTRIBUTING](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md) guidelines.\n\nHappy graphing!"
},
{
"type": "comment",
"name": "duplicate",
"allowUsers": [],
"action": "updateLabels",
"addLabel": "type/duplicate"
},
{
"type": "label",
"name": "type/duplicate",
"action": "close",
"comment": "Thanks for creating this issue! It looks like this has already been reported by another user. Weve closed this in favor of the existing one. Please consider adding any details you think is missing to that issue.\n\nTo avoid having your issue closed in the future, please read our [CONTRIBUTING](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md) guidelines.\n\nHappy graphing!"
},
{
"type": "label",
"name": "no new info",
"action": "close",
"comment": "We've closed this issue since it needs more information and hasn't had any activity recently. We can re-open it after you you add more information. To avoid having your issue closed in the future, please read our [CONTRIBUTING](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md) guidelines.\n\nHappy graphing!"
}
]

View File

@@ -1,71 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"
on:
push:
branches: [master, v1.8.x, v2.0.x, v2.1.x, v2.6.x, v3.0.x, v3.1.x, v4.0.x, v4.1.x, v4.2.x, v4.3.x, v4.4.x, v4.5.x, v4.6.x, v4.7.x, v5.0.x, v5.1.x, v5.2.x, v5.3.x, v5.4.x, v6.0.x, v6.1.x, v6.2.x, v6.3.x, v6.4.x, v6.5.x, v6.6.x, v6.7.x, v7.0.x, v7.1.x, v7.2.x]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: '0 4 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['javascript', 'go', 'python']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -1,25 +0,0 @@
name: Run commands when issues are labeled or comments added
on:
issues:
types: [labeled]
issue_comment:
types: [created]
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout Actions
uses: actions/checkout@v2
with:
repository: "grafana/grafana-github-actions"
path: ./actions
ref: main
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Run Commands
uses: ./actions/commands
with:
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
token: ${{secrets.GH_BOT_ACCESS_TOKEN}}
config-path: commands

View File

@@ -1,34 +0,0 @@
#
# When triggered by the cron job it will also collect metrics for:
# * number of issues without label
# * number of issues with "needs more info"
# * number of issues with "needs investigation"
# * number of issues with label type/bug
# * number of open issues in current milestone
#
# https://github.com/grafana/grafana-github-actions/blob/main/metrics-collector/index.ts
#
name: Github issue metrics collection
on:
schedule:
- cron: "*/10 * * * *"
issues:
types: [opened, closed]
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout Actions
uses: actions/checkout@v2
with:
repository: "grafana/grafana-github-actions"
path: ./actions
ref: main
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Run metrics collector
uses: ./actions/metrics-collector
with:
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
token: ${{secrets.GH_BOT_ACCESS_TOKEN}}

View File

@@ -6,7 +6,6 @@ on:
- master
paths:
- 'docs/sources/**'
- 'packages/grafana-*/**'
jobs:
build:
@@ -15,13 +14,6 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: generate-packages-docs
uses: actions/setup-node@v1
id: generate-docs
with:
node-version: '12'
- run: yarn install --pure-lockfile --no-progress
- run: ./scripts/ci-reference-docs-build.sh
- name: publish-to-git
uses: ./.github/actions/gha-publish-to-git
id: publish

10
.gitignore vendored
View File

@@ -20,9 +20,6 @@ vendor/
/emails/templates/enterprise_*
/public/emails/enterprise_*
# Enterprise devenv
/devenv/docker/blocks/grafana-enterprise
/tmp
tools/phantomjs/phantomjs
tools/phantomjs/phantomjs.exe
@@ -46,7 +43,6 @@ public/css/*.min.css
.DS_Store
.vscode/
.vs/
.eslintcache
/data/*
/bin/*
@@ -112,9 +108,9 @@ compilation-stats.json
/packages/grafana-e2e/cypress/videos
/packages/grafana-e2e/cypress/logs
/e2e/server.log
/e2e/**/screenshots
!/e2e/**/screenshots/expected/*
/e2e/**/videos/*
/e2e/suite1/screenshots
!/e2e/suite1/screenshots/expeced/*
/e2e/suite1/videos/*
# report dumping the whole system env
/report.*.json

View File

@@ -6,4 +6,4 @@ node_modules
public/vendor/
vendor/
data/
e2e/tmp

File diff suppressed because it is too large Load Diff

View File

@@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo
Examples of behavior that contributes to creating a positive environment include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
@@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at conduct@grafana.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@grafana.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

View File

@@ -58,11 +58,10 @@ When you're ready to contribute, it's time to [Create a pull request](/contribut
#### Contributor License Agreement (CLA)
Before we can accept your pull request, you need to [sign our CLA](https://grafana.com/docs/grafana/latest/developers/cla/). If you haven't, our CLA assistant prompts you to when you create your pull request.
Before we can accept your pull request, you need to [sign our CLA](https://grafana.com/docs/contribute/cla/). If you haven't, our CLA assistant prompts you to when you create your pull request.
## Where do I go from here?
- Set up your [development environment](contribute/developer-guide.md).
- Learn how to [contribute documentation](contribute/documentation.md).
- Get started [developing plugins](https://grafana.com/docs/grafana/latest/developers/plugins/) for Grafana.
- Look through the resources in the [contribute](https://github.com/grafana/grafana/tree/master/contribute) folder.
- Get started [developing plugins](https://grafana.com/docs/plugins/developing/development/) for Grafana.

View File

@@ -1,4 +1,21 @@
FROM node:12.19.0-alpine3.12 as js-builder
# Golang build container
FROM golang:1.14.1-alpine
RUN apk add --no-cache gcc g++
WORKDIR $GOPATH/src/github.com/grafana/grafana
COPY go.mod go.sum ./
RUN go mod verify
COPY pkg pkg
COPY build.go package.json ./
RUN go run build.go build
# Node build container
FROM node:12.13.0-alpine
WORKDIR /usr/src/app/
@@ -16,23 +33,8 @@ COPY emails emails
ENV NODE_ENV production
RUN ./node_modules/.bin/grunt build
FROM golang:1.15.1-alpine3.12 as go-builder
RUN apk add --no-cache gcc g++
WORKDIR $GOPATH/src/github.com/grafana/grafana
COPY go.mod go.sum ./
RUN go mod verify
COPY pkg pkg
COPY build.go package.json ./
RUN go run build.go build
# Final stage
FROM alpine:3.12
# Final container
FROM alpine:3.10
LABEL maintainer="Grafana team <hello@grafana.com>"
@@ -50,7 +52,7 @@ ENV PATH="/usr/share/grafana/bin:$PATH" \
WORKDIR $GF_PATHS_HOME
RUN apk add --no-cache ca-certificates bash tzdata && \
apk add --no-cache openssl musl-utils
apk add --no-cache --upgrade --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main openssl musl-utils
COPY conf ./conf
@@ -68,9 +70,9 @@ RUN mkdir -p "$GF_PATHS_HOME/.aws" && \
chown -R grafana:grafana "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \
chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING"
COPY --from=go-builder /go/src/github.com/grafana/grafana/bin/linux-amd64/grafana-server /go/src/github.com/grafana/grafana/bin/linux-amd64/grafana-cli ./bin/
COPY --from=js-builder /usr/src/app/public ./public
COPY --from=js-builder /usr/src/app/tools ./tools
COPY --from=0 /go/src/github.com/grafana/grafana/bin/linux-amd64/grafana-server /go/src/github.com/grafana/grafana/bin/linux-amd64/grafana-cli ./bin/
COPY --from=1 /usr/src/app/public ./public
COPY --from=1 /usr/src/app/tools ./tools
EXPOSE 3000

View File

@@ -1,4 +1,17 @@
FROM node:12.19.0-slim AS js-builder
FROM golang:1.14.1 AS go-builder
WORKDIR /src/grafana
COPY go.mod go.sum ./
RUN go mod verify
COPY build.go package.json ./
COPY pkg pkg/
RUN go run build.go build
FROM node:12.13 AS js-builder
WORKDIR /usr/src/app/
@@ -16,19 +29,6 @@ COPY emails emails
ENV NODE_ENV production
RUN ./node_modules/.bin/grunt build
FROM golang:1.15.1 AS go-builder
WORKDIR /src/grafana
COPY go.mod go.sum ./
RUN go mod verify
COPY build.go package.json ./
COPY pkg pkg/
RUN go run build.go build
FROM ubuntu:20.04
LABEL maintainer="Grafana team <hello@grafana.com>"
@@ -50,7 +50,7 @@ WORKDIR $GF_PATHS_HOME
COPY conf conf
# curl should be part of the image
RUN apt-get update && apt-get install -y ca-certificates curl
RUN apt-get update && apt-get upgrade -y && apt-get install -y ca-certificates curl
RUN mkdir -p "$GF_PATHS_HOME/.aws" && \
addgroup --system --gid $GF_GID grafana && \
@@ -66,6 +66,7 @@ RUN mkdir -p "$GF_PATHS_HOME/.aws" && \
chown -R grafana:grafana "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \
chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING"
COPY --from=go-builder /src/grafana/bin/linux-amd64/grafana-server /src/grafana/bin/linux-amd64/grafana-cli bin/
COPY --from=js-builder /usr/src/app/public public
COPY --from=js-builder /usr/src/app/tools tools

View File

@@ -1,205 +0,0 @@
# Governance
This document describes the rules and governance of the project. It is meant to be followed by all the developers of the project and the Grafana community. Common terminology used in this governance document are listed below:
- **Team members**: Any members of the private [grafana-team][team] Google group.
- **Maintainers**: Maintainers lead an individual project or parts thereof ([`MAINTAINERS.md`][maintainers]).
- **Projects**: A single repository in the Grafana GitHub organization and listed below is referred to as a project:
- clock-panel
- devtools
- gel-app
- grafana
- grafana-github-datasource
- grafana-image-renderer
- grafana-kiosk
- grafana-plugin-sdk-go
- grafana-polystat-panel
- grafonnet-lib
- kairosdb-datasource
- piechart-panel
- simple-angular-panel
- simple-app-plugin
- simple-datasource
- simple-datasource-backend
- simple-json-backend-datasource
- simple-json-datasource
- simple-react-panel
- strava-datasource
- tutorials
- worldmap-panel
- **The Grafana project**: The sum of all activities performed under this governance, concerning one or more repositories or the community.
## Values
The Grafana developers and community are expected to follow the values defined in the Grafana Code of Conduct. Furthermore, the Grafana community strives for kindness, giving feedback effectively, and building a welcoming environment. The Grafana developers generally decide by consensus and only resort to conflict resolution by a majority vote if consensus cannot be reached.
## Projects
Each project must have a [`MAINTAINERS.md`][maintainers] file with at least one maintainer. Where a project has a release process, access and documentation should be such that more than one person can perform a release. Releases should be announced on the Grafana Labs blog. Any new projects should be first proposed on the [team mailing list][team] following the voting procedures listed below.
## Decision making
### Team members
Team member status may be given to those who have made ongoing contributions to the Grafana project for at least 3 months. This is usually in the form of code improvements and/or notable work on documentation, but organizing events or user support could also be taken into account.
New members may be proposed by any existing member by email to [grafana-team][team]. It is highly desirable to reach consensus about acceptance of a new member. However, the proposal is ultimately voted on by a formal [supermajority vote](#supermajority-vote).
If the new member proposal is accepted, the proposed team member should be contacted privately via email to confirm or deny their acceptance of team membership. This email will also be CC'd to [grafana-team][team] for record-keeping purposes.
If they choose to accept, the [onboarding](#onboarding) procedure is followed.
Team members may retire at any time by emailing [the team][team].
Team members can be removed by [supermajority vote](#supermajority-vote) on [the team mailing list][team].
For this vote, the member in question is not eligible to vote and does not count towards the quorum.
Any removal vote can cover only one single person.
Upon death of a member, they leave the team automatically.
In case a member leaves, the [offboarding](#offboarding) procedure is applied.
The current team members are:
- Alexander Zobnin ([Grafana Labs](https://grafana.com/))
- Alex Khomenko ([Grafana Labs](https://grafana.com/))
- Andrej Ocenas ([Grafana Labs](https://grafana.com/))
- Arve Knudsen ([Grafana Labs](https://grafana.com/))
- Brian Gann ([Grafana Labs](https://grafana.com/))
- Carl Bergquist ([Grafana Labs](https://grafana.com/))
- Chris Trott ([Grafana Labs](https://grafana.com/))
- Daniel Lee ([Grafana Labs](https://grafana.com/))
- David Kaltschmidt ([Grafana Labs](https://grafana.com/))
- Diana Payton ([Grafana Labs](https://grafana.com/))
- Diana Sarlinska ([Grafana Labs](https://grafana.com/))
- Dominik Prokop ([Grafana Labs](https://grafana.com/))
- Emil Tullstedt ([Grafana Labs](https://grafana.com/))
- Fredrik Enestad ([Soundtrack Your Brand](https://www.soundtrackyourbrand.com/))
- Hugo Häggmark ([Grafana Labs](https://grafana.com/))
- Ivana Huckova ([Grafana Labs](https://grafana.com/))
- Jeroen Op 't Eynde ([Grafana Labs](https://grafana.com/))
- Jessica Müller ([Grafana Labs](https://grafana.com/))
- Julien Pivotto ([Inuits](https://inuits.eu/))
- Kay Delaney ([Grafana Labs](https://grafana.com/))
- Kyle Brandt ([Grafana Labs](https://grafana.com/))
- Leonard Gram ([Grafana Labs](https://grafana.com/))
- Lukas Siatka ([Grafana Labs](https://grafana.com/))
- Malcolm Holmes ([Grafana Labs](https://grafana.com/))
- Marcus Andersson ([Grafana Labs](https://grafana.com/))
- Marcus Efraimsson ([Grafana Labs](https://grafana.com/))
- Marcus Olsson ([Grafana Labs](https://grafana.com/))
- Mitsuhiro Tanda ([GREE](https://corp.gree.net/jp/en/))
- Patrick OCarroll ([Grafana Labs](https://grafana.com/))
- Peter Holmberg ([Grafana Labs](https://grafana.com/))
- Richard Hartmann ([Grafana Labs](https://grafana.com/))
- Ryan McKinley ([Grafana Labs](https://grafana.com/))
- Sofia Papagiannaki ([Grafana Labs](https://grafana.com/))
- Stephanie Closson ([Grafana Labs](https://grafana.com/))
- Tobias Skarhed ([Grafana Labs](https://grafana.com/))
- Torkel Ödegaard ([Grafana Labs](https://grafana.com/))
- Utkarsh Bhatnagar ([Tinder](https://www.tinder.com/))
### Maintainers
Maintainers lead one or more project(s) or parts thereof and serve as a point of conflict resolution amongst the contributors to this project. Ideally, maintainers are also team members, but exceptions are possible for suitable maintainers that, for whatever reason, are not yet team members.
Changes in maintainership have to be announced on the [developers mailing list][devs]. They are decided by [rough consensus](#consensus) and formalized by changing the [`MAINTAINERS.md`][maintainers] file of the respective repository.
Maintainers are granted commit rights to all projects covered by this governance.
A maintainer or committer may resign by notifying the [team mailing list][team]. A maintainer with no project activity for a year is considered to have resigned. Maintainers that wish to resign are encouraged to propose another team member to take over the project.
A project may have multiple maintainers, as long as the responsibilities are clearly agreed upon between them. This includes coordinating who handles which issues and pull requests.
### Technical decisions
Technical decisions that only affect a single project are made informally by the maintainer of this project, and [rough consensus](#consensus) is assumed. Technical decisions that span multiple parts of the Grafana project should be discussed and made on the [Grafana developer mailing list][devs].
Decisions are usually made by [rough consensus](#consensus). If no consensus can be reached, the matter may be resolved by [majority vote](#majority-vote).
### Governance changes
Changes to this document are made by Grafana Labs.
### Other matters
Any matter that needs a decision may be called to a vote by any member if they deem it necessary. For private or personnel matters, discussion and voting takes place on the [team mailing list][team], otherwise on the [developer mailing list][devs].
## Voting
The Grafana project usually runs by informal consensus, however sometimes a formal decision must be made.
Depending on the subject matter, as laid out [above](#decision-making), different methods of voting are used.
For all votes, voting must be open for at least one week. The end date should be clearly stated in the call to vote. A vote may be called and closed early if enough votes have come in one way so that further votes cannot change the final decision.
In all cases, all and only [team members](#team-members) are eligible to vote, with the sole exception of the forced removal of a team member, in which said member is not eligible to vote.
Discussion and votes on personnel matters (including but not limited to team membership and maintainership) are held in private on the [team mailing list][team]. All other discussion and votes are held in public on the [developer mailing list][devs].
For public discussions, anyone interested is encouraged to participate. Formal power to object or vote is limited to [team members](#team-members).
### Consensus
The default decision making mechanism for the Grafana project is [rough][rough] consensus. This means that any decision on technical issues is considered supported by the [team][team] as long as nobody objects or the objection has been considered but not necessarily accommodated.
Silence on any consensus decision is implicit agreement and equivalent to explicit agreement. Explicit agreement may be stated at will. Decisions may, but do not need to be called out and put up for decision on the [developers mailing list][devs] at any time and by anyone.
Consensus decisions can never override or go against the spirit of an earlier explicit vote.
If any [team member](#team-members) raises objections, the team members work together towards a solution that all involved can accept. This solution is again subject to rough consensus.
In case no consensus can be found, but a decision one way or the other must be made, any [team member](#team-members) may call a formal [majority vote](#majority-vote).
### Majority vote
Majority votes must be called explicitly in a separate thread on the appropriate mailing list. The subject must be prefixed with `[VOTE]`. In the body, the call to vote must state the proposal being voted on. It should reference any discussion leading up to this point.
Votes may take the form of a single proposal, with the option to vote yes or no, or the form of multiple alternatives.
A vote on a single proposal is considered successful if more vote in favor than against.
If there are multiple alternatives, members may vote for one or more alternatives, or vote “no” to object to all alternatives. It is not possible to cast an “abstain” vote. A vote on multiple alternatives is considered decided in favor of one alternative if it has received the most votes in favor, and a vote from more than half of those voting. Should no alternative reach this quorum, another vote on a reduced number of options may be called separately.
### Supermajority vote
Supermajority votes must be called explicitly in a separate thread on the appropriate mailing list. The subject must be prefixed with `[VOTE]`. In the body, the call to vote must state the proposal being voted on. It should reference any discussion leading up to this point.
Votes may take the form of a single proposal, with the option to vote yes or no, or the form of multiple alternatives.
A vote on a single proposal is considered successful if at least two thirds of those eligible to vote vote in favor.
If there are multiple alternatives, members may vote for one or more alternatives, or vote “no” to object to all alternatives. A vote on multiple alternatives is considered decided in favor of one alternative if it has received the most votes in favor, and a vote from at least two thirds of those eligible to vote. Should no alternative reach this quorum, another vote on a reduced number of options may be called separately.
## On- / Offboarding
### Onboarding
The new member is
- added to the list of [team members](#team-members). Ideally by sending a PR of their own, at least approving said PR.
- announced on the [developers mailing list][devs] by an existing team member. Ideally, the new member replies in this thread, acknowledging team membership.
- added to the projects with commit rights.
- added to the [team mailing list][team].
### Offboarding
The ex-member is
- removed from the list of [team members](#team-members). Ideally by sending a PR of their own, at least approving said PR. In case of forced removal, no approval is needed.
- removed from the projects. Optionally, they can retain maintainership of one or more repositories if the [team](#team-members) agrees.
- removed from the team mailing list and demoted to a normal member of the other mailing lists.
- not allowed to call themselves an active team member any more, nor allowed to imply this to be the case.
- added to a list of previous members if they so choose.
If needed, we reserve the right to publicly announce removal.
[coc]: https://github.com/grafana/grafana/blob/master/CODE_OF_CONDUCT.md
[devs]: https://groups.google.com/forum/#!forum/grafana-developers
[maintainers]: https://github.com/grafana/grafana/blob/master/MAINTAINERS.md
[rough]: https://tools.ietf.org/html/rfc7282
[team]: https://groups.google.com/forum/#!forum/grafana-team

View File

@@ -1,5 +1,5 @@
'use strict';
module.exports = function(grunt) {
module.exports = function (grunt) {
var os = require('os');
var config = {
pkg: grunt.file.readJSON('package.json'),
@@ -47,20 +47,18 @@ module.exports = function(grunt) {
// Utility function to load plugin settings into config
function loadConfig(config, path) {
require('glob')
.sync('*', { cwd: path })
.forEach(function(option) {
var key = option.replace(/\.js$/, '');
// If key already exists, extend it. It is your responsibility to avoid naming collisions
config[key] = config[key] || {};
grunt.util._.extend(config[key], require(path + option)(config, grunt));
});
require('glob').sync('*', {cwd: path}).forEach(function(option) {
var key = option.replace(/\.js$/,'');
// If key already exists, extend it. It is your responsibility to avoid naming collisions
config[key] = config[key] || {};
grunt.util._.extend(config[key], require(path + option)(config,grunt));
});
// technically not required
return config;
}
// Merge that object with what with whatever we have here
loadConfig(config, './scripts/grunt/options/');
loadConfig(config,'./scripts/grunt/options/');
// pass the config to grunt
grunt.initConfig(config);
};

View File

@@ -2,16 +2,16 @@
The main goal of issue triage is to categorize all incoming Grafana issues and make sure each issue has all basic information needed for anyone else to understand and be able to start working on it.
> **Note:** This information is for Grafana project Maintainers, Owners, and Admins. If you are a Contributor, then you will not be able to perform most of the tasks in this topic.
**Note:** This information is for Grafana project Maintainers, Owners, and Admins. If you are a Contributor, then you will not be able to perform most of the tasks in this topic.
The core maintainers of the Grafana project are responsible for categorizing all incoming issues and delegating any critical or important issue to other maintainers. Currently one maintainer each week is responsible. Besides that part, triage provides an important way to contribute to an open source project.
Triage helps ensure issues resolve quickly by:
- Ensuring the issue's intent and purpose is conveyed precisely. This is necessary because it can be difficult for an issue to explain how an end user experiences a problem and what actions they took.
- Giving a contributor the information they need before they commit to resolving an issue.
- Lowering the issue count by preventing duplicate issues.
- Streamlining the development process by preventing duplicate discussions.
* Ensuring the issue's intent and purpose is conveyed precisely. This is necessary because it can be difficult for an issue to explain how an end user experiences a problem and what actions they took.
* Giving a contributor the information they need before they commit to resolving an issue.
* Lowering the issue count by preventing duplicate issues.
* Streamlining the development process by preventing duplicate discussions.
If you don't have the knowledge or time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours.
@@ -32,7 +32,7 @@ If you don't have the knowledge or time to code, consider helping with triage. T
| | |
+------+-------+-------------+ +------------+---------+ +----------------------------+
| | | | | |
| label: needs more info | | Needs investigation? +--YES---+ label: needs investigation |
| label: needs more details | | Needs investigation? +--YES---+ label: needs investigation |
| | | | | |
+----------------------------+ +----------------+-----+ +--------------+-------------+
NO | |
@@ -82,7 +82,7 @@ Before triaging an issue very far, make sure that the issue's author provided th
Given a certain [issue template]([template](https://github.com/grafana/grafana/issues/new/choose)) have been used by the issue author or depending how the issue is perceived by the issue triage responsible, the following should help you understand what standard issue information that must be included.
#### Bug reports
#### Bug report?
Should explain what happened, what was expected and how to reproduce it together with any additional information that may help giving a complete picture of what happened such as screenshots, [query inspector](https://community.grafana.com/t/using-grafanas-query-inspector-to-troubleshoot-issues/2630) output and any environment related information that's applicable and/or maybe related to the reported problem:
- Grafana version
@@ -96,15 +96,15 @@ Should explain what happened, what was expected and how to reproduce it together
- Non-default configuration settings
- Development environment like Go and Node versions, if applicable
#### Enhancement requests
#### Enhancement request?
Should explain what enhancement or feature that the author wants to be added and why that is needed.
#### Accessibility issues
#### Accessibility issue?
This is a mix between a bug report and enhancement request but focused on accessibility issues to help make Grafana improve keyboard navigation, screen-reader support and being accessible to everyone. The report should include relevant WCAG criteria, if applicable.
#### Support requests
#### Support request?
In general, if the issue description and title is perceived as a question no more information is needed.
@@ -112,11 +112,11 @@ In general, if the issue description and title is perceived as a question no mor
To make it easier for everyone to understand and find issues they're searching for it's suggested as a general rule of thumbs to:
- Make sure that issue titles are named to explain the subject of the issue, has a correct spelling and doesn't include irrelevant information and/or sensitive information.
- Make sure that issue descriptions doesn't include irrelevant information, information from template that haven't been filled out and/or sensitive information.
- Do your best effort to change title and description or request suggested changes by adding a comment.
* Make sure that issue titles are named to explain the subject of the issue, has a correct spelling and doesn't include irrelevant information and/or sensitive information.
* Make sure that issue descriptions doesn't include irrelevant information, information from template that haven't been filled out and/or sensitive information.
* Do your best effort to change title and description or request suggested changes by adding a comment.
> **Note:** Above rules is applicable to both new and existing issues of the Grafana project.
Note: Above rules is applicable to both new and existing issues of the Grafana project.
### Do you have all the information needed to categorize an issue?
@@ -137,28 +137,29 @@ An issue can have multiple of the following labels. Typically, a properly catego
- One label identifying its type (`type/*`).
- One or multiple labels identifying the functional areas of interest or component (`area/*`) and/or data source (`datasource/*`), if applicable.
| Label | Description |
| ------------------------ | ------------------------------------------------------------------------- |
| `type/bug` | A feature isn't working as expected given design or documentation. |
| `type/feature-request` | Request for a new feature or enhancement. |
| `type/docs` | Documentation problem or enhancement. |
| `type/accessibility` | Accessibility problem or enhancement. |
| `type/question` | Issue is a question or is perceived as such. |
| `type/duplicate` | An existing issue of the same subject/request have already been reported. |
| `type/works-as-intended` | A reported bug works as intended/by design. |
| `type/build-packaging` | Build or packaging problem or enhancement. |
| `area/*` | Subject is related to a functional area of interest or component. |
| `datasource/*` | Subject is related to a core data source plugin. |
Label | Description
------- | --------
`type/bug` | A feature isn't working as expected given design or documentation.
`type/feature-request` | Request for a new feature or enhancement.
`type/docs` | Documentation problem or enhancement.
`type/accessibility` | Accessibility problem or enhancement.
`type/question` | Issue is or perceived as a question.
`type/duplicate` | An existing issue of the same subject/request have already been reported.
`type/works-as-intended` | A reported bug works as intended/by design.
`type/build-packaging` | Build or packaging problem or enhancement.
`area/*` | Subject is related to a functional area of interest or component.
`datasource/*` | Subject is related to a core data source plugin.
### Duplicate issues
### Duplicate issue?
Make sure it's not a duplicate by searching existing issues using related terms from the issue title and description. If you think you know there is an existing issue, but can't find it, please reach out to one of the maintainers and ask for help. If you identify that the issue is a duplicate of an existing issue:
Make sure that it's not a duplicate by searching existing issues using related terms from the issue title and description. If you think you know there are an existing issue, but can't find it please reach out to one of the maintainers and ask for help. If you identify that the issue is a duplicate of an existing issue:
1. Add a comment `/duplicate of #<issue number>`. GitHub will recognize this and add some additional context to the issue activity.
2. The Grafana bot will do the rest, adding the correct label and closing comment
1. Add a comment `Duplicate of #<issue number>`. GitHub will recognize this and add some additional context to the issue activity.
2. Close the issue and label it with `type/duplicate`.
3. Optionally add any related `area/*` or `datasource/*` labels.
4. If applicable, add a comment with additional information.
### Bug reports
### Bug report?
If it's not perfectly clear that it's an actual bug, quickly try to reproduce it.
@@ -187,8 +188,8 @@ If it's not perfectly clear that it's an actual bug, quickly try to reproduce it
First, evaluate if the documentation makes sense to be included in the Grafana project:
- Is this something we want/can maintain as a project?
- Is this referring to usage of some specific integration/tool and in that case is that a popular use case in combination with Grafana?
- If unsure, kindly and politely add a comment explaining that we would need [upvotes](https://help.github.com/en/articles/about-conversations-on-github#reacting-to-ideas-in-comments) to identify that lots of other users want/need this.
- Is this referring to usage of some specific integration/tool and in that case are those a popular use case in combination with Grafana?
- If unsure, kindly and politely add a comment explaining that we would need [upvotes](https://help.github.com/en/articles/about-conversations-on-github#reacting-to-ideas-in-comments) to identify that lots of other users wants/needs this.
Second, label the issue `type/docs` and at least one `area/*` or `datasource/*` label.
@@ -203,11 +204,11 @@ There's a minor typo/error/lack of information that adds a lot of confusion for
1. Label the issue with `help wanted` and `beginner friendly`, if applicable, to signal that we find this important to fix and we would appreciate any help we can get from the community.
2. Move on to [prioritizing the issue](#4-prioritization-of-issues).
### Accessibility issues
### Accessibility issue?
1. Label the issue `type/accessibility` and at least one `area/*` or `datasource/*` label.
### Support requests
### Support request?
1. Kindly and politely direct the issue author to the [community site](https://community.grafana.com/) and explain that GitHub is mainly used for tracking bugs and feature requests. If possible, it's usually a good idea to add some pointers to the issue author's question.
2. Close the issue and label it with `type/question`.
@@ -218,23 +219,23 @@ In general bugs and enhancement issues should be labeled with a priority.
This is the most difficult thing with triaging issues since it requires a lot of knowledge, context and experience before being able to think of and start feel comfortable adding a certain priority label.
The key here is asking for help and discuss issues to understand how more experienced project members think and reason. By doing that you learn more and eventually be more and more comfortable with prioritizing issues.
The key here is asking for help and discuss issues to understand how more experienced project members thinks and reason. By doing that you learn more and eventually be more and more comfortable with prioritizing issues.
In case there is an uncertainty around the prioritization of an issue, please ask the maintainers for help.
In any case there are uncertainty around the priorization of an issue, please ask the maintainers for help.
| Label | Description |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `priority/critical` | Highest priority. Must be actively worked on as someone's top priority right now. |
| `priority/support-subscription` | This is important for one or several customers having a paid Grafana support subscription. |
| `priority/important-soon` | Must be staffed and worked on either currently, or very soon, ideally in time for the next release. |
| `priority/important-longterm` | Important over the long term, but may not be staffed and/or may need multiple releases to complete. |
| `priority/nice-to-have` | It's a good idea, but not scheduled for any release. |
| `priority/awaiting-more-evidence` | Lowest priority. Possibly useful, but not yet enough interest in it. |
| `priority/unscheduled` | Something to look into before and to be discussed during the planning of the next (upcoming) major/minor stable release. |
Label | Description
------- | --------
`priority/critical` | Highest priority. Must be actively worked on as someone's top priority right now.
`priority/support-subscription` | This is important for one or several customers having a paid Grafana support subscription.
`priority/important-soon` | Must be staffed and worked on either currently, or very soon, ideally in time for the next release.
`priority/important-longterm` | Important over the long term, but may not be staffed and/or may need multiple releases to complete.
`priority/nice-to-have` | It's a good idea, but not scheduled for any release.
`priority/awaiting-more-evidence` | Lowest priority. Possibly useful, but not yet enough interest in it.
`priority/unscheduled` | Something to look into before and to be discussed during the planning of the next (upcoming) major/minor stable release.
**Critical bugs**
**Critical bug?**
1. If a bug has been categorized and any of the following criteria apply, the bug should be labeled as critical and must be actively worked on as someone's top priority right now.
1. If a bug have been categorized and any of the following problems applies the bug should be labeled as critical and must be actively worked on as someone's top priority right now.
- Results in any data loss
- Critical security or performance issues
@@ -247,7 +248,7 @@ In case there is an uncertainty around the prioritization of an issue, please as
5. Escalate the problem to the maintainers.
6. Assign or ask a maintainer for help assigning someone to make this issue their top priority right now.
**Important short-term**
**Important short-term?**
1. Label the issue `priority/important-soon`.
2. If applicable, label the issue `priority/support-subscription`.
@@ -255,12 +256,12 @@ In case there is an uncertainty around the prioritization of an issue, please as
4. Make sure to add the issue to a suitable backlog of a GitHub project and prioritize it or assign someone to work on it now or very soon.
5. Consider requesting [help from the community](#5-requesting-help-from-the-community), even though it may be problematic given a short amount of time until it should be released.
**Important long-term**
**Important long-term?**
1. Label the issue `priority/important-longterm`.
2. Consider requesting [help from the community](#5-requesting-help-from-the-community).
**Nice to have**
**Nice to have?**
1. Label the issue `priority/nice-to-have`.
2. Consider requesting [help from the community](#5-requesting-help-from-the-community).
@@ -272,9 +273,9 @@ In case there is an uncertainty around the prioritization of an issue, please as
## 5. Requesting help from the community
Depending on the issue and/or priority, it's always a good idea to consider signalling to the community that help from community is appreciated and needed in case an issue is not prioritized to be worked on by maintainers. Use your best judgement. In general, requesting help from the community means that a contribution has a good chance of getting accepted and merged.
Depending on the issue and/or priority, it's always a good idea to consider signalling to the community that help from community is appreciated and needed in case an issue is not prioritized to be worked on by maintainers. Use your best judgement. In general, when requesting help from the community it means a contribution has a good chance of getting accepted and merged.
In many cases the issue author or community as a whole is more suitable to contribute changes since they're experts in their domain. It's also quite common that someone has tried to get something to work using the documentation without success and made an effort to get it to work and/or reached out to the [community site](https://community.grafana.com/) to get the missing information. Particularly in these areas it's more likely that there exist experts in their own domain and it is usually a good idea to request help from contributors:
In many cases the issue author or community as a whole is more suitable to contribute changes since they're experts in their domain. It's also quite common that someone has tried to get something to work using the documentation without success and made an effort to get it to work and/or reached out to the [community site](https://community.grafana.com/) to get the missing information. In especially these areas it's more likely that there exists experts in their own domain and usually a good idea to request help from contributors:
- Database setups
- Authentication like OAuth providers and LDAP setups
@@ -283,7 +284,7 @@ In many cases the issue author or community as a whole is more suitable to contr
- Alert notifiers
1. Kindly and politely add a comment to signal to users subscribed to updates of the issue.
- Explain that the issue would be nice to get resolved, but it isn't prioritized to work on by maintainers for an unforeseen future.
- Explain that the issue would be nice to get resolved, but it isn't prioritized to work on by maintainers for an unforseen future.
- If possible or applicable, try to help contributors getting starting by adding pointers and references to what code/files need to be changed and/or ideas of a good way to solve/implement the issue.
2. Label the issue with `help wanted`.
3. If applicable, label the issue with `beginner friendly` to denote that the issue is suitable for a beginner to work on.
@@ -291,35 +292,28 @@ In many cases the issue author or community as a whole is more suitable to contr
## Investigation of issues
When an issue has all basic information provided, but the triage responsible haven't been able to reproduce the reported problem at a first glance, the issue is labeled [Needs investigation](https://github.com/grafana/grafana/labels/needs%20investigation). Depending on the perceived severity and/or number of [upvotes](https://help.github.com/en/articles/about-conversations-on-github#reacting-to-ideas-in-comments), the investigation will either be delegated to another maintainer for further investigation or put on hold until someone else (maintainer or contributor) picks it up and eventually starts investigating it.
When an issue has all basic information provided, but the triage responsible haven't been able to reproduce the reported problem at a first glance, the issue is labeled [Needs investigation](https://github.com/grafana/grafana/labels/needs%20investigation). Depending of the perceived severity and/or number of [upvotes](https://help.github.com/en/articles/about-conversations-on-github#reacting-to-ideas-in-comments), the investigation will either be delegated to another maintainer for further investigation or either put on hold until someone else (maintainer or contributor) picks it up and eventually start investigating it.
Investigating issues can be a very time consuming task, especially for the maintainers, given the huge number of combinations of plugins, data sources, platforms, databases, browsers, tools, hardware, integrations, versions and cloud services, etc that are being used with Grafana. There is a certain number of combinations that are more common than others, and these are in general easier for maintainers to investigate.
Investigating issues can be a very time consuming task, especially for the maintainers given the huge number of combinations of plugins, data sources, platforms, databases, browsers, tools, hardware, integrations, versions and cloud services etc that are being used with Grafana. There are a certain amount of combinations that are more common than others and these are in general easier for maintainers to investigate.
For some other combinations it may not be possible at all for a maintainer to setup a proper test environment to investigate the issue. In these cases we really appreciate any help we can get from the community. Otherwise the issue is highly likely to be closed.
For some other combinations there may not be possible at all for a maintainer to setup a proper test environment for being able to investigate. In these cases we really appreciate any help we can get from the community. Otherwise the issue is highly likely to be closed.
Even if you don't have the time or knowledge to investigate an issue we highly recommend that you [upvote](https://help.github.com/en/articles/about-conversations-on-github#reacting-to-ideas-in-comments) the issue if you happen to have the same problem. If you have further details that may help investigating the issue please provide as much information as possible.
## Automation
We have some automation that triggers on comments or labels being added to issues. Many of these automated behaviors are defined in [commands.json](https://github.com/grafana/grafana/blob/master/.github/commands.json). Or in other [GitHub Actions](https://github.com/grafana/grafana/tree/master/.github/workflows)
* Add /duplicate `#<issue number>` to have Grafana label & close issue with an appropriate message.
* Add `type/question` and the bot will close it with an appropriate message.
## External PRs
Part of issue triage should also be triaging of external PRs. Main goal should be to make sure PRs from external contributors have an owner/reviewer and are not forgotten.
1. Check new external PRs which do not have a reviewer.
1. Check if there is a link to an existing issue.
1. If not and you know which issue it is solving, add the link yourself, otherwise ask the author to link the issue or create one.
1. If not and you know which issue it is solving add the link yourself, otherwise ask the author to link the issue or create one.
1. Assign a reviewer based on who was handling the linked issue or what code or feature does the PR touches (look at who was the last to make changes there if all else fails).
## Appendix
### Setting up Gmail filters
If you're using Gmail it's highly recommended that you setup filters to automatically remove email from the inbox and label them accordingly to make it easy for you to understand when you need to act upon a notification or process all incoming issues that haven't been triaged.
If you're using Gmail it's highly recommened that you setup filters to automatically remove email from the inbox and label them accordingly to make it easy for you to understand when you need to act upon a notification or process all incoming issues that haven't been triaged.
This may be setup by personal preference, but here's a working configuration for reference.
1. Follow instructions in [gist](https://gist.github.com/marefr/9167c2e31466f6316c1cba118874e74f)
@@ -333,14 +327,14 @@ This will give you a structure of labels in the sidebar similar to the following
```
- Inbox
...
- GitHub (mine)
- Github (mine)
- activity
- assigned
- mentions
- GitHub (other)
- Github (other)
- Grafana
```
- All notifications youll need to read/take action on show up as unread in GitHub (mine) and its sub-labels.
- All other notifications you dont need to take action on show up as unread in GitHub (other) and its sub-labels
- This is convenient for issue triage and to follow the activity in the Grafana project.
* All notifications youll need to read/take action on shows up as unread in Github (mine) and its sub-labels.
* All other notifications you dont need to take action on shows up as unread in Github (other) and its sub-labels
* This is convenient for issue triage and to follow the activity in the Grafana project.

View File

@@ -1,8 +0,0 @@
@torkelo is the main/default maintainer, some parts of the codebase have other maintainers:
- Backend:
- @bergquist
- Plugins:
- @ryantxu
- UX/UI:
- @davkal

View File

@@ -4,7 +4,7 @@
-include local/Makefile
.PHONY: all deps-go deps-js deps build-go build-server build-cli build-js build build-docker-dev build-docker-full lint-go revive golangci-lint tidy-check test-go test-js test run run-frontend clean devenv devenv-down revive-strict protobuf help
.PHONY: all deps-go deps-js deps build-go build-server build-cli build-js build build-docker-dev build-docker-full lint-go gosec revive golangci-lint go-vet test-go test-js test run run-frontend clean devenv devenv-down revive-alerting protobuf help
GO = GO111MODULE=on go
GO_FILES ?= ./pkg/...
@@ -42,7 +42,6 @@ build-cli: ## Build Grafana CLI application.
build-js: ## Build frontend assets.
@echo "build frontend"
yarn run build
yarn run plugins:build-bundled
build: build-go build-js ## Build backend and frontend.
@@ -81,9 +80,14 @@ revive: scripts/go/bin/revive
-config ./scripts/go/configs/revive.toml \
$(GO_FILES)
revive-strict: scripts/go/bin/revive
@echo "lint via revive (strict)"
@scripts/revive-strict scripts/go/bin/revive
revive-alerting: scripts/go/bin/revive
@echo "lint alerting via revive"
@scripts/go/bin/revive \
-formatter stylish \
-config ./scripts/go/configs/revive-strict.toml \
./pkg/services/alerting/... \
./pkg/services/provisioning/datasources/... \
./pkg/services/provisioning/dashboards/...
scripts/go/bin/golangci-lint: scripts/go/go.mod
@cd scripts/go; \
@@ -92,14 +96,26 @@ scripts/go/bin/golangci-lint: scripts/go/go.mod
golangci-lint: scripts/go/bin/golangci-lint
@echo "lint via golangci-lint"
@scripts/go/bin/golangci-lint run \
--config ./scripts/go/configs/.golangci.toml \
--config ./scripts/go/configs/.golangci.yml \
$(GO_FILES)
tidy-check:
@echo "check whether go.mod and go.sum are consistent"
@scripts/tidy-check.sh
scripts/go/bin/gosec: scripts/go/go.mod
@cd scripts/go; \
$(GO) build -o ./bin/gosec github.com/securego/gosec/cmd/gosec
lint-go: golangci-lint revive revive-strict tidy-check # Run all code checks for backend.
# TODO recheck the rules and leave only necessary exclusions
gosec: scripts/go/bin/gosec
@echo "lint via gosec"
@scripts/go/bin/gosec -quiet \
-exclude=G104,G107,G108,G201,G202,G204,G301,G304,G401,G402,G501 \
-conf=./scripts/go/configs/gosec.json \
$(GO_FILES)
go-vet:
@echo "lint via go vet"
@$(GO) vet $(GO_FILES)
lint-go: go-vet golangci-lint revive revive-alerting gosec ## Run all code checks for backend.
# with disabled SC1071 we are ignored some TCL,Expect `/usr/bin/env expect` scripts
shellcheck: $(SH_FILES) ## Run checks for shell scripts.

View File

@@ -6,7 +6,7 @@ Please encrypt your message to us; please use our PGP key. The key fingerprint i
F988 7BEA 027A 049F AE8E 5CAA D125 8932 BE24 C5CA
The key is available from [keyserver.ubuntu.com](https://keyserver.ubuntu.com/pks/lookup?search=0xF9887BEA027A049FAE8E5CAAD1258932BE24C5CA&fingerprint=on&op=index).
The key is available from [pgp.mit.edu](https://pgp.mit.edu/pks/lookup?op=get&search=0xF9887BEA027A049FAE8E5CAAD1258932BE24C5CA) by searching for [grafana](https://pgp.mit.edu/pks/lookup?search=grafana&op=index).
Grafana Labs will send you a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.

View File

@@ -20,7 +20,7 @@ Upgrading Go or Node.js requires making changes in many different files. See bel
The Grafana project uses [Go modules](https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more) to manage dependencies on external packages. This requires a working Go environment with version 1.11 or greater installed.
> **Note:** Since most developers of Grafana still use the `GOPATH` we need to specify `GO111MODULE=on` to make `go mod` and `got get` work as intended. If you have setup Grafana outside of the `GOPATH` on your machine you can skip `GO111MODULE=on` when running the commands below.
_Note:_ Since most developers of Grafana still use the `GOPATH` we need to specify `GO111MODULE=on` to make `go mod` and `got get` work as intended. If you have setup Grafana outside of the `GOPATH` on your machine you can skip `GO111MODULE=on` when running the commands below.
To add or update a new dependency, use the `go get` command:

View File

@@ -1,73 +0,0 @@
# Grafana workflow
This document is based on [GOVERNANCE.md](GOVERNANCE.md). We assume good faith and intend to keep all processes as lightweight as possible but as specific as required. In case of disagreements about anything in this document, GOVERNANCE.md applies.
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC2119](http://tools.ietf.org/html/rfc2119).
Git and [GitHub terminology](https://help.github.com/en/github/getting-started-with-github/github-glossary) are used throughout this document.
Team members and their access to repositories is maintained through [GitHub teams](https://help.github.com/en/github/setting-up-and-managing-organizations-and-teams/about-teams). Team maintainers add and remove team members as outlined in GOVERNANCE.md.
# Code changes
## Proposing changes
Examples of proposed changes are overarching architecture, component design, and specific code or graphical elements. Proposed changes SHOULD cover the big picture and intention, but individual parts SHOULD be split into the smallest possible changes. Changes SHOULD be based on and target the master branch. Depending on size of the proposed change, each change SHOULD be discussed, in increasing order of change size and complexity:
- Directly in a RR (Pull Request) - this MAY be done, but SHOULD not be the common case.
- Issue
- Developer mailing list
- Design document, shared via Google Docs, accessible to at least all team members.
Significant changes MUST be discussed and agreed upon with the relevant subsystem maintainers.
## Merging PRs (Pull Requests)
Depending on the size and complexity of a PR, different requirements MUST be applied. Any team member contributing substantially to a PR MUST NOT count against review requirements.
Commits MUST be merged into master using PRs. They MUST NOT be merged into master directly.
- Every merge MUST be approved by at least one team member.
- Non-trivial changes MUST be approved by at least
- two team members, or
- one subsystem maintainer.
- Significant changes MUST be approved by at least
- two team members, AND
- the relevant subsystem maintainer.
PRs MUST be [reviewed](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/reviewing-changes-in-pull-requests) and [approved](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/approving-a-pull-request-with-required-reviews) via GitHubs review system.
- Reviewers MAY write comments if approving
- Reviewers MUST write comments if rejecting a PR or if requesting changes.
Once a PR is approved as per above, any team member MAY merge the PR.
# Release workflow
## Branch structure
Grafana uses trunk-based development.
In particular, we found that the following principles match how we work:
- Master and release branches MUST always build without failure.
- Branches SHOULD be merged often. Larger changes SHOULD be activated with feature flags until they are ready. Long-lived development branches SHOULD be avoided.
- Changes MAY be enabled by default once they are in a complete state
- Changes which span multiple PRs MUST be described in an overarching issue or Google Doc.
## Releases
Releases MUST follow [Semantic Versioning](https://semver.org/) in naming and SHOULD follow Semantic Versioning as closely as reasonably possible for non-library software.
Release branches MUST be split from the following branches.
- MAJOR release branches MUST be based on master.
- MINOR release branches MUST be based on master.
- PATCH release branches MUST be split from the relevant MINOR release branchs most current PATCH
Security releases follow the same process but MUST be prepared in secret. Security releases MUST NOT include changes which are not related to the security fix. Normal release processes MUST accommodate the security release process. SECURITY.md MUST be followed.
PRs intended for inclusion in the next PATCH release MUST be labeled with `cherry-pick-needed` so they can be picked up by automated release tooling.
Releases follow the following cadence
- MAJOR: Yearly
- MINOR: Every 4-6 weeks
- PATCH: As needed
Releases SHOULD NOT be delayed by pending changes.
Releases MUST be coordinated with the relevant subsystem maintainers.

View File

@@ -9,7 +9,6 @@ import (
"encoding/json"
"flag"
"fmt"
"go/build"
"io"
"io/ioutil"
"log"
@@ -58,6 +57,8 @@ func main() {
log.SetOutput(os.Stdout)
log.SetFlags(0)
ensureGoPath()
var buildIdRaw string
flag.StringVar(&goarch, "goarch", runtime.GOARCH, "GOARCH")
@@ -105,16 +106,16 @@ func main() {
case "build-srv", "build-server":
clean()
doBuild("grafana-server", "./pkg/cmd/grafana-server", []string{})
build("grafana-server", "./pkg/cmd/grafana-server", []string{})
case "build-cli":
clean()
doBuild("grafana-cli", "./pkg/cmd/grafana-cli", []string{})
build("grafana-cli", "./pkg/cmd/grafana-cli", []string{})
case "build":
//clean()
for _, binary := range binaries {
doBuild(binary, "./pkg/cmd/"+binary, []string{})
build(binary, "./pkg/cmd/"+binary, []string{})
}
case "build-frontend":
@@ -416,6 +417,18 @@ func createPackage(options linuxPackageOptions) {
runPrint("fpm", append([]string{"-t", options.packageType}, args...)...)
}
func ensureGoPath() {
if os.Getenv("GOPATH") == "" {
cwd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
gopath := filepath.Clean(filepath.Join(cwd, "../../../../"))
log.Println("GOPATH is", gopath)
os.Setenv("GOPATH", gopath)
}
}
func grunt(params ...string) {
if runtime.GOOS == windows {
runPrint(`.\node_modules\.bin\grunt`, params...)
@@ -463,7 +476,7 @@ func test(pkg string) {
runPrint("go", "test", "-short", "-timeout", "60s", pkg)
}
func doBuild(binaryName, pkg string, tags []string) {
func build(binaryName, pkg string, tags []string) {
libcPart := ""
if libc != "" {
libcPart = fmt.Sprintf("-%s", libc)
@@ -541,7 +554,7 @@ func clean() {
rmr("dist")
rmr("tmp")
rmr(filepath.Join(build.Default.GOPATH, fmt.Sprintf("pkg/%s_%s/github.com/grafana", goos, goarch)))
rmr(filepath.Join(os.Getenv("GOPATH"), fmt.Sprintf("pkg/%s_%s/github.com/grafana", goos, goarch)))
}
func setBuildEnv() {

View File

@@ -126,29 +126,10 @@ connstr =
# This enables data proxy logging, default is false
logging = false
# How long the data proxy waits before timing out, default is 30 seconds.
# This setting also applies to core backend HTTP data sources where query requests use an HTTP client with timeout set.
# How long the data proxy should wait before timing out default is 30 (seconds)
timeout = 30
# How many seconds the data proxy waits before sending a keepalive request.
keep_alive_seconds = 30
# How many seconds the data proxy waits for a successful TLS Handshake before timing out.
tls_handshake_timeout_seconds = 10
# How many seconds the data proxy will wait for a server's first response headers after
# fully writing the request headers if the request has an "Expect: 100-continue"
# header. A value of 0 will result in the body being sent immediately, without
# waiting for the server to approve.
expect_continue_timeout_seconds = 1
# The maximum number of idle connections that Grafana will keep alive.
max_idle_connections = 100
# How many seconds the data proxy keeps an idle connection open before timing out.
idle_conn_timeout_seconds = 90
# If enabled and user is not anonymous, data proxy will add X-Grafana-User header with username into the request.
# If enabled and user is not anonymous, data proxy will add X-Grafana-User header with username into the request, default is false.
send_user_header = false
#################################### Analytics ###########################
@@ -207,6 +188,7 @@ allow_embedding = false
# Set to true if you want to enable http strict transport security (HSTS) response header.
# This is only sent when HTTPS is enabled in this configuration.
# HSTS tells browsers that the site should only be accessed using HTTPS.
# The default will change to true in the next minor release, 6.3.
strict_transport_security = false
# Sets how long a browser should cache HSTS. Only applied if strict_transport_security is enabled.
@@ -220,12 +202,12 @@ strict_transport_security_subdomains = false
# Set to true to enable the X-Content-Type-Options response header.
# The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised
# in the Content-Type headers should not be changed and be followed.
x_content_type_options = true
# in the Content-Type headers should not be changed and be followed. The default will change to true in the next minor release, 6.3.
x_content_type_options = false
# Set to true to enable the X-XSS-Protection header, which tells browsers to stop pages from loading
# when they detect reflected cross-site scripting (XSS) attacks.
x_xss_protection = true
# when they detect reflected cross-site scripting (XSS) attacks. The default will change to true in the next minor release, 6.3.
x_xss_protection = false
#################################### Snapshots ###########################
@@ -252,9 +234,6 @@ versions_to_keep = 20
# The interval string is a possibly signed sequence of decimal numbers, followed by a unit suffix (ms, s, m, h, d), e.g. 30s or 1m.
min_refresh_interval = 5s
# Path to the default home dashboard. If this value is empty, then Grafana uses StaticRootPath + "dashboards/home.json"
default_home_dashboard_path =
#################################### Users ###############################
[users]
# disable user signup / registration
@@ -293,18 +272,15 @@ viewers_can_edit = false
# Editors can administrate dashboard, folders and teams they create
editors_can_admin = false
# The duration in time a user invitation remains valid before expiring. This setting should be expressed as a duration. Examples: 6h (hours), 2d (days), 1w (week). Default is 24h (24 hours). The minimum supported duration is 15m (15 minutes).
user_invite_max_lifetime_duration = 24h
[auth]
# Login cookie name
login_cookie_name = grafana_session
# The maximum lifetime (duration) an authenticated user can be inactive before being required to login at next visit. Default is 7 days (7d). This setting should be expressed as a duration, e.g. 5m (minutes), 6h (hours), 10d (days), 2w (weeks), 1M (month). The lifetime resets at each successful token rotation (token_rotation_interval_minutes).
login_maximum_inactive_lifetime_duration =
# The lifetime (days) an authenticated user can be inactive before being required to login at next visit. Default is 7 days.
login_maximum_inactive_lifetime_days = 7
# The maximum lifetime (duration) an authenticated user can be logged in since login time before being required to login. Default is 30 days (30d). This setting should be expressed as a duration, e.g. 5m (minutes), 6h (hours), 10d (days), 2w (weeks), 1M (month).
login_maximum_lifetime_duration =
# The maximum lifetime (days) an authenticated user can be logged in since login time before being required to login. Default is 30 days.
login_maximum_lifetime_days = 30
# How often should auth tokens be rotated for authenticated users when being active. The default is each 10 minutes.
token_rotation_interval_minutes = 10
@@ -322,15 +298,12 @@ signout_redirect_url =
# This setting is ignored if multiple OAuth providers are configured.
oauth_auto_login = false
# OAuth state max age cookie duration in seconds. Defaults to 600 seconds.
oauth_state_cookie_max_age = 600
# OAuth state max age cookie duration. Defaults to 60 seconds.
oauth_state_cookie_max_age = 60
# limit of api_key seconds to live before expiration
api_key_max_seconds_to_live = -1
# Set to true to enable SigV4 authentication option for HTTP-based datasources
sigv4_auth_enabled = false
#################################### Anonymous Auth ######################
[auth.anonymous]
# enable anonymous access
@@ -342,15 +315,12 @@ org_name = Main Org.
# specify role for unauthenticated users
org_role = Viewer
# mask the Grafana version number for unauthenticated users
hide_version = false
#################################### GitHub Auth #########################
#################################### Github Auth #########################
[auth.github]
enabled = false
allow_sign_up = true
client_id = some_id
client_secret =
client_secret = some_secret
scopes = user:email,read:org
auth_url = https://github.com/login/oauth/authorize
token_url = https://github.com/login/oauth/access_token
@@ -364,7 +334,7 @@ allowed_organizations =
enabled = false
allow_sign_up = true
client_id = some_id
client_secret =
client_secret = some_secret
scopes = api
auth_url = https://gitlab.com/oauth/authorize
token_url = https://gitlab.com/oauth/token
@@ -377,7 +347,7 @@ allowed_groups =
enabled = false
allow_sign_up = true
client_id = some_client_id
client_secret =
client_secret = some_client_secret
scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email
auth_url = https://accounts.google.com/o/oauth2/auth
token_url = https://accounts.google.com/o/oauth2/token
@@ -391,7 +361,7 @@ hosted_domain =
enabled = false
allow_sign_up = true
client_id = some_id
client_secret =
client_secret = some_secret
scopes = user:email
allowed_organizations =
@@ -399,7 +369,7 @@ allowed_organizations =
enabled = false
allow_sign_up = true
client_id = some_id
client_secret =
client_secret = some_secret
scopes = user:email
allowed_organizations =
@@ -409,7 +379,7 @@ name = Azure AD
enabled = false
allow_sign_up = true
client_id = some_client_id
client_secret =
client_secret = some_client_secret
scopes = openid email profile
auth_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize
token_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
@@ -422,7 +392,7 @@ name = Okta
enabled = false
allow_sign_up = true
client_id = some_id
client_secret =
client_secret = some_secret
scopes = openid profile email groups
auth_url = https://<tenant-id>.okta.com/oauth2/v1/authorize
token_url = https://<tenant-id>.okta.com/oauth2/v1/token
@@ -437,13 +407,11 @@ name = OAuth
enabled = false
allow_sign_up = true
client_id = some_id
client_secret =
client_secret = some_secret
scopes = user:email
email_attribute_name = email:primary
email_attribute_path =
login_attribute_path =
role_attribute_path =
id_token_attribute_name =
auth_url =
token_url =
api_url =
@@ -496,7 +464,6 @@ skip_verify = false
from_address = admin@grafana.localhost
from_name = Grafana
ehlo_identity =
startTLS_policy =
[emails]
welcome_email_on_sign_up = false
@@ -623,36 +590,6 @@ max_attempts = 3
# Makes it possible to enforce a minimal interval between evaluations, to reduce load on the backend
min_interval_seconds = 1
# Configures for how long alert annotations are stored. Default is 0, which keeps them forever.
# This setting should be expressed as an duration. Ex 6h (hours), 10d (days), 2w (weeks), 1M (month).
max_annotation_age =
# Configures max number of alert annotations that Grafana stores. Default value is 0, which keeps all alert annotations.
max_annotations_to_keep =
#################################### Annotations #########################
[annotations.dashboard]
# Dashboard annotations means that annotations are associated with the dashboard they are created on.
# Configures how long dashboard annotations are stored. Default is 0, which keeps them forever.
# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month).
max_age =
# Configures max number of dashboard annotations that Grafana stores. Default value is 0, which keeps all dashboard annotations.
max_annotations_to_keep =
[annotations.api]
# API annotations means that the annotations have been created using the API without any
# association with a dashboard.
# Configures how long Grafana stores API annotations. Default is 0, which keeps them forever.
# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month).
max_age =
# Configures max number of API annotations that Grafana keeps. Default value is 0, which keeps all API annotations.
max_annotations_to_keep =
#################################### Explore #############################
[explore]
# Enable the Explore section
@@ -731,8 +668,6 @@ public_url =
key_file =
bucket =
path =
enable_signed_urls = false
signed_url_expiration =
[external_image_storage.azure_blob]
account_name =
@@ -760,8 +695,6 @@ disable_sanitize_html = false
[plugins]
enable_alpha = false
app_tls_skip_verify_insecure = false
# Enter a comma-separated list of plugin identifiers to identify plugins that are allowed to be loaded even if they lack a valid signature.
allow_loading_unsigned_plugins =
#################################### Grafana Image Renderer Plugin ##########################
[plugin.grafana-image-renderer]
@@ -813,7 +746,7 @@ rendering_clustering_mode =
# When rendering_mode = clustered you can define maximum number of browser instances/incognito pages that can execute concurrently..
rendering_clustering_max_concurrency =
# Limit the maximum viewport width, height and device scale factor that can be requested.
# Limit the maxiumum viewport width, height and device scale factor that can be requested.
rendering_viewport_max_width =
rendering_viewport_max_height =
rendering_viewport_max_device_scale_factor =
@@ -829,23 +762,3 @@ license_path =
[feature_toggles]
# enable features, separated by spaces
enable =
[date_formats]
# For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/
# Default system date format used in time range picker and other places where full time is displayed
full_date = YYYY-MM-DD HH:mm:ss
# Used by graph and other places where we only show small intervals
interval_second = HH:mm:ss
interval_minute = HH:mm
interval_hour = MM/DD HH:mm
interval_day = MM/DD
interval_month = YYYY-MM
interval_year = YYYY
# Experimental feature
use_browser_locale = false
# Default timezone for user preferences. Options are 'browser' for the browser local timezone or a timezone name from IANA Time Zone database, e.g. 'UTC' or 'Europe/Amsterdam' etc.
default_timezone = browser

View File

@@ -1,11 +0,0 @@
# # config file version
apiVersion: 1
# apps:
# - type: grafana-example-app
# org_name: Main Org.
# disabled: true
# - type: raintank-worldping-app
# org_id: 1
# jsonData:
# apiKey: "API KEY"

View File

@@ -127,28 +127,9 @@
# This enables data proxy logging, default is false
;logging = false
# How long the data proxy waits before timing out, default is 30 seconds.
# This setting also applies to core backend HTTP data sources where query requests use an HTTP client with timeout set.
# How long the data proxy should wait before timing out default is 30 (seconds)
;timeout = 30
# How many seconds the data proxy waits before sending a keepalive probe request.
;keep_alive_seconds = 30
# How many seconds the data proxy waits for a successful TLS Handshake before timing out.
;tls_handshake_timeout_seconds = 10
# How many seconds the data proxy will wait for a server's first response headers after
# fully writing the request headers if the request has an "Expect: 100-continue"
# header. A value of 0 will result in the body being sent immediately, without
# waiting for the server to approve.
;expect_continue_timeout_seconds = 1
# The maximum number of idle connections that Grafana will keep alive.
;max_idle_connections = 100
# How many seconds the data proxy keeps an idle connection open before timing out.
;idle_conn_timeout_seconds = 90
# If enabled and user is not anonymous, data proxy will add X-Grafana-User header with username into the request, default is false.
;send_user_header = false
@@ -161,7 +142,7 @@
;reporting_enabled = true
# Set to false to disable all checks to https://grafana.net
# for new versions (grafana itself and plugins), check is used
# for new vesions (grafana itself and plugins), check is used
# in some UI views to notify that grafana or plugin update exists
# This option does not cause any auto updates, nor send any information
# only a GET request to http://grafana.com to get latest versions
@@ -208,6 +189,7 @@
# Set to true if you want to enable http strict transport security (HSTS) response header.
# This is only sent when HTTPS is enabled in this configuration.
# HSTS tells browsers that the site should only be accessed using HTTPS.
# The default version will change to true in the next minor release, 6.3.
;strict_transport_security = false
# Sets how long a browser should cache HSTS. Only applied if strict_transport_security is enabled.
@@ -221,12 +203,12 @@
# Set to true to enable the X-Content-Type-Options response header.
# The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised
# in the Content-Type headers should not be changed and be followed.
;x_content_type_options = true
# in the Content-Type headers should not be changed and be followed. The default will change to true in the next minor release, 6.3.
;x_content_type_options = false
# Set to true to enable the X-XSS-Protection header, which tells browsers to stop pages from loading
# when they detect reflected cross-site scripting (XSS) attacks.
;x_xss_protection = true
# when they detect reflected cross-site scripting (XSS) attacks. The default will change to true in the next minor release, 6.3.
;x_xss_protection = false
#################################### Snapshots ###########################
[snapshots]
@@ -251,9 +233,6 @@
# The interval string is a possibly signed sequence of decimal numbers, followed by a unit suffix (ms, s, m, h, d), e.g. 30s or 1m.
;min_refresh_interval = 5s
# Path to the default home dashboard. If this value is empty, then Grafana uses StaticRootPath + "dashboards/home.json"
;default_home_dashboard_path =
#################################### Users ###############################
[users]
# disable user signup / registration
@@ -292,18 +271,15 @@
# Editors can administrate dashboard, folders and teams they create
;editors_can_admin = false
# The duration in time a user invitation remains valid before expiring. This setting should be expressed as a duration. Examples: 6h (hours), 2d (days), 1w (week). Default is 24h (24 hours). The minimum supported duration is 15m (15 minutes).
;user_invite_max_lifetime_duration = 24h
[auth]
# Login cookie name
;login_cookie_name = grafana_session
# The maximum lifetime (duration) an authenticated user can be inactive before being required to login at next visit. Default is 7 days (7d). This setting should be expressed as a duration, e.g. 5m (minutes), 6h (hours), 10d (days), 2w (weeks), 1M (month). The lifetime resets at each successful token rotation.
;login_maximum_inactive_lifetime_duration =
# The lifetime (days) an authenticated user can be inactive before being required to login at next visit. Default is 7 days,
;login_maximum_inactive_lifetime_days = 7
# The maximum lifetime (duration) an authenticated user can be logged in since login time before being required to login. Default is 30 days (30d). This setting should be expressed as a duration, e.g. 5m (minutes), 6h (hours), 10d (days), 2w (weeks), 1M (month).
;login_maximum_lifetime_duration =
# The maximum lifetime (days) an authenticated user can be logged in since login time before being required to login. Default is 30 days.
;login_maximum_lifetime_days = 30
# How often should auth tokens be rotated for authenticated users when being active. The default is each 10 minutes.
;token_rotation_interval_minutes = 10
@@ -321,15 +297,12 @@
# This setting is ignored if multiple OAuth providers are configured.
;oauth_auto_login = false
# OAuth state max age cookie duration in seconds. Defaults to 600 seconds.
;oauth_state_cookie_max_age = 600
# OAuth state max age cookie duration. Defaults to 60 seconds.
;oauth_state_cookie_max_age = 60
# limit of api_key seconds to live before expiration
;api_key_max_seconds_to_live = -1
# Set to true to enable SigV4 authentication option for HTTP-based datasources.
;sigv4_auth_enabled = false
#################################### Anonymous Auth ######################
[auth.anonymous]
# enable anonymous access
@@ -341,10 +314,7 @@
# specify role for unauthenticated users
;org_role = Viewer
# mask the Grafana version number for unauthenticated users
;hide_version = false
#################################### GitHub Auth ##########################
#################################### Github Auth ##########################
[auth.github]
;enabled = false
;allow_sign_up = true
@@ -431,8 +401,6 @@
;scopes = user:email,read:org
;email_attribute_name = email:primary
;email_attribute_path =
;login_attribute_path =
;id_token_attribute_name =
;auth_url = https://foo.bar/login/oauth/authorize
;token_url = https://foo.bar/login/oauth/access_token
;api_url = https://foo.bar/user
@@ -486,8 +454,6 @@
;from_name = Grafana
# EHLO identity in SMTP dialog (defaults to instance_name)
;ehlo_identity = dashboard.example.com
# SMTP startTLS policy (defaults to 'OpportunisticStartTLS')
;startTLS_policy = NoStartTLS
[emails]
;welcome_email_on_sign_up = false
@@ -615,36 +581,6 @@
# Makes it possible to enforce a minimal interval between evaluations, to reduce load on the backend
;min_interval_seconds = 1
# Configures for how long alert annotations are stored. Default is 0, which keeps them forever.
# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month).
;max_annotation_age =
# Configures max number of alert annotations that Grafana stores. Default value is 0, which keeps all alert annotations.
;max_annotations_to_keep =
#################################### Annotations #########################
[annotations.dashboard]
# Dashboard annotations means that annotations are associated with the dashboard they are created on.
# Configures how long dashboard annotations are stored. Default is 0, which keeps them forever.
# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month).
;max_age =
# Configures max number of dashboard annotations that Grafana stores. Default value is 0, which keeps all dashboard annotations.
;max_annotations_to_keep =
[annotations.api]
# API annotations means that the annotations have been created using the API without any
# association with a dashboard.
# Configures how long Grafana stores API annotations. Default is 0, which keeps them forever.
# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month).
;max_age =
# Configures max number of API annotations that Grafana keeps. Default value is 0, which keeps all API annotations.
;max_annotations_to_keep =
#################################### Explore #############################
[explore]
# Enable the Explore section
@@ -748,8 +684,6 @@
[plugins]
;enable_alpha = false
;app_tls_skip_verify_insecure = false
# Enter a comma-separated list of plugin identifiers to identify plugins that are allowed to be loaded even if they lack a valid signature.
;allow_loading_unsigned_plugins =
#################################### Grafana Image Renderer Plugin ##########################
[plugin.grafana-image-renderer]
@@ -801,7 +735,7 @@
# When rendering_mode = clustered you can define maximum number of browser instances/incognito pages that can execute concurrently..
;rendering_clustering_max_concurrency =
# Limit the maximum viewport width, height and device scale factor that can be requested.
# Limit the maxiumum viewport width, height and device scale factor that can be requested.
;rendering_viewport_max_width =
;rendering_viewport_max_height =
;rendering_viewport_max_device_scale_factor =
@@ -818,23 +752,3 @@
[feature_toggles]
# enable features, separated by spaces
;enable =
[date_formats]
# For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/
# Default system date format used in time range picker and other places where full time is displayed
;full_date = YYYY-MM-DD HH:mm:ss
# Used by graph and other places where we only show small intervals
;interval_second = HH:mm:ss
;interval_minute = HH:mm
;interval_hour = MM/DD HH:mm
;interval_day = MM/DD
;interval_month = YYYY-MM
;interval_year = YYYY
# Experimental feature
;use_browser_locale = false
# Default timezone for user preferences. Options are 'browser' for the browser local timezone or a timezone name from IANA Time Zone database, e.g. 'UTC' or 'Europe/Amsterdam' etc.
;default_timezone = browser

View File

@@ -66,7 +66,7 @@ if err := s.bus.Dispatch(cmd); err != nil {
}
```
> **Note:** `Dispatch` will return an error if no handler is registered for that command.
**Note:** `Dispatch` will return an error if no handler is registered for that command.
**Tip:** Browse the available commands in the `models` package.
@@ -87,7 +87,7 @@ func (s *MyService) SendStickers(cmd *models.SendStickersCommand) error {
}
```
> **Note:** The handler method may return an error if unable to complete the command.
**Note:** The handler method may return an error if unable to complete the command.
## Queries

View File

@@ -40,7 +40,7 @@ func init() {
}
```
`init` functions are only run whenever a package is imported, so we also need to import the package in the application. In the `server.go` file under `pkg/server`, import the package we just created:
`init` functions are only run whenever a package is imported, so we also need to import the package in the application. In the `server.go` file under `pkg/cmd/grafana-server`, import the package we just created:
```go
import _ "github.com/grafana/grafana/pkg/services/mysvc"
@@ -66,4 +66,4 @@ type MyService struct {
}
```
> **Note:** Any injected dependency needs to be an exported field. Any unexported fields result in a runtime error.
**Note:** Any injected dependency needs to be an exported field. Any unexported fields result in a runtime error.

View File

@@ -27,14 +27,11 @@ npm install -g yarn
## Download Grafana
We recommend using the Git command-line interface to download the source code for the Grafana project:
We recommend using Go to download the source code for the Grafana project:
1. Open a terminal and run `git clone https://github.com/grafana/grafana.git`. This command downloads Grafana to a new `grafana` directory in your current directory.
1. Open the `grafana` directory in your favorite code editor.
For alternative ways of cloning the Grafana repository, please refer to [GitHub's cloning a repository](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository) documentation.
**Warning:** Do not use `go get` to download Grafana. Recent versions of Go have added behavior which isn't compatible with the way the Grafana repository is structured.
1. Add `export GOPATH=$HOME/go/` to the bottom of your `$HOME/.bash_profile`.
1. Open a terminal and run `go get github.com/grafana/grafana` in your terminal. This command downloads, and installs Grafana to your `$GOPATH`.
1. Open `$GOPATH/src/github.com/grafana/grafana` in your favorite code editor.
## Build Grafana
@@ -100,35 +97,29 @@ go test -v ./pkg/...
### Run end-to-end tests
The end to end tests in Grafana use [Cypress](https://www.cypress.io/) to run automated scripts in a headless Chromium browser. Read more about our [e2e framework](/contribute/style-guides/e2e.md).
The end to end tests in Grafana use [Cypress](https://www.cypress.io/) to run automated scripts in a headless Chromium browser. Read more about our [e2e framework](/contribute/style-guides/e2e.md).
To run the tests:
```
yarn e2e
yarn e2e-tests
```
By default, the end-to-end tests starts a Grafana instance listening on `localhost:3001`. To use a specific URL, set the `BASE_URL` environment variable:
By default, the end-to-end tests assume Grafana is available on `localhost:3000`. To use a specific URL, set the `BASE_URL` environment variable:
```
BASE_URL=http://localhost:3333 yarn e2e
BASE_URL=http://localhost:3333 yarn e2e-tests
```
To follow the tests in the browser while they're running, use the `yarn e2e:debug`.
To follow the tests in the browser while they're running, use the `yarn e2e-tests:debug` instead.
```
yarn e2e:debug
```
If you want to pick a test first, use the `yarn e2e:dev`, to pick a test and follow the test in the browser while it runs.
```
yarn e2e:dev
yarn e2e-tests:debug
```
## Configure Grafana for development
The default configuration, `defaults.ini`, is located in the `conf` directory.
The default configuration, `grafana.ini`, is located in the `conf` directory.
To override the default configuration, create a `custom.ini` file in the `conf` directory. You only need to add the options you wish to override.
@@ -174,7 +165,7 @@ make build-docker-full
The resulting image will be tagged as grafana/grafana:dev.
> **Note:** If you've already set up a local development environment, and you're running a `linux/amd64` machine, you can speed up building the Docker image:
**Note:** If you've already set up a local development environment, and you're running a `linux/amd64` machine, you can speed up building the Docker image:
1. Build the frontend: `go run build.go build-frontend`.
1. Build the Docker image: `make build-docker-dev`.
@@ -187,7 +178,7 @@ Are you having issues with setting up your environment? Here are some tips that
### Too many open files when running `make run`
Depending on your environment, you may have to increase the maximum number of open files allowed. For the rest of this section, we will assume you are on a Unix like OS (e.g. Linux/macOS), where you can control the maximum number of open files through the [ulimit](https://ss64.com/bash/ulimit.html) shell command.
Depending on your environment, you may have to increase the maximum number of open files allowed. For the rest of this section, we will assume you are on a Unix like OS (e.g. Linux/MacOS), where you can control the maximum number of open files through the [ulimit](https://ss64.com/bash/ulimit.html) shell command.
To see how many open files are allowed, run:
@@ -207,14 +198,14 @@ The number of files needed may be different on your environment. To determine th
find ./conf ./pkg ./public/views | wc -l
```
Another alternative is to limit the files being watched. The directories that are watched for changes are listed in the `.bra.toml` file in the root directory.
Another alternative is to limit the files being watched. The directories that are watched for changes are listed in the `.bra.toml` file in the root directory.
To retain your `ulimit` configuration, i.e. so it will be remembered for future sessions, you need to commit it to your command line shell initialization file. Which file this will be depends on the shell you are using, here are some examples:
- zsh -> ~/.zshrc
- bash -> ~/.bashrc
* zsh -> ~/.zshrc
* bash -> ~/.bashrc
Commit your ulimit configuration to your shell initialization file as follows ($LIMIT being your chosen limit and $INIT_FILE being the initialization file for your shell):
Commit your ulimit configuration to your shell initialization file as follows ($LIMIT being your chosen limit and $INIT_FILE being the initialization file for your shell):
```
echo ulimit -S -n $LIMIT >> $INIT_FILE
@@ -228,7 +219,7 @@ For some people, typically using the bash shell, ulimit fails with an error simi
ulimit: open files: cannot modify limit: Operation not permitted
```
If that happens to you, chances are you've already set a lower limit and your shell won't let you set a higher one. Try looking in your shell initialization files (~/.bashrc typically), if there's already a ulimit command that you can tweak.
If that happens to you, chances are you've already set a lower limit and your shell won't let you set a higher one. Try looking in your shell initalization files (~/.bashrc typically), if there's already a ulimit command that you can tweak.
## Next steps

View File

@@ -1,6 +1,6 @@
# Backend style guide
Grafana's backend has been developed for a long time with a mix of code styles. This guide explains how we want to write Go code in the future.
Grafanas backend has been developed for a long time with a mix of code styles. This guide explains how we want to write Go code in the future.
Unless stated otherwise, use the guidelines listed in the following articles:

View File

@@ -25,7 +25,7 @@ All `exported` apis from the package should have a release tag to indicate its s
- [`@alpha`](https://api-extractor.com/pages/tsdoc/tag_alpha/) - early draft of api and will probably change.
- [`@beta`](https://api-extractor.com/pages/tsdoc/tag_beta/) - close to being stable but might change.
- [`@public`](https://api-extractor.com/pages/tsdoc/tag_public/) - ready for usage in production.
- [`@public`](https://api-extractor.com/pages/tsdoc/tag_public/) - ready for useage in production.
- [`@internal`](https://api-extractor.com/pages/tsdoc/tag_internal/) - for internal use only.
### Main stability of APIs
@@ -139,7 +139,7 @@ This attribute can be skipped if the type provided by `typescript` and the funct
```typescript
/**
* Will help to create a resource resolver depending
* Will help to create a resource resovler depending
* on the current execution context.
*
* @param context - The current execution context.
@@ -179,7 +179,7 @@ This attribute can be skipped if the type provided by `typescript` and the funct
```typescript
/**
* Will help to create a resource resolver depending
* Will help to create a resource resovler depending
* on the current execution context.
*
* @param context - The current execution context.
@@ -206,4 +206,4 @@ export const factory = (context: Context): IResolver => {
export const isEqual = (x: number, y: number): boolean => {
return x === y;
}
```
```

View File

@@ -1,41 +1,46 @@
# Markdown style guide
This guide for Markdown style helps keep contributions consistent across all documentation created for Grafana products. Refer to the guide and update its sections as needed when a Subject Matter Expert answers a question on Markdown style, or a decision is made about how to apply Markdown.
This guide for Markdown style helps keep contributions consistent across all documentation
created for Grafana products. Refer to the guide and update its sections as needed when a
Subject Matter Expert answers a question on Markdown style, or a decision is made about
how to apply Markdown.
## Headers
In Markdown, the number of "#" symbols creates different heading levels, similar to HTML heading levels:
In Markdown, the number of "#" symbols creates different heading levels, similar to
HTML heading levels:
**Example**
- \# is \<h1>.
- \#\# is \<h2>.
- \#\#\# is \<h3>.
* \# is \<h1>.
* \#\# is \<h2>.
* \#\#\# is \<h3>.
Start your document with a single ``#`` for the title of the page. Add the sub-headings with two ``##``.
## Bold and emphasis
- Make text **bold** using two asterisks.
* Make text **bold** using two asterisks.
**Example:** It is ``**important**`` to use GitHub-flavored Markdown emoji consistently.
**Example:** It is ``**important**`` to use Github Flavored Markdown emoji consistently.
- Make text ``_emphasized_`` using single `` _underscores_``. Do not use the single asterisk, it can be easily confused with bold.
* Make text ``*emphasized*`` using single `` _underscores_`` or a single asterisk.
**Example:** GitHub-flavored markdown emoji should _only_ appear in specific cases.
**Example:** Github Flavored Markdown emoji should _only_ appear in specific cases.
## Links and references
Create links to other website by wrapping the display text in square brackets, and the web URL in curved brackets.
Create links to other website by wrapping the display text in square brackets, and
the web URL in curved brackets.
\[text to display](www.website.com)
**Example:** For more information on including emoji in GitHub-flavored markdown, refer to the [webfx page on emoji](https://www.webfx.com/tools/emoji-cheat-sheet/) for a list of emoji.
**Example:** For more information on including emoji in Github flavored Markdown, refer to the [webfx page on emoji](https://www.webfx.com/tools/emoji-cheat-sheet/) for a list of emoji.
## Block quotes
Include block quotes inside text using right-facing arrows:
Include Block quotes inside text using right-facing arrows:
**Example**
@@ -45,7 +50,8 @@ Include block quotes inside text using right-facing arrows:
## Code blocks
Code blocks written with markdown can show off syntax highlighting specific to different languages. Use three back tics to create a code block:
Code blocks written with markdown can show off syntax highlighting specific
to different languages. Use three back tics to create a code block:
```
function testNum(a) {
@@ -57,7 +63,8 @@ function testNum(a) {
}
```
Write the name of the language after the first set of back tics, no spaces, to show specific syntax highlighting. For example; "\```javascript" produces the following:
Write the name of the language after the first set of back tics, no spaces,
to show specific syntax highlighting. For example; "\```javascript" produces the following:
```javascript
function testNum(a) {
@@ -70,7 +77,10 @@ function testNum(a) {
```
## Tables
Construct a table by typing the table headings, and separating them with a "|" character. Then, add a second line of dashes ("-") separated by another "|" character. When constructing the table cells, separate each cell data with another "|".
Construct a table by typing the table headings, and separating them with
a "|" character. Then, add a second line of dashes ("-") separated by
another "|" character. When constructing the table cells, separate each cell data with another
"|".
**Example**
@@ -106,13 +116,14 @@ The list above will always display as:
### Unordered lists
Build a list of points - an unordered or unnumbered list - by using "\-" (hyphen) characters.
Build a list of points - an unordered or unnumbered list - by
using "\*" characters.
**Example**
- First
- Another item
- The last list item
* First
* Another item
* The last list item
## Images
@@ -124,8 +135,10 @@ This follows the format of "!", alt text wrapped in "[]" and the link URL wrappe
## Comments
You can include comments that will not appear in published markdown using the following syntax:
You can include comments that will not appear in published markdown using the
following syntax:
\[comment]: <> (Comment text to display)
The word "comment" wrapped in "[]" followed by a ":", a space, "<>", and then the comment itself wrapped in "()".
The word "comment" wrapped in "[]" followed by a ":", a space, "<>", and then
the comment itself wrapped in "()".

View File

@@ -4,7 +4,7 @@ This style guide applies to all documentation created for Grafana products.
For information about how to write technical documentation, we suggest reviewing the content of the [Google Technical Writing courses](https://developers.google.com/tech-writing).
The [Divio documentation system](https://documentation.divio.com/) site and the [Vue writing principles](https://v3.vuejs.org/guide/contributing/writing-guide.html#principles) are also good resources.
The [Divio documentation system](https://documentation.divio.com/) site is also a good resource.
## Contributing
@@ -18,51 +18,21 @@ For all items not covered in this guide, refer to the [Microsoft Style Guide](ht
The [codespell](https://github.com/codespell-project/codespell) tool is run for every change to catch common misspellings.
## Inclusive language
This section provides guidelines on how to avoid using charged language in documentation.
### Allowing and blocking
Don't use "whitelist" or "blacklist" when referring to allowing or blocking content or traffic.
- When used as a noun, use "allowlist" or "blocklist".
- When used as a verb, use "allow" or "block"
Example: _To **allow** outgoing traffic, add the IP to the **allowlist**._
### Leader and follower
Don't use "master" or "slave" to describe relationships between nodes or processes.
- Use "leader", "main" or "primary," instead of "master."
- Use "follower" or "secondary," instead of "slave."
### Exceptions
When referring to a configuration or settings used by third-party libraries och technologies outside the Grafana project, prefer the original name to avoid confusion.
For example, use "master" when referring to the default Git branch.
## Grafana-specific style
The following sections provide general guidelines on topics specific to Grafana documentation. Note that for the most part, these are *guidelines*, not rigid rules. If you have questions, ask in the #docs channel of Grafana Slack.
### General
- Use active voice. Avoid passive voice.
* Use active voice. Avoid passive voice.
- Passive: The heatmap visualization is displayed.
- Active: Grafana displays the heatmap visualization.
- Write in the imperative second person. Examples: You can write a query. Click the panel. Close the window.
- Write in present tense.
* Write in the imperative second person. Examples: You can write a query. Click the panel. Close the window.
* Write in present tense.
- Not: The panel will open.
- Use: The panel opens. Grafana opens the panel.
- Do not use an ampersand (&) as an abbreviation for "and."
* Do not use an ampersand (&) as an abbreviation for "and."
- **Exceptions:** If an ampersand is used in the Grafana UI, then match the UI.
- Avoid using internal slang and jargon in technical documentation.
- Do not use two spaces after a period. Only add one space after each sentence. Do not add a space at the end of the paragraph.
- Sentence length should be 25 words or less. If your thought is longer than 25 words, consider breaking up the sentence or changing the format to a list.
- Paragraphs should be three sentences or fewer. Break up long paragraphs.
### File naming conventions
@@ -72,39 +42,39 @@ The following sections provide general guidelines on topics specific to Grafana
### Headings
- Write headings in sentence case, not title case.
* Write headings in sentence case, not title case.
- This is sentence case
- This Is Title Case
- Task topic headings start with a verb.
* Task topic headings start with a verb.
- Write a query. Create a dashboard.
- Concept and reference topic headings should be nouns or gerunds. Examples: Contributing to docs, Visualizations, Style guide
- Avoid following one heading with another heading.
- Avoid skipping heading levels. For example, an h1 should be followed by an h2 rather than an h3.
- Avoid having just one lower-level heading. For example, h1, h2, h2, h3, h3, h2 is a good order. Do not go h1, h2, h3, h2, h3, h2.
- Don't include parenthetical words like (Important!) in headings.
* Concept and reference topic headings should be nouns or gerunds. Examples: Contributing to docs, Visualizations, Style guide
* Avoid following one heading with another heading.
* Avoid skipping heading levels. For example, an h1 should be followed by an h2 rather than an h3.
* Avoid having just one lower-level heading. For example, h1, h2, h2, h3, h3, h2 is a good order. Do no go h1, h2, h3, h2, h3, h2.
* Don't include parenthetical words like (Important!) in headings.
### Images
- Preferred format is .png
- File extension should be all lowercase.
- Preferred DPI is 72.
- Assume all graphics will be exclusively viewed on the web.
- Maximum image size is 3840px X 2160px.
- Screenshots should be readable, but not too large.
* Preferred format is .png
* File extension should be all lowercase.
* Preferred DPI is 72.
* Assume all graphics will be exclusively viewed on the web.
* Maximum image size is 3840px X 2160px.
* Screenshots should be readable, but not too large.
### Capitalization
- Grafana, Loki, and Prometheus are always capitalized unless part of a code block.
- API names are always Title Case, followed by "API"—for example, "Dashboard Permissions API"
- Git is always capitalized, unless part of a code block.
- Abbreviations are always capitalized (such as API, HTTP, ID, JSON, SQL, or URL) unless they are part of a code block.
- Menu and submenu titles always use sentence case: capitalize the first word, and lowercase the rest.
* Grafana, Loki, and Prometheus are always capitalized unless part of a code block.
* API names are always Title Case, followed by "API"—for example, "Dashboard Permissions API"
* Git is always capitalized, unless part of a code block.
* Abbreviations are always capitalized (such as API, HTTP, ID, JSON, SQL, or URL) unless they are part of a code block.
* Menu and submenu titles always use sentence case: capitalize the first word, and lowercase the rest.
- "Dashboards" when referring to the submenu title.
- "Keyboard shortcuts" when referring to the submenu topic.
- Generic and plural versions are always lowercase.
* Generic and plural versions are always lowercase.
- Lowercase "dashboard" when referring to a dashboard generally.
- Lowercase "dashboards" when referring to multiple dashboards.
- **Exceptions:** If a term is lowercased in the Grafana UI, then match the UI.
* **Exceptions:** If a term is lowercased in the Grafana UI, then match the UI.
### Links and references
@@ -117,46 +87,16 @@ When possible, use the exact title of the page or section you are linking to as
**Example**
Refer to the [Documentation style guide](documentation-style-guide.md) for information about word usage and capitalization guidelines.
### Notes, tips, cautions, and warnings
Grafana documentation uses notes, tips, cautions, and warnings. Notes are the most common. The format for all of them is indented, bold, sentence case:
```
> **Note:**
```
#### Notes
Notes provide additional information that the user should be extra aware of. For example:
> **Note:** This page describes a feature for Grafana 7.0 beta.
#### Tips
Tips describe alternate or more efficient ways of doing things. Rarely used.
#### Cautions
Cautions warn the user that they should proceed with caution. Use cautions to emphasize the potential downside of a course of action.
> **Caution:** If you turn off authentication requirements, then anyone can access your Grafana instance. This poses a considerable security risk.
#### Warnings
Warnings tell the user not to do something. For example:
> **Warning:** Grafana does not back up your dashboards. If you delete a dashboard, then you might not be able to recover it.
### Command line examples
- Do not assume everyone is using Linux. Make sure instructions include enough information for Windows and Mac users to successfully complete procedures.
* Do not assume everyone is using Linux. Make sure instructions include enough information for Windows and Mac users to successfully complete procedures.
- Do not add `$` before commands. Make it easy for users to copy and paste commands.
* Do not add `$` before commands. Make it easy for users to copy and paste commands.
- **Wrong:** `$ sudo yum install grafana`
- **Right:** `sudo yum install grafana`
* **Wrong:** `$ sudo yum install grafana`
* **Right:** `sudo yum install grafana`
- Include `sudo` before commands that require `sudo` to work.
* Include `sudo` before commands that require `sudo` to work.
For terminal examples and Grafana configuration, use a `bash` code block:
```bash
@@ -172,7 +112,7 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
### Word usage
Grafana products has some words, abbreviations, and terms particular to the Grafana discourse community.
Grafana products has some words, abbreviations, and slang particular to this discourse community.
#### checkout, check out
@@ -180,30 +120,26 @@ Two words if used as a verb, one word if used as a noun.
**Examples**
- Check out these new features!
- Proceed to checkout.
* Check out these new features!
* Proceed to checkout.
#### data source
Two words, not one
**Exceptions:**
- "datasource" used as an identifier
- "datasource" in a URL
- Use "data source" instead of "datasource" unless used as an identifier, in code, or as part of a URL.
- Spell out "repository" and avoid the shorter "repo."
- Use "Unix" as the preferred spelling (as opposed to "UNIX", or "unix") when referring to the family of operating systems.
* "datasource" used as an identifier
* "datasource" in a URL
* Use "data source" instead of "datasource" unless used as an identifier, in code, or as part of a URL.
* Spell out "repository" and avoid the shorter "repo."
* Use "Unix" as the preferred spelling (as opposed to "UNIX", or "unix") when referring to the family of operating systems.
#### display (verb)
*Display* is a transitive verb, which means it always needs a direct object.
- Correct, active voice: Grafana displays your list of active alarms.
- Correct, but passive voice: Your list of active alarms is displayed.
- Incorrect: The list of active alarms displays.
#### drawer
Do not use. This is developer jargon that refers to a UI panel. Refer to the panel or feature by its proper name.
* Correct, active voice: Grafana displays your list of active alarms.
* Correct, but passive voice: Your list of active alarms is displayed.
* Incorrect: The list of active alarms displays.
#### intro, introduction
@@ -215,7 +151,7 @@ One word, not two.
#### open source, open-source
Do not hyphenate when used as an adjective unless the lack of hyphen would cause confusion. For example: _Open source software design is the most open open-source system I can imagine._
Do not hyphenate when used as an adjective unless the lack of hyphen would cause confusion. For example: _Open source software design is the most open open-source system I can imagine._
Do not hyphenate when it is used as a noun. For example: _Open source is the best way to develop software._
@@ -225,5 +161,5 @@ Two words if used as a verb, one word if used as a noun.
**Examples**
- Set up the workspace.
- Initial setup might take five minutes.
* Set up the workspace.
* Initial setup might take five minutes.

View File

@@ -1,25 +0,0 @@
# End-to-End Tests for core Grafana
This document is specific to the [Grafana repository](https://github.com/grafana/grafana). Be sure that you've read the [generalized E2E document](e2e.md).
## Commands
- `yarn e2e` Creates an isolated `grafana-server` home under _\<repo-root>/e2e/tmp_ with provisioned data sources and dashboards. This copies locally build binary and frontend assets from your repo root so you need to have a built backend and frontend for this to run locally. The server starts on port 3001 so it does not conflict with your normal dev server.
- `yarn e2e:debug` Same as above but runs the tests in chrome and does not shutdown after completion.
- `yarn e2e:dev` Same as above but does not run any tests on startup. It lets you pick a test first.
If you already have a Grafana instance running, you can provide a specific URL by setting the `BASE_URL` environment variable:
```shell
BASE_URL=http://172.0.10.2:3333 yarn e2e
```
The above commands use some utils scripts under [_\<repo-root>/e2e_](../../e2e) that can also be used for more control.
- `./e2e/start-server` This creates a fresh new grafana server working dir, setup's config and starts the server. It will also kill any previously started server that is still running using pid file at _\<repo-root>/e2e/tmp/pid_.
- `./e2e/wait-for-grafana` waits for `$HOST` and `$PORT` to be available. Per default localhost and 3001.
- `./e2e/run-suite <debug|dev|noarg>` Starts cypress in different modes.
## Test suites
All the integration tests are located at _\<repo-root>/e2e/suite\<x>/specs_. The page objects and reusable flows are in the [_\<repo-root>/packages/grafana-e2e_](../../packages/grafana-e2e) package.

View File

@@ -1,28 +0,0 @@
# End-to-End Tests for plugins
Be sure that you've read the [generalized E2E document](e2e.md).
## Commands
- `yarn test:e2e` will run [Grafana's E2E utility](../../packages/grafana-e2e) against an already running Grafana server.
- `yarn test:e2e:update` will run `test:e2e` but instead of asserting that screenshots match their expected fixtures, they'll be replaced with new ones.
Your running Grafana instance can be targeted by setting the `CYPRESS_BASE_URL`, `CYPRESS_USERNAME` and `CYPRESS_PASSWORD` environment variableS:
```shell
CYPRESS_BASE_URL=https://localhost:3000 CYPRESS_USERNAME=admin CYPRESS_PASSWORD=admin yarn test:e2e
```
## Test suites
All tests are located at _\<repo-root>/cypress/integration_ by default.
## Things to test
- Add data source (if applicable)
- Add panel
- Edit panel
- Annotations (if applicable)
- Aliases (if applicable)
- Template variables
- "Explore" view

View File

@@ -1,122 +1,132 @@
# End-to-End tests
# End to end test framework
Grafana Labs uses a minimal [homegrown solution](../../packages/grafana-e2e) built on top of [Cypress](https://cypress.io) for its end-to-end (E2E) tests.
Grafana Labs uses a minimal home grown solution built on top of Cypress for our end to end (e2e) tests.
Important notes:
## Commands
- We generally store all element identifiers ([CSS selectors](https://mdn.io/docs/Web/CSS/CSS_Selectors)) within the framework for reuse and maintainability.
- We generally do not use stubs or mocks as to fully simulate a real user.
- Cypress' promises [do not behave as you'd expect](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Mixing-Async-and-Sync-code).
- [Testing core Grafana](e2e-core.md) is slightly different than [testing plugins](e2e-plugins.md).
- `yarn e2e` Creates an isolated grafana-server home under `<repo-root>/e2e/tmp` with provisioned data sources and dashboards. This
copies locally build binary and frontned assets from your repo root so you need to have a built backend and frontend
for this to run locally. The server starts on port 3001 so it does not conflict with your normal dev server.
- `yarn e2e:debug` Same as above but runs the tests in chrome and does not shutdown after completion.
- `yarn e2e:dev` Same as above but does not run any tests on startup. It lets you pick a test first.
## Framework structure
The above commands use some utils scripts under `<repo-root>/e2e` that can also be used for more control.
Inspired by https://martinfowler.com/bliki/PageObject.html
- `./e2e/start-server` This creates a fresh new grafana server working dir, setup's config and starts the server. It
will also kill any previously started server that is still running using pid file at `<repo-root>/e2e/tmp/pid`.
- `./e2e/run-suite <debug|dev|noarg>` Starts cypress in different modes.
- `Selector`: A unique identifier that is used from the E2E framework to retrieve an element from the Browser
## Test Suites
All the integration tests are located at `e2e/suite<x>/specs`. The page objects and reusable flows are in the
`packages/grafana-e2e` package.
## Basic concepts
Here is a good introduction to e2e best practices: https://martinfowler.com/bliki/PageObject.html.
- `Selector`: A unique identifier that is used from the e2e framework to retrieve an element from the Browser
- `Page`: An abstraction for an object that contains one or more `Selectors` with `visit` function to navigate to the page.
- `Component`: An abstraction for an object that contains one or more `Selectors` but without `visit` function
- `Flow`: An abstraction that contains a sequence of actions on one or more `Pages` that can be reused and shared between tests
## Basic example
Let's start with a simple [JSX](https://reactjs.org/docs/introducing-jsx.html) example containing a single input field that we want to populate during our E2E test:
Let's start with a simple example with a single selector. For simplicity, all examples are in JSX.
```jsx
<input
className="gf-form-input login-form-input"
type="text"
/>
In our example app, we have an input that we want to type some text into during our e2e test.
```jsx harmony
<div>
<input type="text" className="gf-form-input login-form-input" />
</div>
```
We _could_ target the field with a CSS selector like `.gf-form-input.login-form-input` but that would be brittle as style changes occur frequently. Furthermore there is nothing that signals to future developers that this input is part of an E2E test. At Grafana, we use `aria-label` attributes as our preferred way of defining selectors instead of [`data-*`](https://mdn.io/docs/Web/HTML/Global_attributes/data-*) as they also aid in [accessibility](https://mdn.io/docs/Learn/Accessibility/What_is_accessibility):
We could define a selector using `JQuery` [type selectors](https://api.jquery.com/category/selectors/) with a string like `'.gf-form-input.login-form-input'` but that would be brittle as style changes occur frequently. Furthermore there is nothing that signals to future developers that this input is part of an e2e test.
```jsx
<input
aria-label="Username input field"
className="gf-form-input login-form-input"
type="text"
/>
At Grafana, we use `aria-label` as our preferred way of defining selectors instead of `data-*` attributes. This also aids in accessibility.
Let's add a descriptive `aria-label` to our simple example.
```jsx harmony
<div>
<input type="text" className="gf-form-input login-form-input" aria-label="Username input field" />
</div>
```
The next step is to create a `Page` representation in our E2E framework to glue the test with the real implementation using the `pageFactory` function. For that function we can supply a `url` and `selectors` like in the example below:
Now that we added the `aria-label` we suddenly get more information about this particular field. It's an input field that represents a username, but there it's still not really signaling that it's part of an e2e test.
The next step is to create a `Page` representation in our e2e test framework to glue the test with the real implementation using the `pageFactory` function. For that function we can supply a `url` and `selectors` like in the example below:
```typescript
export const Login = {
// Called via `Login.visit()`
url: '/login',
// Called via `Login.username()`
username: 'Username input field',
url: "/login", // used when called from Login.visit()
username: "Username input field", // used when called from Login.username().type('Hello World')
};
```
The next step is to add the `Login` page to the `Pages` export within [_\<repo-root>/packages/grafana-e2e-selectors/src/selectors/pages.ts_](../../packages/grafana-e2e-selectors/src/selectors/pages.ts) so that it appears when we type `e2e.pages` in our IDE.
The next step is to add the `Login` page to the exported const `Pages` in `packages/grafana-e2e-selectors/src/selectors/pages.ts` so that it appears when we type `e2e.pages` in our IDE.
```typescript
```ecmascript 6
export const Pages = {
Login,
,
,
,
...,
...,
...,
};
```
Now that we have a `Page` called `Login` in our `Pages` const we can use that to add a selector in our html like shown below and now this really signals to future developers that it is part of an E2E test.
Now that we have a `Page` called `Login` in our `Pages` const we can use that to add a selector in our html like shown below and now this really signals to future developers that it is part of an e2e test.
```jsx
import { selectors } from '@grafana/e2e-selectors';
<input
aria-label={selectors.pages.Login.username}
className="gf-form-input login-form-input"
type="text"
/>
```jsx harmony
<div>
<input type="text" className="gf-form-input login-form-input" aria-label={selectors.pages.Login.username} />
</div>
```
The last step in our example is to use our `Login` page as part of a test.
- The `url` property is used whenever we call the `visit` function and is equivalent to the Cypress' [`cy.visit()`](https://docs.cypress.io/api/commands/visit.html#Syntax).
- The `url` property is used whenever we call the `visit` function and is equivalent to the Cypress function [cy.visit()](https://docs.cypress.io/api/commands/visit.html#Syntax).
> Best practice after calling `visit` is to always call `should` on a selector to prevent flaky tests when you try to access an element that isn't ready. For more information, refer to [Commands vs. assertions](https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions).
- Any defined selector can be accessed from the `Login` page by invoking it. This is equivalent to the result of the Cypress function [cy.get(...)](https://docs.cypress.io/api/commands/get.html#Syntax).
- Any defined selector can be accessed from the `Login` page by invoking it. This is equivalent to the result of the Cypress function [`cy.get(…)`](https://docs.cypress.io/api/commands/get.html#Syntax).
```typescript
```ecmascript 6
describe('Login test', () => {
it('passes', () => {
it('Should pass', () => {
e2e.pages.Login.visit();
// To prevent flaky tests, always do a `.should` on any selector that you expect to be in the DOM.
// To prevent flaky tests, always do a .should on any selector that you expect to be in the DOM.
// Read more here: https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions
e2e.pages.Login.username()
.should('be.visible')
.type('admin');
e2e.pages.Login.username().should('be.visible');
e2e.pages.Login.username().type('admin');
});
});
```
## Advanced example
Let's take a look at an example that uses the same `selector` for multiple items in a list for instance. In this example app we have a list of data sources that we want to click on during an E2E test.
Let's take a look at an example that uses the same `selector` for multiple items in a list for instance. In this example app we have a list of data sources that we want to click on during an e2e test.
```jsx
```jsx harmony
<ul>
{dataSources.map(({ id, name }) => (
<li className="card-item-wrapper" key={id}>
<a className="card-item" href={`datasources/edit/${id}`}>
<div className="card-item-name">{name}</div>
{dataSources.map(dataSource => (
<li className="card-item-wrapper" key={dataSource.id}>
<a className="card-item" href={`datasources/edit/${dataSource.id}`}>
<div className="card-item-name">{dataSource.name}</div>
</a>
</li>
))}
</ul>
```
Just as before in the basic example we'll start by creating a page abstraction using the `pageFactory` function:
````
Just as before in the basic example we'll start by creating a page abstraction using the `pageFactory` function:
```typescript
export const DataSources = {
url: '/datasources',
dataSources: (dataSourceName: string) => `Data source list item ${dataSourceName}`,
};
```
````
You might have noticed that instead of a simple `string` as the `selector`, we're using a `function` that takes a string parameter as an argument and returns a formatted string using the argument.
@@ -124,13 +134,13 @@ Just as before we need to add the `DataSources` page to the exported const `Page
The next step is to use the `dataSources` selector function as in our example below:
```jsx
```jsx harmony
<ul>
{dataSources.map(({ id, name }) => (
<li className="card-item-wrapper" key={id}>
<a className="card-item" href={`datasources/edit/${id}`}>
<div className="card-item-name" aria-label={selectors.pages.DataSources.dataSources(name)}>
{name}
{dataSources.map(dataSource => (
<li className="card-item-wrapper" key={dataSource.id}>
<a className="card-item" href={`datasources/edit/${dataSource.id}`}>
<div className="card-item-name" aria-label={selectors.pages.DataSources.dataSources(dataSource.name)}>
{dataSource.name}
</div>
</a>
</li>
@@ -138,25 +148,55 @@ The next step is to use the `dataSources` selector function as in our example be
</ul>
```
When this list is rendered with the data sources with names `A`, `B` and `C` ,the resulting HTML would look like:
When this list is rendered with the data sources with names `A`, `B`, `C` the resulting html would become:
```html
<div class="card-item-name" aria-label="Data source list item A">A</div>
<div class="card-item-name" aria-label="Data source list item B">B</div>
<div class="card-item-name" aria-label="Data source list item C">C</div>
```jsx harmony
<div class="card-item-name" aria-label="Data source list item A">
A
</div>
...
<div class="card-item-name" aria-label="Data source list item B">
B
</div>
...
<div class="card-item-name" aria-label="Data source list item C">
C
</div>
```
Now we can write our test. The one thing that differs from the [basic example](#basic-example) above is that we pass in which data source we want to click on as an argument to the selector function:
Now we can write our test. The one thing that differs from the `Basic example` is that we pass in which data source we want to click on as an argument to the selector function:
```typescript
> Best practice after calling `visit` is to always call `should` on a selector to prevent flaky tests when you try to access an element that isn't ready. For more information, refer to [Commands vs. assertions](https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions).
```ecmascript 6
describe('List test', () => {
it('clicks on data source named B', () => {
it('Clicking on data source named B', () => {
e2e.pages.DataSources.visit();
// To prevent flaky tests, always do a .should on any selector that you expect to be in the DOM.
// Read more here: https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions
e2e.pages.DataSources.dataSources('B')
.should('be.visible')
.click();
e2e.pages.DataSources.dataSources('B').should('be.visible');
e2e.pages.DataSources.dataSources('B').click();
});
});
```
## Debugging PhantomJS image rendering
### Common Error
The most common error with PhantomJs image rendering is when a PR introduces an import that has functionality that's not supported by PhantomJs. To quickly identify which new import causes this you can use a tool like `es-check`.
1. Run > `npx es-check es5 './public/build/*.js'`
2. Check the output for files that break es5 compatibility.
3. Lazy load the failing imports if possible.
### Debugging
There is no easy or comprehensive way to debug PhantomJS smoke test (image rendering) failures. However, PhantomJS exposes remote debugging interface which can give you a sense of what is going wrong in the smoke test. Before performing the steps described below make sure your local Grafana instance is running:
1. Go to `tools/phantomjs` directory
2. Execute `phantomjs` binary against `render.js` file: `./phantomjs --remote-debugger-port=9009 --remote-debugger-autorun=yes ./render.js url="http://localhost:3000"`
3. In your browser navigate to `http://localhost:9009/`
4. Select `http://localhost:3000/login` from the list. You will get access to Webkit's inspector to see the console's output from the smoke test.
The method described above is not perfect, but is helpful to evaluate smoke tests breaking due to bundle errors.

View File

@@ -7,34 +7,14 @@ Generally we follow the Airbnb [React Style Guide](https://github.com/airbnb/jav
- [Frontend Style Guide](#frontend-style-guide)
- [Table of Contents](#table-of-contents)
- [Basic rules](#basic-rules)
- [Naming conventions](#naming-conventions)
- [Use `PascalCase` for:](#use-pascalcase-for)
- [Typescript class names](#typescript-class-names)
- [Types and interfaces](#types-and-interfaces)
- [Enums](#enums)
- [Use `camelCase` for:](#use-camelcase-for)
- [Functions](#functions)
- [Methods](#methods)
- [Variables](#variables)
- [React state and properties](#react-state-and-properties)
- [Emotion class names](#emotion-class-names)
- [Use `ALL_CAPS` for constants.](#use-all_caps-for-constants)
- [Use BEM convention for SASS styles.](#use-bem-convention-for-sass-styles)
- [Typing](#typing)
- [File and directory naming conventions](#file-and-directory-naming-conventions)
- [Code organization](#code-organization)
- [Exports](#exports)
- [Comments](#comments)
- [Linting](#linting)
- [Naming conventions](#naming-conventions)
- [Files and directories naming conventions](#files-and-directories-naming-conventions)
- [Code organization](#code-organization)
- [Exports](#exports)
- [Comments](#comments)
- [React](#react)
- [Props](#props)
- [Name callback props and handlers with an "on" prefix.](#name-callback-props-and-handlers-with-an-on-prefix)
- [React Component definitions](#react-component-definitions)
- [React Component constructor](#react-component-constructor)
- [React Component defaultProps](#react-component-defaultprops)
- [State management](#state-management)
- [Proposal for removing or replacing Angular dependencies](https://github.com/grafana/grafana/pull/23048)
## Basic rules
@@ -127,7 +107,7 @@ class DateCalculator {
}
class DateCalculator {
// bad
calculate_time_range () {...}
calculate_timee_range () {...}
}
class DateCalculator {
@@ -167,7 +147,7 @@ interface ModalState {
```typescript
const getStyles = = () => ({
// bad
ElementWrapper: css`...`,
ElementWraper: css`...`,
// bad
["element-wrapper"]: css`...`,
@@ -192,44 +172,6 @@ const CONSTANT_VALUE = "This string won't change";
_SASS styles are deprecated. Please migrate to Emotion whenever you need to modify SASS styles._
### Typing
In general, you should let Typescript infer the types so that there's no need to explicitly define type for each variable.
There are some exceptions to this:
```typescript
// Typescript needs to know type of arrays or objects otherwise it would infer it as array of any
// bad
const stringArray = [];
// good
const stringArray: string[] = [];
```
Specify function return types explicitly in new code. This improves readability by being able to tell what a function returns just by looking at the signature. It also prevents errors when a function's return type is broader than expected by the author.
> **Note:** We don't have linting for this enabled because of lots of old code that needs to be fixed first.
```typescript
// bad
function transform(value?: string) {
if (!value) {
return undefined
}
return applyTransform(value)
};
// good
function transform(value?: string): TransformedValue | undefined {
if (!value) {
return undefined
}
return applyTransform(value)
};
```
### File and directory naming conventions
Name files according to the primary export:
@@ -344,6 +286,6 @@ static defaultProps: Partial<Props> = { ... }
## State management
- Don't mutate state in reducers or thunks.
- Use `createSlice`. See [Redux Toolkit](https://redux-toolkit.js.org/) for more details.
- Use helpers `actionCreatorFactory` and `reducerFactory` instead of traditional `switch statement` reducers in Redux. See [Redux framework](redux.md) for more details.
- Use `reducerTester` to test reducers. See [Redux framework](redux.md) for more details.
- Use state selectors to access state instead of accessing state directly.

View File

@@ -23,27 +23,6 @@ const ComponentA = () => (
);
```
### Styling with theme
To access the theme in your styles, use the `useStyles` hook. It provides basic memoization and access to the theme object.
```tsx
import React, { FC } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { useStyles } from '@grafana/ui';
import { css } from 'emotion';
const getComponentStyles = (theme: GrafanaTheme) => css`
padding: ${theme.spacing.md};
`;
const Foo: FC<FooProps> = () => {
const styles = useStyles(getComponentsStyles);
// Use styles with className
};
```
### Styling complex components
In more complex cases, especially when you need to style multiple DOM elements in one component, or when using styles that depend on properties and/or state, you should create a helper function that returns an object of styles. This function should also be wrapped in the `stylesFactory` helper function, which will provide basic memoization.
@@ -57,7 +36,10 @@ import { GrafanaTheme } from '@grafana/data';
import { selectThemeVariant, stylesFactory, useTheme } from '@grafana/ui';
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const backgroundColor = selectThemeVariant({ light: theme.colors.red, dark: theme.colors.blue }, theme.type);
const backgroundColor = selectThemeVariant(
{ light: theme.colors.red, dark: theme.colors.blue },
theme.type
);
return {
wrapper: css`

View File

@@ -18,40 +18,6 @@ This section provides usage guidelines.
Here's how to use Grafana themes in React components.
#### useStyles hook
`useStyles` memoizes the function and provides access to the theme.
```tsx
import React, { FC } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { useStyles } from '@grafana/ui';
import { css } from 'emotion';
const getComponentStyles = (theme: GrafanaTheme) => css`
padding: ${theme.spacing.md};
`;
const Foo: FC<FooProps> = () => {
const styles = useStyles(getComponentsStyles);
// Use styles with className
};
```
#### Get the theme object
```tsx
import React, { FC } from 'react';
import { useTheme } from '@grafana/ui';
const Foo: FC<FooProps> = () => {
const theme = useTheme();
// Your component has access to the theme variables now
};
```
#### Using `ThemeContext` directly
```tsx
@@ -60,6 +26,19 @@ import { ThemeContext } from '@grafana/ui';
<ThemeContext.Consumer>{theme => <Foo theme={theme} />}</ThemeContext.Consumer>;
```
or
```tsx
import React, { useContext } from 'react';
import { ThemeContext } from '@grafana/ui';
const Foo: React.FunctionComponent<FooProps> = () => {
const theme = useContext(ThemeContext);
// Your component has access to the theme variables now
}
```
#### Using `withTheme` higher-order component (HOC)
With this method your component will be automatically wrapped in `ThemeContext.Consumer` and provided with current theme via `theme` prop. Components used with `withTheme` must implement the `Themeable` interface.
@@ -97,38 +76,69 @@ describe('MyComponent', () => {
restoreThemeContext();
});
it('renders correctly', () => {
it('renders correctyl', () => {
const wrapper = mount(<MyComponent />)
expect(wrapper).toMatchSnapshot();
});
});
```
### Using themes in [Storybook](https://storybook.js.org/)
All stories are wrapped with `ThemeContext.Provider` using a global decorator. To render a `Themeable` component that isn't wrapped by a `withTheme` HOC, either create a new component in your story, or use the `renderComponentWithTheme` helper.
#### Create a new component:
```tsx
// Foo.story.tsx
const FooWithTheme = withTheme(Foo);
FooStories.add('Story' () => {
return <FooWithTheme />
});
```
#### Use `renderComponentWithTheme` helper:
```tsx
// Bar.story.tsx
BarStories.add('Story' () => {
return renderComponentWithTheme(Bar, /* pass props here */)
});
```
### Using themes in Angular code
There should be very few cases where a theme would be used in an Angular context. For this purpose, there is a function available that retrieves the current theme:
```ts
import { getCurrentTheme } from app/core/utils/ConfigProvider
```
Angular components should be migrated to React, or if that's not possible at the moment, styled using Sass.
## FAQ
This section provides insight into frequently-asked questions.
### How can I modify Sass variable files?
**If possible, migrate styles to Emotion**
> For the following to apply you need to run `yarn dev` task.
`[_variables|_variables.dark|_variables.light].generated.scss` files are the ones that are referenced in the main Sass files for Sass variables to be available. **These files are automatically generated and should never be modified by hand!**
#### If you need to modify a _Sass variable value_ you need to modify the corresponding Typescript file that is the source of the variables:
#### If you need to modify a *Sass variable value* you need to modify the corresponding Typescript file that is the source of the variables:
- `_variables.generated.scss` - modify `grafana-ui/src/themes/default.ts`
- `_variables.light.generated.scss` - modify `grafana-ui/src/themes/light.ts`
- `_variables.dark.generated.scss` - modify `grafana-ui/src/themes/dark.ts`
#### If you need to _add new variable_ to Sass variables you need to modify corresponding template file:
#### If you need to *add new variable* to Sass variables you need to modify corresponding template file:
- `_variables.generated.scss` - modify `grafana-ui/src/themes/_variables.scss.tmpl.ts`
- `_variables.light.generated.scss` - modify `grafana-ui/src/themes/_variables.light.scss.tmpl.ts`
- `_variables.dark.generated.scss` - modify `grafana-ui/src/themes/_variables.dark.scss.tmpl.ts`
## Limitations
This section describes limitations with Grafana's theming system.

View File

@@ -26,19 +26,19 @@ Try to *chunk* your content. This means you should organize the document so that
If I was writing content for a site called *Doggie handbook*, I might organize it like this.
**Concept**
- What a dog is
- Brief history of dogs
- Why you might want a dog
- Tasks dogs can be trained to do
* What a dog is
* Brief history of dogs
* Why you might want a dog
* Tasks dogs can be trained to do
**Tasks**
- Feed the dog
- Groom the dog
- Train the dog
* Feed the dog
* Groom the dog
* Train the dog
**Reference**
- List of dog equipment you will need
- Table of breeds that includes breed name, size range, short or long hair, and type of dog
* List of dog equipment you will need
* Table of breeds that includes breed name, size range, short or long hair, and type of dog
### Audience

View File

@@ -30,12 +30,12 @@ Concept topics or sections explain *what* and *why*. They do not explain *how*.
Continuing the example in the previous section, here is a sample Grafana workflow.
1. Install Grafana. <link to task for installing Grafana>
1. Set up data sources. <link to data sources concept topic, which links to data source task topics>
1. Create panels. <link to panel concept topic, which links to tasks>
1. Create dashboards. <link to panel concept topic, which links to tasks>
1. Enter queries. <link to query editor concept topic>
1. Add users. <link to user management concept topic, which links to tasks>
1. Create playlists. <link to Playlist topic that contains concept information and tasks>
2. Set up data sources. <link to data sources concept topic, which links to data source task topics>
3. Create panels. <link to panel concept topic, which links to tasks>
4. Create dashboards. <link to panel concept topic, which links to tasks>
5. Enter queries. <link to query editor concept topic>
6. Add users. <link to user management concept topic, which links to tasks>
7. Create playlists. <link to Playlist topic that contains concept information and tasks>
## Next steps

View File

@@ -25,9 +25,9 @@ Often reference topics are linked from *task* topics, because they contain infor
Lists of commands or parameters are often organized in reference topics. The information you need to present will dictate the format.
- They might
- be in
- unordered lists.
* They might
* be in
* unordered lists.
[Configuration](https://grafana.com/docs/grafana/latest/installation/configuration/) is an example of lists.

View File

@@ -42,7 +42,7 @@ Write one-step tasks as simple sentences, not as unordered lists or numbered lis
Short tasks can be grouped. How short constitutes "short" is a judgment call based on number of steps and how long individual steps are.
1. Use your judgment.
1. Ask your coworkers or someone on the Comm team for advice if you aren't sure.
2. Ask your coworkers or someone on the Comm team for advice if you aren't sure.
## Next steps

View File

@@ -2,9 +2,9 @@
This folder contains useful scripts and configuration so you can:
- Configure data sources in Grafana for development.
- Configure dashboards for development and test scenarios.
- Create docker-compose file with databases and fake data.
* Configure data sources in Grafana for development.
* Configure dashboards for development and test scenarios.
* Create docker-compose file with databases and fake data.
## Install Docker
@@ -39,11 +39,4 @@ Some of the blocks support dynamic change of the image version used in the Docke
make devenv sources=postgres,openldap,grafana postgres_version=9.2 grafana_version=6.7.0-beta1
```
### Notes per block
#### Grafana
The grafana block is pre-configured with the dev-datasources and dashboards.
#### Jaeger
Jaeger block runs both Jaeger and Loki container. Loki container sends traces to Jaeger and also logs its own logs into itself so it is possible to setup derived field for traceID from Loki to Jaeger. You need to install a docker plugin for the self logging to work, without it the container won't start. See https://github.com/grafana/loki/tree/master/cmd/docker-driver#plugin-installation for installation instructions.
Note: The grafana block is pre-configured with the dev-datasources and dashboards.

View File

@@ -1,3 +1,4 @@
apiVersion: 1
datasources:
@@ -225,7 +226,6 @@ datasources:
jsonData:
authType: credentials
defaultRegion: eu-west-2
customMetricsNamespaces: "CWAgent"
# Keep to test old /api/prom API
- name: gdev-loki-0.3
@@ -246,27 +246,5 @@ datasources:
access: proxy
url: http://localhost:3100
editable: false
jsonData:
derivedFields:
- name: "traceID"
matcherRegex: "traceID=(\\w+)"
url: "$${__value.raw}"
datasourceUid: gdev-jaeger
- name: "traceID"
matcherRegex: "traceID=(\\w+)"
url: "$${__value.raw}"
datasourceUid: gdev-zipkin
- name: gdev-jaeger
type: jaeger
uid: gdev-jaeger
access: proxy
url: http://localhost:16686
editable: false
- name: gdev-zipkin
type: zipkin
uid: gdev-zipkin
access: proxy
url: http://localhost:9411
editable: false

View File

@@ -454,7 +454,7 @@
"yaxes": [
{
"format": "percent",
"label": "Percent",
"label": "Perecent",
"logBase": 1,
"max": null,
"min": null,
@@ -1632,7 +1632,10 @@
"revision": 8,
"schemaVersion": 16,
"style": "dark",
"tags": ["gdev", "panel-tests"],
"tags": [
"gdev",
"panel-tests"
],
"templating": {
"list": []
},
@@ -1641,8 +1644,29 @@
"to": "now"
},
"timepicker": {
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "browser",
"title": "Panel Tests - Graph",

View File

@@ -428,14 +428,6 @@
{
"text": "Bitcoin (฿)",
"value": "currencyBTC"
},
{
"text": "Milli Bitcoin (mBTC)",
"value": "currencymBTC"
},
{
"text": "Micro Bitcoin (μBTC)",
"value": "currencyμBTC"
}
],
"text": "currency"

View File

@@ -28,7 +28,7 @@
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1591027568655,
"iteration": 1554310942895,
"links": [
{
"asDropdown": true,
@@ -47,14 +47,7 @@
"datasource": "gdev-elasticsearch-v2-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
@@ -62,7 +55,6 @@
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 1,
"legend": {
"alignAsTable": true,
@@ -79,9 +71,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -181,14 +170,7 @@
"datasource": "gdev-elasticsearch-v2-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 6,
@@ -196,7 +178,6 @@
"x": 0,
"y": 7
},
"hiddenSeries": false,
"id": 2,
"legend": {
"alignAsTable": true,
@@ -213,9 +194,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -314,14 +292,7 @@
"datasource": "gdev-elasticsearch-v2-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 6,
@@ -329,7 +300,6 @@
"x": 12,
"y": 7
},
"hiddenSeries": false,
"id": 3,
"legend": {
"alignAsTable": true,
@@ -346,9 +316,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -460,12 +427,6 @@
"datasource": "gdev-elasticsearch-v2-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fontSize": "100%",
"gridPos": {
"h": 7,
@@ -484,13 +445,11 @@
},
"styles": [
{
"align": "auto",
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"pattern": "@timestamp",
"type": "date"
},
{
"align": "auto",
"colorMode": null,
"colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
"dateFormat": "YYYY-MM-DD HH:mm:ss",
@@ -546,7 +505,7 @@
],
"title": "ES Metrics",
"transform": "table",
"type": "table-old"
"type": "table"
},
{
"columns": [
@@ -570,12 +529,6 @@
"datasource": "gdev-elasticsearch-v2-logs",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fontSize": "100%",
"gridPos": {
"h": 7,
@@ -594,7 +547,6 @@
},
"styles": [
{
"align": "auto",
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"pattern": "@timestamp",
"type": "date"
@@ -622,7 +574,7 @@
],
"title": "ES Log query",
"transform": "json",
"type": "table-old"
"type": "table"
},
{
"circleMaxSize": 30,
@@ -632,12 +584,6 @@
"decimals": 0,
"esGeoPoint": "@location",
"esMetric": "Average",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"gridPos": {
"h": 12,
"w": 24,
@@ -699,7 +645,7 @@
"valueName": "total"
}
],
"schemaVersion": 25,
"schemaVersion": 18,
"style": "dark",
"tags": ["elasticsearch", "gdev", "datasource-test"],
"templating": {
@@ -732,5 +678,5 @@
"timezone": "browser",
"title": "Datasource tests - Elasticsearch v2",
"uid": "RlqLq2fiz",
"version": 1
"version": 5
}

View File

@@ -28,7 +28,7 @@
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1591027589702,
"iteration": 1554310560048,
"links": [
{
"asDropdown": true,
@@ -47,14 +47,7 @@
"datasource": "gdev-elasticsearch-v5-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
@@ -62,7 +55,6 @@
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 1,
"legend": {
"alignAsTable": true,
@@ -79,9 +71,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -181,14 +170,7 @@
"datasource": "gdev-elasticsearch-v5-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 6,
@@ -196,7 +178,6 @@
"x": 0,
"y": 7
},
"hiddenSeries": false,
"id": 2,
"legend": {
"alignAsTable": true,
@@ -213,9 +194,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -314,14 +292,7 @@
"datasource": "gdev-elasticsearch-v5-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 6,
@@ -329,7 +300,6 @@
"x": 12,
"y": 7
},
"hiddenSeries": false,
"id": 3,
"legend": {
"alignAsTable": true,
@@ -346,9 +316,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -460,12 +427,6 @@
"datasource": "gdev-elasticsearch-v5-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fontSize": "100%",
"gridPos": {
"h": 7,
@@ -484,13 +445,11 @@
},
"styles": [
{
"align": "auto",
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"pattern": "@timestamp",
"type": "date"
},
{
"align": "auto",
"colorMode": null,
"colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
"dateFormat": "YYYY-MM-DD HH:mm:ss",
@@ -546,7 +505,7 @@
],
"title": "ES Metrics",
"transform": "table",
"type": "table-old"
"type": "table"
},
{
"columns": [
@@ -570,12 +529,6 @@
"datasource": "gdev-elasticsearch-v5-logs",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fontSize": "100%",
"gridPos": {
"h": 7,
@@ -594,7 +547,6 @@
},
"styles": [
{
"align": "auto",
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"pattern": "@timestamp",
"type": "date"
@@ -622,7 +574,7 @@
],
"title": "ES Log query",
"transform": "json",
"type": "table-old"
"type": "table"
},
{
"circleMaxSize": 30,
@@ -633,12 +585,6 @@
"esGeoPoint": "@location",
"esLocationName": "",
"esMetric": "Average",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"gridPos": {
"h": 12,
"w": 24,
@@ -700,7 +646,7 @@
"valueName": "total"
}
],
"schemaVersion": 25,
"schemaVersion": 18,
"style": "dark",
"tags": ["elasticsearch", "gdev", "datasource-test"],
"templating": {
@@ -733,5 +679,5 @@
"timezone": "browser",
"title": "Datasource tests - Elasticsearch v5",
"uid": "8HjT32Bmz",
"version": 1
"version": 5
}

View File

@@ -28,7 +28,7 @@
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1591027529668,
"iteration": 1554310839317,
"links": [
{
"asDropdown": true,
@@ -47,14 +47,7 @@
"datasource": "gdev-elasticsearch-v6-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
@@ -62,7 +55,6 @@
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 1,
"legend": {
"alignAsTable": true,
@@ -79,9 +71,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -181,14 +170,7 @@
"datasource": "gdev-elasticsearch-v6-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 6,
@@ -196,7 +178,6 @@
"x": 0,
"y": 7
},
"hiddenSeries": false,
"id": 2,
"legend": {
"alignAsTable": true,
@@ -213,9 +194,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -314,14 +292,7 @@
"datasource": "gdev-elasticsearch-v6-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 6,
@@ -329,7 +300,6 @@
"x": 12,
"y": 7
},
"hiddenSeries": false,
"id": 3,
"legend": {
"alignAsTable": true,
@@ -346,9 +316,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -460,12 +427,6 @@
"datasource": "gdev-elasticsearch-v6-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fontSize": "100%",
"gridPos": {
"h": 7,
@@ -484,13 +445,11 @@
},
"styles": [
{
"align": "auto",
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"pattern": "@timestamp",
"type": "date"
},
{
"align": "auto",
"colorMode": null,
"colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
"dateFormat": "YYYY-MM-DD HH:mm:ss",
@@ -546,7 +505,7 @@
],
"title": "ES Metrics",
"transform": "table",
"type": "table-old"
"type": "table"
},
{
"columns": [
@@ -570,12 +529,6 @@
"datasource": "gdev-elasticsearch-v6-logs",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fontSize": "100%",
"gridPos": {
"h": 7,
@@ -594,7 +547,6 @@
},
"styles": [
{
"align": "auto",
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"pattern": "@timestamp",
"type": "date"
@@ -622,7 +574,7 @@
],
"title": "ES Log query",
"transform": "json",
"type": "table-old"
"type": "table"
},
{
"circleMaxSize": 30,
@@ -632,12 +584,6 @@
"decimals": 0,
"esGeoPoint": "@location",
"esMetric": "Average",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"gridPos": {
"h": 12,
"w": 24,
@@ -699,8 +645,7 @@
"valueName": "total"
}
],
"refresh": false,
"schemaVersion": 25,
"schemaVersion": 18,
"style": "dark",
"tags": ["elasticsearch", "gdev", "datasource-test"],
"templating": {
@@ -717,7 +662,7 @@
]
},
"time": {
"from": "now-1h",
"from": "now-30m",
"to": "now"
},
"timepicker": {
@@ -733,5 +678,5 @@
"timezone": "browser",
"title": "Datasource tests - Elasticsearch v6",
"uid": "NF8Pq2Biz",
"version": 1
"version": 5
}

View File

@@ -15,7 +15,7 @@
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1591027621672,
"iteration": 1554902936982,
"links": [
{
"asDropdown": true,
@@ -34,21 +34,13 @@
"dashLength": 10,
"dashes": false,
"datasource": "gdev-elasticsearch-v6-filebeat",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 5,
"w": 24,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 4,
"legend": {
"avg": false,
@@ -62,9 +54,6 @@
"lines": false,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 2,
"points": false,
@@ -153,13 +142,22 @@
}
},
{
"datasource": "gdev-elasticsearch-v6-filebeat",
"fieldConfig": {
"defaults": {
"custom": {}
"columns": [
{
"text": "@timestamp",
"value": "@timestamp"
},
"overrides": []
},
{
"text": "fields.level",
"value": "fields.level"
},
{
"text": "message",
"value": "message"
}
],
"datasource": "gdev-elasticsearch-v6-filebeat",
"fontSize": "100%",
"gridPos": {
"h": 22,
"w": 24,
@@ -168,35 +166,58 @@
},
"id": 2,
"links": [],
"options": {
"showLabels": false,
"showTime": true,
"sortOrder": "Descending",
"wrapLogMessage": true
"pageSize": null,
"scroll": true,
"showHeader": true,
"sort": {
"col": 0,
"desc": true
},
"styles": [
{
"alias": "Time",
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"pattern": "@timestamp",
"type": "date"
},
{
"alias": "Level",
"colorMode": null,
"colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"decimals": 2,
"mappingType": 1,
"pattern": "fields.level",
"thresholds": [""],
"type": "string",
"unit": "short",
"valueMaps": []
},
{
"alias": "Message",
"colorMode": null,
"colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
"decimals": 2,
"pattern": "message",
"preserveFormat": false,
"sanitize": false,
"thresholds": [],
"type": "string",
"unit": "short"
}
],
"targets": [
{
"bucketAggs": [
{
"$$hashKey": "object:394",
"field": "@timestamp",
"id": "2",
"settings": {
"interval": "auto",
"min_doc_count": 0,
"trimEdges": 0
},
"type": "date_histogram"
}
],
"bucketAggs": [],
"metrics": [
{
"$$hashKey": "object:359",
"field": "select field",
"id": "1",
"meta": {},
"settings": {},
"type": "logs"
"settings": {
"size": 500
},
"type": "raw_document"
}
],
"query": "fields.app:grafana",
@@ -207,10 +228,11 @@
"timeFrom": null,
"timeShift": null,
"title": "Panel Title",
"type": "logs"
"transform": "json",
"type": "table"
}
],
"schemaVersion": 25,
"schemaVersion": 18,
"style": "dark",
"tags": ["gdev", "elasticsearch", "datasource-test"],
"templating": {
@@ -227,7 +249,7 @@
]
},
"time": {
"from": "now-30m",
"from": "now-1h",
"to": "now"
},
"timepicker": {
@@ -237,5 +259,5 @@
"timezone": "",
"title": "Datasource tests - Elasticsearch v6 Filebeat",
"uid": "06tPt4gZz",
"version": 1
"version": 8
}

View File

@@ -28,7 +28,8 @@
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1591027717495,
"id": 2342,
"iteration": 1555593977614,
"links": [
{
"asDropdown": true,
@@ -47,14 +48,7 @@
"datasource": "gdev-elasticsearch-v7-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
@@ -62,7 +56,6 @@
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 1,
"legend": {
"alignAsTable": true,
@@ -79,9 +72,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -181,14 +171,7 @@
"datasource": "gdev-elasticsearch-v7-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 6,
@@ -196,7 +179,6 @@
"x": 0,
"y": 7
},
"hiddenSeries": false,
"id": 2,
"legend": {
"alignAsTable": true,
@@ -213,9 +195,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -314,14 +293,7 @@
"datasource": "gdev-elasticsearch-v7-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 6,
@@ -329,7 +301,6 @@
"x": 12,
"y": 7
},
"hiddenSeries": false,
"id": 3,
"legend": {
"alignAsTable": true,
@@ -346,9 +317,6 @@
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -460,12 +428,6 @@
"datasource": "gdev-elasticsearch-v7-metrics",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fontSize": "100%",
"gridPos": {
"h": 7,
@@ -484,13 +446,11 @@
},
"styles": [
{
"align": "auto",
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"pattern": "@timestamp",
"type": "date"
},
{
"align": "auto",
"colorMode": null,
"colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
"dateFormat": "YYYY-MM-DD HH:mm:ss",
@@ -546,7 +506,7 @@
],
"title": "ES Metrics",
"transform": "table",
"type": "table-old"
"type": "table"
},
{
"columns": [
@@ -570,12 +530,6 @@
"datasource": "gdev-elasticsearch-v7-logs",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fontSize": "100%",
"gridPos": {
"h": 7,
@@ -594,7 +548,6 @@
},
"styles": [
{
"align": "auto",
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"pattern": "@timestamp",
"type": "date"
@@ -622,7 +575,7 @@
],
"title": "ES Log query",
"transform": "json",
"type": "table-old"
"type": "table"
},
{
"circleMaxSize": 30,
@@ -632,12 +585,6 @@
"decimals": 0,
"esGeoPoint": "@location",
"esMetric": "Average",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"gridPos": {
"h": 12,
"w": 24,
@@ -699,7 +646,7 @@
"valueName": "total"
}
],
"schemaVersion": 25,
"schemaVersion": 18,
"style": "dark",
"tags": ["elasticsearch", "gdev", "datasource-test"],
"templating": {

View File

@@ -15,7 +15,8 @@
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1591027736516,
"id": 2341,
"iteration": 1555591591930,
"links": [
{
"asDropdown": true,
@@ -34,21 +35,13 @@
"dashLength": 10,
"dashes": false,
"datasource": "gdev-elasticsearch-v7-filebeat",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 5,
"w": 24,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 4,
"legend": {
"avg": false,
@@ -62,9 +55,6 @@
"lines": false,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 2,
"points": false,
@@ -153,13 +143,22 @@
}
},
{
"datasource": "gdev-elasticsearch-v7-filebeat",
"fieldConfig": {
"defaults": {
"custom": {}
"columns": [
{
"text": "@timestamp",
"value": "@timestamp"
},
"overrides": []
},
{
"text": "fields.level",
"value": "fields.level"
},
{
"text": "message",
"value": "message"
}
],
"datasource": "gdev-elasticsearch-v7-filebeat",
"fontSize": "100%",
"gridPos": {
"h": 22,
"w": 24,
@@ -168,35 +167,58 @@
},
"id": 2,
"links": [],
"options": {
"showLabels": false,
"showTime": true,
"sortOrder": "Descending",
"wrapLogMessage": true
"pageSize": null,
"scroll": true,
"showHeader": true,
"sort": {
"col": 0,
"desc": true
},
"styles": [
{
"alias": "Time",
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"pattern": "@timestamp",
"type": "date"
},
{
"alias": "Level",
"colorMode": null,
"colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"decimals": 2,
"mappingType": 1,
"pattern": "fields.level",
"thresholds": [""],
"type": "string",
"unit": "short",
"valueMaps": []
},
{
"alias": "Message",
"colorMode": null,
"colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
"decimals": 2,
"pattern": "message",
"preserveFormat": false,
"sanitize": false,
"thresholds": [],
"type": "string",
"unit": "short"
}
],
"targets": [
{
"bucketAggs": [
{
"$$hashKey": "object:522",
"field": "@timestamp",
"id": "2",
"settings": {
"interval": "auto",
"min_doc_count": 0,
"trimEdges": 0
},
"type": "date_histogram"
}
],
"bucketAggs": [],
"metrics": [
{
"$$hashKey": "object:484",
"field": "select field",
"id": "1",
"meta": {},
"settings": {},
"type": "logs"
"settings": {
"size": 500
},
"type": "raw_document"
}
],
"query": "fields.app:grafana",
@@ -207,10 +229,11 @@
"timeFrom": null,
"timeShift": null,
"title": "Panel Title",
"type": "logs"
"transform": "json",
"type": "table"
}
],
"schemaVersion": 25,
"schemaVersion": 18,
"style": "dark",
"tags": ["elasticsearch", "gdev", "datasource-test"],
"templating": {

View File

@@ -1,110 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1596705352582,
"links": [],
"panels": [
{
"datasource": null,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"gridPos": {
"h": 16,
"w": 24,
"x": 0,
"y": 0
},
"id": 11,
"options": {
"content": "## Global variables\n\n* `__dashboard` = `${__dashboard}`\n* `__dashboard.name` = `${__dashboard.name}`\n* `__dashboard.uid` = `${__dashboard.uid}`\n* `__org.name` = `${__org.name}`\n* `__org.id` = `${__org.id}`\n* `__user.id` = `${__user.id}`\n* `__user.login` = `${__user.login}`\n \n## Formats\n\n* `Server:raw` = `${Server:raw}`\n* `Server:regex` = `${Server:regex}`\n* `Server:lucene` = `${Server:lucene}`\n* `Server:glob` = `${Server:glob}`\n* `Server:pipe` = `${Server:pipe}`\n* `Server:distributed` = `${Server:distributed}`\n* `Server:csv` = `${Server:csv}`\n* `Server:html` = `${Server:html}`\n* `Server:json` = `${Server:json}`\n* `Server:percentencode` = `${Server:percentencode}`\n* `Server:singlequote` = `${Server:singlequote}`\n* `Server:doublequote` = `${Server:doublequote}`\n* `Server:sqlstring` = `${Server:sqlstring}`\n* `Server:date` = `${Server:date}`\n* `Server:text` = `${Server:text}`\n\n",
"mode": "markdown"
},
"pluginVersion": "7.1.0",
"targets": [
{
"refId": "A",
"scenarioId": "random_walk"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Variable interpolation",
"type": "text"
}
],
"schemaVersion": 26,
"style": "dark",
"tags": ["gdev", "templating"],
"templating": {
"list": [
{
"allValue": null,
"current": {
"selected": true,
"text": "All",
"value": ["$__all"]
},
"hide": 0,
"includeAll": true,
"label": null,
"multi": true,
"name": "Server",
"options": [
{
"selected": true,
"text": "All",
"value": "$__all"
},
{
"selected": false,
"text": "A'A\"A",
"value": "A'A\"A"
},
{
"selected": false,
"text": "BB\\B",
"value": "BB\\B"
},
{
"selected": false,
"text": "CCC",
"value": "CCC"
}
],
"query": "A'A\"A,BB\\B,CCC",
"queryValue": "",
"skipUrlSync": false,
"type": "custom"
}
]
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Templating - Global variables and interpolation",
"uid": "HYaGDGIMk",
"version": 5
}

View File

@@ -1,132 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": null,
"iteration": 1601526910610,
"links": [
{
"icon": "external link",
"includeVars": true,
"tags": [],
"title": "Grafana",
"tooltip": "",
"type": "link",
"url": "http://www.grafana.com"
},
{
"asDropdown": true,
"icon": "external link",
"includeVars": true,
"tags": ["templating"],
"title": "Link as DropDown",
"type": "dashboards"
},
{
"icon": "external link",
"includeVars": true,
"tags": ["demo"],
"type": "dashboards"
}
],
"panels": [
{
"description": "",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 0
},
"id": 2,
"options": {
"content": "# ${custom.text}\n ",
"mode": "markdown"
},
"pluginVersion": "7.3.0-pre",
"targets": [
{
"refId": "A",
"scenarioId": "random_walk"
}
],
"timeFrom": null,
"timeShift": null,
"title": "${custom.text}",
"type": "text"
}
],
"schemaVersion": 26,
"style": "dark",
"tags": ["gdev", "templating"],
"templating": {
"list": [
{
"allValue": null,
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"hide": 0,
"includeAll": true,
"label": null,
"multi": true,
"name": "custom",
"options": [
{
"selected": true,
"text": "All",
"value": "$__all"
},
{
"selected": false,
"text": "p1",
"value": "p1"
},
{
"selected": false,
"text": "p2",
"value": "p2"
},
{
"selected": false,
"text": "p3",
"value": "p3"
}
],
"query": "p1,p2,p3",
"skipUrlSync": false,
"type": "custom"
}
]
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Templating - Dashboard Links and Variables",
"uid": "yBCC3aKGk",
"version": 7
}

View File

@@ -15,18 +15,12 @@
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1590677937026,
"id": 13844,
"iteration": 1566896059256,
"links": [],
"panels": [
{
"content": "## Data center = $datacenter\n\n### server = $server\n\n#### pod = $pod",
"datasource": null,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
@@ -35,6 +29,7 @@
},
"id": 4,
"mode": "markdown",
"options": {},
"targets": [
{
"refId": "A",
@@ -52,12 +47,6 @@
"colorValue": false,
"colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"],
"datasource": "gdev-testdata",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"format": "none",
"gauge": {
"maxValue": 100,
@@ -86,6 +75,7 @@
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"options": {},
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
@@ -129,41 +119,6 @@
},
{
"cacheTimeout": null,
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"links": [
{
"targetBlank": true,
"title": "Go to drilldown",
"url": "/d/O6GmNPvWk/dashboard-tests-nested-template-variables-drilldown?orgId=1&${__all_variables}&${__url_time_range}"
}
],
"mappings": [],
"max": 100,
"min": 0,
"nullValueMode": "connected",
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 4,
@@ -173,15 +128,40 @@
"id": 8,
"links": [],
"options": {
"orientation": "horizontal",
"reduceOptions": {
"fieldOptions": {
"calcs": ["mean"],
"defaults": {
"links": [
{
"targetBlank": true,
"title": "Go to drilldown",
"url": "/d/O6GmNPvWk/dashboard-tests-nested-template-variables-drilldown?orgId=1&${__all_variables}&${__url_time_range}"
}
],
"mappings": [],
"max": 100,
"min": 0,
"nullValueMode": "connected",
"thresholds": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
],
"unit": "none"
},
"override": {},
"values": false
},
"orientation": "horizontal",
"showThresholdLabels": false,
"showThresholdMarkers": true
},
"pluginVersion": "7.1.0-pre",
"pluginVersion": "6.4.0-pre",
"targets": [
{
"refId": "A",
@@ -195,41 +175,6 @@
},
{
"cacheTimeout": null,
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"links": [
{
"targetBlank": true,
"title": "Go to drilldown",
"url": "/d/O6GmNPvWk/dashboard-tests-nested-template-variables-drilldown?orgId=1&${__all_variables}&${__url_time_range}"
}
],
"mappings": [],
"max": 100,
"min": 0,
"nullValueMode": "connected",
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 4,
@@ -240,14 +185,38 @@
"links": [],
"options": {
"displayMode": "basic",
"orientation": "vertical",
"reduceOptions": {
"fieldOptions": {
"calcs": ["mean"],
"defaults": {
"links": [
{
"targetBlank": true,
"title": "Go to drilldown",
"url": "/d/O6GmNPvWk/dashboard-tests-nested-template-variables-drilldown?orgId=1&${__all_variables}&${__url_time_range}"
}
],
"mappings": [],
"max": 100,
"min": 0,
"nullValueMode": "connected",
"thresholds": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
],
"unit": "none"
},
"override": {},
"values": false
},
"showUnfilled": true
"orientation": "vertical"
},
"pluginVersion": "7.1.0-pre",
"pluginVersion": "6.4.0-pre",
"targets": [
{
"refId": "A",
@@ -259,108 +228,20 @@
"title": "React gauge datalink",
"type": "bargauge"
},
{
"datasource": "CsvData",
"fieldConfig": {
"defaults": {
"custom": {
"align": null
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "server"
},
"properties": [
{
"id": "links",
"value": [
{
"title": "filter",
"url": "http://localhost:3000/d/-Y-tnEDWk/templating-nested-template-variables?var-datacenter=${__data.fields[datacenter]}&var-server=${__value.raw}"
}
]
}
]
}
]
},
"gridPos": {
"h": 6,
"w": 24,
"x": 0,
"y": 9
},
"id": 11,
"options": {
"showHeader": true
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"data": [
{
"fields": [
{
"config": {},
"name": "datacenter",
"type": "string",
"values": ["A", "B", "C"]
},
{
"config": {},
"name": "server",
"type": "string",
"values": ["AA", "BB", "CC"]
}
]
}
],
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Data links that filter update variables on current dashboard",
"type": "table"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 13,
"w": 24,
"x": 0,
"y": 15
"y": 9
},
"hiddenSeries": false,
"id": 2,
"legend": {
"avg": false,
@@ -435,7 +316,7 @@
}
],
"refresh": false,
"schemaVersion": 25,
"schemaVersion": 19,
"style": "dark",
"tags": ["gdev", "templating"],
"templating": {
@@ -443,7 +324,6 @@
{
"allValue": null,
"current": {
"selected": true,
"text": "A",
"value": ["A"]
},
@@ -469,7 +349,6 @@
{
"allValue": null,
"current": {
"selected": true,
"text": "AA",
"value": ["AA"]
},
@@ -495,7 +374,6 @@
{
"allValue": null,
"current": {
"selected": true,
"text": "All",
"value": ["$__all"]
},
@@ -525,7 +403,7 @@
"to": "now"
},
"timepicker": {
"refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Templating - Nested Template Variables",

View File

@@ -1,235 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1597300832273,
"links": [],
"panels": [
{
"datasource": "CsvData",
"fieldConfig": {
"defaults": {
"custom": {
"align": null
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Query"
},
"properties": [
{
"id": "links",
"value": [
{
"title": "Search",
"url": "/d/spVR9LSMk/templating-textbox-and-data-links?var-query=${__value.raw:percentencode}"
}
]
}
]
}
]
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 2,
"options": {
"showHeader": true
},
"pluginVersion": "7.2.0-pre",
"targets": [
{
"data": [
{
"fields": [
{
"config": {},
"name": "Query",
"type": "string",
"values": ["Contains+Plus", "Contains&Ampersand", "Contains white space"]
},
{
"config": {},
"name": " Test",
"type": "string",
"values": ["asd", "asd", "asd"]
}
]
}
],
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Data",
"type": "table"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": null,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"hiddenSeries": false,
"id": 4,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.2.0-pre",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "${query}",
"refId": "A",
"scenarioId": "random_walk"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Query: ${query}",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
}
],
"schemaVersion": 26,
"style": "dark",
"tags": ["gdev", "templating"],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "asdasda+",
"value": "asdasda+"
},
"hide": 0,
"label": null,
"name": "query",
"options": [
{
"selected": true,
"text": "asdasda+",
"value": "asdasda+"
}
],
"query": "asdasda+",
"skipUrlSync": false,
"type": "textbox"
}
]
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Templating - Textbox & data links",
"uid": "spVR9LSMk",
"version": 9
}

View File

@@ -155,7 +155,7 @@
],
"timeFrom": null,
"timeShift": null,
"title": "Last non-null",
"title": "Last non nulll",
"type": "gauge"
},
{

File diff suppressed because it is too large Load Diff

View File

@@ -454,7 +454,7 @@
"yaxes": [
{
"format": "percent",
"label": "Percent",
"label": "Perecent",
"logBase": 1,
"max": null,
"min": null,

View File

@@ -428,14 +428,6 @@
{
"text": "Bitcoin (฿)",
"value": "currencyBTC"
},
{
"text": "Milli Bitcoin (mBTC)",
"value": "currencymBTC"
},
{
"text": "Micro Bitcoin (μBTC)",
"value": "currencyμBTC"
}
],
"text": "currency"

View File

@@ -85,7 +85,7 @@
}
],
"thresholds": "5,10",
"title": "prefix 3 ms (green) postfix + sparkline",
"title": "prefix 3 ms (green) postfixt + sparkline",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [

View File

@@ -19,42 +19,6 @@
"panels": [
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": {
"h": 3,
"w": 24,
@@ -65,20 +29,51 @@
"interval": "6m",
"options": {
"colorMode": "background",
"fieldOptions": {
"calcs": ["mean"],
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": [],
"values": false
},
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "auto"
}
},
"pluginVersion": "7.1.0-pre",
"pluginVersion": "6.6.0-pre",
"targets": [
{
"alias": "__house_locations",
@@ -98,42 +93,6 @@
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": {
"h": 6,
"w": 24,
@@ -144,20 +103,51 @@
"interval": "7m",
"options": {
"colorMode": "background",
"fieldOptions": {
"calcs": ["mean"],
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": [],
"values": false
},
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "auto"
}
},
"pluginVersion": "7.1.0-pre",
"pluginVersion": "6.6.0-pre",
"targets": [
{
"alias": "__house_locations",
@@ -176,42 +166,6 @@
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": {
"h": 6,
"w": 24,
@@ -222,20 +176,51 @@
"interval": "7m",
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": ["mean"],
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": [],
"values": false
},
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "auto"
}
},
"pluginVersion": "7.1.0-pre",
"pluginVersion": "6.6.0-pre",
"targets": [
{
"alias": "__house_locations",
@@ -254,44 +239,8 @@
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": {
"h": 18,
"h": 14,
"w": 6,
"x": 0,
"y": 15
@@ -300,20 +249,51 @@
"interval": "5m",
"options": {
"colorMode": "background",
"fieldOptions": {
"calcs": ["mean"],
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": [],
"values": false
},
"graphMode": "area",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "auto"
}
},
"pluginVersion": "7.1.0-pre",
"pluginVersion": "6.6.0-pre",
"targets": [
{
"alias": "__server_names",
@@ -326,49 +306,13 @@
],
"timeFrom": null,
"timeShift": null,
"title": "Horizontal with graph",
"title": "Panel Title",
"type": "stat"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": {
"h": 9,
"h": 11,
"w": 4,
"x": 6,
"y": 15
@@ -377,20 +321,51 @@
"interval": "10m",
"options": {
"colorMode": "background",
"fieldOptions": {
"calcs": ["mean"],
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": [],
"values": false
},
"graphMode": "line",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "auto"
}
},
"pluginVersion": "7.1.0-pre",
"pluginVersion": "6.6.0-pre",
"targets": [
{
"refId": "A",
@@ -423,50 +398,14 @@
],
"timeFrom": null,
"timeShift": null,
"title": "Auto grid",
"title": "Panel Title",
"type": "stat"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 6,
"w": 8,
"x": 10,
"y": 15
},
@@ -474,20 +413,51 @@
"interval": "10m",
"options": {
"colorMode": "background",
"fieldOptions": {
"calcs": ["mean"],
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": [],
"values": false
},
"graphMode": "line",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "auto"
}
},
"pluginVersion": "7.1.0-pre",
"pluginVersion": "6.6.0-pre",
"targets": [
{
"refId": "A",
@@ -520,257 +490,11 @@
],
"timeFrom": null,
"timeShift": null,
"title": "Horizontal",
"type": "stat"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"max": 200,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 8,
"x": 16,
"y": 15
},
"id": 15,
"interval": "5m",
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "name"
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"alias": "__server_names",
"max": 200,
"min": 0,
"noise": 5,
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 7,
"spread": 20,
"startValue": 0
}
],
"timeFrom": null,
"timeShift": null,
"title": "Text mode name",
"type": "stat"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"max": 200,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 18,
"x": 6,
"y": 24
},
"id": 16,
"interval": "5m",
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "value"
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"alias": "__server_names",
"max": 200,
"min": 0,
"noise": 15,
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 45,
"spread": 1,
"startValue": 0
}
],
"timeFrom": null,
"timeShift": null,
"title": "Value only",
"type": "stat"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"max": 200,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": {
"h": 5,
"w": 24,
"x": 0,
"y": 33
},
"id": 17,
"interval": "5m",
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "none"
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"alias": "__server_names",
"max": 200,
"min": 0,
"noise": 15,
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 200,
"spread": 1,
"startValue": 0
}
],
"timeFrom": null,
"timeShift": null,
"title": "No text",
"title": "Panel Title",
"type": "stat"
}
],
"schemaVersion": 26,
"schemaVersion": 22,
"style": "dark",
"tags": ["gdev", "panel-tests"],
"templating": {
@@ -784,7 +508,5 @@
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - Stat",
"uid": "EJ8_d9jZk",
"version": 1
"title": "Panel Tests - Stat"
}

View File

@@ -1,602 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"links": [],
"panels": [
{
"datasource": null,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 7,
"title": "Cell styles",
"type": "row"
},
{
"datasource": "gdev-testdata",
"fieldConfig": {
"defaults": {
"custom": {
"align": "center",
"displayMode": "color-background"
},
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "blue",
"value": 20
},
{
"color": "orange",
"value": 60
},
{
"color": "red",
"value": 70
}
]
},
"unit": "degree"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Max"
},
"properties": [
{
"id": "custom.width",
"value": 84
}
]
},
{
"matcher": {
"id": "byName",
"options": "Last"
},
"properties": [
{
"id": "custom.width",
"value": 78
}
]
},
{
"matcher": {
"id": "byName",
"options": "Mean"
},
"properties": [
{
"id": "custom.width",
"value": 74
}
]
},
{
"matcher": {
"id": "byName",
"options": "Field"
},
"properties": [
{
"id": "custom.align",
"value": "left"
}
]
}
]
},
"gridPos": {
"h": 16,
"w": 7,
"x": 0,
"y": 1
},
"id": 4,
"options": {
"showHeader": true,
"sortBy": [
{
"desc": true,
"displayName": "Last"
}
]
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 15,
"stringInput": ""
}
],
"timeFrom": null,
"timeShift": null,
"title": "Colored background",
"transformations": [
{
"id": "reduce",
"options": {
"reducers": ["max", "mean", "last"]
}
}
],
"type": "table"
},
{
"datasource": "gdev-testdata",
"fieldConfig": {
"defaults": {
"custom": {
"align": null
},
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "orange",
"value": null
},
{
"color": "red",
"value": 50
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "custom.displayMode",
"value": "gradient-gauge"
}
]
},
{
"matcher": {
"id": "byName",
"options": "Info"
},
"properties": [
{
"id": "custom.width",
"value": 92
}
]
},
{
"matcher": {
"id": "byName",
"options": "Min"
},
"properties": [
{
"id": "custom.width",
"value": 76
}
]
},
{
"matcher": {
"id": "byName",
"options": "Max"
},
"properties": [
{
"id": "custom.width",
"value": 89
}
]
},
{
"matcher": {
"id": "byName",
"options": "Time"
},
"properties": [
{
"id": "custom.width",
"value": 165
}
]
}
]
},
"gridPos": {
"h": 16,
"w": 8,
"x": 7,
"y": 1
},
"id": 2,
"options": {
"showHeader": true,
"sortBy": [
{
"desc": false,
"displayName": "Min"
}
]
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"refId": "A",
"scenarioId": "random_walk_table",
"stringInput": ""
}
],
"timeFrom": null,
"timeShift": null,
"title": "Bar gauge cells",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {
"Time": true
},
"indexByName": {
"Info": 1,
"Max": 3,
"Min": 2,
"Time": 0,
"Value": 4
},
"renameByName": {}
}
}
],
"type": "table"
},
{
"datasource": "gdev-testdata",
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"align": null
},
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 50
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "custom.displayMode",
"value": "lcd-gauge"
},
{
"id": "custom.align",
"value": "center"
}
]
}
]
},
"gridPos": {
"h": 16,
"w": 9,
"x": 15,
"y": 1
},
"id": 5,
"options": {
"showHeader": true,
"sortBy": []
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"refId": "A",
"scenarioId": "random_walk_table",
"stringInput": ""
}
],
"timeFrom": null,
"timeShift": null,
"title": "Retro LCD cell",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {
"Info": false,
"Max": true,
"Min": true,
"Time": false
},
"indexByName": {
"Info": 1,
"Max": 3,
"Min": 2,
"Time": 0,
"Value": 4
},
"renameByName": {}
}
}
],
"type": "table"
},
{
"collapsed": false,
"datasource": null,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 17
},
"id": 9,
"panels": [],
"title": "Data links",
"type": "row"
},
{
"datasource": "gdev-testdata",
"fieldConfig": {
"defaults": {
"custom": {
"align": "center",
"displayMode": "color-text"
},
"decimals": 2,
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "blue",
"value": 20
},
{
"color": "orange",
"value": 50
},
{
"color": "red",
"value": 70
}
]
},
"unit": "percent"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Time"
},
"properties": [
{
"id": "custom.align",
"value": null
}
]
},
{
"matcher": {
"id": "byName",
"options": "{name=\"S1\", server=\"A\"}"
},
"properties": [
{
"id": "links",
"value": [
{
"title": "Details",
"url": "http://detail?serverLabel=${__field.labels.server}&valueNumeric=${__value.numeric}"
}
]
}
]
}
]
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 18
},
"id": 3,
"maxDataPoints": "10",
"options": {
"showHeader": true
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"alias": "S1",
"labels": "server=A",
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 1,
"stringInput": ""
},
{
"alias": "S2",
"labels": "server=B",
"refId": "B",
"scenarioId": "random_walk",
"seriesCount": 1,
"stringInput": ""
},
{
"alias": "S3",
"labels": "server=C",
"refId": "C",
"scenarioId": "random_walk",
"seriesCount": 1,
"stringInput": ""
}
],
"timeFrom": null,
"timeShift": null,
"title": "Data link with labels and numeric value",
"transformations": [
{
"id": "seriesToColumns",
"options": {}
}
],
"type": "table"
},
{
"datasource": "gdev-testdata",
"fieldConfig": {
"defaults": {
"custom": {
"align": "center",
"displayMode": "auto"
},
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "blue",
"value": 20
},
{
"color": "orange",
"value": 60
},
{
"color": "red",
"value": 70
}
]
},
"unit": "degree"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 5,
"x": 12,
"y": 18
},
"id": 10,
"options": {
"showHeader": false,
"sortBy": [
{
"desc": true,
"displayName": "Last"
}
]
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"refId": "A",
"scenarioId": "random_walk_table",
"seriesCount": 5,
"stringInput": ""
}
],
"timeFrom": null,
"timeShift": null,
"title": "No header",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {
"Min": true,
"Time": true,
"Value": true
},
"indexByName": {
"Info": 2,
"Max": 4,
"Min": 3,
"Time": 0,
"Value": 1
},
"renameByName": {}
}
}
],
"type": "table"
}
],
"schemaVersion": 25,
"style": "dark",
"tags": ["gdev", "panel-tests"],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {
"refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - React Table",
"uid": "U_bZIMRMk",
"version": 17
}

View File

@@ -1,695 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": 28,
"links": [],
"panels": [
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 4,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"refId": "A",
"scenario": "random_walk",
"scenarioId": "random_walk",
"target": ""
}
],
"thresholds": [],
"timeFrom": "2s",
"timeRegions": [],
"timeShift": null,
"title": "Millisecond res x-axis and tooltip",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 0
},
"hiddenSeries": false,
"id": 3,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"refId": "A",
"scenario": "random_walk",
"scenarioId": "random_walk",
"target": ""
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Random walk series",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 7
},
"hiddenSeries": false,
"id": 5,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "B-series",
"yaxis": 2
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"refId": "A",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,0",
"target": ""
},
{
"refId": "B",
"scenarioId": "csv_metric_values",
"stringInput": "2000,3000,4000,1000,3000,10000",
"target": ""
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "2 yaxis and axis labels",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "percent",
"label": "Perecent",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": "Pressure",
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 7
},
"hiddenSeries": false,
"id": 9,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "B-series",
"zindex": -3
}
],
"spaceLength": 10,
"stack": true,
"steppedLine": false,
"targets": [
{
"hide": false,
"refId": "B",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,null,null,null,null,null,null,100,10,10,20,30,40,10",
"target": ""
},
{
"alias": "",
"hide": false,
"refId": "A",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,10,20,30,40,40,40,100,10,20,20",
"target": ""
},
{
"alias": "",
"hide": false,
"refId": "C",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,10,20,30,40,40,40,100,10,20,20",
"target": ""
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Stacking value ontop of nulls",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 0,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 15
},
"hiddenSeries": false,
"id": 21,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "C-series",
"steppedLine": true
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "",
"hide": false,
"refId": "B",
"scenarioId": "csv_metric_values",
"stringInput": "1,null,40,null,90,null,null,100,null,null,100,null,null,80,null",
"target": ""
},
{
"alias": "",
"hide": false,
"refId": "C",
"scenarioId": "csv_metric_values",
"stringInput": "20,null40,null,null,50,null,70,null,100,null,10,null,30,null",
"target": ""
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Null between points",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"decimals": 3,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 15
},
"hiddenSeries": false,
"id": 16,
"legend": {
"alignAsTable": true,
"avg": true,
"current": true,
"max": true,
"min": true,
"show": true,
"total": true,
"values": true
},
"lines": true,
"linewidth": 1,
"links": [],
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"refId": "A",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,0",
"target": ""
},
{
"refId": "B",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,0",
"target": ""
},
{
"refId": "C",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,0",
"target": ""
},
{
"refId": "D",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,0",
"target": ""
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Legend Table No Scroll Visible",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
}
],
"refresh": false,
"revision": 8,
"schemaVersion": 25,
"style": "dark",
"tags": ["gdev", "panel-tests", "graph", "table"],
"templating": {
"list": []
},
"time": {
"from": "now-1h",
"to": "now"
},
"timepicker": {
"refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
},
"timezone": "utc",
"title": "Panel Tests - Time zone support",
"uid": "5SdHCasdf",
"version": 1
}

View File

@@ -10,7 +10,7 @@ ADD etc_mtab /etc/mtab
ADD collectd.conf.tpl /etc/collectd/collectd.conf.tpl
RUN pip install --no-cache-dir envtpl
RUN pip install envtpl
ADD start_container /usr/bin/start_container
RUN chmod +x /usr/bin/start_container
CMD start_container

View File

@@ -5,33 +5,33 @@ Basic collectd-based server monitoring. Sends stats to Graphite.
Collectd metrics:
- CPU used/free/idle/etc
- Free disk (via mounting hosts '/' into container, eg: -v /:/hostfs:ro)
- Disk performance
- Load average
- Memory used/free/etc
- Uptime
- Network interface
- Swap
* CPU used/free/idle/etc
* Free disk (via mounting hosts '/' into container, eg: -v /:/hostfs:ro)
* Disk performance
* Load average
* Memory used/free/etc
* Uptime
* Network interface
* Swap
Environment variables
---------------------
- `HOST_NAME`
* `HOST_NAME`
- Will be sent to Graphite
- Required
- `GRAPHITE_HOST`
* `GRAPHITE_HOST`
- Graphite IP or hostname
- Required
- `GRAPHITE_PORT`
* `GRAPHITE_PORT`
- Graphite port
- Optional, defaults to 2003
- `GRAPHITE_PREFIX`
* `GRAPHITE_PREFIX`
- Graphite prefix
- Optional, defaults to collectd.
- `REPORT_BY_CPU`
* `REPORT_BY_CPU`
- Report per-CPU metrics if true, global sum of CPU metrics if false (details: [collectd.conf man page](https://collectd.org/documentation/manpages/collectd.conf.5.shtml#plugin_cpu))
- Optional, defaults to false.
- `COLLECT_INTERVAL`
* `COLLECT_INTERVAL`
- Collection interval and thus resolution of metrics
- Optional, defaults to 10

View File

@@ -821,7 +821,7 @@ filebeat.inputs:
# By default Ingest pipelines are not updated if a pipeline with the same ID
# already exists. If this option is enabled Filebeat overwrites pipelines
# every time a new Elasticsearch connection is established.
# everytime a new Elasticsearch connection is established.
#filebeat.overwrite_pipelines: false
# How long filebeat waits on shutdown for the publisher to finish.

View File

@@ -821,7 +821,7 @@ filebeat.inputs:
# By default Ingest pipelines are not updated if a pipeline with the same ID
# already exists. If this option is enabled Filebeat overwrites pipelines
# every time a new Elasticsearch connection is established.
# everytime a new Elasticsearch connection is established.
#filebeat.overwrite_pipelines: false
# How long filebeat waits on shutdown for the publisher to finish.

View File

@@ -6,9 +6,3 @@
- "./dashboards.yaml:/etc/grafana/provisioning/dashboards/dashboards.yaml"
- "./dev-dashboards:/usr/share/grafana/devenv/dev-dashboards"
- "./datasources_docker.yaml:/etc/grafana/provisioning/datasources/datasources.yaml"
environment:
GF_RENDERING_SERVER_URL: http://renderer:8081/render
GF_RENDERING_CALLBACK_URL: http://grafana:3000/
renderer:
image: grafana/grafana-image-renderer:latest

View File

@@ -35,7 +35,7 @@ RUN if [ ! -z "${CONTAINER_TIMEZONE}" ]; \
# fix python dependencies (LTS Django and newer memcached/txAMQP)
RUN pip install --upgrade pip && \
pip install --no-cache-dir django==1.8.18 \
pip install django==1.8.18 \
python-memcached==1.53 \
txAMQP==0.6.2
@@ -62,13 +62,13 @@ RUN python ./setup.py install
# install carbon
RUN git clone -b ${carbon_version} --depth 1 ${carbon_repo} /usr/local/src/carbon
WORKDIR /usr/local/src/carbon
RUN pip install --no-cache-dir -r requirements.txt \
RUN pip install -r requirements.txt \
&& python ./setup.py install
# install graphite
RUN git clone -b ${graphite_version} --depth 1 ${graphite_repo} /usr/local/src/graphite-web
WORKDIR /usr/local/src/graphite-web
RUN pip install --no-cache-dir -r requirements.txt \
RUN pip install -r requirements.txt \
&& python ./setup.py install
# install statsd

View File

@@ -30,7 +30,7 @@ fi
# - /opt/statsd
statsd_dir_contents=$(find /opt/statsd -mindepth 1 -print -quit)
if [[ -z $statsd_dir_contents ]]; then
git clone --depth 1 -b v0.7.2 https://github.com/etsy/statsd.git /opt/statsd
git clone -b v0.7.2 https://github.com/etsy/statsd.git /opt/statsd
cp $conf_dir/opt/statsd/config.js /opt/statsd/config.js
fi

View File

@@ -1 +0,0 @@
influxdb_version=1.8.1-alpine

View File

@@ -1,5 +1,5 @@
influxdb:
image: influxdb:${influxdb_version}
image: influxdb:1.7.6
container_name: influxdb
ports:
- '2004:2004'

View File

@@ -1057,7 +1057,7 @@
# ## Custom resource type
# # resource_type = "generic_node"
#
# ## Additional resource labels
# ## Additonal resource labels
# # [outputs.stackdriver.resource_labels]
# # node_id = "$HOSTNAME"
# # namespace = "myapp"
@@ -2169,7 +2169,7 @@
#
# ## Metrics list
# ## List of metrics can be found on Graylog webservice documentation.
# ## Or by hitting the web service api at:
# ## Or by hitting the the web service api at:
# ## http://[graylog-host]:12900/system/metrics
# metrics = [
# "jvm.cl.loaded",
@@ -3346,7 +3346,7 @@
# # pid_finder = "pgrep"
# # Reads last_run_summary.yaml file and converts to measurements
# # Reads last_run_summary.yaml file and converts to measurments
# [[inputs.puppetagent]]
# ## Location of puppet last run summary file
# location = "/var/lib/puppet/state/last_run_summary.yaml"
@@ -5196,11 +5196,11 @@
# ## separator character to use for measurement and field names (default: "_")
# # separator = "_"
#
# ## number of objects to retrieve per query for realtime resources (vms and hosts)
# ## number of objects to retreive per query for realtime resources (vms and hosts)
# ## set to 64 for vCenter 5.5 and 6.0 (default: 256)
# # max_query_objects = 256
#
# ## number of metrics to retrieve per query for non-realtime resources (clusters and datastores)
# ## number of metrics to retreive per query for non-realtime resources (clusters and datastores)
# ## set to 64 for vCenter 5.5 and 6.0 (default: 256)
# # max_query_metrics = 256
#

View File

@@ -10,11 +10,6 @@
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
# For this to work you need to install the logging driver see https://github.com/grafana/loki/tree/master/cmd/docker-driver#plugin-installation
logging:
driver: loki
options:
loki-url: "http://localhost:3100/loki/api/v1/push"
# Optional jaeger tracing
environment:
- JAEGER_AGENT_HOST=jaeger

View File

@@ -1,6 +1,6 @@
#!/bin/bash
# When not limiting the open file descriptors limit, the memory consumption of
# When not limiting the open file descritors limit, the memory consumption of
# slapd is absurdly high. See https://github.com/docker/docker/issues/8231
ulimit -n 8192

View File

@@ -1,6 +1,6 @@
#!/bin/bash
# When not limiting the open file descriptors limit, the memory consumption of
# When not limiting the open file descritors limit, the memory consumption of
# slapd is absurdly high. See https://github.com/docker/docker/issues/8231
ulimit -n 8192

View File

@@ -1,4 +1,3 @@
FROM prom/prometheus:v2.7.2
ADD prometheus.yml /etc/prometheus/
ADD recording.yml /etc/prometheus/
ADD alert.yml /etc/prometheus/
ADD alert.rules /etc/prometheus/

View File

@@ -0,0 +1,10 @@
# Alert Rules
ALERT AppCrash
IF process_open_fds > 0
FOR 15s
LABELS { severity="critical" }
ANNOTATIONS {
summary = "Number of open fds > 0",
description = "Just testing"
}

View File

@@ -1,11 +0,0 @@
groups:
- name: ALERT
rules:
- alert: AppCrash
expr: process_open_fds > 0
for: 15s
labels:
severity: critical
annotations:
summary: Number of open fds > 0
description: Just testing

View File

@@ -5,17 +5,17 @@ global:
# scrape_timeout is set to the global default (10s).
# Load and evaluate rules in this file every 'evaluation_interval' seconds.
rule_files:
- "alert.yml"
- "recording.yml"
#rule_files:
# - "alert.rules"
# - "first.rules"
# - "second.rules"
alerting:
alertmanagers:
- scheme: http
static_configs:
- targets:
- "alertmanager:9093"
# alerting:
# alertmanagers:
# - scheme: http
# static_configs:
# - targets:
# - "127.0.0.1:9093"
scrape_configs:
- job_name: 'prometheus'

View File

@@ -1,16 +0,0 @@
groups:
- name: RECORDING_RULES
rules:
- record: instance_path:requests:rate5m
expr: rate(prometheus_http_requests_total{job="prometheus"}[5m])
- record: path:requests:rate5m
expr: sum without (instance)(instance_path:requests:rate5m{job="prometheus"})
- record: instance_path:reloads_failures:rate5m
expr: rate(prometheus_tsdb_reloads_failures_total{job="prometheus"}[5m])
- record: instance_path:reloads:rate5m
expr: rate(prometheus_tsdb_reloads_total{job="prometheus"}[5m])
- record: instance_path:request_failures_per_requests:ratio_rate5m
expr: |2
instance_path:reloads_failures:rate5m{job="prometheus"}
/
instance_path:reloads:rate5m{job="prometheus"}

View File

@@ -1,7 +1,7 @@
# This Dockerfile builds an image for a client_golang example.
# Builder image, where we build the example.
FROM golang:1.15.1 AS builder
FROM golang:1.14.1 AS builder
# Download prometheus/client_golang/examples/random first
RUN go get github.com/prometheus/client_golang/examples/random
WORKDIR /go/src/github.com/prometheus/client_golang

View File

@@ -5,10 +5,10 @@ scaling up/down number of Grafana instances.
Included services
- Grafana
- Mysql - Grafana configuration database and session storage
- Prometheus - Monitoring of Grafana and used as data source of provisioned alert rules
- Nginx - Reverse proxy for Grafana and Prometheus. Enables browsing Grafana/Prometheus UI using a hostname
* Grafana
* Mysql - Grafana configuration database and session storage
* Prometheus - Monitoring of Grafana and used as data source of provisioned alert rules
* Nginx - Reverse proxy for Grafana and Prometheus. Enables browsing Grafana/Prometheus UI using a hostname
## Prerequisites
@@ -53,8 +53,8 @@ $ docker-compose up -d
```
Browse
- http://grafana.loc/
- http://prometheus.loc/
* http://grafana.loc/
* http://prometheus.loc/
Check for any errors

View File

@@ -35,12 +35,6 @@ Run load test for 10 virtual users:
$ ./run.sh -v 10
```
Run load test and send the results to the database "myDb" in influxDB running locally on port 8086 (with no authentication):
```bash
$ ./run.sh -o influxdb=http://localhost:8086/myDb
```
Run auth token slow test (random query latency between 1 and 30 seconds):
```bash
@@ -75,7 +69,7 @@ Example output:
█ user auth token test
█ user authenticates through ui with username and password
█ user authenticates thru ui with username and password
✓ response status is 200
✓ response has cookie 'grafana_session' with 32 characters

View File

@@ -3,7 +3,7 @@ import { createClient, createBasicAuthClient } from './modules/client.js';
import { createTestOrgIfNotExists, createTestdataDatasourceIfNotExists } from './modules/util.js';
export let options = {
noCookiesReset: true,
noCookiesReset: true
};
let endpoint = __ENV.URL || 'http://localhost:3000';
@@ -18,38 +18,35 @@ export const setup = () => {
orgId: orgId,
datasourceId: datasourceId,
};
};
}
export default data => {
group('annotation by tag test', () => {
export default (data) => {
group("annotation by tag test", () => {
if (__ITER === 0) {
group('user authenticates through ui with username and password', () => {
group("user authenticates thru ui with username and password", () => {
let res = client.ui.login('admin', 'admin');
check(res, {
'response status is 200': r => r.status === 200,
"response has cookie 'grafana_session' with 32 characters": r =>
r.cookies.grafana_session[0].value.length === 32,
'response status is 200': (r) => r.status === 200,
'response has cookie \'grafana_session\' with 32 characters': (r) => r.cookies.grafana_session[0].value.length === 32,
});
});
}
if (__ITER !== 0) {
group('batch tsdb requests with annotations by tag', () => {
group("batch tsdb requests with annotations by tag", () => {
const batchCount = 20;
const requests = [];
const payload = {
from: '1547765247624',
to: '1547768847624',
queries: [
{
refId: 'A',
scenarioId: 'random_walk',
intervalMs: 10000,
maxDataPoints: 433,
datasourceId: data.datasourceId,
},
],
queries: [{
refId: 'A',
scenarioId: 'random_walk',
intervalMs: 10000,
maxDataPoints: 433,
datasourceId: data.datasourceId,
}]
};
requests.push({ method: 'GET', url: '/api/annotations?from=1580825186534&to=1580846786535' });
@@ -61,14 +58,14 @@ export default data => {
let responses = client.batch(requests);
for (let n = 0; n < batchCount; n++) {
check(responses[n], {
'response status is 200': r => r.status === 200,
'response status is 200': (r) => r.status === 200,
});
}
});
}
});
sleep(5);
};
sleep(5)
}
export const teardown = data => {};
export const teardown = (data) => {}

View File

@@ -2,7 +2,7 @@ import { sleep, check, group } from 'k6';
import { createBasicAuthClient } from './modules/client.js';
export let options = {
noCookiesReset: true,
noCookiesReset: true
};
let endpoint = __ENV.URL || 'http://localhost:10080/grafana';
@@ -19,17 +19,17 @@ export const setup = () => {
return {
datasourceId: res.json().id,
};
};
}
export default data => {
group('auth proxy test', () => {
group('batch proxy requests', () => {
export default (data) => {
group("auth proxy test", () => {
group("batch proxy requests", () => {
const d = new Date();
const batchCount = 300;
const requests = [];
const query = encodeURI('topk(5, max(scrape_duration_seconds) by (job))');
const start = d.getTime() / 1000 - 3600;
const end = d.getTime() / 1000;
const start = (d.getTime() / 1000) - 3600;
const end = (d.getTime() / 1000);
const step = 20;
requests.push({ method: 'GET', url: '/api/annotations?dashboardId=8&from=1558670300607&to=1558691900607' });
@@ -44,13 +44,13 @@ export default data => {
let responses = client.batch(requests);
for (let n = 0; n < batchCount; n++) {
check(responses[n], {
'response status is 200': r => r.status === 200,
'response status is 200': (r) => r.status === 200,
});
}
});
});
sleep(5);
};
sleep(5)
}
export const teardown = data => {};
export const teardown = (data) => {}

View File

@@ -3,11 +3,11 @@ import { createClient, createBasicAuthClient } from './modules/client.js';
import { createTestOrgIfNotExists, createTestdataDatasourceIfNotExists } from './modules/util.js';
export let options = {
noCookiesReset: true,
noCookiesReset: true
};
let endpoint = __ENV.URL || 'http://localhost:3000';
const slowQuery = __ENV.SLOW_QUERY && __ENV.SLOW_QUERY.length > 0 ? parseInt(__ENV.SLOW_QUERY, 10) : 5;
const slowQuery = (__ENV.SLOW_QUERY && __ENV.SLOW_QUERY.length > 0) ? parseInt(__ENV.SLOW_QUERY, 10) : 5;
const client = createClient(endpoint);
export const setup = () => {
@@ -19,18 +19,17 @@ export const setup = () => {
orgId: orgId,
datasourceId: datasourceId,
};
};
}
export default data => {
export default (data) => {
group(`user auth token slow test (queries between 1 and ${slowQuery} seconds)`, () => {
if (__ITER === 0) {
group('user authenticates through ui with username and password', () => {
group("user authenticates thru ui with username and password", () => {
let res = client.ui.login('admin', 'admin');
check(res, {
'response status is 200': r => r.status === 200,
"response has cookie 'grafana_session' with 32 characters": r =>
r.cookies.grafana_session[0].value.length === 32,
'response status is 200': (r) => r.status === 200,
'response has cookie \'grafana_session\' with 32 characters': (r) => r.cookies.grafana_session[0].value.length === 32,
});
});
}
@@ -42,16 +41,14 @@ export default data => {
const payload = {
from: '1547765247624',
to: '1547768847624',
queries: [
{
refId: 'A',
scenarioId: 'slow_query',
stringInput: `${Math.floor(Math.random() * slowQuery) + 1}s`,
intervalMs: 10000,
maxDataPoints: 433,
datasourceId: data.datasourceId,
},
],
queries: [{
refId: 'A',
scenarioId: 'slow_query',
stringInput: `${Math.floor(Math.random() * slowQuery) + 1}s`,
intervalMs: 10000,
maxDataPoints: 433,
datasourceId: data.datasourceId,
}]
};
requests.push({ method: 'GET', url: '/api/annotations?dashboardId=2074&from=1548078832772&to=1548082432772' });
@@ -63,14 +60,14 @@ export default data => {
let responses = client.batch(requests);
for (let n = 0; n < batchCount; n++) {
check(responses[n], {
'response status is 200': r => r.status === 200,
'response status is 200': (r) => r.status === 200,
});
}
});
}
});
sleep(5);
};
sleep(5)
}
export const teardown = data => {};
export const teardown = (data) => {}

View File

@@ -3,7 +3,7 @@ import { createClient, createBasicAuthClient } from './modules/client.js';
import { createTestOrgIfNotExists, createTestdataDatasourceIfNotExists } from './modules/util.js';
export let options = {
noCookiesReset: true,
noCookiesReset: true
};
let endpoint = __ENV.URL || 'http://localhost:3000';
@@ -18,38 +18,35 @@ export const setup = () => {
orgId: orgId,
datasourceId: datasourceId,
};
};
}
export default data => {
group('user auth token test', () => {
export default (data) => {
group("user auth token test", () => {
if (__ITER === 0) {
group('user authenticates through ui with username and password', () => {
group("user authenticates thru ui with username and password", () => {
let res = client.ui.login('admin', 'admin');
check(res, {
'response status is 200': r => r.status === 200,
"response has cookie 'grafana_session' with 32 characters": r =>
r.cookies.grafana_session[0].value.length === 32,
'response status is 200': (r) => r.status === 200,
'response has cookie \'grafana_session\' with 32 characters': (r) => r.cookies.grafana_session[0].value.length === 32,
});
});
}
if (__ITER !== 0) {
group('batch tsdb requests', () => {
group("batch tsdb requests", () => {
const batchCount = 20;
const requests = [];
const payload = {
from: '1547765247624',
to: '1547768847624',
queries: [
{
refId: 'A',
scenarioId: 'random_walk',
intervalMs: 10000,
maxDataPoints: 433,
datasourceId: data.datasourceId,
},
],
queries: [{
refId: 'A',
scenarioId: 'random_walk',
intervalMs: 10000,
maxDataPoints: 433,
datasourceId: data.datasourceId,
}]
};
requests.push({ method: 'GET', url: '/api/annotations?dashboardId=2074&from=1548078832772&to=1548082432772' });
@@ -61,14 +58,14 @@ export default data => {
let responses = client.batch(requests);
for (let n = 0; n < batchCount; n++) {
check(responses[n], {
'response status is 200': r => r.status === 200,
'response status is 200': (r) => r.status === 200,
});
}
});
}
});
sleep(5);
};
sleep(5)
}
export const teardown = data => {};
export const teardown = (data) => {}

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