Compare commits

..

49 Commits

Author SHA1 Message Date
Leonard Gram
57a57932af release 6.3.0-beta4 2019-08-02 14:24:40 +02:00
Torkel Ödegaard
62a226b1c3 Navigation: Fixed double settings menus (#18349)
(cherry picked from commit f3fb178efa)
2019-08-02 14:24:40 +02:00
Oleg Gaidarenko
a38dcc3ac7 Build: allow bash to expand the wildcard (#18354)
If wildcards are in the quotes they not going to be expanded

(cherry picked from commit 89a4f30eab)
2019-08-02 14:24:40 +02:00
Torkel Ödegaard
c39b0e246b Gauges: Fixes error when mappings array was undefined (#18353)
(cherry picked from commit 142c7eb0e6)
2019-08-02 14:24:40 +02:00
gotjosh
f8f1f506ed Auth Proxy: Include additional headers as part of the cache key (#18298)
* Auth Proxy: Include additional headers as part of the cache key

Auth proxy has support to send additional user attributes as part of the
authentication flow. These attributes (e.g. Groups) need to be monitored
as part of the process in case of change.

This commit changes the way we compute the cache key to include all of the
attributes sent as part of the authentication request. That way, if we
change any user attributes we'll upsert the user information.

(cherry picked from commit ed8aeb2999)
2019-08-02 14:24:40 +02:00
Ryan McKinley
9d57a1f192 Plugins: avoid app importDashboards() NPE (#18128)
* tables display

* add missing file

* adding toolbar option

* adding toolbar option

* add items to index

* use root import path

* merge master

* show tables info

* add importDashboards code

* remove table changes

* remove table changes

* use deprecation warning

(cherry picked from commit 06b43f6d4b)
2019-08-02 14:24:40 +02:00
Leonard Gram
ba4a870632 release 6.3.0-beta3 2019-08-02 11:47:05 +02:00
kay delaney
ef9ec32c32 QueryEditors: Fixes flakey text edit mode toggle (#18335)
Closes #18037

(cherry picked from commit 9b5890cc62)
2019-08-02 11:47:05 +02:00
Oleg Gaidarenko
17235e4bd1 Auth: consistently return same basic auth errors (#18310)
* Auth: consistently return same basic auth errors

* Put repeated errors in consts and return only those consts as error strings

* Add tests for errors basic auth cases and moves tests to separate test-case.
  Also names test cases consistently

* Add more error logs and makes their messages consistent

* A bit of code style

* Add additional test helper

* Auth: do not expose even incorrect password

* Auth: address review comments

Use `Debug` for the cases when it's an user error

(cherry picked from commit 82661b9f69)
2019-08-02 11:47:05 +02:00
Leonard Gram
eb82b77782 cli: fix for recognizing when in dev mode. (#18334)
(cherry picked from commit c675449aa2)
2019-08-02 11:47:05 +02:00
Sofia Papagiannaki
3af8aa5c4f Fix failing end to end tests job for release (#18323)
Create and push the expected tag to grafana-dev repository
and use this instead for running the end to end tests
for the release.

(cherry picked from commit c9f7e3059f)
2019-08-02 11:47:05 +02:00
Sofia Papagiannaki
5b588af73c Fix OAuth error due to SameSite cookie policy (#18332)
The `oauth_state` cookie used to be created with the SameSite value set
according to the `cookie_samesite` configuration.
However, due to a Safari bug SameSite=None or SameSite=invalid are treated
as Strict which results in "missing saved state" OAuth login failures
because the cookie is not sent with the redirect requests to the OAuth
provider.
This commit always creates the `oauth_state` cookie with SameSite=Lax
to compensate for this.

(cherry picked from commit 69b7b8bb46)
2019-08-02 11:47:05 +02:00
kay delaney
5ec6eccfac [Shortcuts] Fixes shortcuts for moving time range backwards and forwards (#18305)
Closes #18159

(cherry picked from commit bcf28cb7a2)
2019-08-02 11:47:05 +02:00
Oleg Gaidarenko
237e0e8631 Build: fix use of env vars in parentheses execs (#18249)
* Build: fix use of env vars in parentheses execs

* Build: disable shellcheck rule SC2086 for a file

Follow up for 4b16cd6cc8

(cherry picked from commit f9a6414b92)
2019-08-02 11:47:05 +02:00
Oleg Gaidarenko
7a165febf3 Build: correct verify script (#18236)
Follow-up for 4b16cd6cc8

(cherry picked from commit ba46cf40e4)
2019-08-02 11:47:05 +02:00
Oleg Gaidarenko
fd7c38c62f Build: Introduce shellcheck (#18081)
* Build: introduce shellcheck

Fixes #16198

(cherry picked from commit 4b16cd6cc8)
2019-08-02 11:47:05 +02:00
Oleg Gaidarenko
00519f1105 Build: change definition of the vars in makefile (#18151)
Prompted by the @slim-bean talk (thanks!). With that definition
`GO_FILES` var can be dynamically changed, that will be very helpful
in grafana enterprise repo

(cherry picked from commit 8202fa2fde)
2019-08-02 11:47:05 +02:00
Leonard Gram
c8740d98b0 release 6.3.0-beta2 2019-07-26 15:56:18 +02:00
gotjosh
54030deaf6 SAML: Only show SAML login button on Enterprise version (#18270)
SAML Authentication is an Enterprise only feature. This change enables
the SAML login button to only be shown on enterprise.

(cherry picked from commit 2f240a11ce)
2019-07-26 15:56:18 +02:00
Andrej Ocenas
880f6b63a1 Permissions: Show plugins in nav for non admin users but hide plugin configuration (#18234)
Allow non admins to see plugins list but only with readme. Any config tabs are hidden from the plugin page. Also plugin panel does not show action buttons (like Enable) for non admins.

(cherry picked from commit 7f1214ac46)
2019-07-26 15:56:18 +02:00
Sofia Papagiannaki
d8ddfa5622 Run End-to-End tests for release builds (#18211)
(cherry picked from commit 13c41b781a)
2019-07-26 15:56:18 +02:00
Torkel Ödegaard
9af2ea1b53 DataLinks: Fixed interpolation of series name, fixes #18250 (#18251)
(cherry picked from commit 43543d5682)
2019-07-26 15:56:18 +02:00
kay delaney
d98ee66bd8 Timerange: Fixes a bug where custom time ranges didn't respect UTC (#18248)
Closes #18170
Closes #18178

(cherry picked from commit c01bbf2058)
2019-07-26 15:56:18 +02:00
Ryan McKinley
d3ecc963e6 Registry: add a reusable function registry (#17047)
(cherry picked from commit c194ae1ba5)
2019-07-26 15:56:18 +02:00
Ryan McKinley
0961ec9748 FieldDisplay: move threshold and mapping to Field (#17043)
(cherry picked from commit 14caa6a068)
2019-07-26 15:56:18 +02:00
Torkel Ödegaard
a2c7570c5c TimePicker: Increase max height of quick range dropdown (#18247)
(cherry picked from commit 996567ac42)
2019-07-26 15:56:18 +02:00
Torkel Ödegaard
9cbe0abb44 TimePicker: Fixed css issue casued by CSS Optimizer (#18244)
Fixes #18158

(cherry picked from commit 3145a1dd29)
2019-07-26 15:56:18 +02:00
Oleg Gaidarenko
2fecdaf6b4 LDAP: improve POSIX support (#18235)
* LDAP: improve POSIX support

* Correctly abtain DN attributes result

* Allow more flexibility with comparison mapping between POSIX group & user

* Add devenv for POSIX LDAP server

* Correct the docs

Fixes #18140

(cherry picked from commit 1e5fc76601)
2019-07-26 15:56:18 +02:00
Hassan Farid
a5f360e50e Replaced ubuntu:latest with ubuntu:18.04; specific image version to make grafana build images consistent (#18224)
(cherry picked from commit 711f62c813)
2019-07-26 15:56:18 +02:00
Markus Blaschke
99f2386bd9 remote_cache: Fix redis connstr parsing (#18204)
* Fix redis connstr parsing

* Don’t log the password

(cherry picked from commit 31547597d3)
2019-07-26 15:56:18 +02:00
Oleg Gaidarenko
bffa956068 Auth: do not expose disabled user disabled status (#18229)
Fixes #17947

(cherry picked from commit d16fd58bdb)
2019-07-26 15:56:18 +02:00
gotjosh
1b7a54c084 Docs: Update documentation with new SAML features (#18163)
* Update defaults.ini and sample.ini with the SAML assertion mapping
fields

* Document Grafana's ability to map ACS attributes while a Grafana user is created

(cherry picked from commit 87a794fe0a)
2019-07-26 15:56:18 +02:00
David
8128eb6c77 Graph: fix time label description for datalink suggestions (#18214)
(cherry picked from commit 9cd069f2c5)
2019-07-26 15:56:18 +02:00
Leonard Gram
10c4d6eccc PhantomJS: Fixes rendering on Debian Buster (#18162)
Closes #17588

(cherry picked from commit 2014549fa5)
2019-07-26 15:56:18 +02:00
Alexander Zobnin
8a062dde35 SAML: add auth provider label (#18197)
(cherry picked from commit ccf11fb7a2)
2019-07-26 15:56:18 +02:00
Ryan McKinley
041c1c3cb1 Plugins: fix previous commit, output "build" property in json
(cherry picked from commit 0ca1e90b2e)
2019-07-26 15:56:18 +02:00
Alexander Zobnin
aba6df2e09 SAML: add metrics (#18194)
(cherry picked from commit 214195441f)
2019-07-26 15:56:18 +02:00
Oleg Gaidarenko
5192504748 Metrics: use consistent naming for exported variables (#18134)
* Metrics: remove unused metrics

Metric `M_Grafana_Version` is not used anywhere, nor the mentioned
`M_Grafana_Build_Version`. Seems to be an artefact?

* Metrics: make the naming consistent

* Metrics: add comments to exported vars

* Metrics: use proper naming

Fixes #18110

(cherry picked from commit 75fa1f0207)
2019-07-26 15:56:18 +02:00
Ryan McKinley
8a0e2ac3a4 Plugins: add build info to plugin metadata (#18164)
(cherry picked from commit 3e0625ff3d)
2019-07-26 15:56:18 +02:00
Alexander Zobnin
373d082363 Docs: SAML idp_metadata_url option (#18181)
(cherry picked from commit e47546d529)
2019-07-26 15:56:18 +02:00
gotjosh
94765294a2 Docs: SAML (#18069)
* docs: Link to SAML docs and document configuration options

- Document configuration options `defaults.ini` and `sample.ini`
- Add the SAML documentation
- Link to the SAML documentation from "what's new in 6.3"

(cherry picked from commit d006f7c916)
2019-07-26 15:56:18 +02:00
Oleg Gaidarenko
1f482a5f0b SQLStore: use bool pointer instead of string (#18111)
(cherry picked from commit d9f01cb822)
2019-07-26 15:56:18 +02:00
Oleg Gaidarenko
ae04813045 SQLStore: allow to look for is_disabled flag (#18032)
* Add support for `is_disabled` to `CreateUser()`

* Add support for `is_disabled` to `SearchUsers()`
  Had to add it as a `string` type not as `bool`, since if that's property
  is omitted, we would have add it to SQL request, which might be dangerous

* Restructure desctructive tests and add more

(cherry picked from commit 8e0f091f14)
2019-07-26 15:56:18 +02:00
Oleg Gaidarenko
3d7c52dcd1 Metrics: add LDAP active sync summary metric (#18079)
(cherry picked from commit 09eb9a45ce)
2019-07-26 15:56:18 +02:00
Sofia Papagiannaki
81f8158010 API: Minor fix for nil pointer when trying to log error during creating new dashboard via the API (#18003)
* Minor fix for nil pointer when trying to log error

* Do not return error if a dashboard is created

Only log the failures

* Do not return error if the folder is created

Only log the failures

(cherry picked from commit f2ad3242be)
2019-07-26 15:56:18 +02:00
kay delaney
5de014a91d Explore/Loki: Display live tailed logs in correct order (#18031)
Closes #18027

(cherry picked from commit bf7fb67f73)
2019-07-26 15:56:18 +02:00
gotjosh
777311a759 Docs: Archive 6.2 and make 6.3 current version (#18257) 2019-07-24 19:30:03 +01:00
Marcus Efraimsson
829b5d0d40 Build: Update links to release notes and what's new article for v6.3.x 2019-07-11 16:34:05 +02:00
Sofia Papagiannaki
12878409db release 6.3.0-beta1 2019-07-10 15:58:07 +03:00
7552 changed files with 1173084 additions and 500839 deletions

View File

@@ -3,11 +3,8 @@
[
"@babel/preset-env",
{
"targets": {
"browsers": "last 3 versions"
},
"useBuiltIns": "entry",
"modules": "false",
"targets": { "browsers": "last 3 versions" },
"useBuiltIns": "entry"
}
]
]

View File

@@ -1,19 +1,19 @@
[run]
init_cmds = [
["go", "run", "build.go", "-dev", "build-cli"],
["go", "run", "build.go", "-dev", "build-server"],
["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"]
["go", "run", "build.go", "-dev", "build-server"],
["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"]
]
watch_all = true
follow_symlinks = true
watch_dirs = [
"$WORKDIR/pkg",
"$WORKDIR/public/views",
"$WORKDIR/conf",
"$WORKDIR/pkg",
"$WORKDIR/public/views",
"$WORKDIR/conf",
]
watch_exts = [".go", ".ini", ".toml", ".template.html"]
build_delay = 1500
cmds = [
["go", "run", "build.go", "-dev", "build-server"],
["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"]
["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"]
]

View File

@@ -1,60 +1,864 @@
version: 2.1
aliases:
# Workflow filters
- &filter-only-release
branches:
ignore: /.*/
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
jobs:
scan-docker-image:
description: "Scans a docker image for vulnerabilities using trivy"
parameters:
image:
type: string
tag:
type: string
docker:
- image: circleci/buildpack-deps:stretch
steps:
- setup_remote_docker
- restore_cache:
key: vulnerability-db
- run:
name: Install trivy
command: |
VERSION=$(
curl --silent "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | \
grep '"tag_name":' | \
sed -E 's/.*"v([^"]+)".*/\1/'
)
version: 2
wget https://github.com/aquasecurity/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz
tar zxvf trivy_${VERSION}_Linux-64bit.tar.gz
sudo mv trivy /usr/local/bin
jobs:
mysql-integration-test:
docker:
- image: circleci/golang:1.12.6
- image: circleci/mysql:5.6-ram
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: grafana_tests
MYSQL_USER: grafana
MYSQL_PASSWORD: password
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run: sudo apt update
- run: sudo apt install -y mysql-client
- run: dockerize -wait tcp://127.0.0.1:3306 -timeout 120s
- run: cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h 127.0.0.1 -P 3306 -u root -prootpass
- run:
name: mysql integration tests
command: './scripts/circle-test-mysql.sh'
postgres-integration-test:
docker:
- image: circleci/golang:1.12.6
- image: circleci/postgres:9.3-ram
environment:
POSTGRES_USER: grafanatest
POSTGRES_PASSWORD: grafanatest
POSTGRES_DB: grafanatest
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run: sudo apt update
- run: sudo apt install -y postgresql-client
- run: dockerize -wait tcp://127.0.0.1:5432 -timeout 120s
- run: 'PGPASSWORD=grafanatest psql -p 5432 -h 127.0.0.1 -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql'
- run:
name: postgres integration tests
command: './scripts/circle-test-postgres.sh'
cache-server-test:
docker:
- image: circleci/golang:1.12.6
- image: circleci/redis:4-alpine
- image: memcached
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run: dockerize -wait tcp://127.0.0.1:11211 -timeout 120s
- run: dockerize -wait tcp://127.0.0.1:6379 -timeout 120s
- run:
name: cache server tests
command: './scripts/circle-test-cache-servers.sh'
end-to-end-test:
docker:
- image: circleci/node:10-browsers
- image: grafana/grafana-dev:master-$CIRCLE_SHA1
steps:
- run: dockerize -wait tcp://127.0.0.1:3000 -timeout 120s
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "yarn.lock" }}
- run:
name: yarn install
command: 'yarn install --pure-lockfile --no-progress'
no_output_timeout: 5m
- save_cache:
key: dependency-cache-{{ checksum "yarn.lock" }}
paths:
- node_modules
- run:
name: run end-to-end tests
command: 'env BASE_URL=http://127.0.0.1:3000 yarn e2e-tests'
no_output_timeout: 5m
- store_artifacts:
path: public/e2e-test/screenShots/theTruth
destination: expected-screenshots
- store_artifacts:
path: public/e2e-test/screenShots/theOutput
destination: output-screenshots
end-to-end-test-release:
docker:
- image: circleci/node:10-browsers
- image: grafana/grafana-dev:$CIRCLE_TAG
steps:
- run: dockerize -wait tcp://127.0.0.1:3000 -timeout 120s
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "yarn.lock" }}
- run:
name: yarn install
command: 'yarn install --pure-lockfile --no-progress'
no_output_timeout: 5m
- save_cache:
key: dependency-cache-{{ checksum "yarn.lock" }}
paths:
- node_modules
- run:
name: run end-to-end tests
command: 'env BASE_URL=http://127.0.0.1:3000 yarn e2e-tests'
no_output_timeout: 5m
- store_artifacts:
path: public/e2e-test/screenShots/theTruth
destination: expected-screenshots
- store_artifacts:
path: public/e2e-test/screenShots/theOutput
destination: output-screenshots
codespell:
docker:
- image: circleci/python
steps:
- checkout
- run:
name: Clear trivy cache
command: trivy --clear-cache
name: install codespell
command: 'sudo pip install codespell'
- run:
name: Scan Docker image for unkown/low/medium vulnerabilities
command: trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM << parameters.image >>:<< parameters.tag >>
# Important: all words have to be in lowercase, and separated by "\n".
name: exclude known exceptions
command: 'echo -e "unknwon\nreferer\nerrorstring" > words_to_ignore.txt'
- run:
name: Scan Docker image for high/critical vulnerabilities
command: trivy --exit-code 1 --severity HIGH,CRITICAL << parameters.image >>:<< parameters.tag >>
name: check documentation spelling errors
command: 'codespell -I ./words_to_ignore.txt docs/'
lint-go:
docker:
- image: circleci/golang:1.12.6
environment:
# we need CGO because of go-sqlite3
CGO_ENABLED: 1
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run:
name: Lint Go
command: 'make lint-go'
shellcheck:
machine: true
working_directory: ~/go/src/github.com/grafana/grafana
steps:
- checkout
- run:
name: ShellCheck
command: 'make shellcheck'
test-frontend:
docker:
- image: circleci/node:10
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "yarn.lock" }}
- run:
name: yarn install
command: 'yarn install --pure-lockfile --no-progress'
no_output_timeout: 15m
- save_cache:
key: vulnerability-db
key: dependency-cache-{{ checksum "yarn.lock" }}
paths:
- $HOME/.cache/trivy
- node_modules
- run:
name: frontend tests
command: './scripts/circle-test-frontend.sh'
test-backend:
docker:
- image: circleci/golang:1.12.6
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run:
name: build backend and run go tests
command: './scripts/circle-test-backend.sh'
build-all:
docker:
- image: grafana/build-container:1.2.7
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run:
name: prepare build tools
command: '/tmp/bootstrap.sh'
- restore_cache:
key: phantomjs-binaries-{{ checksum "scripts/build/download-phantomjs.sh" }}
- run:
name: download phantomjs binaries
command: './scripts/build/download-phantomjs.sh'
- save_cache:
key: phantomjs-binaries-{{ checksum "scripts/build/download-phantomjs.sh" }}
paths:
- /tmp/phantomjs
- run:
name: build and package grafana
command: './scripts/build/build-all.sh'
- run:
name: sign packages
command: './scripts/build/sign_packages.sh'
- run:
name: verify signed packages
command: |
mkdir -p ~/.rpmdb/pubkeys
curl -s https://grafanarel.s3.amazonaws.com/RPM-GPG-KEY-grafana > ~/.rpmdb/pubkeys/grafana.key
./scripts/build/verify_signed_packages.sh dist/*.rpm
- run:
name: sha-sum packages
command: 'go run build.go sha-dist'
- run:
name: Test and build Grafana.com release publisher
command: 'cd scripts/build/release_publisher && go test . && go build -o release_publisher .'
- persist_to_workspace:
root: .
paths:
- dist/*
- scripts/*.sh
- scripts/build/release_publisher/release_publisher
- scripts/build/publish.sh
build:
docker:
- image: grafana/build-container:1.2.7
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run:
name: prepare build tools
command: '/tmp/bootstrap.sh'
- run:
name: build and package grafana
command: './scripts/build/build.sh'
- run:
name: sign packages
command: './scripts/build/sign_packages.sh'
- run:
name: sha-sum packages
command: 'go run build.go sha-dist'
- run:
name: Test Grafana.com release publisher
command: 'cd scripts/build/release_publisher && go test .'
- persist_to_workspace:
root: .
paths:
- dist/*
build-fast-backend:
docker:
- image: grafana/build-container:1.2.7
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run:
name: prepare build tools
command: '/tmp/bootstrap.sh'
- run:
name: build grafana backend
command: './scripts/build/build.sh --fast --backend-only'
- persist_to_workspace:
root: .
paths:
- bin/*
build-fast-frontend:
docker:
- image: grafana/build-container:1.2.7
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run:
name: prepare build tools
command: '/tmp/bootstrap.sh'
- restore_cache:
key: frontend-dependency-cache-{{ checksum "yarn.lock" }}
- run:
name: build grafana frontend
command: './scripts/build/build.sh --fast --frontend-only'
- save_cache:
key: frontend-dependency-cache-{{ checksum "yarn.lock" }}
paths:
- node_modules
- persist_to_workspace:
root: .
paths:
- public/build/*
- tools/phantomjs/*
build-fast-package:
docker:
- image: grafana/build-container:1.2.7
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- attach_workspace:
at: .
- restore_cache:
key: frontend-dependency-cache-{{ checksum "yarn.lock" }}
- run:
name: prepare build tools
command: '/tmp/bootstrap.sh'
- run:
name: package grafana
command: './scripts/build/build.sh --fast --package-only'
- run:
name: sha-sum packages
command: 'go run build.go sha-dist'
- run:
name: Test Grafana.com release publisher
command: 'cd scripts/build/release_publisher && go test .'
- persist_to_workspace:
root: /go/src/github.com/grafana/grafana
paths:
- dist/*
build-fast-save:
docker:
- image: grafana/build-container:1.2.7
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- attach_workspace:
at: .
- restore_cache:
key: dependency-cache-{{ checksum "yarn.lock" }}
- run:
name: debug cache
command: 'ls -al /go/src/github.com/grafana/grafana/node_modules'
- run:
name: prepare build tools
command: '/tmp/bootstrap.sh'
- run:
name: build grafana backend
command: './scripts/build/build.sh --fast --backend-only'
- run:
name: build grafana frontend
command: './scripts/build/build.sh --fast --frontend-only'
- save_cache:
key: dependency-cache-{{ checksum "yarn.lock" }}
paths:
- /go/src/github.com/grafana/grafana/node_modules
- run:
name: package grafana
command: './scripts/build/build.sh --fast --package-only'
- run:
name: sign packages
command: './scripts/build/sign_packages.sh'
- run:
name: sha-sum packages
command: 'go run build.go sha-dist'
- run:
name: Test Grafana.com release publisher
command: 'cd scripts/build/release_publisher && go test .'
- persist_to_workspace:
root: .
paths:
- dist/*
grafana-docker-master:
machine:
image: circleci/classic:201808-01
steps:
- checkout
- attach_workspace:
at: .
- run: docker info
- run: docker run --privileged linuxkit/binfmt:v0.6
- run: cp dist/grafana-latest.linux-*.tar.gz packaging/docker
- run: cd packaging/docker && ./build-deploy.sh "master-${CIRCLE_SHA1}"
- run: rm packaging/docker/grafana-latest.linux-*.tar.gz
- run: cp enterprise-dist/grafana-enterprise-*.linux-amd64.tar.gz packaging/docker/grafana-latest.linux-x64.tar.gz
- run: cd packaging/docker && ./build-enterprise.sh "master"
grafana-docker-pr:
machine:
image: circleci/classic:201808-01
steps:
- checkout
- attach_workspace:
at: .
- run: docker info
- run: docker run --privileged linuxkit/binfmt:v0.6
- run: cp dist/grafana-latest.linux-*.tar.gz packaging/docker
- run: cd packaging/docker && ./build.sh --fast "${CIRCLE_SHA1}"
grafana-docker-release:
machine:
image: circleci/classic:201808-01
steps:
- checkout
- attach_workspace:
at: .
- run: docker info
- run: docker run --privileged linuxkit/binfmt:v0.6
- run: cp dist/grafana-latest.linux-*.tar.gz packaging/docker
- run: cd packaging/docker && ./build-deploy.sh "${CIRCLE_TAG}"
- run: rm packaging/docker/grafana-latest.linux-*.tar.gz
- run: cp enterprise-dist/grafana-enterprise-*.linux-amd64.tar.gz packaging/docker/grafana-latest.linux-x64.tar.gz
- run: cd packaging/docker && ./build-enterprise.sh "${CIRCLE_TAG}"
build-enterprise:
docker:
- image: grafana/build-container:1.2.7
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run:
name: prepare build tools
command: '/tmp/bootstrap.sh'
- run:
name: checkout enterprise
command: './scripts/build/prepare-enterprise.sh'
- run:
name: test enterprise
command: 'go test ./pkg/extensions/...'
- run:
name: build and package enterprise
command: './scripts/build/build.sh -enterprise'
- run:
name: sign packages
command: './scripts/build/sign_packages.sh'
- run:
name: sha-sum packages
command: 'go run build.go sha-dist'
- run:
name: move enterprise packages into their own folder
command: 'mv dist enterprise-dist'
- persist_to_workspace:
root: .
paths:
- enterprise-dist/*
build-all-enterprise:
docker:
- image: grafana/build-container:1.2.7
working_directory: /go/src/github.com/grafana/grafana
steps:
- checkout
- run:
name: prepare build tools
command: '/tmp/bootstrap.sh'
- run:
name: checkout enterprise
command: './scripts/build/prepare-enterprise.sh'
- restore_cache:
key: phantomjs-binaries-{{ checksum "scripts/build/download-phantomjs.sh" }}
- run:
name: download phantomjs binaries
command: './scripts/build/download-phantomjs.sh'
- save_cache:
key: phantomjs-binaries-{{ checksum "scripts/build/download-phantomjs.sh" }}
paths:
- /tmp/phantomjs
- run:
name: test enterprise
command: 'go test ./pkg/extensions/...'
- run:
name: build and package grafana
command: './scripts/build/build-all.sh -enterprise'
- run:
name: sign packages
command: './scripts/build/sign_packages.sh'
- run:
name: verify signed packages
command: |
mkdir -p ~/.rpmdb/pubkeys
curl -s https://grafanarel.s3.amazonaws.com/RPM-GPG-KEY-grafana > ~/.rpmdb/pubkeys/grafana.key
./scripts/build/verify_signed_packages.sh dist/*.rpm
- run:
name: sha-sum packages
command: 'go run build.go sha-dist'
- run:
name: move enterprise packages into their own folder
command: 'mv dist enterprise-dist'
- persist_to_workspace:
root: .
paths:
- enterprise-dist/*
deploy-enterprise-master:
docker:
- image: grafana/grafana-ci-deploy:1.2.2
steps:
- attach_workspace:
at: .
- run:
name: gcp credentials
command: 'echo ${GCP_GRAFANA_UPLOAD_KEY} > /tmp/gcpkey.json'
- run:
name: sign in to gcp
command: '/opt/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=/tmp/gcpkey.json'
- run:
name: deploy to s3
command: 'aws s3 sync ./enterprise-dist s3://$ENTERPRISE_BUCKET_NAME/master'
- run:
name: deploy to gcp
command: '/opt/google-cloud-sdk/bin/gsutil cp ./enterprise-dist/* gs://$GCP_BUCKET_NAME/enterprise/master'
- run:
name: Deploy to grafana.com
command: |
cd enterprise-dist
../scripts/build/release_publisher/release_publisher -apikey ${GRAFANA_COM_API_KEY} -enterprise -version "v$(cat grafana.version)" --nightly
deploy-enterprise-release:
docker:
- image: grafana/grafana-ci-deploy:1.2.2
steps:
- checkout
- attach_workspace:
at: .
- run:
name: gcp credentials
command: 'echo ${GCP_GRAFANA_UPLOAD_KEY} > /tmp/gcpkey.json'
- run:
name: sign in to gcp
command: '/opt/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=/tmp/gcpkey.json'
- run:
name: deploy to s3
command: 'aws s3 sync ./enterprise-dist s3://$ENTERPRISE_BUCKET_NAME/release'
- run:
name: deploy to gcp
command: '/opt/google-cloud-sdk/bin/gsutil cp ./enterprise-dist/* gs://$GCP_BUCKET_NAME/enterprise/release'
- run:
name: Deploy to Grafana.com
command: './scripts/build/publish.sh --enterprise'
- run:
name: Load GPG private key
command: './scripts/build/load-signing-key.sh'
- run:
name: Update Debian repository
command: './scripts/build/update_repo/update-deb.sh "enterprise" "$GPG_KEY_PASSWORD" "$CIRCLE_TAG" "enterprise-dist"'
- run:
name: Update RPM repository
command: './scripts/build/update_repo/update-rpm.sh "enterprise" "$GPG_KEY_PASSWORD" "$CIRCLE_TAG" "enterprise-dist"'
deploy-master:
docker:
- image: grafana/grafana-ci-deploy:1.2.2
steps:
- attach_workspace:
at: .
- run:
name: deploy to s3
command: |
# Also
cp dist/grafana-latest.linux-x64.tar.gz dist/grafana-master-$(echo "${CIRCLE_SHA1}" | cut -b1-7).linux-x64.tar.gz
aws s3 sync ./dist s3://$BUCKET_NAME/master
- run:
name: Trigger Windows build
command: './scripts/trigger_windows_build.sh ${APPVEYOR_TOKEN} ${CIRCLE_SHA1} master'
- run:
name: gcp credentials
command: 'echo ${GCP_GRAFANA_UPLOAD_KEY} > /tmp/gcpkey.json'
- run:
name: sign in to gcp
command: '/opt/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=/tmp/gcpkey.json'
- run:
name: deploy to gcp
command: '/opt/google-cloud-sdk/bin/gsutil cp ./dist/* gs://$GCP_BUCKET_NAME/oss/master'
- run:
name: Publish to Grafana.com
command: |
rm dist/grafana-master-$(echo "${CIRCLE_SHA1}" | cut -b1-7).linux-x64.tar.gz
rm dist/*latest*
cd dist && ../scripts/build/release_publisher/release_publisher -apikey ${GRAFANA_COM_API_KEY} -version "v$(cat grafana.version)" --nightly
deploy-release:
docker:
- image: grafana/grafana-ci-deploy:1.2.2
steps:
- checkout
- attach_workspace:
at: .
- run:
name: deploy to s3
command: 'aws s3 sync ./dist s3://$BUCKET_NAME/release'
- run:
name: gcp credentials
command: 'echo ${GCP_GRAFANA_UPLOAD_KEY} > /tmp/gcpkey.json'
- run:
name: sign in to gcp
command: '/opt/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=/tmp/gcpkey.json'
- run:
name: deploy to gcp
command: '/opt/google-cloud-sdk/bin/gsutil cp ./dist/* gs://$GCP_BUCKET_NAME/oss/release'
- run:
name: Deploy to Grafana.com
command: './scripts/build/publish.sh'
- run:
name: Load GPG private key
command: './scripts/build/load-signing-key.sh'
- run:
name: Update Debian repository
command: './scripts/build/update_repo/update-deb.sh "oss" "$GPG_KEY_PASSWORD" "$CIRCLE_TAG" "dist"'
- run:
name: Update RPM repository
command: './scripts/build/update_repo/update-rpm.sh "oss" "$GPG_KEY_PASSWORD" "$CIRCLE_TAG" "dist"'
build-oss-msi:
docker:
- image: grafana/wix-toolset-ci:v3
steps:
- checkout
- attach_workspace:
at: .
- run:
name: Build OSS MSI
command: './scripts/build/ci-msi-build/ci-msi-build-oss.sh'
- persist_to_workspace:
root: .
paths:
- dist/grafana-*.msi
- dist/grafana-*.msi.sha256
store-build-artifacts:
docker:
- image: circleci/node:10
steps:
- attach_workspace:
at: .
- store_artifacts:
path: ./dist
trigger-docs-update:
docker:
- image: circleci/python:3.6.8
steps:
- checkout
- run:
name: Trigger Docs update
command: |
if git diff --name-only HEAD^ | grep -q "^docs"; then
echo "Build URL:"
curl -s -u "$DOCS_CIRCLE_TOKEN:" \
-d build_parameters[CIRCLE_JOB]=pull-submodule-changes \
https://circleci.com/api/v1.1/project/github/grafana/docs.grafana.com/tree/staging \
| jq .build_url
else
echo "-- no changes to docs files --"
fi
workflows:
nightly:
triggers:
- schedule:
cron: "0 0 * * *"
filters: *filter-only-master
version: 2
build-master:
jobs:
- scan-docker-image:
matrix:
parameters:
image: [grafana/grafana, grafana/grafana-enterprise]
tag: [latest, master, latest-ubuntu, master-ubuntu]
- build-all:
filters: *filter-only-master
- build-all-enterprise:
filters: *filter-only-master
- codespell:
filters: *filter-only-master
- lint-go:
filters: *filter-only-master
- shellcheck:
filters: *filter-only-master
- test-frontend:
filters: *filter-only-master
- test-backend:
filters: *filter-only-master
- mysql-integration-test:
filters: *filter-only-master
- postgres-integration-test:
filters: *filter-only-master
- deploy-master:
requires:
- build-all
- test-backend
- test-frontend
- codespell
- lint-go
- shellcheck
- mysql-integration-test
- postgres-integration-test
- build-oss-msi
filters: *filter-only-master
- grafana-docker-master:
requires:
- build-all
- build-all-enterprise
- test-backend
- test-frontend
- codespell
- lint-go
- shellcheck
- mysql-integration-test
- postgres-integration-test
filters: *filter-only-master
- deploy-enterprise-master:
requires:
- build-all
- test-backend
- test-frontend
- codespell
- lint-go
- shellcheck
- mysql-integration-test
- postgres-integration-test
- build-all-enterprise
filters: *filter-only-master
- build-oss-msi:
requires:
- build-all
- test-backend
- test-frontend
- codespell
- lint-go
- shellcheck
- mysql-integration-test
- postgres-integration-test
filters: *filter-only-master
- end-to-end-test:
requires:
- grafana-docker-master
filters: *filter-only-master
- trigger-docs-update:
requires:
- end-to-end-test
filters: *filter-only-master
release:
jobs:
- build-all:
filters: *filter-only-release
- build-all-enterprise:
filters: *filter-only-release
- codespell:
filters: *filter-only-release
- lint-go:
filters: *filter-only-release
- shellcheck:
filters: *filter-only-release
- test-frontend:
filters: *filter-only-release
- test-backend:
filters: *filter-only-release
- mysql-integration-test:
filters: *filter-only-release
- postgres-integration-test:
filters: *filter-only-release
- deploy-release:
requires:
- build-all
- test-backend
- test-frontend
- codespell
- lint-go
- shellcheck
- mysql-integration-test
- postgres-integration-test
- build-oss-msi
filters: *filter-only-release
- deploy-enterprise-release:
requires:
- build-all
- build-all-enterprise
- test-backend
- test-frontend
- codespell
- lint-go
- shellcheck
- mysql-integration-test
- postgres-integration-test
filters: *filter-only-release
- grafana-docker-release:
requires:
- build-all
- build-all-enterprise
- test-backend
- test-frontend
- codespell
- lint-go
- shellcheck
- mysql-integration-test
- postgres-integration-test
filters: *filter-only-release
- build-oss-msi:
requires:
- build-all
- test-backend
- test-frontend
- codespell
- lint-go
- shellcheck
- mysql-integration-test
- postgres-integration-test
filters: *filter-only-release
- end-to-end-test-release:
requires:
- grafana-docker-release
filters: *filter-only-release
build-branches-and-prs:
jobs:
- build-fast-backend:
filters: *filter-not-release-or-master
- build-fast-frontend:
filters: *filter-not-release-or-master
- build-fast-package:
filters: *filter-not-release-or-master
requires:
- build-fast-backend
- build-fast-frontend
- codespell:
filters: *filter-not-release-or-master
- lint-go:
filters: *filter-not-release-or-master
- lint-go:
filters: *filter-not-release-or-master
- shellcheck:
filters: *filter-not-release-or-master
- test-frontend:
filters: *filter-not-release-or-master
- test-backend:
filters: *filter-not-release-or-master
- mysql-integration-test:
filters: *filter-not-release-or-master
- postgres-integration-test:
filters: *filter-not-release-or-master
- cache-server-test:
filters: *filter-not-release-or-master
- grafana-docker-pr:
requires:
- build-fast-package
- test-backend
- test-frontend
- codespell
- lint-go
- shellcheck
- mysql-integration-test
- postgres-integration-test
- cache-server-test
filters: *filter-not-release-or-master
- store-build-artifacts:
requires:
- build-fast-package
- test-backend
- test-frontend
- codespell
- lint-go
- shellcheck
- mysql-integration-test
- postgres-integration-test
- cache-server-test
filters: *filter-not-release-or-master

View File

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

3328
.drone.yml

File diff suppressed because it is too large Load Diff

View File

@@ -16,15 +16,9 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{js,ts,tsx,scss}]
quote_type = single
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
indent_size = 2
[*.star]
indent_size = 4

View File

@@ -1,8 +0,0 @@
node_modules
compiled
build
vendor
devenv
data
dist
e2e/tmp

View File

@@ -1,23 +0,0 @@
{
"extends": ["@grafana/eslint-config"],
"root": true,
"plugins": [
"no-only-tests"
],
"rules": {
"no-only-tests/no-only-tests": "error",
"react/prop-types": "off"
},
"overrides": [
{
"files": [
"packages/grafana-ui/src/components/uPlot/**/*.{ts,tsx}",
"public/app/**/*.{ts,tsx}"
],
"rules": {
"react-hooks/rules-of-hooks": "off",
"react-hooks/exhaustive-deps": "off"
}
}
]
}

1
.gitattributes vendored
View File

@@ -1 +0,0 @@
* text=auto eol=lf

76
.github/CODEOWNERS vendored
View File

@@ -1,76 +0,0 @@
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners.
# More details are here: https://help.github.com/articles/about-codeowners/
# The '*' pattern is global owners.
# Order is important. The last matching pattern has the most precedence.
# The folders are ordered as follows:
# In each subsection folders are ordered first by depth, then alphabetically.
# This should make it easy to add new rules without breaking existing ones.
# Documentation owner: Diana Payton
/docs/ @grafana/docs-squad
/contribute/ @marcusolsson @grafana/docs-squad
/docs/sources/developers/plugins/ @marcusolsson
/docs/sources/enterprise/ @osg-grafana
# Backend code
*.go @grafana/backend-platform
go.mod @grafana/backend-platform
go.sum @grafana/backend-platform
#Cloud Datasources backend code
/pkg/tsdb/cloudwatch @grafana/cloud-datasources
/pkg/tsdb/azuremonitor @grafana/cloud-datasources
/pkg/tsdb/cloudmonitoring @grafana/cloud-datasources
# Database migrations
/pkg/services/sqlstore/migrations @grafana/backend-platform @grafana/hosted-grafana-team
*_mig.go @grafana/backend-platform @grafana/hosted-grafana-team
# Backend code docs
/contribute/style-guides/backend.md @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/cloud-datasources @grafana/observability-squad
/public/app/plugins/datasource/elasticsearch @grafana/observability-squad
/public/app/plugins/datasource/grafana-azure-monitor-datasource @grafana/cloud-datasources
/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/cloud-datasources
/public/app/plugins/datasource/zipkin @grafana/observability-squad
# Cloud middleware
/grafana-mixin/ @grafana/cloud-middleware

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

14
.github/ISSUE_TEMPLATE/4-question.md vendored Normal file
View File

@@ -0,0 +1,14 @@
---
name: Support request
about: 'Question or support request relating to using Grafana'
title: ''
labels: ''
assignees: ''
---
STOP -- PLEASE READ!
GitHub is not the right place for questions and support requests.
Please ask questions on our community site: [https://community.grafana.com/](https://community.grafana.com/)

View File

@@ -1,5 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Questions & Help
url: https://community.grafana.com
about: Please ask and answer questions here.

View File

@@ -1,33 +1,20 @@
<!--
Thank you for sending a pull request! Here are some tips:
1. If this is your first time, please read our contribution guide at https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md
2. Ensure you include and run the appropriate tests as part of your Pull Request.
3. In a new feature or configuration option, an update to the documentation is necessary. Everything related to the documentation is under the docs folder in the root of the repository.
4. If the Pull Request is a work in progress, make use of GitHub's "Draft PR" feature and mark it as such.
5. If you can not merge your Pull Request due to a merge conflict, Rebase it. This gets it in sync with the master branch.
6. Name your PR as "<FeatureArea>: Describe your change", e.g. Alerting: Prevent race condition. If it's a fix or feature relevant for the changelog describe the user impact in the title. The PR title is used to auto-generate the changelog for issues marked with the "add to changelog" label.
<!-- Thanks for sending a pull request! Here are some tips for you:
1. If this is your first time, please read our [`CONTRIBUTING.md`](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md) guide.
2. Ensure you have added or ran the appropriate tests for your PR.
3. If it's a new feature or config option it will need a docs update. Docs are under the docs folder in repo root.
4. If the PR is unfinished, mark it as a draft PR.
5. Rebase your PR if it gets out of sync with master
6. Name your PR as `<FeatureArea>: Describe your change`. If it's a fix or feature relevant for changelog describe the user impact in the title. The PR title is used in changelog for issues marked with `add to changelog` label.
-->
**What this PR does / why we need it**:
**Which issue(s) this PR fixes**:
<!--
- Automatically closes linked issue when the Pull Request is merged.
Usage: "Fixes #<issue number>", or "Fixes (paste link of issue)"
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->
Fixes #
**Special notes for your reviewer**:

30
.github/bot.md vendored
View File

@@ -1,30 +0,0 @@
# GitHub & grafanabot automation
The bot is configured via [commands.json](https://github.com/grafana/grafana/blob/master/.github/commands.json) and some other GitHub workflows [workflows](https://github.com/grafana/grafana/tree/master/.github/workflows).
Comment commands:
* Write the word `/duplicate #<number>` anywhere in a comment and the bot will add the correct label and standard message.
* Write the word `/needsMoreInfo` anywhere in a comment and the bot will add the correct label and standard message.
Label commands:
* Add label `bot/question` the the bot will close with standard question message and add label `type/question`
* Add label `bot/duplicate` the the bot will close with standard duplicate message and add label `type/duplicate`
* Add label `bot/needs more info` for bot to request more info (or use comment command mentioned above)
* Add label `bot/close feature request` for bot to close a feature request with standard message and adds label `not implemented`
* Add label `bot/no new info` for bot to close an issue where we asked for more info but has not received any updates in at least 14 days.
## Metrics
Metrics are configured in [metrics-collector.json](https://github.com/grafana/grafana/blob/master/.github/metrics-collector.json) and are also defined in the
[metrics-collector](https://github.com/grafana/grafana-github-actions/blob/main/metrics-collector/index.ts) GitHub action.
## Backport PR
To automatically backport a PR to a release branch like v7.3.x add a label named `backport v7.3.x`. The label name should follow the pattern `backport <branch-name>`. Once merged grafanabot will automatically
try to cherry-pick the PR merge commit into that branch and open a PR. It will sync the milestone with the source PR so make sure the source PR also is assigned the milestone for the patch release. If the PR is already merged you can still add this label and trigger the backport automation.
If there are merge conflicts the bot will write a comment on the source PR saying the cherry-pick failed. In this case you have to do the cherry pick and backport PR manually.
The backport logic is written [here](https://github.com/grafana/grafana-github-actions/blob/main/backport/backport.ts)

53
.github/commands.json vendored
View File

@@ -1,53 +0,0 @@
[
{
"type": "label",
"name": "bot/question",
"addLabel": "type/question",
"removeLabel": "bot/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": "bot/duplicate",
"addLabel": "type/duplicate",
"removeLabel": "bot/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": "comment",
"name": "needsMoreInfo",
"allowUsers": [],
"action": "updateLabels",
"addLabel": "bot/needs more info"
},
{
"type": "label",
"name": "bot/needs more info",
"action": "updateLabels",
"addLabel": "needs more info",
"removeLabel": "bot/needs more info",
"comment": "Thanks for creating this issue! We think it's missing some basic information. \r\n\r\nFollow the issue template and add additional information that will help us replicate the problem. \r\nFor data visualization issues: \r\n- Query results from the inspect drawer (data tab & query inspector)\r\n- Panel settings can be extracted in the panel inspect drawer JSON tab\r\n\r\nFor dashboard related issues: \r\n- Dashboard JSON can be found in the dashboard settings JSON model view\r\n\r\nFor authentication, provisioning and alerting issues, Grafana server logs are useful. \r\n\r\nHappy graphing!"
},
{
"type": "label",
"name": "bot/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!"
},
{
"type": "label",
"name": "bot/close feature request",
"action": "close",
"addLabel": "not implemented",
"comment": "This feature request has been open for a long time with few received upvotes or comments, so we are closing it. We're trying to limit open GitHub issues in order to better track planned work and features. \r\n\r\nThis doesn't mean that we'll never ever implement it or that we will never accept a PR for it. A closed issue can still attract upvotes and act as a ticket to track feature demand\/interest. \r\n\r\nThank You to you for taking the time to create this issue!"
}
]

View File

@@ -1,10 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -1,32 +0,0 @@
{
"queries": [
{
"name": "type_bug",
"query": "label:\"type/bug\" is:open"
},
{
"name": "type_docs",
"query": "label:\"type/docs\" is:open"
},
{
"name": "needs_investigation",
"query": "label:\"needs investigation\" is:open"
},
{
"name": "needs_more_info",
"query": "label:\"needs more info\" is:open"
},
{
"name": "unlabeled",
"query": "is:open is:issue no:label"
},
{
"name": "open_prs",
"query": "is:open is:pr"
},
{
"name": "milestone_7_4_open",
"query": "is:open is:issue milestone:7.4"
}
]
}

47
.github/stale.yml vendored
View File

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

View File

@@ -1,26 +0,0 @@
name: Backport PR Creator
on:
pull_request_target:
types:
- closed
- labeled
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 backport
uses: ./actions/backport
with:
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
token: ${{secrets.GH_BOT_ACCESS_TOKEN}}
labelsToAdd: "backport"
title: "[{{base}}] {{originalTitle}}"

View File

@@ -1,27 +0,0 @@
name: Bump version
on:
workflow_dispatch:
inputs:
version:
required: true
default: '7.x.x'
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout Actions
uses: actions/checkout@v2
with:
repository: "grafana/grafana-github-actions"
path: ./actions
ref: main
- uses: actions/setup-node@v2.1.4
with:
node-version: '14'
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Run bump version
uses: ./actions/bump-version
with:
token: ${{secrets.GH_BOT_ACCESS_TOKEN}}
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}

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}}
configPath: commands

View File

@@ -1,24 +0,0 @@
name: Create or update GitHub release
on:
workflow_dispatch:
inputs:
version:
required: true
description: Needs to match, exactly, the name of a milestone (NO v prefix)
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 github release action
uses: ./actions/github-release
with:
token: ${{secrets.GH_BOT_ACCESS_TOKEN}}
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}

View File

@@ -1,35 +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}}
configPath: "metrics-collector"

View File

@@ -1,44 +0,0 @@
name: publish_docs
on:
push:
branches:
- master
paths:
- 'docs/sources/**'
- 'packages/grafana-*/**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: git clone --single-branch --no-tags --depth 1 -b master https://grafanabot:${{ secrets.GH_BOT_ACCESS_TOKEN }}@github.com/grafana/website-sync ./.github/actions/website-sync
- uses: actions/cache@v2.1.4
with:
path: '**/node_modules'
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- name: generate-packages-docs
uses: actions/setup-node@v2.1.4
id: generate-docs
with:
node-version: '14'
- run: yarn install --pure-lockfile --no-progress
- run: ./scripts/ci-reference-docs-build.sh
- name: publish-to-git
uses: ./.github/actions/website-sync
id: publish
with:
repository: grafana/website
branch: master
host: github.com
github_pat: '${{ secrets.GH_BOT_ACCESS_TOKEN }}'
source_folder: docs/sources
target_folder: content/docs/grafana/latest
allow_no_changes: 'true'
- shell: bash
run: |
test -n "${{ steps.publish.outputs.commit_hash }}"
test -n "${{ steps.publish.outputs.working_directory }}"

View File

@@ -1,24 +0,0 @@
name: Update changelog
on:
workflow_dispatch:
inputs:
version:
required: true
description: Needs to match, exactly, the name of a milestone
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 update changelog
uses: ./actions/update-changelog
with:
token: ${{secrets.GH_BOT_ACCESS_TOKEN}}
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}

53
.gitignore vendored
View File

@@ -10,23 +10,8 @@ awsconfig
/public/views/index.html
/public/views/error.html
/emails/dist
/reports
/e2e/tmp
.yarnrc
.yarn/
vendor/
/docs/menu.yaml
# Enterprise emails
/emails/templates/enterprise_*
/public/emails/enterprise_*
# Enterprise reporting fonts
/public/fonts/dejavu
# Enterprise devenv
/devenv/docker/blocks/grafana-enterprise
/public_gen
/public/vendor/npm
/tmp
tools/phantomjs/phantomjs
tools/phantomjs/phantomjs.exe
@@ -50,16 +35,14 @@ public/css/*.min.css
.DS_Store
.vscode/
.vs/
.eslintcache
/data/*
/bin/*
# devenv
/devenv/docker-compose.yaml
/devenv/.env
conf/custom.ini
fig.yml
devenv/docker-compose.yml
devenv/docker-compose.yaml
/conf/provisioning/**/custom.yaml
/conf/provisioning/**/dev.yaml
/conf/ldap_dev.toml
@@ -72,8 +55,7 @@ profile.cov
/pkg/cmd/grafana-cli/grafana-cli
/pkg/cmd/grafana-server/grafana-server
/pkg/cmd/grafana-server/debug
/pkg/extensions/*
!/pkg/extensions/main.go
/pkg/extensions
/public/app/extensions
debug.test
/examples/*/dist
@@ -93,8 +75,6 @@ debug.test
/devenv/bulk-dashboards/*.json
/devenv/bulk_alerting_dashboards/*.json
/devenv/datasources_bulk.yaml
/devenv/bulk_alerting_dashboards/bulk_alerting_datasources.yaml
/scripts/build/release_publisher/release_publisher
*.patch
@@ -103,25 +83,8 @@ debug.test
/packages/**/dist
/packages/**/compiled
/packages/**/.rpt2_cache
/packages/**/tsdoc-metadata.json
theOutput/
# Ignore go local build dependencies
/scripts/go/bin/**
# Ignore compilation stats from `yarn stats`
compilation-stats.json
# e2e tests
/packages/grafana-e2e/cypress/screenshots
/packages/grafana-e2e/cypress/videos
/packages/grafana-e2e/cypress/logs
/e2e/server.log
/e2e/**/screenshots
!/e2e/**/screenshots/expected/*
/e2e/**/videos/*
# report dumping the whole system env
/report.*.json
# auto generated frontend docs
/docs/sources/packages_api

View File

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

View File

@@ -1,3 +0,0 @@
module.exports = {
...require('@grafana/toolkit/src/config/prettier.plugin.config.json'),
};

File diff suppressed because it is too large Load Diff

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

@@ -1,79 +1,62 @@
# Contributing to Grafana
# Contributing
Thank you for your interest in contributing to Grafana! We welcome all people who want to contribute in a healthy and constructive manner within our community. To help us create a safe and positive community experience for all, we require all participants to adhere to the [Code of Conduct](CODE_OF_CONDUCT.md).
Grafana uses GitHub to manage contributions.
Contributions take the form of pull requests that will be reviewed by the core team.
This document is a guide to help you through the process of contributing to Grafana.
- If you are a new contributor see: [Steps to Contribute](#steps-to-contribute)
## Become a contributor
- If you have a trivial fix or improvement, go ahead and create a pull request.
You can contribute to Grafana in several ways. Here are some examples:
- If you plan to do something more involved, discuss your idea on the respective [issue](https://github.com/grafana/grafana/issues) or create a [new issue](https://github.com/grafana/grafana/issues/new) if it does not exist. This will avoid unnecessary work and surely give you and us a good deal of inspiration.
- Contribute to the Grafana codebase.
- Report and triage bugs.
- Develop community plugins and dashboards.
- Write technical documentation and blog posts, for users and contributors.
- Organize meetups and user groups in your local area.
- Help others by answering questions about Grafana.
- Sign our [CLA](http://docs.grafana.org/contribute/cla/).
For more ways to contribute, check out the [Open Source Guides](https://opensource.guide/how-to-contribute/).
- Make sure to follow the code style guides
- [Backend](https://github.com/grafana/grafana/tree/master/pkg)
- [Frontend](https://github.com/grafana/grafana/tree/master/style_guides)
### Report bugs
## Steps to Contribute
Before submitting a new issue, try to make sure someone hasn't already reported the problem. Look through the [existing issues](https://github.com/grafana/grafana/issues) for similar issues.
Should you wish to work on a GitHub issue, check first if it is not already assigned to someone. If it is free, you claim it by commenting on the issue that you want to work on it. This is to prevent duplicated efforts from contributors on the same issue.
Report a bug by submitting a [bug report](https://github.com/grafana/grafana/issues/new?labels=type%3A+bug&template=1-bug_report.md). Make sure that you provide as much information as possible on how to reproduce the bug.
Please check the [`beginner friendly`](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22) and [`help wanted`](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) labels to find issues that are good for getting started. If you have questions about one of the issues, with or without the tag, please comment on them and one of the core team or the original poster will clarify it.
Follow the issue template and add additional information that will help us replicate the problem.
To setup a local development environment we recommend reading [Building Grafana from source](http://docs.grafana.org/project/building_from_source/)
For data visualization issues:
- Query results from the inspect drawer (data tab & query inspector)
- Panel settings can be extracted in the panel inspect drawer JSON tab
## Pull Request Checklist
For a dashboard related issues:
- Dashboard JSON can be found in the dashboard settings JSON model view
- Branch from the master branch and, if needed, rebase to the current master branch before submitting your pull request. If it doesn't merge cleanly with master you may be asked to rebase your changes.
For authentication and alerting Grafana server logs are useful.
- If your patch is not getting reviewed or you need a specific person to review it, you can @-reply a reviewer asking for a review in the pull request or a comment.
#### Security issues
- Add tests relevant to the fixed bug or new feature.
If you believe you've found a security vulnerability, please read our [security policy](https://github.com/grafana/grafana/security/policy) for more details.
- Follow [PR and commit messages guidelines](#PR-and-commit-messages-guidelines)
### Suggest enhancements
### Pull Requests titles and message
If you have an idea of how to improve Grafana, submit an [enhancement request](https://github.com/grafana/grafana/issues/new?labels=type%3A+feature+request&template=2-feature_request.md).
Pull request titles should follow this format: `Area: Name of the change`.
Titles are used to generate the changelog so they should be as descriptive as possible in one line.
We want to make Grafana accessible to even more people. Submit an [accessibility issue](https://github.com/grafana/grafana/issues/new?labels=type%3A+accessibility&template=3-accessibility.md) to help us understand what we can improve.
Good Examples
### Triage issues
- `Explore: Adds Live option for supported datasources`
- `GraphPanel: Don't sort series when legend table & sort column is not visible`
- `Build: Support publishing MSI to grafana.com`
If you don't have the knowledge or time to code, consider helping with _issue triage_. The community will thank you for saving them time by spending some of yours.
The message in the Pull requests should contain a reference so the issue if there is one. Ex `Closes #<issue number>`, `Fixes #<issue number>`, or `Ref #<issue number>` if the change is related to an issue but does not close it. Make sure to explain what problem the pull request is solving and why its implemented this way. As a new contributor its often better to overcommunicate to avoid back and forth communication, as it consumes time and energy.
Read more about the ways you can [Triage issues](/contribute/triage-issues.md).
### GIT commit formating.
### Answering questions
Grafana Squash Pull requests when merging them into master. This means the maintainer will be responsible for the title in the git commit message.
The commit message of the commits in the Pull Request can still be part of the git commit body. So it's always encouraged to write informative commit messages.
If you have a question and you can't find the answer in the [documentation](https://grafana.com/docs/), the next step is to ask it on the [community site](https://community.grafana.com/).
The Git commit title should be short, descriptive and include the Pull Request ID.
It's important to us to help these users, and we'd love your help. Sign up to our [community site](https://community.grafana.com/), and start helping other Grafana users by answering their questions.
Good Examples
### Your first contribution
- `Explore: Live supprt in datasources (#12345)`
- `GraphPanel: Fix legend sorting issues (#12345)`
- `Build: Support publishing MSI to grafana.com (#12345)`
Unsure where to begin contributing to Grafana? Start by browsing issues labeled `beginner friendly` or `help wanted`.
- [Beginner-friendly](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22) issues are generally straightforward to complete.
- [Help wanted](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) issues are problems we would like the community to help us with regardless of complexity.
If you're looking to make a code change, see how to set up your environment for [local development](contribute/developer-guide.md).
When you're ready to contribute, it's time to [Create a pull request](/contribute/create-pull-request.md).
#### 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.
## 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.
Its also good practice to include a reference to the issue in the git commit body when possible.

View File

@@ -1,4 +1,21 @@
FROM node:14.15.5-alpine3.13 as js-builder
# Golang build container
FROM golang:1.12.4
WORKDIR $GOPATH/src/github.com/grafana/grafana
COPY go.mod go.sum ./
COPY vendor vendor
RUN go mod verify
COPY pkg pkg
COPY build.go build.go
COPY package.json package.json
RUN go run build.go build
# Node build container
FROM node:10.14.2
WORKDIR /usr/src/app/
@@ -7,39 +24,23 @@ COPY packages packages
RUN yarn install --pure-lockfile --no-progress
COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js ./
COPY Gruntfile.js tsconfig.json tslint.json ./
COPY public public
COPY tools tools
COPY scripts scripts
COPY emails emails
ENV NODE_ENV production
RUN yarn build
RUN ./node_modules/.bin/grunt build
FROM golang:1.16.1-alpine3.13 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.13
# Final container
FROM ubuntu:18.04
LABEL maintainer="Grafana team <hello@grafana.com>"
ARG GF_UID="472"
ARG GF_GID="0"
ARG GF_GID="472"
ENV PATH="/usr/share/grafana/bin:$PATH" \
ENV PATH=/usr/share/grafana/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
GF_PATHS_CONFIG="/etc/grafana/grafana.ini" \
GF_PATHS_DATA="/var/lib/grafana" \
GF_PATHS_HOME="/usr/share/grafana" \
@@ -49,33 +50,31 @@ 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
RUN apt-get update && apt-get upgrade -y && \
apt-get install -qq -y libfontconfig1 ca-certificates && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*
COPY conf ./conf
RUN if [ ! $(getent group "$GF_GID") ]; then \
addgroup -S -g $GF_GID grafana; \
fi
RUN export GF_GID_NAME=$(getent group $GF_GID | cut -d':' -f1) && \
mkdir -p "$GF_PATHS_HOME/.aws" && \
adduser -S -u $GF_UID -G "$GF_GID_NAME" grafana && \
RUN mkdir -p "$GF_PATHS_HOME/.aws" && \
groupadd -r -g $GF_GID grafana && \
useradd -r -u $GF_UID -g grafana grafana && \
mkdir -p "$GF_PATHS_PROVISIONING/datasources" \
"$GF_PATHS_PROVISIONING/dashboards" \
"$GF_PATHS_PROVISIONING/notifiers" \
"$GF_PATHS_PROVISIONING/plugins" \
"$GF_PATHS_LOGS" \
"$GF_PATHS_PLUGINS" \
"$GF_PATHS_DATA" && \
cp "$GF_PATHS_HOME/conf/sample.ini" "$GF_PATHS_CONFIG" && \
cp "$GF_PATHS_HOME/conf/ldap.toml" /etc/grafana/ldap.toml && \
chown -R "grafana:$GF_GID_NAME" "$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"
chown -R grafana:grafana "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \
chmod 777 -R "$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
COPY tools/phantomjs/render.js ./tools/phantomjs/render.js
EXPOSE 3000

View File

@@ -1,77 +0,0 @@
FROM node:14.15.1-slim AS js-builder
WORKDIR /usr/src/app/
COPY package.json yarn.lock ./
COPY packages packages
RUN yarn install --pure-lockfile
COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js ./
COPY public public
COPY tools tools
COPY scripts scripts
COPY emails emails
ENV NODE_ENV production
RUN yarn 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>"
EXPOSE 3000
ARG GF_UID="472"
ARG GF_GID="472"
ENV PATH="/usr/share/grafana/bin:$PATH" \
GF_PATHS_CONFIG="/etc/grafana/grafana.ini" \
GF_PATHS_DATA="/var/lib/grafana" \
GF_PATHS_HOME="/usr/share/grafana" \
GF_PATHS_LOGS="/var/log/grafana" \
GF_PATHS_PLUGINS="/var/lib/grafana/plugins" \
GF_PATHS_PROVISIONING="/etc/grafana/provisioning"
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 mkdir -p "$GF_PATHS_HOME/.aws" && \
addgroup --system --gid $GF_GID grafana && \
adduser --uid $GF_UID --system --ingroup grafana grafana && \
mkdir -p "$GF_PATHS_PROVISIONING/datasources" \
"$GF_PATHS_PROVISIONING/dashboards" \
"$GF_PATHS_PROVISIONING/notifiers" \
"$GF_PATHS_PROVISIONING/plugins" \
"$GF_PATHS_LOGS" \
"$GF_PATHS_PLUGINS" \
"$GF_PATHS_DATA" && \
cp conf/sample.ini "$GF_PATHS_CONFIG" && \
cp conf/ldap.toml /etc/grafana/ldap.toml && \
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
COPY packaging/docker/run.sh /
USER grafana
ENTRYPOINT [ "/run.sh" ]

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

60
Gruntfile.js Normal file
View File

@@ -0,0 +1,60 @@
'use strict';
module.exports = function (grunt) {
var os = require('os');
var config = {
pkg: grunt.file.readJSON('package.json'),
baseDir: '.',
srcDir: 'public',
genDir: 'public_gen',
destDir: 'dist',
tempDir: 'tmp',
platform: process.platform.replace('win32', 'windows'),
enterprise: false,
};
if (grunt.option('platform')) {
config.platform = grunt.option('platform');
}
if (grunt.option('enterprise')) {
config.enterprise = true;
}
if (grunt.option('arch')) {
config.arch = grunt.option('arch');
} else {
config.arch = os.arch();
if (process.platform.match(/^win/)) {
config.arch = process.env.hasOwnProperty('ProgramFiles(x86)') ? 'x64' : 'x86';
}
}
config.phjs = grunt.option('phjsToRelease');
config.pkg.version = grunt.option('pkgVer') || config.pkg.version;
console.log('Version', config.pkg.version);
// load plugins
require('load-grunt-tasks')(grunt);
// load task definitions
grunt.loadTasks('./scripts/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));
});
// technically not required
return config;
}
// Merge that object with what with whatever we have here
loadConfig(config,'./scripts/grunt/options/');
// pass the config to grunt
grunt.initConfig(config);
};

View File

@@ -1,22 +1,17 @@
# Triage issues
Triaging of issues
------------------
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.
Grafana being a popular open source project there are a lot of incoming issues. The main goal of issue triage is to categorize all incoming issues and make sure it has all basic information needed for anyone else to understand and/or being able to start working with 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.
The core maintainers of the Grafana project is responsible for categorizing all incoming issues and delegate any critical and/or important issue to other maintainers. Currently there's one maintainer each week responsible. Besides that part, triage provides an important way to contribute to an open source project. Triage helps ensure issues resolve quickly by:
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.
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.
## Simplified flowchart diagram of the issue triage process
* Describing 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.
**Simplified flowchart diagram of the issue triage process:**
<!-- https://textik.com/#610afa78553def29 -->
```
+--------------------------+
@@ -32,7 +27,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 | |
@@ -58,13 +53,73 @@ If you don't have the knowledge or time to code, consider helping with triage. T
+------------------+ +--------------+
```
## How you can help
There are multiple ways that you can help with the Grafana project, especially without writing a single line of code. Everyone in the Grafana community will be greatly thankful you for helping out with any of the below tasks.
### Answer/ask questions
The [community site](https://community.grafana.com/) is the main channel to be used for asking and answering questions related to the Grafana project. This may be the first place a new or existing Grafana user look/ask for help after they found that the [documentation](https://grafana.com/docs) wasn't answering their questions. It's very important to help new and existing users so that these new users can find proper answers and eventually help out other users and by that keep growing the Grafana community.
Please signup to the Grafana [community site](https://community.grafana.com/) and start help other Grafana users by answering their questions and/or ask for help.
### Report documentation enhancements
If you visit the [documentation site](https://grafana.com/docs) and find typos/error/lack of information please report these by clicking on the `Request doc changes` link found on every page and/or contribute the changes yourself by clicking on `Edit this page` and open a pull request. Everyone in the community will greatly thank you for.
Please read about how documentation issues is triaged [below](#documentation-issue) to understand what kind of documentation may be suitable to request/add.
### Report a security vulnerability
Please review the [security policy](https://github.com/grafana/grafana/security/policy) for more details.
### Report bugs
Report a bug you found when using Grafana by [opening a new bug report](https://github.com/grafana/grafana/issues/new?labels=type%3A+bug&template=1-bug_report.md).
### Request enhancements/new features
Suggest an enhancement or new feature for the Grafana project by [opening a new enhancement issue](https://github.com/grafana/grafana/issues/new?labels=type%3A+feature+request&template=2-feature_request.md).
Alternatively, help make Grafana be better at being accessible to all by [opening a new accessibility issue](https://github.com/grafana/grafana/issues/new?labels=type%3A+accessibility&template=3-accessibility.md).
### Report inaccurate issue information
If you find an issue that have a badly formatted title and/or description, bad language/grammar and/or wrong labels it's important to let the issue author or maintainers know so it can be fixed. See [good practices](#good-practices) regarding basic information for issues below.
### Request closing of issues
The Grafana project have a lot of open issues and the main goal is to only have issues open if their still relevant. If you find an issue that you think already have been resolved or no longer is relevant please report by adding a comment and explain why you think it should be closed including related issues (`#<issue number>`), if applicable, and optionally mention one of the maintainers.
### Investigate issues
See [investigation of issues](#investigation-of-issues).
### Vote on enhancements/bugs
Helping the Grafana project to know which issues are most important by users and the community is crucial for the success of the project. Read more about [prioritizing issues](#4-prioritization-of-issues) for details about how issues are being prioritized. The Grafana project use GitGub issues and reactions for collecting votes on enhancement and bugs.
**Please don't add `+1` issue comments or similar since that will notify everyone that have subscribed to an issue and it doesn't add any useful update, rather it creates a bad .**
If you want to show your interest or importance of an issue, please use [GitHub's reactions](https://help.github.com/en/articles/about-conversations-on-github#reacting-to-ideas-in-comments).
### Report duplicates
If you find two issues describing the same bug/enhancement/feature please add a comment in one of the issue and explain which issues (`#<issue number>`) you think is a duplicate of another issue (`#<issue number>`).
### Suggest ideas for resolving bugs/enhancements
Related to how [issues are being prioritized](#4-prioritization-of-issues) it's important to help anyone that's interested in contributing code for resolving a bug or enhancement. This can be anything from getting started and setup the development environment to reference code and files where changes probably needs to be made and/or suggest ideas on how enhancements may function/be implemented.
Please read about how [help from the community](#5-requesting-help-from-the-community) may be requested when issues being triaged.
## 1. Find uncategorized issues
To get started with issue triage and finding issues that haven't been triaged you have two alternatives.
### Browse unlabeled issues
The easiest and straight forward way of getting started and finding issues that haven't been triaged is to browse [unlabeled issues](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+no%3Alabel) and starting from the bottom and working yourself to the top.
The easiest and straigt forward way of getting started and finding issues that haven't been triaged is to browse [unlabeled issues](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+no%3Alabel) and starting from the bottom and working yourself to the top.
### Subscribe to all notifications
@@ -82,7 +137,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 +151,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 +167,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?
@@ -124,41 +179,40 @@ Depending on the issue, you might not feel all this information is needed. Use y
If the author provides the standard information but you are still unable to triage the issue, request additional information. Do this kindly and politely because you are asking for more of the author's time.
If the author does not respond to the requested information within the timespan of a week, close the issue with a kind note stating that the author can request for the issue to be reopened when the necessary information is provided.
If the author does not respond requested information within the timespan of a week, close the issue with a kind note stating that the author can request for the issue to be reopened when the necessary information is provided.
When you feel you have all the information needed you're ready to [categorizing the issue](#3-categorizing-an-issue).
If you receive a notification with additional information provided but you are not anymore on issue triage and you feel you do not have time to handle it, you should delegate it to the current person on issue triage.
## 3. Categorizing an issue
An issue can have multiple of the following labels. Typically, a properly categorized issue should at least have:
- 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.
- One or multiple labels identifying the functional areas of interest or component (`area/*`) and/or datasource (`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 datasource 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 +241,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 +257,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 +272,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 +301,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 +309,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 +326,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 +337,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,37 +345,19 @@ 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, datasources, 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 `bot/question` and the bot will close it with an appropriate message.
[Read more on bot actions](https://github.com/grafana/grafana/blob/master/.github/bot.md)
## 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. 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)
@@ -335,14 +371,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

160
Makefile
View File

@@ -1,10 +1,6 @@
## This is a self-documented Makefile. For usage information, run `make help`:
##
## For more information, refer to https://suva.sh/posts/well-documented-makefiles/
-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 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 clean devenv devenv-down revive-alerting
GO = GO111MODULE=on go
GO_FILES ?= ./pkg/...
@@ -12,68 +8,77 @@ SH_FILES ?= $(shell find ./scripts -name *.sh)
all: deps build
##@ Dependencies
deps-go:
go run build.go setup
deps-go: ## Install backend dependencies.
$(GO) run build.go setup
deps-js: node_modules
deps-js: node_modules ## Install frontend dependencies.
deps: deps-js
deps: deps-js ## Install all dependencies.
node_modules: package.json yarn.lock ## Install node modules.
@echo "install frontend dependencies"
yarn install --pure-lockfile --no-progress
##@ Building
build-go: ## Build all Go binaries.
build-go:
@echo "build go files"
$(GO) run build.go build
GO111MODULE=on go run build.go build
build-server: ## Build Grafana server.
build-server:
@echo "build server"
$(GO) run build.go build-server
GO111MODULE=on go run build.go build-server
build-cli: ## Build Grafana CLI application.
build-cli:
@echo "build in CI environment"
$(GO) run build.go build-cli
GO111MODULE=on go run build.go build-cli
build-js: ## Build frontend assets.
build-js:
@echo "build frontend"
yarn run build
yarn run plugins:build-bundled
build: build-go build-js ## Build backend and frontend.
build: build-go build-js
scripts/go/bin/bra: scripts/go/go.mod
@cd scripts/go; \
$(GO) build -o ./bin/bra github.com/unknwon/bra
build-docker-dev:
@echo "build development container"
@echo "\033[92mInfo:\033[0m the frontend code is expected to be built already."
GO111MODULE=on go run build.go -goos linux -pkg-arch amd64 ${OPT} build pkg-archive latest
cp dist/grafana-latest.linux-x64.tar.gz packaging/docker
cd packaging/docker && docker build --tag grafana/grafana:dev .
run: scripts/go/bin/bra ## Build and run web server on filesystem changes.
@GO111MODULE=on scripts/go/bin/bra run
build-docker-full:
@echo "build docker container"
docker build --tag grafana/grafana:dev .
run-frontend: deps-js ## Fetch js dependencies and watch frontend for rebuild
yarn start
##@ Testing
test-go: ## Run tests for backend.
test-go:
@echo "test backend"
$(GO) test -v ./pkg/...
GO111MODULE=on go test -v ./pkg/...
test-js: ## Run tests for frontend.
test-js:
@echo "test frontend"
yarn test
test: test-go test-js ## Run all tests.
test: test-go test-js
##@ Linting
clean:
@echo "cleaning"
rm -rf node_modules
rm -rf public/build
node_modules: package.json yarn.lock
@echo "install frontend dependencies"
yarn install --pure-lockfile --no-progress
scripts/go/bin/revive: scripts/go/go.mod
@cd scripts/go; \
$(GO) build -o ./bin/revive github.com/mgechev/revive
scripts/go/bin/gosec: scripts/go/go.mod
@cd scripts/go; \
$(GO) build -o ./bin/gosec github.com/securego/gosec/cmd/gosec
scripts/go/bin/bra: scripts/go/go.mod
@cd scripts/go; \
$(GO) build -o ./bin/bra github.com/Unknwon/bra
scripts/go/bin/golangci-lint: scripts/go/go.mod
@cd scripts/go; \
$(GO) build -o ./bin/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint
revive: scripts/go/bin/revive
@echo "lint via revive"
@scripts/go/bin/revive \
@@ -81,41 +86,39 @@ 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 \
./pkg/services/alerting/...
scripts/go/bin/golangci-lint: scripts/go/go.mod
@cd scripts/go; \
$(GO) build -o ./bin/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint
# 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,G201,G202,G204,G301,G304,G401,G402,G501 \
-conf=./scripts/go/configs/gosec.json \
$(GO_FILES)
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)
lint-go: golangci-lint revive revive-strict # Run all code checks for backend.
go-vet:
@echo "lint via go vet"
@go vet $(GO_FILES)
lint-go: go-vet golangci-lint revive revive-alerting gosec
# with disabled SC1071 we are ignored some TCL,Expect `/usr/bin/env expect` scripts
shellcheck: $(SH_FILES) ## Run checks for shell scripts.
shellcheck: $(SH_FILES)
@docker run --rm -v "$$PWD:/mnt" koalaman/shellcheck:stable \
$(SH_FILES) -e SC1071 -e SC2162
$(SH_FILES) -e SC1071
##@ Docker
build-docker-dev: ## Build Docker image for development (fast).
@echo "build development container"
@echo "\033[92mInfo:\033[0m the frontend code is expected to be built already."
$(GO) run build.go -goos linux -pkg-arch amd64 ${OPT} build pkg-archive latest
cp dist/grafana-latest.linux-x64.tar.gz packaging/docker
cd packaging/docker && docker build --tag grafana/grafana:dev .
build-docker-full: ## Build Docker image for development.
@echo "build docker container"
docker build --tag grafana/grafana:dev .
##@ Services
run: scripts/go/bin/bra
@scripts/go/bin/bra run
# create docker-compose file with provided sources and start them
# example: make devenv sources=postgres,openldap
@@ -123,38 +126,19 @@ ifeq ($(sources),)
devenv:
@printf 'You have to define sources for this command \nexample: make devenv sources=postgres,openldap\n'
else
devenv: devenv-down ## Start optional services, e.g. postgres, prometheus, and elasticsearch.
devenv: devenv-down
$(eval targets := $(shell echo '$(sources)' | tr "," " "))
@cd devenv; \
./create_docker_compose.sh $(targets) || \
(rm -rf {docker-compose.yaml,conf.tmp,.env}; exit 1)
(rm -rf docker-compose.yaml; exit 1)
@cd devenv; \
docker-compose up -d --build
endif
devenv-down: ## Stop optional services.
# drop down the envs
devenv-down:
@cd devenv; \
test -f docker-compose.yaml && \
docker-compose down || exit 0;
##@ Helpers
# We separate the protobuf generation because most development tasks on
# Grafana do not involve changing protobuf files and protoc is not a
# go-gettable dependency and so getting it installed can be inconvenient.
#
# If you are working on changes to protobuf interfaces you may either use
# this target or run the individual scripts below directly.
protobuf: ## Compile protobuf definitions
bash scripts/protobuf-check.sh
bash pkg/plugins/backendplugin/pluginextensionv2/generate.sh
clean: ## Clean up intermediate build artifacts.
@echo "cleaning"
rm -rf node_modules
rm -rf public/build
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

View File

@@ -1,5 +1,5 @@
Copyright 2014-2021 Grafana Labs
Copyright 2014-2018 Grafana Labs
This software is based on Kibana:
Copyright 2012-2013 Elasticsearch BV

View File

@@ -1,19 +1,20 @@
# Plugin development
# Plugin Development
This document is not meant as a complete guide for developing plugins but more as a changelog for changes in
Grafana that can impact plugin development. Whenever you as a plugin author encounter an issue with your plugin after
upgrading Grafana please check here before creating an issue.
## Plugin development resources
## Links
- [Grafana plugin developer guide](http://docs.grafana.org/plugins/developing/development/)
- [Webpack Grafana plugin template project](https://github.com/CorpGlory/grafana-plugin-template-webpack)
- [Datasource plugin written in TypeScript](https://github.com/grafana/typescript-template-datasource)
- [Simple JSON datasource plugin](https://github.com/grafana/simple-json-datasource)
- [Plugin development guide](http://docs.grafana.org/plugins/developing/development/)
- [Webpack Grafana plugin template project](https://github.com/CorpGlory/grafana-plugin-template-webpack)
## Changes in Grafana v4.6
## Changes in v4.6
This version of Grafana has big changes that will impact a limited set of plugins. We moved from systemjs to webpack
for built-in plugins and everything internal. External plugins still use systemjs but now with a limited
for built-in plugins & everything internal. External plugins still use systemjs but now with a limited
set of Grafana components they can import. Plugins can depend on libs like lodash & moment and internal components
like before using the same import paths. However since everything in Grafana is no longer accessible, a few plugins could encounter issues when importing a Grafana dependency.
@@ -24,10 +25,10 @@ If you think we missed exposing a crucial lib or Grafana component let us know b
### Deprecated components
The angular directive `<spectrum-picker>` is now deprecated (will still work for a version more) but we recommend plugin authors
upgrade to new `<color-picker color="ctrl.color" onChange="ctrl.onSparklineColorChange"></color-picker>`
to upgrade to new `<color-picker color="ctrl.color" onChange="ctrl.onSparklineColorChange"></color-picker>`
## Changes in Grafana v6.0
## Changes in v6.0
### DashboardSrv.ts
If you utilize [DashboardSrv](https://github.com/grafana/grafana/commit/8574dca081002f36e482b572517d8f05fd44453f#diff-1ab99561f9f6a10e1fafcddc39bc1d65) in your plugin code, `dash` was renamed to `dashboard`.
If you utilize [DashboardSrv](https://github.com/grafana/grafana/commit/8574dca081002f36e482b572517d8f05fd44453f#diff-1ab99561f9f6a10e1fafcddc39bc1d65) in your plugin code, `dash` was renamed to `dashboard`

210
README.md
View File

@@ -1,46 +1,198 @@
![Grafana](docs/logo-horizontal.png)
# [Grafana](https://grafana.com) [![Circle CI](https://circleci.com/gh/grafana/grafana.svg?style=svg)](https://circleci.com/gh/grafana/grafana) [![Go Report Card](https://goreportcard.com/badge/github.com/grafana/grafana)](https://goreportcard.com/report/github.com/grafana/grafana) [![codecov](https://codecov.io/gh/grafana/grafana/branch/master/graph/badge.svg)](https://codecov.io/gh/grafana/grafana)
The open-source platform for monitoring and observability.
[Website](https://grafana.com) |
[Twitter](https://twitter.com/grafana) |
[Community & Forum](https://community.grafana.com)
[![License](https://img.shields.io/github/license/grafana/grafana)](LICENSE)
[![Circle CI](https://img.shields.io/circleci/build/gh/grafana/grafana)](https://circleci.com/gh/grafana/grafana)
[![Go Report Card](https://goreportcard.com/badge/github.com/grafana/grafana)](https://goreportcard.com/report/github.com/grafana/grafana)
Grafana is an open source, feature rich metrics dashboard and graph editor for
Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB.
Grafana allows you to query, visualize, alert on and understand your metrics no matter where they are stored. Create, explore, and share dashboards with your team and foster a data driven culture:
<!---
![](http://docs.grafana.org/assets/img/features/dashboard_ex1.png)
-->
- **Visualize:** Fast and flexible client side graphs with a multitude of options. Panel plugins offer many different ways to visualize metrics and logs.
- **Dynamic Dashboards:** Create dynamic & reusable dashboards with template variables that appear as dropdowns at the top of the dashboard.
- **Explore Metrics:** Explore your data through ad-hoc queries and dynamic drilldown. Split view and compare different time ranges, queries and data sources side by side.
- **Explore Logs:** Experience the magic of switching from metrics to logs with preserved label filters. Quickly search through all your logs or streaming them live.
- **Alerting:** Visually define alert rules for your most important metrics. Grafana will continuously evaluate and send notifications to systems like Slack, PagerDuty, VictorOps, OpsGenie.
- **Mixed Data Sources:** Mix different data sources in the same graph! You can specify a data source on a per-query basis. This works for even custom datasources.
## Installation
## Get started
Head to [docs.grafana.org](http://docs.grafana.org/installation/) for documentation or [download](https://grafana.com/get) to get the latest release.
- [Get Grafana](https://grafana.com/get)
- [Installation guides](http://docs.grafana.org/installation/)
## Documentation & Support
Unsure if Grafana is for you? Watch Grafana in action on [play.grafana.org](https://play.grafana.org/)!
Be sure to read the [getting started guide](http://docs.grafana.org/guides/gettingstarted/) and the other feature guides.
## Documentation
## Run from master
The Grafana documentation is available at [grafana.com/docs](https://grafana.com/docs/).
If you want to build a package yourself, or contribute - here is a guide for how to do that. You can always find
the latest master builds [here](https://grafana.com/grafana/download)
## Contributing
### Dependencies
If you're interested in contributing to the Grafana project:
- Go (Latest Stable)
- Node.js LTS
- yarn [`npm install -g yarn`]
- Start by reading the [Contributing guide](/CONTRIBUTING.md).
- Learn how to set up your local environment, in our [Developer guide](/contribute/developer-guide.md).
- Explore our [beginner-friendly issues](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22).
### Get the project
## Get involved
**The project located in the go-path will be your working directory.**
- Follow [@grafana on Twitter](https://twitter.com/grafana/).
- Read and subscribe to the [Grafana blog](https://grafana.com/blog/).
- If you have a specific question, check out our [discussion forums](https://community.grafana.com/).
- For general discussions, join us on the [official Slack](http://slack.raintank.io/) team.
```bash
go get github.com/grafana/grafana
cd $GOPATH/src/github.com/grafana/grafana
```
### Run and rebuild on source change
#### Backend
To run the backend and rebuild on source change:
```bash
make run
```
#### Frontend
Rebuild on file change, and serve them by Grafana's webserver (http://localhost:3000):
```bash
yarn start
```
Build the assets, rebuild on file change with Hot Module Replacement (HMR), and serve them by webpack-dev-server (http://localhost:3333):
```bash
yarn start:hot
# OR set a theme
env GRAFANA_THEME=light yarn start:hot
```
_Note: HMR for Angular is not supported. If you edit files in the Angular part of the app, the whole page will reload._
Run tests and rebuild on source change:
```bash
yarn jest
```
**Open grafana in your browser (default: e.g. `http://localhost:3000`) and login with admin user (default: `user/pass = admin/admin`).**
### Building
#### The backend
```bash
go run build.go setup
go run build.go build
```
#### Frontend assets
_For this you need Node.js (LTS version)._
```bash
yarn install --pure-lockfile
```
### Building a Docker image
There are two different ways to build a Grafana docker image. If your machine is setup for Grafana development and you run linux/amd64 you can build just the image. Otherwise, there is the option to build Grafana completely within Docker.
Run the image you have built using: `docker run --rm -p 3000:3000 grafana/grafana:dev`
#### Building on linux/amd64 (fast)
1. Build the frontend `go run build.go build-frontend`
2. Build the docker image `make build-docker-dev`
The resulting image will be tagged as `grafana/grafana:dev`
#### Building anywhere (slower)
Choose this option to build on platforms other than linux/amd64 and/or not have to setup the Grafana development environment.
1. `make build-docker-full` or `docker build -t grafana/grafana:dev .`
The resulting image will be tagged as `grafana/grafana:dev`
Notice: If you are using Docker for MacOS, be sure to set the memory limit to be larger than 2 GiB (at docker -> Preferences -> Advanced), otherwise `grunt build` may fail.
## Development
### Dev config
Create a custom.ini in the conf directory to override default configuration options.
You only need to add the options you want to override. Config files are applied in the order of:
1. grafana.ini
1. custom.ini
In your custom.ini uncomment (remove the leading `;`) sign. And set `app_mode = development`.
### Running tests
#### Frontend
Execute all frontend tests
```bash
yarn test
```
Writing & watching frontend tests
- Start watcher: `yarn jest`
- Jest will run all test files that end with the name ".test.ts"
#### Backend
```bash
# Run Golang tests using sqlite3 as database (default)
go test ./pkg/...
# Run Golang tests using mysql as database - convenient to use /docker/blocks/mysql_tests
GRAFANA_TEST_DB=mysql go test ./pkg/...
# Run Golang tests using postgres as database - convenient to use /docker/blocks/postgres_tests
GRAFANA_TEST_DB=postgres go test ./pkg/...
```
#### End-to-end
Execute all end-to-end tests
```bash
yarn e2e-tests
```
Execute all end-to-end tests using using a specific url
```bash
ENV BASE_URL=http://localhost:3333 yarn e2e-tests
```
Debugging all end-to-end tests (BROWSER=1 will start the browser and SLOWMO=1 will delay each puppeteer operation by 100ms)
```bash
ENV BROWSER=1 SLOWMO=1 yarn e2e-tests
```
### Datasource and dashboard provisioning
[Here](https://github.com/grafana/grafana/tree/master/devenv) you can find helpful scripts and docker-compose setup
that will populate your dev environment for quicker testing end experimenting.
## Contribute
If you have any ideas for improvement or have found a bug, do not hesitate to open an issue.
And if you have time, clone this repo and submit a pull request to help me make Grafana
the kickass metrics & devops dashboard we all dream about!
Read the [contributing](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md) guide then check the [`beginner friendly`](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22) label to find issues that are easy and that we would like help with.
## Plugin development
Checkout the [Plugin Development Guide](http://docs.grafana.org/plugins/developing/development/) and checkout the [PLUGIN_DEV.md](https://github.com/grafana/grafana/blob/master/PLUGIN_DEV.md) file for changes in Grafana that relate to
plugin development.
## License
Grafana is distributed under the [Apache 2.0 License](https://github.com/grafana/grafana/blob/master/LICENSE).
Grafana is distributed under [Apache 2.0 License](https://github.com/grafana/grafana/blob/master/LICENSE).

View File

@@ -1,5 +1,4 @@
# Roadmap
The roadmap is a tentative plan for the core development team. Things change constantly as pull requests come in and priorities change, but it will give you an idea of our current vision and plan.
This roadmap is a tentative plan for the core development team. Things change constantly as PRs come in and priorities change.
But it will give you an idea of our current vision and plan.
To view the Roadmap, go to the Issues tab on GitHub. There you will find three roadmap issues pinned at the top.
Go to the Issues tab on GitHub. There you will find, at the top, 3 pinned roadmap issues.

View File

@@ -1,20 +1,17 @@
# Reporting security issues
Reporting Security Issues
------------------
If you think you have found a security vulnerability, please send a report to [security@grafana.com](mailto:security@grafana.com). This address can be used for all of Grafana Labs's open source and commercial products (including but not limited to Grafana, Grafana Cloud, Grafana Enterprise, and grafana.com). We can accept only vulnerability reports at this address.
Please encrypt your message to us; please use our PGP key. The key fingerprint is:
If you think you have found a security vulnerability, please send a report to [security@grafana.com](mailto:security@grafana.com). This address can be used for all of Grafana Labs's open source and commercial products (including but not limited to Grafana, Grafana Cloud, Grafana Enterprise, and grafana.com). We can accept only vulnerability reports at this address. We would prefer that you encrypt your message to us; please use our PGP key. The key fingerprint is:
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.
**Important:** We ask you to not disclose the vulnerability before it have been fixed and announced, unless you received a response from the Grafana Labs security team that you can do so.
**Important:** We ask you to not disclose the vulnerability before it have been fixed and announced, unless you have got a response from the Grafana Labs security team that you can do that.
## Security announcements
### Security Announcements
We maintain a category on the community site called [Security Announcements](https://community.grafana.com/c/security-announcements),
where we will post a summary, remediation, and mitigation details for any patch containing security fixes.
You can also subscribe to email updates to this category if you have a grafana.com account and sign on to the community site or track updates via an [RSS feed](https://community.grafana.com/c/security-announcements.rss).
where we will post a summary, remediation, and mitigation details for any patch containing security fixes. You can also subscribe to email updates to this category if you have a grafana.com account and sign on to the community site or track updates via an [RSS feed](https://community.grafana.com/c/security-announcements.rss).

View File

@@ -1,10 +1,9 @@
# Get Grafana help
Need help or support?
------------------
First, check the official [Grafana documentation](https://grafana.com/docs/).
If you require further help or support then ask a question in the [Grafana community site](https://community.grafana.com/) or [Grafana Slack](http://slack.raintank.io/). You can also search the community site for previously answered questions, in case someone already had your problem and got help.
**Please note:**
- The Grafana project uses GitHub mainly for tracking bugs and feature requests.
- Do not open an issue just to ask a question. The issue will be closed immediately.
- Only submit issues for bug reports, feature requests, or enhancements.
- Only submit issues for bug reports, feature requests or enhancements.
- Grafana project uses GitHub mainly for tracking bugs and feature requests.
- Asking a question by opening an issue will directly result in issue being closed.
If you require help or support then ask a question and/or find existing questions/answers in the [Grafana community site](https://community.grafana.com/).

View File

@@ -1,4 +1,4 @@
# Guide to upgrading dependencies
# Guide to Upgrading Dependencies
Upgrading Go or Node.js requires making changes in many different files. See below for a list and explanation for each.
@@ -16,11 +16,13 @@ Upgrading Go or Node.js requires making changes in many different files. See bel
- Appveyor
- Dockerfile
## Go dependencies
## Go Dependencies
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.
All dependencies are vendored in the `vendor/` directory.
_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:
@@ -33,16 +35,18 @@ GO111MODULE=on go get example.com/some/module/pkg
GO111MODULE=on go get example.com/some/module/pkg@vX.Y.Z
```
Tidy up the `go.mod` and `go.sum` files:
Tidy up the `go.mod` and `go.sum` files and copy the new/updated dependency to the `vendor/` directory:
```bash
# The GO111MODULE variable can be omitted when the code isn't located in GOPATH.
GO111MODULE=on go mod tidy
GO111MODULE=on go mod vendor
```
You have to commit the changes to `go.mod` and `go.sum` before submitting the pull request.
You have to commit the changes to `go.mod`, `go.sum` and the `vendor/` directory before submitting the pull request.
## Node.js dependencies
## Node.js Dependencies
Updated using `yarn`.

View File

@@ -1,77 +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.
## Backporting a PR
PRs intended for inclusion in the next PATCH release they must be backported to the release branch. The bot can do this automatically. [Read more on backport PRs](https://github.com/grafana/grafana/blob/master/.github/bot.md). Both the source PR and the backport PR should be assigned to the patch release milestone, unless you are backporting to many releases then it can differ.
Backport PRs are also needed during the beta period to get fixes into the stable release.
# 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.
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

@@ -1,38 +0,0 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "<projectFolder>/dist/index.d.ts",
"bundledPackages": [],
"compiler": {},
"apiReport": {
"enabled": false
},
"docModel": {
"enabled": true,
"apiJsonFilePath": "<projectFolder>/../../reports/docs/<unscopedPackageName>.api.json"
},
"dtsRollup": {
"enabled": false
},
"tsdocMetadata": {},
"messages": {
"compilerMessageReporting": {
"default": {
"logLevel": "warning"
}
},
"extractorMessageReporting": {
"default": {
"logLevel": "warning"
},
"ae-internal-missing-underscore": {
"logLevel": "none",
"addToApiReportFile": false
}
},
"tsdocMessageReporting": {
"default": {
"logLevel": "warning"
}
}
}
}

356
build.go
View File

@@ -9,7 +9,6 @@ import (
"encoding/json"
"flag"
"fmt"
"go/build"
"io"
"io/ioutil"
"log"
@@ -30,18 +29,17 @@ const (
var (
//versionRe = regexp.MustCompile(`-[0-9]{1,3}-g[0-9a-f]{5,10}`)
goarch string
goos string
gocc string
cgo bool
libc string
pkgArch string
version string = "v1"
buildTags []string
goarch string
goos string
gocc string
cgo bool
pkgArch string
version string = "v1"
// deb & rpm does not support semver so have to handle their version a little differently
linuxPackageVersion string = "v1"
linuxPackageIteration string = ""
race bool
phjsToRelease string
workingDir string
includeBuildId bool = true
buildId string = "0"
@@ -59,16 +57,16 @@ func main() {
log.SetOutput(os.Stdout)
log.SetFlags(0)
ensureGoPath()
var buildIdRaw string
var buildTagsRaw string
flag.StringVar(&goarch, "goarch", runtime.GOARCH, "GOARCH")
flag.StringVar(&goos, "goos", runtime.GOOS, "GOOS")
flag.StringVar(&gocc, "cc", "", "CC")
flag.StringVar(&libc, "libc", "", "LIBC")
flag.StringVar(&buildTagsRaw, "build-tags", "", "Sets custom build tags")
flag.BoolVar(&cgo, "cgo-enabled", cgo, "Enable cgo")
flag.StringVar(&pkgArch, "pkg-arch", "", "PKG ARCH")
flag.StringVar(&phjsToRelease, "phjs", "", "PhantomJS binary")
flag.BoolVar(&race, "race", race, "Use race detector")
flag.BoolVar(&includeBuildId, "includeBuildId", includeBuildId, "IncludeBuildId in package name")
flag.BoolVar(&enterprise, "enterprise", enterprise, "Build enterprise version of Grafana")
@@ -92,10 +90,6 @@ func main() {
return
}
if len(buildTagsRaw) > 0 {
buildTags = strings.Split(buildTagsRaw, ",")
}
log.Printf("Version: %s, Linux Version: %s, Package Iteration: %s\n", version, linuxPackageVersion, linuxPackageIteration)
if flag.NArg() == 0 {
@@ -110,22 +104,53 @@ func main() {
case "setup":
setup()
case "build-srv", "build-server":
case "build-srv":
clean()
doBuild("grafana-server", "./pkg/cmd/grafana-server", buildTags)
build("grafana-server", "./pkg/cmd/grafana-server", []string{})
case "build-cli":
clean()
doBuild("grafana-cli", "./pkg/cmd/grafana-cli", buildTags)
build("grafana-cli", "./pkg/cmd/grafana-cli", []string{})
case "build-server":
clean()
build("grafana-server", "./pkg/cmd/grafana-server", []string{})
case "build":
//clean()
for _, binary := range binaries {
doBuild(binary, "./pkg/cmd/"+binary, buildTags)
build(binary, "./pkg/cmd/"+binary, []string{})
}
case "build-frontend":
yarn("build")
grunt(gruntBuildArg("build")...)
case "test":
test("./pkg/...")
grunt("test")
case "package":
grunt(gruntBuildArg("build")...)
grunt(gruntBuildArg("package")...)
if goos == linux {
createLinuxPackages()
}
case "package-only":
grunt(gruntBuildArg("package")...)
if goos == linux {
createLinuxPackages()
}
case "pkg-archive":
grunt(gruntBuildArg("package")...)
case "pkg-rpm":
grunt(gruntBuildArg("release")...)
createRpmPackages()
case "pkg-deb":
grunt(gruntBuildArg("release")...)
createDebPackages()
case "sha-dist":
shaFilesInDist()
@@ -149,15 +174,12 @@ func makeLatestDistCopies() {
}
latestMapping := map[string]string{
"_amd64.deb": "dist/grafana_latest_amd64.deb",
".x86_64.rpm": "dist/grafana-latest-1.x86_64.rpm",
".linux-amd64.tar.gz": "dist/grafana-latest.linux-x64.tar.gz",
".linux-amd64-musl.tar.gz": "dist/grafana-latest.linux-x64-musl.tar.gz",
".linux-armv7.tar.gz": "dist/grafana-latest.linux-armv7.tar.gz",
".linux-armv7-musl.tar.gz": "dist/grafana-latest.linux-armv7-musl.tar.gz",
".linux-armv6.tar.gz": "dist/grafana-latest.linux-armv6.tar.gz",
".linux-arm64.tar.gz": "dist/grafana-latest.linux-arm64.tar.gz",
".linux-arm64-musl.tar.gz": "dist/grafana-latest.linux-arm64-musl.tar.gz",
"_amd64.deb": "dist/grafana_latest_amd64.deb",
".x86_64.rpm": "dist/grafana-latest-1.x86_64.rpm",
".linux-amd64.tar.gz": "dist/grafana-latest.linux-x64.tar.gz",
".linux-armv7.tar.gz": "dist/grafana-latest.linux-armv7.tar.gz",
".linux-armv6.tar.gz": "dist/grafana-latest.linux-armv6.tar.gz",
".linux-arm64.tar.gz": "dist/grafana-latest.linux-arm64.tar.gz",
}
for _, file := range files {
@@ -206,8 +228,215 @@ func readVersionFromPackageJson() {
}
}
func yarn(params ...string) {
runPrint(`yarn run`, params...)
type linuxPackageOptions struct {
packageType string
packageArch string
homeDir string
homeBinDir string
binPath string
serverBinPath string
cliBinPath string
configDir string
ldapFilePath string
etcDefaultPath string
etcDefaultFilePath string
initdScriptFilePath string
systemdServiceFilePath string
postinstSrc string
initdScriptSrc string
defaultFileSrc string
systemdFileSrc string
cliBinaryWrapperSrc string
depends []string
}
func createDebPackages() {
debPkgArch := pkgArch
if pkgArch == "armv7" || pkgArch == "armv6" {
debPkgArch = "armhf"
}
createPackage(linuxPackageOptions{
packageType: "deb",
packageArch: debPkgArch,
homeDir: "/usr/share/grafana",
homeBinDir: "/usr/share/grafana/bin",
binPath: "/usr/sbin",
configDir: "/etc/grafana",
etcDefaultPath: "/etc/default",
etcDefaultFilePath: "/etc/default/grafana-server",
initdScriptFilePath: "/etc/init.d/grafana-server",
systemdServiceFilePath: "/usr/lib/systemd/system/grafana-server.service",
postinstSrc: "packaging/deb/control/postinst",
initdScriptSrc: "packaging/deb/init.d/grafana-server",
defaultFileSrc: "packaging/deb/default/grafana-server",
systemdFileSrc: "packaging/deb/systemd/grafana-server.service",
cliBinaryWrapperSrc: "packaging/wrappers/grafana-cli",
depends: []string{"adduser", "libfontconfig1"},
})
}
func createRpmPackages() {
rpmPkgArch := pkgArch
switch {
case pkgArch == "armv7":
rpmPkgArch = "armhfp"
case pkgArch == "arm64":
rpmPkgArch = "aarch64"
}
createPackage(linuxPackageOptions{
packageType: "rpm",
packageArch: rpmPkgArch,
homeDir: "/usr/share/grafana",
homeBinDir: "/usr/share/grafana/bin",
binPath: "/usr/sbin",
configDir: "/etc/grafana",
etcDefaultPath: "/etc/sysconfig",
etcDefaultFilePath: "/etc/sysconfig/grafana-server",
initdScriptFilePath: "/etc/init.d/grafana-server",
systemdServiceFilePath: "/usr/lib/systemd/system/grafana-server.service",
postinstSrc: "packaging/rpm/control/postinst",
initdScriptSrc: "packaging/rpm/init.d/grafana-server",
defaultFileSrc: "packaging/rpm/sysconfig/grafana-server",
systemdFileSrc: "packaging/rpm/systemd/grafana-server.service",
cliBinaryWrapperSrc: "packaging/wrappers/grafana-cli",
depends: []string{"/sbin/service", "fontconfig", "freetype", "urw-fonts"},
})
}
func createLinuxPackages() {
if !skipDebGen {
createDebPackages()
}
if !skipRpmGen {
createRpmPackages()
}
}
func createPackage(options linuxPackageOptions) {
packageRoot, _ := ioutil.TempDir("", "grafana-linux-pack")
// create directories
runPrint("mkdir", "-p", filepath.Join(packageRoot, options.homeDir))
runPrint("mkdir", "-p", filepath.Join(packageRoot, options.configDir))
runPrint("mkdir", "-p", filepath.Join(packageRoot, "/etc/init.d"))
runPrint("mkdir", "-p", filepath.Join(packageRoot, options.etcDefaultPath))
runPrint("mkdir", "-p", filepath.Join(packageRoot, "/usr/lib/systemd/system"))
runPrint("mkdir", "-p", filepath.Join(packageRoot, "/usr/sbin"))
// copy grafana-cli wrapper
runPrint("cp", "-p", options.cliBinaryWrapperSrc, filepath.Join(packageRoot, "/usr/sbin/"+cliBinary))
// copy grafana-server binary
runPrint("cp", "-p", filepath.Join(workingDir, "tmp/bin/"+serverBinary), filepath.Join(packageRoot, "/usr/sbin/"+serverBinary))
// copy init.d script
runPrint("cp", "-p", options.initdScriptSrc, filepath.Join(packageRoot, options.initdScriptFilePath))
// copy environment var file
runPrint("cp", "-p", options.defaultFileSrc, filepath.Join(packageRoot, options.etcDefaultFilePath))
// copy systemd file
runPrint("cp", "-p", options.systemdFileSrc, filepath.Join(packageRoot, options.systemdServiceFilePath))
// copy release files
runPrint("cp", "-a", filepath.Join(workingDir, "tmp")+"/.", filepath.Join(packageRoot, options.homeDir))
// remove bin path
runPrint("rm", "-rf", filepath.Join(packageRoot, options.homeDir, "bin"))
// create /bin within home
runPrint("mkdir", "-p", filepath.Join(packageRoot, options.homeBinDir))
// The grafana-cli binary is exposed through a wrapper to ensure a proper
// configuration is in place. To enable that, we need to store the original
// binary in a separate location to avoid conflicts.
runPrint("cp", "-p", filepath.Join(workingDir, "tmp/bin/"+cliBinary), filepath.Join(packageRoot, options.homeBinDir, cliBinary))
args := []string{
"-s", "dir",
"--description", "Grafana",
"-C", packageRoot,
"--url", "https://grafana.com",
"--maintainer", "contact@grafana.com",
"--config-files", options.initdScriptFilePath,
"--config-files", options.etcDefaultFilePath,
"--config-files", options.systemdServiceFilePath,
"--after-install", options.postinstSrc,
"--version", linuxPackageVersion,
"-p", "./dist",
}
name := "grafana"
if enterprise {
name += "-enterprise"
args = append(args, "--replaces", "grafana")
}
fmt.Printf("pkgArch is set to '%s', generated arch is '%s'\n", pkgArch, options.packageArch)
if pkgArch == "armv6" {
name += "-rpi"
args = append(args, "--replaces", "grafana")
}
args = append(args, "--name", name)
description := "Grafana"
if enterprise {
description += " Enterprise"
}
args = append(args, "--vendor", description)
if !enterprise {
args = append(args, "--license", "\"Apache 2.0\"")
}
if options.packageType == "rpm" {
args = append(args, "--rpm-posttrans", "packaging/rpm/control/posttrans")
}
if options.packageType == "deb" {
args = append(args, "--deb-no-default-config-files")
}
if options.packageArch != "" {
args = append(args, "-a", options.packageArch)
}
if linuxPackageIteration != "" {
args = append(args, "--iteration", linuxPackageIteration)
}
// add dependencies
for _, dep := range options.depends {
args = append(args, "--depends", dep)
}
args = append(args, ".")
fmt.Println("Creating package: ", options.packageType)
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...)
} else {
runPrint("./node_modules/.bin/grunt", params...)
}
}
func genPackageVersion() string {
@@ -218,13 +447,26 @@ func genPackageVersion() string {
}
}
func setup() {
args := []string{"install", "-v"}
if goos == windows {
args = append(args, "-buildmode=exe")
func gruntBuildArg(task string) []string {
args := []string{task}
args = append(args, fmt.Sprintf("--pkgVer=%v", genPackageVersion()))
if pkgArch != "" {
args = append(args, fmt.Sprintf("--arch=%v", pkgArch))
}
args = append(args, "./pkg/cmd/grafana-server")
runPrint("go", args...)
if phjsToRelease != "" {
args = append(args, fmt.Sprintf("--phjsToRelease=%v", phjsToRelease))
}
if enterprise {
args = append(args, "--enterprise")
}
args = append(args, fmt.Sprintf("--platform=%v", goos))
return args
}
func setup() {
runPrint("go", "install", "-v", "./pkg/cmd/grafana-server")
}
func printGeneratedVersion() {
@@ -233,22 +475,13 @@ func printGeneratedVersion() {
func test(pkg string) {
setBuildEnv()
args := []string{"test", "-short", "-timeout", "60s"}
if goos == windows {
args = append(args, "-buildmode=exe")
}
args = append(args, pkg)
runPrint("go", args...)
runPrint("go", "test", "-short", "-timeout", "60s", pkg)
}
func doBuild(binaryName, pkg string, tags []string) {
libcPart := ""
if libc != "" {
libcPart = fmt.Sprintf("-%s", libc)
}
binary := fmt.Sprintf("./bin/%s-%s%s/%s", goos, goarch, libcPart, binaryName)
func build(binaryName, pkg string, tags []string) {
binary := fmt.Sprintf("./bin/%s-%s/%s", goos, goarch, binaryName)
if isDev {
//don't include os/arch/libc in output path in dev environment
//don't include os and arch in output path in dev environment
binary = fmt.Sprintf("./bin/%s", binaryName)
}
@@ -260,10 +493,6 @@ func doBuild(binaryName, pkg string, tags []string) {
rmr(binary, binary+".md5")
}
args := []string{"build", "-ldflags", ldflags()}
if goos == windows {
// Work around a linking error on Windows: "export ordinal too large"
args = append(args, "-buildmode=exe")
}
if len(tags) > 0 {
args = append(args, "-tags", strings.Join(tags, ","))
}
@@ -277,11 +506,7 @@ func doBuild(binaryName, pkg string, tags []string) {
if !isDev {
setBuildEnv()
runPrint("go", "version")
libcPart := ""
if libc != "" {
libcPart = fmt.Sprintf("/%s", libc)
}
fmt.Printf("Targeting %s/%s%s\n", goos, goarch, libcPart)
fmt.Printf("Targeting %s/%s\n", goos, goarch)
}
runPrint("go", args...)
@@ -303,9 +528,6 @@ func ldflags() string {
b.WriteString(fmt.Sprintf(" -X main.commit=%s", getGitSha()))
b.WriteString(fmt.Sprintf(" -X main.buildstamp=%d", buildStamp()))
b.WriteString(fmt.Sprintf(" -X main.buildBranch=%s", getGitBranch()))
if v := os.Getenv("LDFLAGS"); v != "" {
b.WriteString(fmt.Sprintf(" -extldflags \"%s\"", v))
}
return b.String()
}
@@ -323,7 +545,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() {
@@ -370,11 +592,6 @@ func getGitSha() string {
}
func buildStamp() int64 {
// use SOURCE_DATE_EPOCH if set.
if s, _ := strconv.ParseInt(os.Getenv("SOURCE_DATE_EPOCH"), 10, 64); s > 0 {
return s
}
bs, err := runError("git", "show", "-s", "--format=%ct")
if err != nil {
return time.Now().Unix()
@@ -396,7 +613,6 @@ func runError(cmd string, args ...string) ([]byte, error) {
func runPrint(cmd string, args ...string) {
log.Println(cmd, strings.Join(args, " "))
ecmd := exec.Command(cmd, args...)
ecmd.Env = append(os.Environ(), "GO111MODULE=on")
ecmd.Stdout = os.Stdout
ecmd.Stderr = os.Stderr
err := ecmd.Run()

View File

@@ -28,7 +28,7 @@ provisioning = conf/provisioning
#################################### Server ##############################
[server]
# Protocol (http, https, h2, socket)
# Protocol (http, https, socket)
protocol = http
# The ip address to bind to, empty will bind to all interfaces
@@ -66,13 +66,6 @@ cert_key =
# Unix socket path
socket = /tmp/grafana.sock
# CDN Url
cdn_url =
# Sets the maximum time in minutes before timing out read of an incoming request and closing idle connections.
# `0` means there is no timeout for reading the request.
read_timeout = 0
#################################### Database ############################
[database]
# You can configure the database connection by specifying type, host, name, user and password
@@ -123,7 +116,7 @@ type = database
# cache connectionstring options
# database: will use Grafana primary database.
# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=0,ssl=false`. Only addr is required. ssl may be 'true', 'false', or 'insecure'.
# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=0`. Only addr is required.
# memcache: 127.0.0.1:11211
connstr =
@@ -133,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 ###########################
@@ -166,9 +140,6 @@ send_user_header = false
# Change this option to false to disable reporting.
reporting_enabled = true
# The name of the distributor of the Grafana instance. Ex hosted-grafana, grafana-labs
reporting_distributor = grafana-labs
# Set to false to disable all checks to https://grafana.com
# for new versions (grafana itself and plugins), check is used
# in some UI views to notify that grafana or plugin update exists
@@ -184,9 +155,6 @@ google_tag_manager_id =
#################################### Security ############################
[security]
# disable creation of admin user on first start of grafana
disable_initial_admin_creation = false
# default admin user, created on startup
admin_user = admin
@@ -208,7 +176,7 @@ disable_brute_force_login_protection = false
# set to true if you host Grafana behind HTTPS. default is false.
cookie_secure = false
# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict", "none" and "disabled"
# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict" and "none"
cookie_samesite = lax
# set to true if you want to allow browsers to render Grafana in a <frame>, <iframe>, <embed> or <object>. default is false.
@@ -217,6 +185,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.
@@ -230,20 +199,13 @@ 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
# Enable adding the Content-Security-Policy header to your requests.
# CSP allows to control resources the user agent is allowed to load and helps prevent XSS attacks.
content_security_policy = false
# Set Content Security Policy template used when adding the Content-Security-Policy header to your requests.
# $NONCE in the template includes a random nonce.
content_security_policy_template = """script-src 'unsafe-eval' 'strict-dynamic' $NONCE;object-src 'none';font-src 'self';style-src 'self' 'unsafe-inline';img-src 'self' data:;base-uri 'self';connect-src 'self' grafana.com;manifest-src 'self';media-src 'none';form-action 'self';"""
#################################### Snapshots ###########################
[snapshots]
@@ -252,10 +214,6 @@ external_enabled = true
external_snapshot_url = https://snapshots-origin.raintank.io
external_snapshot_name = Publish to snapshot.raintank.io
# Set to true to enable this Grafana instance act as an external snapshot server and allow unauthenticated requests for
# creating and deleting snapshots.
public_mode = false
# remove expired snapshot
snapshot_remove_expired = true
@@ -265,18 +223,6 @@ snapshot_remove_expired = true
# Number dashboard versions to keep (per dashboard). Default: 20, Minimum: 1
versions_to_keep = 20
# Minimum dashboard refresh interval. When set, this will restrict users to set the refresh interval of a dashboard lower than given interval. Per default this is 5 seconds.
# 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 =
################################### Data sources #########################
[datasources]
# Upper limit of data sources that Grafana will return. This limit is a temporary configuration and it will be deprecated when pagination will be introduced on the list data sources API.
datasource_limit = 5000
#################################### Users ###############################
[users]
# disable user signup / registration
@@ -315,21 +261,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
# Enter a comma-separated list of usernames to hide them in the Grafana UI. These users are shown to Grafana admins and to themselves.
hidden_users =
[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
@@ -347,15 +287,9 @@ 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
# 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
@@ -367,20 +301,16 @@ 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
api_url = https://api.github.com/user
allowed_domains =
team_ids =
allowed_organizations =
@@ -389,12 +319,11 @@ 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
api_url = https://gitlab.com/api/v4
allowed_domains =
allowed_groups =
#################################### Google Auth #########################
@@ -402,7 +331,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
@@ -416,7 +345,7 @@ hosted_domain =
enabled = false
allow_sign_up = true
client_id = some_id
client_secret =
client_secret = some_secret
scopes = user:email
allowed_organizations =
@@ -424,62 +353,70 @@ allowed_organizations =
enabled = false
allow_sign_up = true
client_id = some_id
client_secret =
client_secret = some_secret
scopes = user:email
allowed_organizations =
#################################### Azure AD OAuth #######################
[auth.azuread]
name = Azure AD
enabled = false
allow_sign_up = true
client_id = some_client_id
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
allowed_domains =
allowed_groups =
#################################### Okta OAuth #######################
[auth.okta]
name = Okta
enabled = false
allow_sign_up = true
client_id = some_id
client_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
api_url = https://<tenant-id>.okta.com/oauth2/v1/userinfo
allowed_domains =
allowed_groups =
role_attribute_path =
#################################### Generic OAuth #######################
[auth.generic_oauth]
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 =
name_attribute_path =
role_attribute_path =
id_token_attribute_name =
auth_url =
token_url =
api_url =
allowed_domains =
team_ids =
allowed_organizations =
tls_skip_verify_insecure = false
tls_client_cert =
tls_client_key =
tls_client_ca =
send_client_credentials_via_post = false
#################################### SAML Auth ###########################
[auth.saml] # Enterprise only
# Defaults to false. If true, the feature is enabled
enabled = false
# Base64-encoded public X.509 certificate. Used to sign requests to the IdP
certificate =
# Path to the public X.509 certificate. Used to sign requests to the IdP
certificate_path =
# Base64-encoded private key. Used to decrypt assertions from the IdP
private_key =
# Path to the private key. Used to decrypt assertions from the IdP
private_key_path =
# Base64-encoded IdP SAML metadata XML. Used to verify and obtain binding locations from the IdP
idp_metadata =
# Path to the SAML metadata XML. Used to verify and obtain binding locations from the IdP
idp_metadata_path =
# URL to fetch SAML IdP metadata. Used to verify and obtain binding locations from the IdP
idp_metadata_url =
# Duration, since the IdP issued a response and the SP is allowed to process it. Defaults to 90 seconds
max_issue_delay = 90s
# Duration, for how long the SP's metadata should be valid. Defaults to 48 hours
metadata_valid_duration = 48h
# Friendly name or name of the attribute within the SAML assertion to use as the user's name
assertion_attribute_name = displayName
# Friendly name or name of the attribute within the SAML assertion to use as the user's login handle
assertion_attribute_login = mail
# Friendly name or name of the attribute within the SAML assertion to use as the user's email
assertion_attribute_email = mail
#################################### Basic Auth ##########################
[auth.basic]
@@ -491,12 +428,9 @@ enabled = false
header_name = X-WEBAUTH-USER
header_property = username
auto_sign_up = true
# Deprecated, use sync_ttl instead
ldap_sync_ttl = 60
sync_ttl = 60
whitelist =
headers =
enable_login_token = false
#################################### Auth LDAP ###########################
[auth.ldap]
@@ -504,24 +438,11 @@ enabled = false
config_file = /etc/grafana/ldap.toml
allow_sign_up = true
# LDAP background sync (Enterprise only)
# LDAP backround sync (Enterprise only)
# At 1 am every day
sync_cron = "0 0 1 * * *"
active_sync_enabled = true
#################################### AWS ###########################
[aws]
# Enter a comma-separated list of allowed AWS authentication providers.
# Options are: default (AWS SDK Default), keys (Access && secret key), credentials (Credentials field), ec2_iam_role (EC2 IAM Role)
allowed_auth_providers = default,keys,credentials
# Allow AWS users to assume a role using temporary security credentials.
# If true, assume role will be enabled for all AWS authentication providers that are specified in aws_auth_providers
assume_role_enabled = true
# Specify max no of pages to be returned by the ListMetricPages API
list_metrics_page_limit = 500
#################################### SMTP / Emailing #####################
[smtp]
enabled = false
@@ -535,7 +456,6 @@ skip_verify = false
from_address = admin@grafana.localhost
from_name = Grafana
ehlo_identity =
startTLS_policy =
[emails]
welcome_email_on_sign_up = false
@@ -598,25 +518,6 @@ facility =
# Syslog tag. By default, the process' argv[0] is used.
tag =
[log.frontend]
# Should Sentry javascript agent be initialized
enabled = false
# Sentry DSN if you want to send events to Sentry.
sentry_dsn =
# Custom HTTP endpoint to send events captured by the Sentry agent to. Default will log the events to stdout.
custom_endpoint = /log
# Rate of events to be reported between 0 (none) and 1 (all), float
sample_rate = 1.0
# Requests per second limit enforced per an extended period, for Grafana backend log ingestion endpoint (/log).
log_endpoint_requests_per_second_limit = 3
# Max requests accepted per short interval of time for Grafana backend log ingestion endpoint (/log)
log_endpoint_burst_limit = 15
#################################### Usage Quotas ########################
[quota]
enabled = false
@@ -678,41 +579,6 @@ notification_timeout_seconds = 30
# Default setting for max attempts to sending alert notifications. Default value is 3
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]
# Configures the batch size for the annotation clean-up job. This setting is used for dashboard, API, and alert annotations.
cleanupjob_batchsize = 100
[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]
@@ -722,28 +588,19 @@ enabled = true
#################################### Internal Grafana Metrics ############
# Metrics available at HTTP API Url /metrics
[metrics]
enabled = true
interval_seconds = 10
# Disable total stats (stat_totals_*) metrics to be generated
disable_total_stats = false
enabled = true
interval_seconds = 10
#If both are set, basic auth will be required for the metrics endpoint.
basic_auth_username =
basic_auth_password =
# Metrics environment info adds dimensions to the `grafana_environment_info` metric, which
# can expose more information about the Grafana instance.
[metrics.environment_info]
#exampleLabel1 = exampleValue1
#exampleLabel2 = exampleValue2
# Send internal Grafana metrics to graphite
[metrics.graphite]
# Enable by setting the address setting (ex localhost:2003)
address =
prefix = prod.grafana.%(instance_name)s.
#################################### Grafana.com integration ##########################
[grafana_net]
url = https://grafana.com
@@ -766,8 +623,6 @@ sampler_type = const
# and indicates the initial sampling rate before the actual one
# is received from the mothership
sampler_param = 1
# sampling_server_url is the URL of a sampling manager providing a sampling strategy.
sampling_server_url =
# Whether or not to use Zipkin span propagation (x-b3- HTTP headers).
zipkin_propagation = false
# Setting this to true disables shared RPC spans.
@@ -776,13 +631,10 @@ disable_shared_zipkin_spans = false
#################################### External Image Storage ##############
[external_image_storage]
# Used for uploading images to public servers so they can be included in slack/email messages.
# You can choose between (s3, webdav, gcs, azure_blob, local)
provider =
[external_image_storage.s3]
endpoint =
path_style_access =
bucket_url =
bucket =
region =
@@ -800,8 +652,6 @@ public_url =
key_file =
bucket =
path =
enable_signed_urls = false
signed_url_expiration =
[external_image_storage.azure_blob]
account_name =
@@ -812,14 +662,9 @@ container_name =
# does not require any configuration
[rendering]
# Options to configure a remote HTTP image rendering service, e.g. using https://github.com/grafana/grafana-image-renderer.
# URL to a remote HTTP image renderer service, e.g. http://localhost:8081/render, will enable Grafana to render panels and dashboards to PNG-images using HTTP requests to an external service.
# Options to configure external image rendering server like https://github.com/grafana/grafana-image-renderer
server_url =
# If the remote HTTP image renderer service runs on a different server than the Grafana server you may have to configure this to a URL where Grafana is reachable, e.g. http://grafana.domain/.
callback_url =
# Concurrent render request limit affects when the /render HTTP endpoint is used. Rendering many images at the same time can overload the server,
# which this setting can help protect against by only allowing a certain amount of concurrent requests.
concurrent_render_request_limit = 30
[panels]
# here for to support old env variables, can remove after a few months
@@ -829,97 +674,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 =
marketplace_url = https://grafana.com/grafana/plugins/
#################################### Grafana Image Renderer Plugin ##########################
[plugin.grafana-image-renderer]
# Instruct headless browser instance to use a default timezone when not provided by Grafana, e.g. when rendering panel image of alert.
# See ICUs metaZones.txt (https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt) for a list of supported
# timezone IDs. Fallbacks to TZ environment variable if not set.
rendering_timezone =
# Instruct headless browser instance to use a default language when not provided by Grafana, e.g. when rendering panel image of alert.
# Please refer to the HTTP header Accept-Language to understand how to format this value, e.g. 'fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5'.
rendering_language =
# Instruct headless browser instance to use a default device scale factor when not provided by Grafana, e.g. when rendering panel image of alert.
# Default is 1. Using a higher value will produce more detailed images (higher DPI), but will require more disk space to store an image.
rendering_viewport_device_scale_factor =
# Instruct headless browser instance whether to ignore HTTPS errors during navigation. Per default HTTPS errors are not ignored. Due to
# the security risk it's not recommended to ignore HTTPS errors.
rendering_ignore_https_errors =
# Instruct headless browser instance whether to capture and log verbose information when rendering an image. Default is false and will
# only capture and log error messages. When enabled, debug messages are captured and logged as well.
# For the verbose information to be included in the Grafana server log you have to adjust the rendering log level to debug, configure
# [log].filter = rendering:debug.
rendering_verbose_logging =
# Instruct headless browser instance whether to output its debug and error messages into running process of remote rendering service.
# Default is false. This can be useful to enable (true) when troubleshooting.
rendering_dumpio =
# Additional arguments to pass to the headless browser instance. Default is --no-sandbox. The list of Chromium flags can be found
# here (https://peter.sh/experiments/chromium-command-line-switches/). Multiple arguments is separated with comma-character.
rendering_args =
# You can configure the plugin to use a different browser binary instead of the pre-packaged version of Chromium.
# Please note that this is not recommended, since you may encounter problems if the installed version of Chrome/Chromium is not
# compatible with the plugin.
rendering_chrome_bin =
# Instruct how headless browser instances are created. Default is 'default' and will create a new browser instance on each request.
# Mode 'clustered' will make sure that only a maximum of browsers/incognito pages can execute concurrently.
# Mode 'reusable' will have one browser instance and will create a new incognito page on each request.
rendering_mode =
# When rendering_mode = clustered you can instruct how many browsers or incognito pages can execute concurrently. Default is 'browser'
# and will cluster using browser instances.
# Mode 'context' will cluster using incognito pages.
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.
rendering_viewport_max_width =
rendering_viewport_max_height =
rendering_viewport_max_device_scale_factor =
# Change the listening host and port of the gRPC server. Default host is 127.0.0.1 and default port is 0 and will automatically assign
# a port not in use.
grpc_host =
grpc_port =
[enterprise]
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
[expressions]
# Enable or disable the expressions functionality.
enabled = true

View File

@@ -7,9 +7,9 @@
host = "127.0.0.1"
# Default port is 389 or 636 if use_ssl = true
port = 389
# Set to true if LDAP server should use an encrypted TLS connection (either with STARTTLS or LDAPS)
# Set to true if ldap server supports TLS
use_ssl = false
# If set to true, use LDAP with STARTTLS instead of LDAPS
# Set to true if connect ldap server with STARTTLS pattern (create connection in insecure, then upgrade to secure connection with TLS)
start_tls = false
# set to true if you want to skip ssl cert validation
ssl_skip_verify = false
@@ -47,7 +47,7 @@ email = "email"
# Map ldap groups to grafana org roles
[[servers.group_mappings]]
group_dn = "cn=admins,ou=groups,dc=grafana,dc=org"
group_dn = "cn=admins,dc=grafana,dc=org"
org_role = "Admin"
# To make user an instance admin (Grafana Admin) uncomment line below
# grafana_admin = true
@@ -55,7 +55,7 @@ org_role = "Admin"
# org_id = 1
[[servers.group_mappings]]
group_dn = "cn=users,ou=groups,dc=grafana,dc=org"
group_dn = "cn=users,dc=grafana,dc=org"
org_role = "Editor"
[[servers.group_mappings]]

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

@@ -28,7 +28,7 @@
#################################### Server ####################################
[server]
# Protocol (http, https, h2, socket)
# Protocol (http, https, socket)
;protocol = http
# The ip address to bind to, empty will bind to all interfaces
@@ -46,7 +46,7 @@
# The full public facing url you use in browser, used for redirects and emails
# If you use reverse proxy and sub path specify full url (with sub path)
;root_url = %(protocol)s://%(domain)s:%(http_port)s/
;root_url = http://localhost:3000
# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons.
;serve_from_sub_path = false
@@ -67,13 +67,6 @@
# Unix socket path
;socket =
# CDN Url
;cdn_url =
# Sets the maximum time using a duration format (5s/5m/5ms) before timing out read of an incoming request and closing idle connections.
# `0` means there is no timeout for reading the request.
;read_timeout = 0
#################################### Database ####################################
[database]
# You can configure the database connection by specifying type, host, name, user and password
@@ -94,11 +87,6 @@
# For "postgres" only, either "disable", "require" or "verify-full"
;ssl_mode = disable
;ca_cert_path =
;client_key_path =
;client_cert_path =
;server_cert_name =
# For "sqlite3" only, path relative to data_path setting
;path = grafana.db
@@ -117,11 +105,6 @@
# For "sqlite3" only. cache mode setting used for connecting to the database. (private, shared)
;cache_mode = private
################################### Data sources #########################
[datasources]
# Upper limit of data sources that Grafana will return. This limit is a temporary configuration and it will be deprecated when pagination will be introduced on the list data sources API.
;datasource_limit = 5000
#################################### Cache server #############################
[remote_cache]
# Either "redis", "memcached" or "database" default is "database"
@@ -129,7 +112,7 @@
# cache connectionstring options
# database: will use Grafana primary database.
# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=0,ssl=false`. Only addr is required. ssl may be 'true', 'false', or 'insecure'.
# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=0`. Only addr is required.
# memcache: 127.0.0.1:11211
;connstr =
@@ -139,28 +122,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
@@ -172,11 +136,8 @@
# Change this option to false to disable reporting.
;reporting_enabled = true
# The name of the distributor of the Grafana instance. Ex hosted-grafana, grafana-labs
;reporting_distributor = grafana-labs
# 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
@@ -190,9 +151,6 @@
#################################### Security ####################################
[security]
# disable creation of admin user on first start of grafana
;disable_initial_admin_creation = false
# default admin user, created on startup
;admin_user = admin
@@ -214,7 +172,7 @@
# set to true if you host Grafana behind HTTPS. default is false.
;cookie_secure = false
# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict", "none" and "disabled"
# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict" and "none"
;cookie_samesite = lax
# set to true if you want to allow browsers to render Grafana in a <frame>, <iframe>, <embed> or <object>. default is false.
@@ -223,6 +181,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.
@@ -236,20 +195,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
# Enable adding the Content-Security-Policy header to your requests.
# CSP allows to control resources the user agent is allowed to load and helps prevent XSS attacks.
;content_security_policy = false
# Set Content Security Policy template used when adding the Content-Security-Policy header to your requests.
# $NONCE in the template includes a random nonce.
;content_security_policy_template = """script-src 'unsafe-eval' 'strict-dynamic' $NONCE;object-src 'none';font-src 'self';style-src 'self' 'unsafe-inline';img-src 'self' data:;base-uri 'self';connect-src 'self' grafana.com;manifest-src 'self';media-src 'none';form-action 'self';"""
# 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]
@@ -258,10 +209,6 @@
;external_snapshot_url = https://snapshots-origin.raintank.io
;external_snapshot_name = Publish to snapshot.raintank.io
# Set to true to enable this Grafana instance act as an external snapshot server and allow unauthenticated requests for
# creating and deleting snapshots.
;public_mode = false
# remove expired snapshot
;snapshot_remove_expired = true
@@ -270,13 +217,6 @@
# Number dashboard versions to keep (per dashboard). Default: 20, Minimum: 1
;versions_to_keep = 20
# Minimum dashboard refresh interval. When set, this will restrict users to set the refresh interval of a dashboard lower than given interval. Per default this is 5 seconds.
# 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
@@ -288,15 +228,9 @@
# Set to true to automatically assign new users to the default organization (id 1)
;auto_assign_org = true
# Set this value to automatically add new users to the provided organization (if auto_assign_org above is set to true)
;auto_assign_org_id = 1
# Default role new users will be automatically assigned (if disabled above is set to true)
;auto_assign_org_role = Viewer
# Require email validation before sign up completes
;verify_email_enabled = false
# Background text for the user field on the login page
;login_hint = email or username
;password_hint = password
@@ -315,21 +249,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
# Enter a comma-separated list of users login to hide them in the Grafana UI. These users are shown to Grafana admins and themselves.
; hidden_users =
[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
@@ -347,15 +275,6 @@
# 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
# 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
@@ -367,10 +286,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
@@ -380,23 +296,9 @@
;auth_url = https://github.com/login/oauth/authorize
;token_url = https://github.com/login/oauth/access_token
;api_url = https://api.github.com/user
;allowed_domains =
;team_ids =
;allowed_organizations =
#################################### GitLab Auth #########################
[auth.gitlab]
;enabled = false
;allow_sign_up = true
;client_id = some_id
;client_secret = some_secret
;scopes = api
;auth_url = https://gitlab.com/oauth/authorize
;token_url = https://gitlab.com/oauth/token
;api_url = https://gitlab.com/api/v4
;allowed_domains =
;allowed_groups =
#################################### Google Auth ##########################
[auth.google]
;enabled = false
@@ -408,7 +310,69 @@
;token_url = https://accounts.google.com/o/oauth2/token
;api_url = https://www.googleapis.com/oauth2/v1/userinfo
;allowed_domains =
;hosted_domain =
#################################### Generic OAuth ##########################
[auth.generic_oauth]
;enabled = false
;name = OAuth
;allow_sign_up = true
;client_id = some_id
;client_secret = some_secret
;scopes = user:email,read:org
;auth_url = https://foo.bar/login/oauth/authorize
;token_url = https://foo.bar/login/oauth/access_token
;api_url = https://foo.bar/user
;team_ids =
;allowed_organizations =
;tls_skip_verify_insecure = false
;tls_client_cert =
;tls_client_key =
;tls_client_ca =
; Set to true to enable sending client_id and client_secret via POST body instead of Basic authentication HTTP header
; This might be required if the OAuth provider is not RFC6749 compliant, only supporting credentials passed via POST payload
;send_client_credentials_via_post = false
#################################### SAML Auth ###########################
[auth.saml] # Enterprise only
# Defaults to false. If true, the feature is enabled.
;enabled = false
# Base64-encoded public X.509 certificate. Used to sign requests to the IdP
;certificate =
# Path to the public X.509 certificate. Used to sign requests to the IdP
;certificate_path =
# Base64-encoded private key. Used to decrypt assertions from the IdP
;private_key =
;# Path to the private key. Used to decrypt assertions from the IdP
;private_key_path =
# Base64-encoded IdP SAML metadata XML. Used to verify and obtain binding locations from the IdP
;idp_metadata =
# Path to the SAML metadata XML. Used to verify and obtain binding locations from the IdP
;idp_metadata_path =
# URL to fetch SAML IdP metadata. Used to verify and obtain binding locations from the IdP
;idp_metadata_url =
# Duration, since the IdP issued a response and the SP is allowed to process it. Defaults to 90 seconds.
;max_issue_delay = 90s
# Duration, for how long the SP's metadata should be valid. Defaults to 48 hours.
;metadata_valid_duration = 48h
# Friendly name or name of the attribute within the SAML assertion to use as the user's name
;assertion_attribute_name = displayName
# Friendly name or name of the attribute within the SAML assertion to use as the user's login handle
;assertion_attribute_login = mail
# Friendly name or name of the attribute within the SAML assertion to use as the user's email
;assertion_attribute_email = mail
#################################### Grafana.com Auth ####################
[auth.grafana_com]
@@ -419,74 +383,19 @@
;scopes = user:email
;allowed_organizations =
#################################### Azure AD OAuth #######################
[auth.azuread]
;name = Azure AD
;enabled = false
;allow_sign_up = true
;client_id = some_client_id
;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
;allowed_domains =
;allowed_groups =
#################################### Okta OAuth #######################
[auth.okta]
;name = Okta
;enabled = false
;allow_sign_up = true
;client_id = some_id
;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
;api_url = https://<tenant-id>.okta.com/oauth2/v1/userinfo
;allowed_domains =
;allowed_groups =
;role_attribute_path =
#################################### Generic OAuth ##########################
[auth.generic_oauth]
;enabled = false
;name = OAuth
;allow_sign_up = true
;client_id = some_id
;client_secret = some_secret
;scopes = user:email,read:org
;email_attribute_name = email:primary
;email_attribute_path =
;login_attribute_path =
;name_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
;allowed_domains =
;team_ids =
;allowed_organizations =
;role_attribute_path =
;tls_skip_verify_insecure = false
;tls_client_cert =
;tls_client_key =
;tls_client_ca =
#################################### Basic Auth ##########################
[auth.basic]
;enabled = true
#################################### Auth Proxy ##########################
[auth.proxy]
;enabled = false
;header_name = X-WEBAUTH-USER
;header_property = username
;auto_sign_up = true
;sync_ttl = 60
;ldap_sync_ttl = 60
;whitelist = 192.168.1.1, 192.168.2.1
;headers = Email:X-User-Email, Name:X-User-Name
# Read the auth proxy docs for details on what the setting below enables
;enable_login_token = false
#################################### Basic Auth ##########################
[auth.basic]
;enabled = true
#################################### Auth LDAP ##########################
[auth.ldap]
@@ -494,27 +403,17 @@
;config_file = /etc/grafana/ldap.toml
;allow_sign_up = true
# LDAP background sync (Enterprise only)
# LDAP backround sync (Enterprise only)
# At 1 am every day
;sync_cron = "0 0 1 * * *"
;active_sync_enabled = true
#################################### AWS ###########################
[aws]
# Enter a comma-separated list of allowed AWS authentication providers.
# Options are: default (AWS SDK Default), keys (Access && secret key), credentials (Credentials field), ec2_iam_role (EC2 IAM Role)
; allowed_auth_providers = default,keys,credentials
# Allow AWS users to assume a role using temporary security credentials.
# If true, assume role will be enabled for all AWS authentication providers that are specified in aws_auth_providers
; assume_role_enabled = true
#################################### SMTP / Emailing ##########################
[smtp]
;enabled = false
;host = localhost:25
;user =
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;"""
;password =
;cert_file =
;key_file =
@@ -523,12 +422,9 @@
;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
;templates_pattern = emails/*.html
#################################### Logging ##########################
[log]
@@ -587,60 +483,6 @@
# Syslog tag. By default, the process' argv[0] is used.
;tag =
[log.frontend]
# Should Sentry javascript agent be initialized
;enabled = false
# Sentry DSN if you want to send events to Sentry.
;sentry_dsn =
# Custom HTTP endpoint to send events captured by the Sentry agent to. Default will log the events to stdout.
;custom_endpoint = /log
# Rate of events to be reported between 0 (none) and 1 (all), float
;sample_rate = 1.0
# Requests per second limit enforced an extended period, for Grafana backend log ingestion endpoint (/log).
;log_endpoint_requests_per_second_limit = 3
# Max requests accepted per short interval of time for Grafana backend log ingestion endpoint (/log).
;log_endpoint_burst_limit = 15
#################################### Usage Quotas ########################
[quota]
; enabled = false
#### set quotas to -1 to make unlimited. ####
# limit number of users per Org.
; org_user = 10
# limit number of dashboards per Org.
; org_dashboard = 100
# limit number of data_sources per Org.
; org_data_source = 10
# limit number of api_keys per Org.
; org_api_key = 10
# limit number of orgs a user can create.
; user_org = 10
# Global limit of users.
; global_user = -1
# global limit of orgs.
; global_org = -1
# global limit of dashboards
; global_dashboard = -1
# global limit of api_keys
; global_api_key = -1
# global limit on number of logged in users.
; global_session = -1
#################################### Alerting ############################
[alerting]
# Disable alerting engine & UI features
@@ -668,42 +510,6 @@
# Default setting for max attempts to sending alert notifications. Default value is 3
;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 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]
# Configures the batch size for the annotation clean-up job. This setting is used for dashboard, API, and alert annotations.
;cleanupjob_batchsize = 100
[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
@@ -714,20 +520,9 @@
[metrics]
# Disable / Enable internal metrics
;enabled = true
# Graphite Publish interval
# Publish interval
;interval_seconds = 10
# Disable total stats (stat_totals_*) metrics to be generated
;disable_total_stats = false
#If both are set, basic auth will be required for the metrics endpoint.
; basic_auth_username =
; basic_auth_password =
# Metrics environment info adds dimensions to the `grafana_environment_info` metric, which
# can expose more information about the Grafana instance.
[metrics.environment_info]
#exampleLabel1 = exampleValue1
#exampleLabel2 = exampleValue2
# Send internal metrics to Graphite
[metrics.graphite]
@@ -735,11 +530,6 @@
;address =
;prefix = prod.grafana.%(instance_name)s.
#################################### Grafana.com integration ##########################
# Url used to import dashboards directly from Grafana.com
[grafana_com]
;url = https://grafana.com
#################################### Distributed tracing ############
[tracing.jaeger]
# Enable by setting the address sending traces to jaeger (ex localhost:6831)
@@ -756,14 +546,17 @@
# and indicates the initial sampling rate before the actual one
# is received from the mothership
;sampler_param = 1
# sampling_server_url is the URL of a sampling manager providing a sampling strategy.
;sampling_server_url =
# Whether or not to use Zipkin propagation (x-b3- HTTP headers).
;zipkin_propagation = false
# Setting this to true disables shared RPC spans.
# Not disabling is the most common setting when using Zipkin elsewhere in your infrastructure.
;disable_shared_zipkin_spans = false
#################################### Grafana.com integration ##########################
# Url used to import dashboards directly from Grafana.com
[grafana_com]
;url = https://grafana.com
#################################### External image storage ##########################
[external_image_storage]
# Used for uploading images to public servers so they can be included in slack/email messages.
@@ -771,8 +564,6 @@
;provider =
[external_image_storage.s3]
;endpoint =
;path_style_access =
;bucket =
;region =
;path =
@@ -799,14 +590,13 @@
# does not require any configuration
[rendering]
# Options to configure a remote HTTP image rendering service, e.g. using https://github.com/grafana/grafana-image-renderer.
# URL to a remote HTTP image renderer service, e.g. http://localhost:8081/render, will enable Grafana to render panels and dashboards to PNG-images using HTTP requests to an external service.
# Options to configure external image rendering server like https://github.com/grafana/grafana-image-renderer
;server_url =
# If the remote HTTP image renderer service runs on a different server than the Grafana server you may have to configure this to a URL where Grafana is reachable, e.g. http://grafana.domain/.
;callback_url =
# Concurrent render request limit affects when the /render HTTP endpoint is used. Rendering many images at the same time can overload the server,
# which this setting can help protect against by only allowing a certain amount of concurrent requests.
;concurrent_render_request_limit = 30
[enterprise]
# Path to a valid Grafana Enterprise license.jwt file
;license_path =
[panels]
# If set to true Grafana will allow script tags in text panels. Not recommended as it enable XSS vulnerabilities.
@@ -815,98 +605,3 @@
[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 =
;marketplace_url = https://grafana.com/grafana/plugins/
#################################### Grafana Image Renderer Plugin ##########################
[plugin.grafana-image-renderer]
# Instruct headless browser instance to use a default timezone when not provided by Grafana, e.g. when rendering panel image of alert.
# See ICUs metaZones.txt (https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt) for a list of supported
# timezone IDs. Fallbacks to TZ environment variable if not set.
;rendering_timezone =
# Instruct headless browser instance to use a default language when not provided by Grafana, e.g. when rendering panel image of alert.
# Please refer to the HTTP header Accept-Language to understand how to format this value, e.g. 'fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5'.
;rendering_language =
# Instruct headless browser instance to use a default device scale factor when not provided by Grafana, e.g. when rendering panel image of alert.
# Default is 1. Using a higher value will produce more detailed images (higher DPI), but will require more disk space to store an image.
;rendering_viewport_device_scale_factor =
# Instruct headless browser instance whether to ignore HTTPS errors during navigation. Per default HTTPS errors are not ignored. Due to
# the security risk it's not recommended to ignore HTTPS errors.
;rendering_ignore_https_errors =
# Instruct headless browser instance whether to capture and log verbose information when rendering an image. Default is false and will
# only capture and log error messages. When enabled, debug messages are captured and logged as well.
# For the verbose information to be included in the Grafana server log you have to adjust the rendering log level to debug, configure
# [log].filter = rendering:debug.
;rendering_verbose_logging =
# Instruct headless browser instance whether to output its debug and error messages into running process of remote rendering service.
# Default is false. This can be useful to enable (true) when troubleshooting.
;rendering_dumpio =
# Additional arguments to pass to the headless browser instance. Default is --no-sandbox. The list of Chromium flags can be found
# here (https://peter.sh/experiments/chromium-command-line-switches/). Multiple arguments is separated with comma-character.
;rendering_args =
# You can configure the plugin to use a different browser binary instead of the pre-packaged version of Chromium.
# Please note that this is not recommended, since you may encounter problems if the installed version of Chrome/Chromium is not
# compatible with the plugin.
;rendering_chrome_bin =
# Instruct how headless browser instances are created. Default is 'default' and will create a new browser instance on each request.
# Mode 'clustered' will make sure that only a maximum of browsers/incognito pages can execute concurrently.
# Mode 'reusable' will have one browser instance and will create a new incognito page on each request.
;rendering_mode =
# When rendering_mode = clustered you can instruct how many browsers or incognito pages can execute concurrently. Default is 'browser'
# and will cluster using browser instances.
# Mode 'context' will cluster using incognito pages.
;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.
;rendering_viewport_max_width =
;rendering_viewport_max_height =
;rendering_viewport_max_device_scale_factor =
# Change the listening host and port of the gRPC server. Default host is 127.0.0.1 and default port is 0 and will automatically assign
# a port not in use.
;grpc_host =
;grpc_port =
[enterprise]
# Path to a valid Grafana Enterprise license.jwt file
;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
[expressions]
# Enable or disable the expressions functionality.
;enabled = true

View File

@@ -1,16 +0,0 @@
# Contribute
This directory contains guides for contributors to the Grafana project.
- [Create a pull request](create-pull-request.md)
- [Contributing documentation](documentation.md)
- [Developer guide](developer-guide.md)
- [Triage issues](triage-issues.md)
The `style-guides` directory contains style guides for the Grafana software project and documentation.
- [Backend style guide](style-guides/backend.md) for how to style and format backend functionality and code.
- [Documentation style guide](style-guides/documentation-style-guide.md) for how to style and format documentation.
- [Frontend style guide](style-guides/frontend.md) for how to style and format the user-facing functionality and code.
- [Redux framework](style-guides/redux.md) for designing the Grafana redux framework.
- [Themes style guide](style-guides/themes.md) for designing and updating Grafana themes.

View File

@@ -1,13 +0,0 @@
# Architecture
Are you looking to take on contributions with bigger impact? These guides help you get a better understanding of the structure and design of the Grafana codebase.
Learn more about the backend architecture:
- Part 1: [Services](services.md)
- Part 2: [Communication](communication.md)
- Part 3: [Database](database.md)
Learn more about the frontend architecture:
- Part 1: [Data requests](frontend-data-requests.md)

View File

@@ -1,123 +0,0 @@
# Communication
Grafana uses a _bus_ to pass messages between different parts of the application. All communication over the bus happens synchronously.
There are three types of messages: _events_, _commands_, and _queries_.
## Events
An event is something that happened in the past. Since an event has already happened, you can't change it. Instead, you can react to events by triggering additional application logic to be run, whenever they occur.
> Because they happened in the past, event names are written in past tense, such as `UserCreated`, and `OrgUpdated`.
### Subscribe to an event
In order to react to an event, you first need to _subscribe_ to it.
To subscribe to an event, register an _event listener_ in the service's `Init` method:
```go
func (s *MyService) Init() error {
s.bus.AddEventListener(s.UserCreated)
return nil
}
func (s *MyService) UserCreated(event *events.UserCreated) error {
// ...
}
```
**Tip:** Browse the available events in the `events` package.
### Publish an event
If you want to let other parts of the application react to changes in a service, you can publish your own events:
```go
event := &events.StickersSentEvent {
UserID: "taylor",
Count: 1,
}
if err := s.bus.Publish(event); err != nil {
return err
}
```
## Commands
A command is a request for an action to be taken. Unlike an event's fire-and-forget approach, a command can fail as it is handled. The handler will then return an error.
> Because we request an operation to be performed, command are written in imperative mood, such as `CreateFolderCommand`, and `DeletePlaylistCommand`.
### Dispatch a command
To dispatch a command, pass the object to the `Dispatch` method:
```go
cmd := &models.SendStickersCommand {
UserID: "taylor",
Count: 1,
}
if err := s.bus.Dispatch(cmd); err != nil {
if err == bus.ErrHandlerNotFound {
return nil
}
return err
}
```
> **Note:** `Dispatch` will return an error if no handler is registered for that command.
**Tip:** Browse the available commands in the `models` package.
### Handle commands
Let other parts of the application dispatch commands to a service, by registering a _command handler_:
To handle a command, register a command handler in the `Init` function.
```go
func (s *MyService) Init() error {
s.bus.AddHandler(s.SendStickers)
return nil
}
func (s *MyService) SendStickers(cmd *models.SendStickersCommand) error {
// ...
}
```
> **Note:** The handler method may return an error if unable to complete the command.
## Queries
A command handler can optionally populate the command sent to it. This pattern is commonly used to implement _queries_.
### Making a query
To make a query, dispatch the query instance just like you would a command. When the `Dispatch` method returns, the `Results` field contains the result of the query.
```go
query := &models.FindDashboardQuery{
ID: "foo",
}
if err := bus.Dispatch(query); err != nil {
return err
}
// The query now contains a result.
for _, item := range query.Results {
// ...
}
```
### Return query results
To return results for a query, set any of the fields on the query argument before returning:
```go
func (s *MyService) FindDashboard(query *models.FindDashboardQuery) error {
// ...
query.Result = dashboard
return nil
}
```

View File

@@ -1,123 +0,0 @@
# Database
Grafana uses a database to persist settings between restarts. In fact, if you don't specify one, Grafana creates a [SQLite3](https://www.sqlite.org/) database file on your local disk. This guide explains how to store and retrieve data from the database.
Grafana supports the [following databases](https://grafana.com/docs/installation/requirements/#database):
- [MySQL](https://www.mysql.com/)
- [PostgreSQL](https://www.postgresql.org/)
- [SQLite3](https://www.sqlite.org/)
Grafana uses the [XORM](https://xorm.io) framework for persisting objects to the database. For more information on how to use XORM, refer to the [documentation](https://gobook.io/read/gitea.com/xorm/manual-en-US/).
[Services](services.md) don't use XORM directly. Instead, services use the _SQL store_, a special type of service that provides an abstraction for the database layer. There are two ways of using the `sqlstore`: using `sqlstore` handlers, and using the `SQLStore` instance.
## `sqlstore` handlers
> **Deprecated:** We are deprecating `sqlstore` handlers in favor of using the `SQLStore` object directly in each service. Since most services still use the `sqlstore` handlers, we still want to explain how they work.
The `sqlstore` package allows you to register [command handlers](communication.md#handle-commands) that either store, or retrieve objects from the database. `sqlstore` handlers are similar to services:
- [Services](services.md) are command handlers that _contain business logic_.
- `sqlstore` handlers are command handlers that _access the database_.
### Register a `sqlstore` handler
> **Deprecated:** Refer to the [deprecation note for `sqlstore` handlers](#sqlstore-handlers).
To register a handler:
- Create a new file `myrepo.go` in the `sqlstore` package.
- Create a [command handler](communication.md#handle-commands).
- Register the handler in the `init` function:
```go
func init() {
bus.AddHandler("sql", DeleteDashboard)
}
func DeleteDashboard(cmd *models.DeleteDashboardCommand) error {
return inTransaction(func(sess *DBSession) error {
_, err := sess.Exec("DELETE FROM dashboards WHERE dashboard_id=?", cmd.DashboardID)
return err
})
}
```
Here, `inTransaction` is a helper function in the `sqlstore` package that provides a session, that lets you execute SQL statements.
## `SQLStore`
As opposed to a `sqlstore` handler, the `SQLStore` is a service itself. The `SQLStore` has the same responsibility however: to store and retrieve objects, to and from the database.
To use the `SQLStore`, inject it in your service struct:
```go
type MyService struct {
SQLStore *sqlstore.SQLStore `inject:""`
}
```
You can now make SQL queries in any of your [command handlers](communication.md#handle-commands) or [event listeners](communication.md#subscribe-to-an-event):
```go
func (s *MyService) DeleteDashboard(cmd *models.DeleteDashboardCommand) error {
if err := s.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
_, err := sess.Exec("DELETE FROM dashboards WHERE dashboard_id=?", cmd.DashboardID)
return err
})
}
```
For transactions, use the `WithTransactionalDbSession` method instead.
## Migrations
As Grafana evolves, it becomes necessary to create _schema migrations_ for one or more database tables.
To see all the types of migrations you can add, refer to [migrations.go](/pkg/services/sqlstore/migrator/migrations.go).
Before you add a migration, make sure that you:
- Never change a migration that has been committed and pushed to master.
- Always add new migrations, to change or undo previous migrations.
Add a migration using one of the following methods:
- Add migrations in the `migrations` package.
- Implement the `DatabaseMigrator` for the service.
**Important:** If there are previous migrations for a service, use that method. By adding migrations using both methods, you risk running migrations in the wrong order.
### Add migrations in `migrations` package
Most services have their migrations located in the [migrations](/pkg/services/sqlstore/migrations/migrations.go) package.
To add a migration:
- Open the [migrations.go](/pkg/services/sqlstore/migrations/migrations.go) file.
- In the `AddMigrations` function, find the `addXxxMigration` function for the service you want to create a migration for.
- At the end of the `addXxxMigration` function, register your migration:
[Example](https://github.com/grafana/grafana/blob/00d0640b6e778ddaca021670fe851fe00982acf2/pkg/services/sqlstore/migrations/migrations.go#L55-L70)
### Implement `DatabaseMigrator`
During initialization, SQL store queries the service registry, and runs migrations for every service that implements the [DatabaseMigrator](https://github.com/grafana/grafana/blob/44c2007498c76c2dbb48e8366b4af410f1ee1b98/pkg/registry/registry.go#L101-L106) interface.
To add a migration:
- If needed, add the `AddMigration(mg *migrator.Migrator)` method to the service.
- At the end of the `AddMigration` method, register your migration:
```go
func (s *MyService) AddMigration(mg *migrator.Migrator) {
// ...
mg.AddMigration("Add column age", NewAddColumnMigration(table, &Column{
Name: "age",
Type: migrator.DB_BigInt,
Nullable: true,
}))
}
```

View File

@@ -1,41 +0,0 @@
# Data requests
[BackendSrv](https://grafana.com/docs/grafana/latest/packages_api/runtime/backendsrv) handles all outgoing HTTP requests from Grafana. This document explains the high-level concepts used by `BackendSrv`.
## Canceling requests
This section describes how canceling requests work in Grafana. While data sources can implement their own cancellation concept, we recommend that you use the method we describe here.
A data request can take a long time to finish. During the time between when a request starts and finishes, the user can change context. For example, the user may navigate away or issue the same request again.
If we wait for canceled requests to complete, it might create unnecessary load on data sources.
Grafana uses a concept called _request cancelation_ to cancel any ongoing request that Grafana doesn't need.
#### Before Grafana 7.2
Before Grafana can cancel any data request, it has to identify that request. Grafana identifies a request using the property `requestId` [passed as options](https://github.com/grafana/grafana/blob/master/docs/sources/packages_api/runtime/backendsrvrequest.md) when you use [BackendSrv](https://grafana.com/docs/grafana/latest/packages_api/runtime/backendsrv).
The cancellation logic is as follows:
- When an ongoing request discovers that an additional request with the same `requestId` has started, then Grafana will cancel the ongoing request.
- When an ongoing request discovers that the special "cancel all requests" `requestId` was sent, then Grafana will cancel the ongoing request.
#### After Grafana 7.2
Grafana 7.2 introduced an additional way of canceling requests using [RxJs](https://github.com/ReactiveX/rxjs). To support the new cancellation functionality, the data source needs to use the new `fetch` function in [BackendSrv](https://grafana.com/docs/grafana/latest/packages_api/runtime/backendsrv).
Migrating the core data sources to the new `fetch` function [is an ongoing process that you can read about in this issue.](https://github.com/grafana/grafana/issues/27222)
## Request queue
Depending on how the web browser implements the protocol for HTTP 1.1, it will limit the number of parallel requests, lets call this limit _max_parallel_browser_request_.
Unless you have configured Grafana to use HTTP2, the browser limits parallel data requests according to the browser's implementation. For more information on how to enable HTTP2, refer to [Configuration](https://grafana.com/docs/grafana/latest/administration/configuration/#protocol).
Because there is a _max_parallel_browser_request_ limit, if some of the requests take a long time, they will block later requests and make interacting with Grafana very slow.
#### Before Grafana 7.2
Not supported.
#### After Grafana 7.2
Grafana uses a _request queue_ to process all incoming data requests in order while reserving a free "spot" for any requests to the Grafana API.
Since the first implementation of the request queue doesn't take into account what browser the user uses, the _request queue_ limit for parallel data source requests is hard-coded to 5.
> **Note:** Grafana instances [configured with HTTP2 ](https://grafana.com/docs/grafana/latest/administration/configuration/#protocol) will have a hard coded limit of 1000.

View File

@@ -1,69 +0,0 @@
# Services
A Grafana _service_ encapsulates and exposes application logic to the rest of the application, through a set of related operations.
Before a service can start communicating with the rest of Grafana, it needs to be registered in the _service registry_.
The service registry keeps track of all available services during runtime. On start-up, Grafana uses the registry to build a dependency graph of services, a _service graph_.
Even though the services in Grafana do different things, they share a number of patterns. To better understand how a service works, let's build one from scratch!
## Create a service
To start building a service:
- Create a new Go package `mysvc` in the [pkg/services](/pkg/services) directory.
- Create a `service.go` file inside your new directory.
All services need to implement the [Service](https://godoc.org/github.com/grafana/grafana/pkg/registry#Service) interface:
```go
type MyService struct {
}
func (s *MyService) Init() error {
return nil
}
```
The `Init` method is used to initialize and configure the service to make it ready to use. Services that return an error halt Grafana's startup process and cause the error to be logged as it exits.
## Register a service
Every service needs to be registered with the application for it to be included in the service graph.
To register a service, call the `registry.RegisterService` function in an `init` function within your package.
```go
func init() {
registry.RegisterService(&MyService{})
}
```
`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:
```go
import _ "github.com/grafana/grafana/pkg/services/mysvc"
```
## Dependencies
Grafana uses the [inject](https://github.com/facebookgo/inject) package to inject dependencies during runtime.
For example, to access the [bus](communication.md), add it to the `MyService` struct:
```go
type MyService struct {
Bus bus.Bus `inject:""`
}
```
You can also inject other services in the same way:
```go
type MyService struct {
Service other.Service `inject:""`
}
```
> **Note:** Any injected dependency needs to be an exported field. Any unexported fields result in a runtime error.

View File

@@ -1,107 +0,0 @@
# Create a pull request
We're excited that you're considering making a contribution to the Grafana project! This document guides you through the process of creating a [pull request](https://help.github.com/en/articles/about-pull-requests/).
## Before you begin
We know you're excited to create your first pull request. Before we get started, read these resources first:
- Learn how to start [Contributing to Grafana](/CONTRIBUTING.md).
- Make sure your code follows the relevant [style guides](/contribute/style-guides).
## Your first pull request
If this is your first time contributing to an open-source project on GitHub, make sure you read about [Creating a pull request](https://help.github.com/en/articles/creating-a-pull-request).
To increase the chance of having your pull request accepted, make sure your pull request follows these guidelines:
- Title and description matches the implementation.
- Commits within the pull request follow the [Formatting guidelines](#Formatting-guidelines).
- The pull request closes one related issue.
- The pull request contains necessary tests that verify the intended behavior.
- If your pull request has conflicts, rebase your branch onto the master branch.
If the pull request fixes a bug:
- The pull request description must include `Closes #<issue number>` or `Fixes #<issue number>`.
- To avoid regressions, the pull request should include tests that replicate the fixed bug.
### Frontend-specific guidelines
Pull requests for frontend contributions must:
- Use [Emotion](/contribute/style-guides/styling.md) for styling.
- Not increase the Angular code base.
- Not use `any` or `{}` without reason.
- Not contain large React components that could easily be split into several smaller components.
- Not contain backend calls directly from components—use actions and Redux instead.
Pull requests for Redux contributions must:
- Use the `actionCreatorFactory` and `reducerFactory` helpers instead of traditional switch statement reducers in Redux. Refer to [Redux framework](/contribute/style-guides/redux.md) for more details.
- Use `reducerTester` to test reducers. Refer to [Redux framework](/contribute/style-guides/redux.md) for more details.
- Not contain code that mutates state in reducers or thunks.
- Not contain code that accesses the reducers state slice directly. Instead, the code should use state selectors to access state.
### Backend-specific guidelines
Please refer to the [backend style guidelines](/contribute/style-guides/backend.md).
## Code review
Once you've created a pull request, the next step is to have someone review your change. A review is a learning opportunity for both the reviewer and the author of the pull request.
If you think a specific person needs to review your pull request, then you can tag them in the description or in a comment. Tag a user by typing the `@` symbol followed by their GitHub username.
We recommend that you read [How to do a code review](https://google.github.io/eng-practices/review/reviewer/) to learn more about code reviews.
## Formatting guidelines
A well-written pull request minimizes the time to get your change accepted. These guidelines help you write good commit messages and descriptions for your pull requests.
### Commit message format
Grafana uses the guidelines for commit messages outlined in [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/), with the following additions:
- Subject line must begin with the _area_ of the commit.
- A footer in the form of an optional [keyword and issue reference](https://help.github.com/en/articles/closing-issues-using-keywords).
#### Area
The area should use upper camel case, e.g. UpperCamelCase.
Prefer using one of the following areas:
- **Build:** Changes to the build system, or external dependencies.
- **Chore:** Changes that don't affect functionality.
- **Dashboard:** Changes to the Dashboard feature.
- **Docs:** Changes to documentation.
- **Explore:** Changes to the Explore feature.
- **Plugins:** Changes to any of the plugins.
For changes to data sources, the area should be the name of the data source, e.g., AzureMonitor, Graphite, and Prometheus.
For changes to panels, the area should be the name of the panel, suffixed with Panel, e.g., GraphPanel, SinglestatPanel, and TablePanel.
**Examples**
- `Build: Support publishing MSI to grafana.com`
- `Explore: Add Live option for supported data sources`
- `GraphPanel: Fix legend sorting issues`
- `Docs: Changed url to URL in all documentation files`
### Pull request titles
The Grafana team _squashes_ all commits into one when we accept a pull request. The title of the pull request becomes the subject line of the squashed commit message. We still encourage contributors to write informative commit messages, as they becomes a part of the Git commit body.
We use the pull request title when we generate change logs for releases. As such, we strive to make the title as informative as possible.
Make sure that the title for your pull request uses the same format as the subject line in the commit message.
## Configuration changes
If your PR includes configuration changes, all of the following files must be changed correspondingly:
* conf/defaults.ini
* conf/sample.ini
* docs/sources/administration/configuration.md

View File

@@ -1,253 +0,0 @@
# Developer guide
This guide helps you get started developing Grafana.
Before you begin, you might want to read [How to contribute to Grafana as a junior dev](https://medium.com/@ivanahuckova/how-to-contribute-to-grafana-as-junior-dev-c01fe3064502) by [Ivana Huckova](https://medium.com/@ivanahuckova).
## Dependencies
Make sure you have the following dependencies installed before setting up your developer environment:
- [Git](https://git-scm.com/)
- [Go](https://golang.org/dl/) (see [go.mod](../go.mod#L3) for minimum required version)
- [Node.js (Long Term Support)](https://nodejs.org)
- [Yarn](https://yarnpkg.com)
### macOS
We recommend using [Homebrew](https://brew.sh/) for installing any missing dependencies:
```
brew install git
brew install go
brew install node@14
npm install -g yarn
```
### Windows
If you are running Grafana on Windows 10, we recommend installing the Windows Subsystem for Linux (WSL). For installation instructions, refer to the [Microsoft WSL Installation Guide](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
## Download Grafana
We recommend using the Git command-line interface 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.
## Build Grafana
Grafana consists of two components; the _frontend_, and the _backend_.
### Frontend
Before we can build the frontend assets, we need to install the dependencies:
```
yarn install --pure-lockfile
```
After the command has finished, we can start building our source code:
```
yarn start
```
Once `yarn start` has built the assets, it will continue to do so whenever any of the files change. This means you don't have to manually build the assets every time you change the code.
Next, we'll build the web server that will serve the frontend assets we just built.
### Backend
Build and run the backend by running `make run` in the root directory of the repository. This command compiles the Go source code and starts a web server.
> Are you having problems with [too many open files](#troubleshooting)?
By default, you can access the web server at `http://localhost:3000/`.
Log in using the default credentials:
| username | password |
| -------- | -------- |
| `admin` | `admin` |
When you log in for the first time, Grafana asks you to change your password.
#### Building on Windows
The Grafana backend includes SQLite which requires GCC to compile. So in order to compile Grafana on Windows you need to install GCC. We recommend [TDM-GCC](http://tdm-gcc.tdragon.net/download). Eventually, if you use [Scoop](https://scoop.sh), you can install GCC through that.
You can simply build the back-end as follows: `go run build.go build`. The Grafana binaries will be in bin\\windows-amd64.
Alternately, if you wish to use the `make` command, install [Make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm) and use it in a Unix shell (f.ex. Git Bash).
## Test Grafana
The test suite consists of three types of tests: _Frontend tests_, _backend tests_, and _end-to-end tests_.
### Run frontend tests
We use [jest](https://jestjs.io/) for our frontend tests. Run them using Yarn:
```
yarn test
```
### Run backend tests
If you're developing for the backend, run the tests with the standard Go tool:
```
go test -v ./pkg/...
```
#### On Windows
Running the backend tests on Windows currently needs some tweaking, so use the build.go script:
```
go run build.go test
```
### 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).
To run the tests:
```
yarn e2e
```
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:
```
BASE_URL=http://localhost:3333 yarn e2e
```
To follow the tests in the browser while they're running, use the `yarn e2e:debug`.
```
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
```
## Configure Grafana for development
The default configuration, `defaults.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.
Enable the development mode, by adding the following line in your `custom.ini`:
```
app_mode = development
```
### Add data sources
By now, you should be able to build and test a change you've made to the Grafana source code. In most cases, you need to add at least one data source to verify the change.
To set up data sources for your development environment, go to the [devenv](/devenv) directory in the Grafana repository:
```
cd devenv
```
Run the `setup.sh` script to set up a set of data sources and dashboards in your local Grafana instance. The script creates a set of data sources called **gdev-\<type\>**, and a set of dashboards located in a folder called **gdev dashboards**.
Some of the data sources require databases to run in the background.
Installing and configuring databases can be a tricky business. Grafana uses [Docker](https://docker.com) to make the task of setting up databases a little easier. Make sure you [install Docker](https://docs.docker.com/docker-for-mac/install/) before proceeding to the next step.
In the root directory of your Grafana repository, run the following command:
```
make devenv sources=influxdb,loki
```
The script generates a Docker Compose file with the databases you specify as `sources`, and runs them in the background.
See the repository for all the [available data sources](/devenv/docker/blocks). Note that some data sources have specific Docker images for macOS, e.g. `prometheus_mac`.
## Build a Docker image
To build a Docker image, run:
```
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:
1. Build the frontend: `go run build.go build-frontend`.
1. Build the Docker image: `make build-docker-dev`.
**Note:** If you are using Docker for macOS, be sure to set the memory limit to be larger than 2 GiB. Otherwise, `grunt build` may fail. The memory limit settings are available under **Docker Desktop** -> **Preferences** -> **Advanced**.
## Troubleshooting
Are you having issues with setting up your environment? Here are some tips that might help.
### 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.
To see how many open files are allowed, run:
```
ulimit -a
```
To change the number of open files allowed, run:
```
ulimit -S -n 2048
```
The number of files needed may be different on your environment. To determine the number of open files needed by `make run`, run:
```
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.
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
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
```
Your command shell should read the initialization file in question every time it gets started, and apply your `ulimit` command.
For some people, typically using the bash shell, ulimit fails with an error similar to the following:
```
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.
## Next steps
- Read our [style guides](/contribute/style-guides).
- Learn how to [Create a pull request](/contribute/create-pull-request.md).
- Read [How to contribute to Grafana as a junior dev](https://medium.com/@ivanahuckova/how-to-contribute-to-grafana-as-junior-dev-c01fe3064502) by [Ivana Huckova](https://medium.com/@ivanahuckova).
- Read about the [architecture](architecture).

View File

@@ -1,42 +0,0 @@
# Contributing to documentation
This documents guides you through the process of contributing to the Grafana documentation. Make sure you've read the guide for [Contributing to Grafana](/CONTRIBUTING.md).
## Your first contribution
If youre unsure about where to start, check out some of our [open docs issues](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3Atype%2Fdocs).
Sometimes it can be difficult to understand an issue when you're just getting started. Refer to this list of [beginner-friendly issues](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3Atype%2Fdocs+label%3A"beginner+friendly") for tasks suitable for first-time contributors.
When youve found an issue you want to work on, please comment on the issue to let other people know you intend to work on it.
If you encounter any misspellings or violations to the style guide, please let us know by submitting an issue (or just fix them if they are minor changes).
On every page in the [documentation](https://grafana.com/docs/) are two links in the upper right corner:
- **Edit this page** takes you directly to the file on GitHub where you can contribute a fix.
- **Request doc changes** prepares an issue on GitHub with relevant information already filled in.
## Join our community
For general discussions on documentation, youre welcome to join the `#docs` channel on our [public Grafana Slack](http://slack.raintank.io) team.
## Style and formatting
All Grafana documentation is written using [Markdown](https://en.wikipedia.org/wiki/Markdown), and can be found in the [docs](/docs) directory in the [Grafana GitHub repository](https://github.com/grafana/grafana). The [documentation website](https://grafana.com/docs) is generated with [Hugo](https://gohugo.io) which uses [Blackfriday](https://github.com/russross/blackfriday) as its Markdown rendering engine.
### Documentation structure
The Grafana documentation is organized into topics, called _sections_. You can take a look at the current build at [grafana.com/docs/](https://grafana.com/docs/).
Each top-level section is located under the [docs/sources](/docs/sources) directory. Subsections are added by creating a subdirectory in the directory of the parent section.
For each section, an `_index.md` file provides an overview of the topic.
### Style guide
Refer to the [Documentation style guide](style-guides/documentation-style-guide.md) for information about Grafana style, word choice, and grammar conventions.
### Spelling
The [codespell](https://github.com/codespell-project/codespell) tool is run for every change to catch common misspellings.

View File

@@ -1,17 +0,0 @@
# Grafana technical terminology
<!-- Keep terms in alphabetical order: -->
This document defines technical terms used in Grafana.
## TLS/SSL
The acronyms [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security) (Transport Layer Security and
[SSL](https://en.wikipedia.org/wiki/SSL) (Secure Socket Layer) are both used to describe the HTTPS security layer,
and are in practice synonymous. However, TLS is considered the current name for the technology, and SSL is considered
[deprecated](https://tools.ietf.org/html/rfc7568).
As such, while both terms are in use (also in our codebase) and are indeed interchangeable, TLS is the preferred term.
That said however, we have at Grafana Labs decided to use both acronyms in combination when referring to this type of
technology, i.e. _TLS/SSL_. This is in order to not confuse those who may not be aware of them being synonymous,
and SSL still being so prevalent in common discourse.

View File

@@ -1,100 +0,0 @@
# 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.
Unless stated otherwise, use the guidelines listed in the following articles:
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
- [Go: Best Practices for Production Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style)
## Linting and formatting
To ensure consistency across the Go codebase, we require all code to pass a number of linter checks.
We use the standard following linters:
- [gofmt](https://golang.org/cmd/gofmt/)
- [golint](https://github.com/golang/lint)
- [go vet](https://golang.org/cmd/vet/)
In addition to the standard linters, we also use:
- [revive](https://revive.run/) with a [custom config](https://github.com/grafana/grafana/blob/master/conf/revive.toml)
- [GolangCI-Lint](https://github.com/golangci/golangci-lint)
- [gosec](https://github.com/securego/gosec)
To run all linters, use the `lint-go` Makefile target:
```bash
make lint-go
```
## Testing
We value clean and readable code, that is loosely coupled and covered by unit tests. This makes it easier to collaborate and maintain the code.
Tests must use the standard library, `testing`. For assertions, prefer using [testify](https://github.com/stretchr/testify).
The majority of our tests uses [GoConvey](http://goconvey.co/) but that's something we want to avoid going forward.
In the `sqlstore` package we do database operations in tests and while some might say that's not suited for unit tests. We think they are fast enough and provide a lot of value.
### Assertions
Use respectively [`assert.*`](https://github.com/stretchr/testify#assert-package) functions to make assertions that
should _not_ halt the test ("soft checks") and [`require.*`](https://github.com/stretchr/testify#require-package)
functions to make assertions that _should_ halt the test ("hard checks"). Typically you want to use the latter type of
check to assert that errors have or have not happened, since continuing the test after such an assertion fails is
chaotic (the system under test will be in an undefined state) and you'll often have segfaults in practice.
### Sub-tests
Use [`t.Run`](https://golang.org/pkg/testing/#T.Run) to group sub-test cases, since it allows common setup and teardown
code, plus lets you run each test case in isolation when debugging. Don't use `t.Run` to e.g. group assertions.
### Cleanup
Use [`t.Cleanup`](https://golang.org/pkg/testing/#T.Cleanup) to clean up resources in tests. It's a less fragile choice than `defer`, since it's independent of which
function you call it in. It will always execute after the test is over in reverse call order (last `t.Cleanup` first, same as `defer`).
## Globals
As a general rule of thumb, avoid using global variables, since they make the code difficult to maintain and reason
about, and to write tests for. The Grafana codebase currently does use a lot of global variables, especially when
it comes to configuration, but that is a problem we're trying to solve.
## Pointers
In general, use value types and only reach for pointers when there's a real need. The reason being that pointers
increase the risk of bugs, since a pointer can be nil and dereferencing a nil pointer leads to a panic (AKA segfault).
Valid reasons to use a pointer include (but not necessarily limited to):
* You might need to pass a modifiable argument to a function
* Copying an object might incur a performance hit (benchmark to check your assumptions, copying is often faster than
allocating heap memory)
* You might *need* `nil` to tell if a variable isn't set, although usually it's better to use the type's zero
value to tell instead
## Database
In database related code, we follow certain patterns.
### Foreign keys
While they can be useful, we don't generally use foreign key constraints in Grafana, for historical and
technical reasons. See this [comment](https://github.com/grafana/grafana/issues/3269#issuecomment-383328548) by Torkel
for context.
### Unique columns
If a column, or column combination, should be unique, add a corresponding uniqueness constraint through a migration.
## JSON
The simplejson package is used a lot throughout the backend codebase, but it's legacy, so if at all possible
avoid using it in new code. Use [json-iterator](https://github.com/json-iterator/go) instead, which is a more performant
drop-in alternative to the standard [encoding/json](https://golang.org/pkg/encoding/json/) package. While encoding/json
is a fine choice, profiling shows that json-iterator may be 3-4 times more efficient for encoding. We haven't profiled
its parsing performance yet, but according to json-iterator's own benchmarks, it appears even more superior in this
department.

View File

@@ -1,209 +0,0 @@
# Guidelines for code comments in grafana-* packages
This document aims to give you some recommendation on how to add code comments to the exported code in the grafana packages.
## Table of Contents
1. [Add package description](#add-package-description)
1. [Set stability of an API](#set-stability-of-an-api)
1. [Deprecate an API](#deprecate-an-api)
1. [Specify parameters](#specify-parameters)
1. [Set return values](#set-return-values)
____
## Add package description
Each package has an overview explaining the overall responsibility and usage of the package.
You can document this description with [`@packageDocumentation`](https://api-extractor.com/pages/tsdoc/tag_packagedocumentation/) tag.
Add this tag to the `<packageRoot>/src/index.ts` entry file to have one place for the package description.
## Set stability of an API
All `exported` apis from the package should have a release tag to indicate its stability.
- [`@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.
- [`@internal`](https://api-extractor.com/pages/tsdoc/tag_internal/) - for internal use only.
### Main stability of APIs
Add a tag to mark the stability of the whole exported `class/interface/function/type` etc.
Please place the `release tag` at the bottom of the comment to make it consistent among files and easier to read.
**Do:**
```typescript
/**
* Will help to create DataFrame objects and handle
* the heavy lifting of creating a complex object.
*
* @example
* ```typescript
* const dataFrame = factory.create();
* ```
*
* @public
**/
export class DataFrameFactory {
create(): DataFrame { }
}
```
**Don't**
```typescript
/**
* Will help to create DataFrame objects and handle
* the heavy lifting of creating a complex object.
*
* @public
* @example
* ```typescript
* const dataFrame = factory.create();
* ```
**/
export class DataFrameFactory {
create(): DataFrame { }
}
```
### Partial stability of APIs
Add the main stability of the API at the top according to [Main stability of API](#main-stability-of-api).
Then override the non-stable parts of the API with the proper [release tag](#release-tags). This should also be place at the bottom of the comment block.
**Do:**
```typescript
/**
* Will help to create DataFrame objects and handle
* the heavy lifting of creating a complex object.
*
* @example
* ```typescript
* const dataFrame = factory.create();
* ```
*
* @public
**/
export class DataFrameFactory {
create(): DataFrame { }
/**
* @beta
**/
createMany(): DataFrames[] {}
}
```
**Don't**
```typescript
/**
* Will help to create DataFrame objects and handle
* the heavy lifting of creating a complex object.
*
* @example
* ```typescript
* const dataFrame = factory.create();
* ```
**/
export class DataFrameFactory {
/**
* @public
**/
create(): DataFrame { }
/**
* @beta
**/
createMany(): DataFrame[] {}
}
```
## Deprecate an API
If you want to mark an API as deprecated to signal that this API will be removed in the future, then add the [`@deprecated`](https://api-extractor.com/pages/tsdoc/tag_deprecated/) tag.
If applicable add a reason why the API is deprecated directly after the `@deprecated tag`.
## Specify parameters
If you want to specify the possible parameters that can be passed to an API, then add the [`@param`](https://api-extractor.com/pages/tsdoc/tag_param/) tag.
This attribute can be skipped if the type provided by `typescript` and the function comment or the function name is enough to explain what the parameters are.
**Do:**
```typescript
/**
* Will help to create a resource resolver depending
* on the current execution context.
*
* @param context - The current execution context.
* @returns FileResolver if executed on the server otherwise a HttpResolver.
* @public
**/
export const factory = (context: Context): IResolver => {
if (context.isServer) {
return new FileResolver();
}
return new HttpResolver();
}
```
**Don't**
```typescript
/**
* Will compare two numbers to see if they are equal to each others.
*
* @param x - The first number
* @param y - The second number
* @public
**/
export const isEqual = (x: number, y: number): boolean => {
return x === y;
}
```
## Set return values
If you want to specify the return value from a function you can use the [`@returns`](https://api-extractor.com/pages/tsdoc/tag_returns/) tag.
This attribute can be skipped if the type provided by `typescript` and the function comment or the function name is enough to explain what the function returns.
**Do:**
```typescript
/**
* Will help to create a resource resolver depending
* on the current execution context.
*
* @param context - The current execution context.
* @returns FileResolver if executed on the server otherwise a HttpResolver.
* @public
**/
export const factory = (context: Context): IResolver => {
if (context.isServer) {
return new FileResolver();
}
return new HttpResolver();
}
```
**Don't**
```typescript
/**
* Will compare two numbers to see if they are equal to each others.
*
* @returns true if values are equal
* @public
**/
export const isEqual = (x: number, y: number): boolean => {
return x === y;
}
```

View File

@@ -1,151 +0,0 @@
# 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.
## Headers
In Markdown, the number of "#" symbols creates different heading levels, similar to HTML heading levels:
**Example**
- \# 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.
**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.
**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.
\[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.
## Block quotes
Include block quotes inside text using right-facing arrows:
**Example**
> Any important information
> about emoji can be separated into
> a blockquote.
## 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:
```
function testNum(a) {
if (a > 0) {
return "positive";
} else {
return "NOT positive";
}
}
```
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) {
if (a > 0) {
return "positive";
} else {
return "NOT positive";
}
}
```
## 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 "|".
**Example**
Heading one | Heading two
\------------|------------
Cell one data| Cell two data
Will publish as:
Heading one | Heading two
------------|------------
Cell one data| Cell two data
## Lists
### Numbered lists
To avoid inconsistent list numbering, use repetitive list numbering:
\1. First
\1. Second
\1. Third
The list above will always display as:
1. First
2. Second
3. Third
### Unordered lists
Build a list of points - an unordered or unnumbered list - by using "\-" (hyphen) characters.
**Example**
- First
- Another item
- The last list item
## Images
_Do not_ use image shortcodes at this time.
Include images in a document using the following syntax:
```
![Alt text](link to image, starting with /img/docs/ if it is to an internal image "Title of image in sentence case")
```
> **Note:** Alt text does not appear when the user hovers the mouse over the image, but title text does.
**Examples:**
- \!\[Grafana logo](/link/to/grafanalogo/logo.png)
- \!\[Example](/img/docs/folder_name/alert_test_rule.png)
This follows the format of "!", alt text wrapped in "[]" and the link URL wrapped in "()".
You can also use HTML such as the following:
```
<img src="example.png"
alt="Example image"
style="float: left; margin-right: 5px;" />
```
In most cases, use the markdown syntax rather than the HTML syntax. Only use the HTML if you need to change the image in ways unsupported by Markdown.
## Comments
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 "()".

View File

@@ -1,316 +0,0 @@
# Documentation style guide
This style guide applies to all documentation created for Grafana products.
For information about how to write technical documentation, refer to the following resources:
* [Google Technical Writing courses](https://developers.google.com/tech-writing)
* [Divio documentation system](https://documentation.divio.com/)
* [Vue writing principles](https://v3.vuejs.org/guide/contributing/writing-guide.html#principles)
## Contributing
The *Documentation style guide* is a living document. Add to it whenever a style decision is made or a question is answered regarding style, grammar, or word choice.
## Published guides
For all items that are not covered in this guide, refer to the [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/) and the [Chicago Manual of Style](https://www.chicagomanualofstyle.org/home.html).
## Spelling
To catch common misspellings, the [codespell](https://github.com/codespell-project/codespell) tool is run for every change.
## Inclusive language
Avoid using charged language.
### Allowing and blocking
When referring to _allowing_ or _blocking_ content or traffic, use a form of _allow_ or _block_:
- (noun) _allowlist_ or _blocklist_
- (verb) _allow_ or _block_
Example: _To **allow** outgoing traffic, add the IP to the **allowlist**._
Avoid _whitelist_ or _blacklist_.
### Primary and secondary
To describe relationships between nodes or processes, there are several options:
- Use _primary_, _main_, or _parent_, instead of _master_.
- Use _secondary_, _replica_, or _child_, instead of _slave_.
Avoid _master_ or _slave_.
## Grafana-specific style
The following guidelines are specific to Grafana documentation. For the most part, these are *guidelines* are not rigid rules. If you have questions, ask in the #docs channel of Grafana Slack.
### General
- Use active voice:
- Active: Grafana displays the heatmap visualization.
- Passive: The heatmap visualization is displayed.
- Write directly to the reader:
- Use: "After you create a dashboard, you can add a panel to it."
- Avoid: "After you create a dashboard, it is possible to add a panel to it."
- Write in the imperative second person:
- "Click the panel."
- "Close the window."
- Write in present tense:
- Use: "The panel opens."
- Avoid: "The panel will open."
- 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 jargon or slang.
- Do not use two spaces after a period; use one space after a sentence.
- Remove any extra space characters at the end of a paragraph.
- Aim for your sentences to be fewer than 25 words. Instead, use smaller complete phrases or change the format, such as using a list.
- Aim for paragraphs to be three sentences or fewer. Make the text more concise, use more headings, or both.
### File naming conventions
- Files that are displayed in the help system should have names that are all lowercase, no spaces. Use hyphens instead of spaces. Example: glossary.md
- Documentation file names should match the title. **Note:** This only applies to new files at this time. Do not change the names of older files unless directed to do so.
- Internal reference file names should be all uppercase except the file extension. Example: CONTRIBUTING.md
- Image file names should be descriptive and unique. Also, add the software version number that the image applies to or the screenshot was taken in. Example: share-dashboard-link-7-3.png
### Headings
- Write headings in sentence case, not title case.
- This is sentence case
- This is Title Case
- 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
#### Heading don'ts
- Avoid stacked headings, which is 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, h2 is a good order. Do not go h1, h2, h3, h2, h3, h2.
- Avoid using hyphens in headings.
- Do not include parenthetical words like (Important!) in headings.
#### Step-by-step headings
In most cases, headings should not be numbered steps.
However, sometimes we need to use headings as numbered steps. This is mostly in cases where each step is complex or a series of other procedures. For example, in [Getting started with Grafana and Prometheus](https://grafana.com/docs/grafana/latest/getting-started/getting-started-prometheus/).
If that is the case, then use the following format for headings:
##### Step 1. Install the software
##### Step 2. Run the software
### 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.
- _Do not_ use image shortcodes. Follow the guidance in the [Grafana markdown guide](https://github.com/grafana/grafana/blob/master/contribute/style-guides/documentation-markdown-guide.md#images).
- Markdown image links are preferred. Only use the HTML image links if you need to style the image in ways unsupported in Markdown.
- When you name a file, follow the [file naming conventions](#file-naming-conventions). Example: image-name-7-3.png
### 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"
- 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.
- 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.
#### Git, GitHub
Git is always capitalized, unless part of a code block. GitHub is the correct spelling and capitalization.
#### Integrations
In general, "integration" is not capitalized. Only capitalize it if it is capitalized in the UI or part of a proper noun, like the name of a specific integration.
The first letter of the name of an integration is always capitalized, even if the original named source is lowercase.
**Examples:**
- MySQL Integration
- CockroachDB Integration
- Etcd Integration
- I installed an integration on my local Grafana.
#### Kubernetes objects
Capitalize Kubernetes objects such as Job, Pod, and StatefulSet when it is clear you are specifically talking about them and not generic jobs, pods, or whatever.
Introduce the object as "Kubernetes XX" on the first usage, then just the object in subsequent uses.
**Example:**
Create the Kubernetes Job and check the logs to retrieve the generated token:
The Job requires the token be submitted as …
### Links and references
When referencing another document, use "Refer to" rather than alternatives such as "See" or "Check out."
Always give the reader some idea of what to expect in the reference. Avoid blind references, such as, "Refer to [this file](link)."
When possible, use the exact title of the page or section you are linking to as the link text.
**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 add `$` before commands. Make it easy for users to copy and paste commands.
- **Right:** `sudo yum install grafana`
- **Wrong:** `$ sudo yum install grafana`
- Include `sudo` before commands that require `sudo` to work.
For terminal examples and Grafana configuration, use a `bash` code block:
```bash
sudo yum install grafana
```
For HTTP request/response, use an `http` code block:
```http
GET /api/dashboards/id/1/permissions HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
```
### Word usage
Grafana products has some words, abbreviations, and terms particular to the Grafana discourse community.
#### changelog
One word, not two.
**Example**
- Read the full changelog.
**Exception:**
- When referring to the file containing the official changelog, use the filename: `CHANGELOG.md`.
#### checkout, check out
Two words if used as a verb, one word if used as a noun.
**Examples**
- 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.
#### 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.
#### intro, introduction
"Introduction" is the preferred word. Use "intro" if there are space constraints (like on the side menu) or you are specifically trying for a less formal, more conversational tone.
#### metadata
One word, not two.
#### mixin
One word, not two. Also, not hyphenated.
#### 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 it is used as a noun. For example: _Open source is the best way to develop software._
#### setup, set up
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.
### node_exporter, windows_exporter
When referencing the Prometheus data source exporters, always use "node_exporter" and "windows_exporter" when referring to those tools.
**Correct:** node_exporter, windows_exporter
**Incorrect:** Node Exporter, node exporter, Windows Exporter, Windows exporter, windows exporter.
#### web server
Two words, not one.
**Correct:** webserver
**Incorrect:** web server
### MS SQL Server
Always use "MS SQL" when referring to MS SQL Server application.
Incorrect UI spellings will be corrected in a later version of Grafana.

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,162 +0,0 @@
# End-to-End tests
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.
Important notes:
- 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).
## Framework structure
Inspired by 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:
```jsx
<input
className="gf-form-input login-form-input"
type="text"
/>
```
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):
```jsx
<input
aria-label="Username input field"
className="gf-form-input login-form-input"
type="text"
/>
```
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:
```typescript
export const Login = {
// Called via `Login.visit()`
url: '/login',
// Called via `Login.username()`
username: 'Username input field',
};
```
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.
```typescript
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.
```jsx
import { selectors } from '@grafana/e2e-selectors';
<input
aria-label={selectors.pages.Login.username}
className="gf-form-input login-form-input"
type="text"
/>
```
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).
- 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
describe('Login test', () => {
it('passes', () => {
e2e.pages.Login.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.Login.username()
.should('be.visible')
.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.
```jsx
<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>
</a>
</li>
))}
</ul>
```
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.
Just as before we need to add the `DataSources` page to the exported const `Pages` in `packages/grafana-e2e-selectors/src/selectors/pages.ts`.
The next step is to use the `dataSources` selector function as in our example below:
```jsx
<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}
</div>
</a>
</li>
))}
</ul>
```
When this list is rendered with the data sources with names `A`, `B` and `C` ,the resulting HTML would look like:
```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>
```
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:
```typescript
describe('List test', () => {
it('clicks 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();
});
});
```

View File

@@ -1,349 +0,0 @@
# Frontend Style Guide
Generally we follow the Airbnb [React Style Guide](https://github.com/airbnb/javascript/tree/master/react).
## Table of Contents
- [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)
- [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
- Try to keep files small and focused.
- Break large components up into sub-components.
- Use spaces for indentation.
### Naming conventions
#### Use `PascalCase` for:
##### Typescript class names
```typescript
// bad
class dataLink {
//...
}
// good
class DataLink {
//...
}
```
##### Types and interfaces
```
// bad
interface buttonProps {
//...
}
// bad
interface button_props {
//...
}
// bad
interface IButtonProps {
//...
}
// good
interface ButtonProps {
//...
}
// bad
type requestInfo = ...
// bad
type request_info = ...
// good
type RequestInfo = ...
```
##### Enums
```
// bad
enum buttonVariant {
//...
}
// good
enum ButtonVariant {
//...
}
```
#### Use `camelCase` for:
##### Functions
```typescript
// bad
const CalculatePercentage = () => { ... }
// bad
const calculate_percentage = () => { ... }
// good
const calculatePercentage = () => { ... }
```
##### Methods
```typescript
class DateCalculator {
// bad
CalculateTimeRange () {...}
}
class DateCalculator {
// bad
calculate_time_range () {...}
}
class DateCalculator {
// good
calculateTimeRange () {...}
}
```
##### Variables
```typescript
// bad
const QueryTargets = [];
// bad
const query_targets = [];
// good
const queryTargets = [];
```
##### React state and properties
```typescript
interface ModalState {
// bad
IsActive: boolean;
// bad
is_active: boolean;
// good
isActive: boolean;
}
```
##### Emotion class names
```typescript
const getStyles = = () => ({
// bad
ElementWrapper: css`...`,
// bad
["element-wrapper"]: css`...`,
// good
elementWrapper: css`...`,
});
```
#### Use `ALL_CAPS` for constants.
```typescript
// bad
const constantValue = "This string won't change";
// bad
const constant_value = "This string won't change";
// good
const CONSTANT_VALUE = "This string won't change";
```
#### Use [BEM](http://getbem.com/) convention for SASS styles.
_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:
- When the primary export is a class or React component, use PascalCase.
- When the primary export is a function, use camelCase.
For files exporting multiple utility functions, use the name that describes the responsibility of grouped utilities. For example, a file exporting math utilities should be named `math.ts`.
- Use `constants.ts` for files exporting constants.
- Use `actions.ts` for files exporting Redux actions.
- Use `reducers.ts` Redux reducers.
- Use `*.test.ts(x)` for test files.
### Code organization
Organize your code in a directory that encloses feature code:
- Put Redux state and domain logic code in `state` directory (i.e. `features/my-feature/state/actions.ts`).
- Put React components in `components` directory (i.e. `features/my-feature/components/ButtonPeopleDreamOf.tsx`).
- Put test files next to the test subject.
- Put containers (pages) in feature root (i.e. `features/my-feature/DashboardPage.tsx`).
- Subcomponents can live in the component folders. Small component do not need their own folder.
- Component SASS styles should live in the same folder as component code.
For code that needs to be used by external plugin:
- Put components and types in `@grafana/ui`.
- Put data models and data utilities in `@grafana/data`.
- Put runtime services interfaces in `@grafana/runtime`.
#### Exports
- Use named exports for all code you want to export from a file.
- Use declaration exports (i.e. `export const foo = ...`).
- Export only the code that is meant to be used outside the module.
### Comments
- Use [TSDoc](https://github.com/microsoft/tsdoc) comments to document your code.
- Use [react-docgen](https://github.com/reactjs/react-docgen) comments (`/** ... */`) for props documentation.
- Use inline comments for comments inside functions, classes etc.
- Please try to follow the [code comment guidelines](./code-comments.md) when adding comments.
### Linting
Linting is performed using [@grafana/eslint-config](https://github.com/grafana/eslint-config-grafana).
## React
Use the following conventions when implementing React components:
### Props
##### Name callback props and handlers with an "on" prefix.
```tsx
// bad
handleChange = () => {
};
render() {
return (
<MyComponent changed={this.handleChange} />
);
}
// good
onChange = () => {
};
render() {
return (
<MyComponent onChange={this.onChange} />
);
}
```
##### React Component definitions
```jsx
// bad
export class YourClass extends PureComponent { ... }
// good
export class YourClass extends PureComponent<{},{}> { ... }
```
##### React Component constructor
```typescript
// bad
constructor(props) {...}
// good
constructor(props: Props) {...}
```
##### React Component defaultProps
```typescript
// bad
static defaultProps = { ... }
// good
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 `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

@@ -1,82 +0,0 @@
# Redux framework
Grafana uses [Redux Toolkit](https://redux-toolkit.js.org/) to handle Redux boilerplate code.
> Some of our Reducers are used by Angular and therefore state is to be considered as mutable for those reducers.
## Test functionality
### reducerTester
Fluent API that simplifies the testing of reducers
#### Usage
```typescript
reducerTester()
.givenReducer(someReducer, initialState)
.whenActionIsDispatched(someAction('reducer tests'))
.thenStateShouldEqual({ ...initialState, data: 'reducer tests' });
```
#### Complex usage
Sometimes you encounter a `resulting state` that contains properties that are hard to compare, such as `Dates`, but you still want to compare that other props in state are correct.
Then you can use `thenStatePredicateShouldEqual` function on `reducerTester` that will return the `resulting state` so that you can expect upon individual properties..
```typescript
reducerTester()
.givenReducer(someReducer, initialState)
.whenActionIsDispatched(someAction('reducer tests'))
.thenStatePredicateShouldEqual(resultingState => {
expect(resultingState.data).toEqual('reducer tests');
return true;
});
```
### thunkTester
Fluent API that simplifies the testing of thunks.
#### Usage
```typescript
const dispatchedActions = await thunkTester(initialState)
.givenThunk(someThunk)
.whenThunkIsDispatched(arg1, arg2, arg3);
expect(dispatchedActions).toEqual([someAction('reducer tests')]);
```
## Typing of connected props
It is possible to infer connected props automatically from `mapStateToProps` and `mapDispatchToProps` using a helper type `ConnectedProps` from Redux. For this to work the `connect` call has to be split into two parts.
```typescript
import { connect, ConnectedProps } from 'react-redux'
const mapStateToProps = (state: StoreState) => {
return {
location: state.location,
initDone: state.panelEditor.initDone,
uiState: state.panelEditor.ui,
};
};
const mapDispatchToProps = {
updateLocation,
initPanelEditor,
panelEditorCleanUp,
setDiscardChanges,
updatePanelEditorUIState,
updateTimeZoneForSession,
};
const connector = connect(mapStateToProps, mapDispatchToProps);
type Props = OwnProps & ConnectedProps<typeof connector>;
class PanelEditorUnconnected extends PureComponent<Props> {};
export const PanelEditor = connector(PanelEditorUnconnected);
```
For more examples, refer to the [Redux docs](https://react-redux.js.org/using-react-redux/static-typing#inferring-the-connected-props-automatically).

View File

@@ -1,209 +0,0 @@
# Storybook
[Storybook](https://storybook.js.org/) is a tool which we use to manage our design system and the components which are a part of it. Storybook consists of _stories:_ each story represents a component and a case in which it is used. To show a wide variety of use cases is good both documentation wise and for troubleshooting -- it might be possible to reproduce a bug for an edge case in a story.
Storybook is:
- A good way to publish our design system with its implementations
- Used as a tool for documentation
- Used for debugging and displaying edge cases
## How to create stories
Stories for a component should be placed next to the component file. The Storybook file requires the same name as the component file. For example, a story for `SomeComponent.tsx` will have the file name `SomeComponent.story.tsx`. If a story should be internal, not visible in production, name the file `SomeComponent.story.internal.tsx`.
### Writing stories
When writing stories, we use the [CSF format](https://storybook.js.org/docs/formats/component-story-format/). For more in-depth information on writing stories, see [Storybooks documentation on writing stories](https://storybook.js.org/docs/basics/writing-stories/).
With the CSF format, the default export defines some general information about the stories in the file:
- `title`: Where the component is going to live in the hierarchy
- `decorators`: A list which can contain wrappers or provide context, such as theming
```jsx
// In MyComponent.story.tsx
import MyComponent from './MyComponent';
export default {
title: 'General/MyComponent',
component: MyComponent,
decorators: [ ... ],
}
```
When it comes to writing the actual stories, you continue in the same file with named exports. The exports are turned into the story name.
```jsx
// Will produce a story name “some story”
export const someStory = () => <MyComponent />;
```
If you want to write cover cases with different values for props, then using knobs is usually enough. You dont need to create a new story. This will be covered further down.
### Categorization
We currently have these categories:
- **Docs Overview** - Guidelines and information regarding the design system
- **Forms** - Components commonly used in forms such as different kind of inputs
- **General** - Components which can be used in a lot of different places
- **Visualizations** - Data visualizations
- **Panel** - Components belonging to panels and panel editors
## Writing MDX documentation
An MDX file is basically a markdown file with the possibility to add jsx. These files are used by Storybook to create a “docs” tab.
### Link the MDX file to a components stories
To link a components stories with an MDX file you have to do this:
```jsx
// In TabsBar.story.tsx
import { TabsBar } from './TabsBar';
// Import the MDX file
import mdx from './TabsBar.mdx';
export default {
title: 'General/Tabs/TabsBar',
component: TabsBar,
parameters: {
docs: {
// This is the reference required for the MDX file
page: mdx,
},
},
};
```
### MDX file structure
There are some things that the MDX file should contain:
- When and why the component should be used
- Best practices - dos and donts for the component
- Usage examples with code. It is possible to use the `Preview` element to show live examples in MDX
- Props table. This can be generated by doing the following:
```jsx
// In MyComponent.mdx
import { Props } from '@storybook/addon-docs/blocks';
import { MyComponent } from './MyComponent';
<Props of={MyComponent} />;
```
### MDX file without a relationship to a component
An MDX file can exist by itself without any connection to a story. This can be good for writing things such as a general guidelines page. Two things are required for this to work:
- The file needs to be named `*.story.mdx`
- A `Meta` tag must exist that says where in the hierarchy the component lives. It can look like this:
```jsx
<Meta title="Docs Overview/Color Palettes"/>
# Guidelines for using colors
...
```
You can add parameters to the Meta tag. This example shows how to hide the tools:
```jsx
<Meta title="Docs Overview/Color Palettes" parameters={{ options: { isToolshown: false }}}/>
# Guidelines for using colors
...
```
## Documenting component properties
A quick way to get an overview of what a component does is by looking at its properties. That's why it is important that we document these in a good way.
### Comments
When writing the props interface for a component, it is possible to add a comment to that specific property, which will end up in the Props table in the MDX file. The comments are generated by [react-docgen](https://github.com/reactjs/react-docgen) and are formatted by writing `/** */`.
```jsx
interface MyProps {
/** Sets the initial values, which are overridden when the query returns a value*/
defaultValues: Array<T>;
}
```
### Controls
The [controls addon](https://storybook.js.org/docs/react/essentials/controls) provides a way to interact with a component's properties dynamically and requires much less code than knobs. We're deprecating knobs in favor of using controls.
#### Migrating a story from Knobs to Controls
As a test, we migrated the [button story](https://github.com/grafana/grafana/blob/master/packages/grafana-ui/src/components/Button/Button.story.tsx). Here's the guide on how to migrate a story to controls.
1. Remove the `@storybook/addon-knobs` dependency.
2. Import the Story type from `@storybook/react`
`import { Story } from @storybook/react`
3. Import the props interface from the component you're working on (these must be exported in the component).
`import { Props } from './Component'`
4. Add the Story type to all stories in the file, then replace the props sent to the component
and remove any knobs.
Before
```tsx
export const Simple = () => {
const prop1 = text('Prop1', 'Example text');
const prop2 = select('Prop2', ['option1', 'option2'], 'option1');
return <Component prop1={prop1} prop2={prop2} />;
};
```
After
```tsx
export const Simple: Story<Props> = ({ prop1, prop2 }) => {
return <Component prop1={prop1} prop2={prop2} />;
};
```
5. Add default props (or args in Storybook language).
```tsx
Simple.args = {
prop1: 'Example text',
prop2: 'option 1',
};
```
6. If the component has advanced props type (ie. other than string, number, boolean), you need to
specify these in an `argTypes`. This is done in the default export of the story.
```tsx
export default {
title: 'Component/Component',
component: Component,
argTypes: {
prop2: { control: { type: 'select', options: ['option1', 'option2'] } },
},
};
```
## Best practices
- When creating a new component or writing documentation for an existing one, always cover the basic use case it was intended for with a code example.
- Use stories and knobs to create edge cases. If you are trying to solve a bug, try to reproduce it with a story.
- Do not create stories in the MDX, always create them in the `*.story.tsx` file.

View File

@@ -1,119 +0,0 @@
# Styling Grafana
[Emotion](https://emotion.sh/docs/introduction) is our default-to-be approach to styling React components. It provides a way for styles to be a consequence of properties and state of a component.
## Usage
### Basic styling
For styling components, use [Emotion's `css` function](https://emotion.sh/docs/emotion#css).
```tsx
import React from 'react';
import { css } from 'emotion';
const ComponentA = () => (
<div
className={css`
background: red;
`}
>
As red as you can get
</div>
);
```
### Styling with theme
To access the theme in your styles, use the `useStyles` hook. It provides basic memoization and access to the theme object.
> Please remember to put `getStyles` function at the end of the file!
```tsx
import React, { FC } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { useStyles } from '@grafana/ui';
import { css } from 'emotion';
const Foo: FC<FooProps> = () => {
const styles = useStyles(getStyles);
// Use styles with classNames
return <div className={styles}>...</div>
};
const getStyles = (theme: GrafanaTheme) => css`
padding: ${theme.spacing.md};
`;
```
### 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.
Let's say you need to style a component that has a different background depending on the `isActive` property :
```tsx
import React from 'react';
import { css } from 'emotion';
import { GrafanaTheme } from '@grafana/data';
import { selectThemeVariant, stylesFactory, useTheme } from '@grafana/ui';
interface ComponentAProps {
isActive: boolean
}
const ComponentA: React.FC<ComponentAProps> = ({isActive}) => {
const theme = useTheme();
const styles = getStyles(theme, isActive);
return (
<div className={styles.wrapper}>
As red as you can get
<i className={styles.icon} />
</div>
);
};
// Mind, that you can pass multiple arguments, theme included
const getStyles = stylesFactory((theme: GrafanaTheme, isActive: boolean) => {
const backgroundColor = isActive ? theme.colors.red : theme.colors.blue;
return {
wrapper: css`
background: ${backgroundColor};
`,
icon: css`
font-size: ${theme.typography.size.sm};
`,
};
});
```
For more information about themes at Grafana please see the [themes guide](./themes.md).
### Composing class names
For class composition, use [Emotion's `cx` function](https://emotion.sh/docs/emotion#cx).
```tsx
import React from 'react';
import { css, cx } from 'emotion';
interface Props {
className?: string;
}
const ComponentA: React.FC<Props> = ({ className }) => {
const finalClassName = cx(
className,
css`
background: red;
`
);
return <div className={finalClassName}>As red as you can ge</div>;
};
```

View File

@@ -1,152 +0,0 @@
# Theming Grafana
## Overview
**Themes are implemented in Typescript.** That's because our goal is to share variables between Grafana TypeScript and [Sass](https://sass-lang.com/) code. Theme definitions are located in the following files:
- [packages/grafana-ui/src/themes/dark.ts](../../packages/grafana-ui/src/themes/dark.ts)
- [packages/grafana-ui/src/themes/default.ts](../../packages/grafana-ui/src/themes/default.ts)
- [packages/grafana-ui/src/themes/light.ts](../../packages/grafana-ui/src/themes/light.ts)
The `default.ts` file holds common variables like typography and spacing definitions, while `[light|dark].ts` primarily specify colors used in themes.
## Usage
This section provides usage guidelines.
### Using themes in React components
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
import { ThemeContext } from '@grafana/ui';
<ThemeContext.Consumer>{theme => <Foo theme={theme} />}</ThemeContext.Consumer>;
```
#### 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.
```ts
import { ThemeContext, Themeable } from '@grafana/ui';
interface FooProps extends Themeable {}
const Foo: React.FunctionComponent<FooProps> = () => ...
export default withTheme(Foo);
```
### Test components that use `ThemeContext`
When implementing snapshot tests for components that use the `withTheme` HOC, the snapshot will contain the entire theme object. Any change to the theme renders the snapshot outdated.
To make your snapshot theme independent, use the `mockThemeContext` helper function:
```tsx
import { mockThemeContext } from '@grafana/ui';
import { MyComponent } from './MyComponent';
describe('MyComponent', () => {
let restoreThemeContext;
beforeAll(() => {
// Create ThemeContext mock before any snapshot test is executed
restoreThemeContext = mockThemeContext({ type: GrafanaThemeType.Dark });
});
afterAll(() => {
// Make sure the theme is restored after snapshot tests are performed
restoreThemeContext();
});
it('renders correctly', () => {
const wrapper = mount(<MyComponent />)
expect(wrapper).toMatchSnapshot();
});
});
```
## 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:
- `_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:
- `_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.
### You must ensure `ThemeContext` provider is available in a React tree
By default all react2angular directives have `ThemeContext.Provider` ensured. But, there are cases where we create another React tree via `ReactDOM.render`. This happens in the case of graph legend rendering and the `ReactContainer` directive. In such cases theme consumption will fail. To make sure theme context is available in such cases, you need to wrap your rendered component with ThemeContext.Provider using the `provideTheme` function:
```ts
// graph.ts
import { provideTheme } from 'app/core/utils/ConfigProvider';
// Create component with ThemeContext.Provider first.
// Otherwise React will create new components every time it renders!
const LegendWithThemeProvider = provideTheme(Legend);
const legendReactElem = React.createElement(LegendWithThemeProvider, legendProps);
ReactDOM.render(legendReactElem, this.legendElem, () => this.renderPanel());
```
`provideTheme` makes current theme available via ThemeContext by checking if user has `lightTheme` set in her boot data.

View File

@@ -1,57 +0,0 @@
# Templates
Templates are both a starting point and an instruction manual for writing something new. They are intended to make life easier by providing a jumping-off point, something besides a blank page to start from. They are not intended to be a limitation. If the template does not work perfectly for your use case, you can adjust or change it. We will work it out in code review.
## Create a template
Feel free to add templates to the `templates` folder. Try to make them as generic as possible and include clear instructions for when and how to use the template. Assume that the template user is a brand new contributor and write accordingly.
## Use a template
1. Read the template. Make sure you understand what it is for and how it is intended to be used.
1. Copy and rename the template. Move it to where you actually need it.
You might also want to copy the content of the template and paste it into a different file. This is acceptable use.
1. Replace the template content with your own. Delete whatever is unnecessary.
## Documentation templates
In an ideal world, each topic will correspond to an information *type* ([task](doc-task-template.md), [reference](doc-reference-template.md), [concept](doc-concept-template.md)) and contain only that type of information.
However, this is not always practical. For example, you have a series of short topics, you can group them into one topic.
Try to *chunk* your content. This means you should organize the document so that the same kinds of content are grouped together.
### Chunking example
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
**Tasks**
- 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
### Audience
Write for an audience that is computer literate and has general technical knowledge, but is not necessarily familiar with Grafana or the finer points of observability.
Pretend you are explaining your topic to a brand new Grafana user or developer.
### Self-contained
Thanks to search engines, every page in the documentation might be a reader's entry point. This means that each page needs to be self-contained and make sense on its own. The reader should not need to read other topics in order to perform the task or understand the concept.
However, try to be helpful and link to related information. Using the *Doggie handbook* example, the concept topic that explains what dogs can be trained to do might link to the Train the dog task.
## Code templates
This is a placeholder for future templates.

View File

@@ -1,42 +0,0 @@
DELETE THIS LINE: If draft = false, then the document will not be built in the doc site. If the date is earlier than the build date, than the document will not show in the build site. Use these settings to control whether future content is shown in the doc site.
+++
draft = "false"
date = "yyyy-mm-dd"
title = "Title in sentence case"
description = "Description in title case"
keywords = ["grafana", "enter", "keywords", "here"]
type = "docs"
[menu.docs]
name = "Name of topic"
identifier = "identifier"
parent = "menu parent"
weight = 100
+++
# Concept
The title of the concept topic will generally be a noun or a gerund. Examples include Templates, Templating, Dashboards, and panels.
Concepts are topic types for any information that doesn't involve task lists or reference information. Ideally you use concept elements to explain concepts, ideas, overviews, workflows, and the like. In the intro section, this first paragraph or two, you should explain to the user what to expect in this topic or section.
[Permissions overview](https://grafana.com/docs/grafana/latest/permissions/overview/) is an example of a concept topic.
## Idea
Concept topics or sections explain *what* and *why*. They do not explain *how*. If you are a new user, you might look for concept information to learn about what Grafana is, why it might be useful to you, and what the general workflow is.
## Workflow
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>
## Next steps
Concept tasks often link to related information, including *tasks* related to the concept and *reference* topics related to the concept.

View File

@@ -1,75 +0,0 @@
DELETE THIS LINE: If draft = false, then the document will not be built in the doc site. If the date is earlier than the build date, than the document will not show in the build site. Use these settings to control whether future content is shown in the doc site.
+++
draft = "false"
date = "yyyy-mm-dd"
title = "Title in sentence case"
description = "Description in title case"
keywords = ["grafana", "enter", "keywords", "here"]
type = "docs"
[menu.docs]
name = "Name of topic"
identifier = "identifier"
parent = "menu parent"
weight = 100
+++
# Reference
The *reference* topic type is for storing reference information, such as extensive tables, lists, or other information that is used as support for a task. Reference topics are also designed for API information.
Often reference topics are linked from *task* topics, because they contain information the user needs in order to perform a task.
[Grafana CLI](https://grafana.com/docs/grafana/latest/administration/cli/) is one example of a reference topic.
## Lists
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.
[Configuration](https://grafana.com/docs/grafana/latest/installation/configuration/) is an example of lists.
## Tables
If you have a large list of things to store in a table, then you are probably dealing with reference information. Hugo accepts either tables in Markdown or in HTML format, so use whichever is easier for you.
The [Glossary](https://grafana.com/docs/grafana/latest/guides/glossary/) provides an example of reference data in a table.
### Empty markdown table
While you might not need a heading for each table, headings are a good way to chunk information if you have several tables. They also make the content easy to skim. Use headings or intro paragraphs like this one to explain to the reader what the information in the table is used for.
| | | | | | |
|:---|:---|:--:|:--:|---:|---:|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
### Empty HTML table
And here is intro text, similar to the paragraph in the previous section. Do not add local styling to the table. The website CSS will take care of that for you.
<table>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
## API documentation
API documentation is always a reference topic rather than a task topic, but it has its own rules.

View File

@@ -1,57 +0,0 @@
+++
draft = "false"
date = "yyyy-mm-dd"
title = "Title in sentence case"
description = "Description in title case"
keywords = ["grafana", "enter", "keywords", "here"]
type = "docs"
[menu.docs]
name = "Name of topic"
identifier = "identifier"
parent = "menu parent"
weight = 100
+++
# Task
A *task* topic is intended for a procedure that describes how to accomplish a task. It lists a series of steps that users follow to produce an intended outcome. It tells the reader *how* to do something. [Install Grafana plugins](https://grafana.com/docs/grafana/latest/plugins/installation/) and [Playlist](https://grafana.com/docs/grafana/latest/reference/playlist/) are examples of task topics. Playlist includes a small amount of concept information in the introduction, which is appropriate.
Always include an introduction of a short paragraph or two to explain what the task is for, perhaps give the reader an idea of what the outcome will be.
In most cases, each topic should only contain one task. If you have several very short, related tasks, then you might combine them into one topic.
In the case of a long task, then you probably won't need any headings except for the h1 at the top of the page.
1. Start with step one.
1. Use second-person imperative tense.
1. Basically, "You, do this" with every sentence.
1. Do not use the third-person "user" for steps you want the reader ("you") to perform.
1. Write steps that contain one action, possibly two related actions, such as copy and paste a thing or save and quit the program.
If a sentence is not telling the reader to do something, then it is not a step. You can use nested images or paragraphs like this one to add information if necessary.
In many cases, you should tell the reader what the outcome should be so that they know when they are done.
## One-step task
Some tasks are so short, they only contain one step.
Write one-step tasks as simple sentences, not as unordered lists or numbered lists.
## Short task
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.
## Next steps
If the task you are writing leads naturally to one or more other tasks, then include links after the task to help the reader figure out where to go next.
Thanks to internet search engines, every page in the documentation could be page one. Pretend you are explaining your task to a new Grafana user who just walked in off the street.
## Testing
It is a good practice to have someone else test the task you have written. If they can successfully complete the task using *only* what the steps you have written, not guessing or using their inherent knowledge, then your task has passed the test. However, it is very common to find you have skipped steps, because *you* are very familiar with Grafana and the topic you are explaining.
New users or people from other teams are very helpful for these tests.

View File

@@ -1,32 +0,0 @@
# Triage issues
Triage helps ensure that 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.
This document gives you some ideas on what you can do to help. For more information, read more about [how the core Grafana team triage issues](/ISSUE_TRIAGE.md).
## Improve issues
Improve issues by suggesting improvements to the title and description. If you think an issue has formatting issues, bad language, or grammatical errors, post a comment to let the author and maintainers know.
## Report resolved issues
If you think an issue has been resolved, or is no longer relevant, suggest us to close it. Add a comment on the issue, where you explain the reason it should be closed. Make sure to include any related issues and pull requests.
## Investigate issues
Investigate issues that we haven't been able to reproduce yet. In some cases, there are many combinations of panels, dashboards, and data sources that make it difficult for us to reproduce certain issues. Help us by adding more information.
## Vote on issues
Use [GitHub reactions](https://help.github.com/en/articles/about-conversations-on-github#reacting-to-ideas-in-comments) to let us know what's important to you. Vote on bugs if you've experienced the same problem. **Don't vote, or react, by commenting on the issue.**
Read more about [how we prioritize issues](/ISSUE_TRIAGE.md#4-prioritization-of-issues).
## Report duplicates
If you find two issues that describe the same thing, add a comment in one of the issues, with a reference (`#<issue number>`) to the other. Explain why you think the issue is duplicated.

View File

@@ -1,68 +0,0 @@
package main
#Dashboard: {
// Unique numeric identifier for the dashboard. (generated by the db)
id: int
// Unique dashboard identifier that can be generated by anyone. string (8-40)
uid: string
// Title of dashboard.
title?: string
// Description of dashboard.
description?: string
// Tags associated with dashboard.
tags?: [...string]
// Theme of dashboard.
style: *"light" | "dark"
// Timezone of dashboard,
timezone?: *"browser" | "utc"
// Whether a dashboard is editable or not.
editable: bool | *true
// 0 for no shared crosshair or tooltip (default).
// 1 for shared crosshair.
// 2 for shared crosshair AND shared tooltip.
graphTooltip: int >= 0 <= 2 | *0
// Time range for dashboard, e.g. last 6 hours, last 7 days, etc
time?: {
from: string | *"now-6h"
to: string | *"now"
}
// Timepicker metadata.
timepicker?: {
// Whether timepicker is collapsed or not.
collapse: bool | *false
// Whether timepicker is enabled or not.
enable: bool | *true
// Whether timepicker is visible or not.
hidden: bool | *false
// Selectable intervals for auto-refresh.
refresh_intervals: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
}
// Templating.
templating?: list: [...{}]
// Annotations.
annotations?: list: [...{
builtIn: int | *0
// Datasource to use for annotation.
datasource: string
// Whether annotation is enabled.
enable?: bool | *true
// Whether to hide annotation.
hide?: bool | *false
// Annotation icon color.
iconColor?: string
// Name of annotation.
name?: string
// Query for annotation data.
rawQuery: string
showIn: int | *0
}] | *[]
// Auto-refresh interval.
refresh: string
// Version of the JSON schema, incremented each time a Grafana update brings
// changes to said schema.
schemaVersion: int | *25
// Version of the dashboard, incremented each time the dashboard is updated.
version: string
// Dashboard panels.
panels?: [...{}]
}

View File

@@ -1,86 +0,0 @@
# Dashboard Schemas
Schema description documents for [Grafana Dashboard
JSON](https://grafana.com/docs/grafana/latest/reference/dashboard/) and core
panels.
> **Note:** This directory is experimental. The schemas are not currently
> implemented or enforced in Grafana.
Schemas are defined in [Cue](https://cuelang.org/). Cue was chosen because it
strongly facilitates our primary use cases - [schema
definition](https://cuelang.org/docs/usecases/datadef/), [data
validation](https://cuelang.org/docs/usecases/validation/), and [code
generation/extraction](https://cuelang.org/docs/usecases/generate/).
## Schema Organization
Each schema describes part of a dashboard. `Dashboard.cue` is the main dashboard
schema object. All other schemas describe nested objects within a dashboard.
They are grouped in the following directories:
* `panels` - schemas for
[panels](https://grafana.com/docs/grafana/latest/panels/panels-overview/).
* `targets` - targets represent
[queries](https://grafana.com/docs/grafana/latest/panels/queries/). Each [data
source](https://grafana.com/docs/grafana/latest/datasources/) type has a
unique target schema.
* `variables` - schemas for
[variables](https://grafana.com/docs/grafana/latest/variables/variable-types/).
* `transformations` - schemas for
[transformations](https://grafana.com/docs/grafana/latest/panels/transformations/types-options/).
The following somewhat conveys how they fit together when constructing a
dashboard:
```
+-----------+ +-----------+
| Dashboard +------> Variables |
+---------+-+ +-----------+
| +--------+ +---------+
+----> Panels +----> Targets |
+------+-+ +---------+
| +-----------------+
+------> Transformations |
+-----------------+
```
## Definitions
All schemas are [Cue
definitions](https://cuelang.org/docs/references/spec/#definitions-and-hidden-fields).
Schemas intended to be exported must begin with a capital letter. For example,
[Gauge](./panels/Gauge.cue). Definitions beginning with a lowercase letter will
not be exported. These are reusable components for constructing the exported
definitions. For example, [`#panel`](./panels/panel.cue) is intended to
be a base schema for panels. `#Gauge` extends `#panel` with the following:
```
#Gauge: panel & {
...
}
```
## Exporting OpenAPI
[OpenAPI](https://www.openapis.org/) schemas can be exported from these CUE
sources.
### Command Line
While you can use `cue export` to output OpenAPI documents, it does not expand
references which makes the output unusable.
```
cue export --out openapi -o - ./...
```
### Using Go
You need to use Go to generate useable OpenAPI schemas. This directory contains
a Go program that will output just the OpenAPI schemas for one or many Cue
packages.
```
go run . <entrypoint> ...
```

View File

@@ -1 +0,0 @@
module: "github.com/grafana/grafana/dashboard-schemas"

View File

@@ -1,5 +0,0 @@
module github.com/grafana/grafana/dashboard-schemas
go 1.15
require cuelang.org/go v0.2.2

View File

@@ -1,185 +0,0 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cuelang.org/go v0.2.2 h1:i/wFo48WDibGHKQTRZ08nB8PqmGpVpQ2sRflZPj73nQ=
cuelang.org/go v0.2.2/go.mod h1:Dyjk8Y/B3CfFT1jQKJU0g5PpCeMiDe0yMOhk57oXwqo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/apd/v2 v2.0.1 h1:y1Rh3tEU89D+7Tgbw+lp52T6p/GJLpDmNvr10UWqLTE=
github.com/cockroachdb/apd/v2 v2.0.1/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/emicklei/proto v1.6.15 h1:XbpwxmuOPrdES97FrSfpyy67SSCV/wBIKXqgJzh6hNw=
github.com/emicklei/proto v1.6.15/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de h1:D5x39vF5KCwKQaw+OC9ZPiLVHXz3UFw2+psEX+gYcto=
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de/go.mod h1:kJun4WP5gFuHZgRjZUWWuH1DTxCtxbHDOIJsudS8jzY=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.6.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200612220849-54c614fe050c h1:g6oFfz6Cmw68izP3xsdud3Oxu145IPkeFzyRg58AKHM=
golang.org/x/tools v0.0.0-20200612220849-54c614fe050c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -1,58 +0,0 @@
package main
import (
"fmt"
"log"
"os"
"cuelang.org/go/cue"
"cuelang.org/go/cue/load"
"cuelang.org/go/encoding/openapi"
)
func main() {
b, err := openAPISchemas(os.Args[1:])
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
}
// openAPISchemas returns OpenAPI schema JSON of the Cue entrypoints passed to
// it. It is not a valid OpenAPI document - just the schemas.
func openAPISchemas(entrypoints []string) ([]byte, error) {
var r cue.Runtime
cfg := openapi.Config{
ExpandReferences: true,
}
bis := load.Instances(entrypoints, nil)
// collect all schemas
var pairs []openapi.KeyValue
for _, bi := range bis {
if bi.Err != nil {
return nil, bi.Err
}
inst, err := r.Build(bi)
if err != nil {
return nil, err
}
om, err := cfg.Schemas(inst)
if err != nil {
return nil, err
}
pairs = append(pairs, om.Pairs()...)
}
// add all schemas to new ordered map
om := openapi.OrderedMap{}
om.SetAll(pairs)
j, err := om.MarshalJSON()
if err != nil {
return nil, err
}
return j, nil
}

View File

@@ -1,47 +0,0 @@
package main
import (
"encoding/json"
"testing"
)
func TestOpenAPISchemas(t *testing.T) {
tests := map[string]struct {
entrypoints []string
}{
"All packages": {
entrypoints: []string{"./..."},
},
"One package": {
entrypoints: []string{"./panels"},
},
"Many packags": {
entrypoints: []string{
"./panels",
"./targets",
"./transformations",
"./variables",
},
},
}
for testName, test := range tests {
t.Logf("Running test case %s...", testName)
j, err := openAPISchemas(test.entrypoints)
if err != nil {
t.Fatal(err)
}
// We don't want to validate the JSON content since it's expected to change
// often. Only that it is valid JSON by unmarshalling it.
var iface interface{}
err = json.Unmarshal(j, &iface)
if err != nil {
t.Fatal(err)
}
}
}

View File

@@ -1,74 +0,0 @@
package panels
// Gauge is a single value panel that can repeat a gauge for every series,
// column or row.
#Gauge: _panel & {
// Field config.
fieldConfig: {
// Defaults.
defaults: {
// Custom.
custom: {}
// Unit.
unit: string
// Min.
min: int
// Max.
max: int
// Decimals.
decimals: int
// Change the field or series name.
displayName: string
// What to show when there is no value.
noValue: string
// Threshold config.
thresholds: _thresholds
// Mappings.
mappings: [..._mapping]
// Data Links.
links: [..._dataLink]
}
// Overrides.
overrides: [..._override]
}
// Options.
options: {
// Reduce options.
reduceOptions: {
// * `true` - Show a calculated value based on all rows.
// * `false` - Show a separate stat for every row.
values: bool | *false
// If values is false, sets max number of rows to
// display.
limit: int
// Reducer function/calculation.
calcs: [
"allIsZero",
"allIsNull",
"changeCount",
"count",
"delta",
"diff",
"distinctCount",
"first",
"firstNotNull",
"lastNotNull",
"last",
"logmin",
"max",
"min",
"range",
"step",
"sum",
] | *["mean"]
// Fields that should be included in the panel.
fields: string | *""
}
// Render the threshold values around the gauge bar.
showThresholdLabels: bool | *false
// Render the thresholds as an outer bar.
showThresholdMarkers: bool | *true
}
// Panel type.
type: string | *"gauge"
}

View File

@@ -1,192 +0,0 @@
package panels
#Graph: _panel & {
// Display values as a bar chart.
bars: bool | *false
// Dashed line length.
dashLength: int | *10
// Show line with dashes.
dashes: bool | *false
// Dashed line spacing when `dashes` is true.
spaceLength: int | *10
// Controls how many decimals are displayed for legend values and graph hover
// tooltips.
decimals: int
// Field config.
fieldConfig: {
// Defaults.
defaults: custom: {}
// Overrides.
overrides: [..._override]
}
// Amount of color fill for a series. Expects a value between 0 and 1.
fill: number >= 0 <= 1 | *1
// Degree of gradient on the area fill. 0 is no gradient, 10 is a steep
// gradient.
fillGradient: int >= 0 <= 10 | *0
// Hide the series.
hiddenSeries: bool | *false
// Lengend options.
legend: {
// Whether to display legend in table.
alignAsTable: bool | *false
// Average of all values returned from the metric query.
avg: bool | *false
// Last value returned from the metric query.
current: bool | *false
// Maximum of all values returned from the metric query.
max: bool | *false
// Minimum of all values returned from the metric query.
min: bool | *false
// Display legend to the right.
rightSide: bool | *false
// Show or hide the legend.
show: bool | *true
// Available when `rightSide` is true. The minimum width for the legend in
// pixels.
sideWidth?: int
// Sum of all values returned from the metric query.
total: bool | *false
// Values.
values: bool | *true
}
// Display values as a line graph.
lines: bool | *true
// The width of the line for a series.
linewidth: int | *1
// How null values are displayed.
// * 'null' - If there is a gap in the series, meaning a null value, then the
// line in the graph will be broken and show the gap.
// * 'null as zero' - If there is a gap in the series, meaning a null value,
// then it will be displayed as a zero value in the graph panel.
// * 'connected' - If there is a gap in the series, meaning a null value or
// values, then the line will skip the gap and connect to the next non-null
// value.
nullPointMode: string | *"null"
// Options.
options: {
// Data links.
dataLinks: [..._dataLink]
}
// Available when `stack` is true. Each series is drawn as a percentage of the
// total of all series.
percentage: bool | *false
// Controls how large the points are.
pointradius: int
// Display points for values.
points: bool | *true
// Renderer.
renderer: string | *"flot"
// Series overrides allow a series in a graph panel to be rendered
// differently from the others. You can customize display options on a
// per-series bases or by using regex rules. For example, one series can have
// a thicker line width to make it stand out or be moved to the right Y-axis.
seriesOverrides: [...{
// Alias or regex matching the series you'd like to target.
alias?: string
bars?: bool
lines?: bool
fill?: int
fillGradient?: int
linewidth?: int
nullPointMode?: string
fillBelowTo?: string
steppedLine?: bool
dashes?: bool
hiddenSeries?: bool
dashLength?: int
spaceLength?: int
points?: bool
pointradius?: int
stack?: int
color?: string
yaxis?: int
zindex?: int
transform?: string
legend?: bool
hideTooltip?: bool
}]
// Each series is stacked on top of another.
stack: bool | *false
// Draws adjacent points as staircase.
steppedLine: bool | *false
// Threshold config.
thresholds: _thresholds
// Time from.
timeFrom: string
// Time regions.
timeRegions: [...string]
// Time shift
timeShift: string
// Tooltip settings.
tooltip: {
// * true - The hover tooltip shows all series in the graph. Grafana
// highlights the series that you are hovering over in bold in the series
// list in the tooltip.
// * false - The hover tooltip shows only a single series, the one that you
// are hovering over on the graph.
shared: bool | *true
// * 0 (none) - The order of the series in the tooltip is determined by the
// sort order in your query. For example, they could be alphabetically
// sorted by series name.
// * 1 (increasing) - The series in the hover tooltip are sorted by value
// and in increasing order, with the lowest value at the top of the list.
// * 2 (decreasing) - The series in the hover tooltip are sorted by value
// and in decreasing order, with the highest value at the top of the list.
sort: int >= 0 <= 2 | *2
// Value type.
value_type: string | *"individual"
}
// Panel type.
type: string | *"graph"
xaxis: {
// Buckets.
buckets: string
// The display mode completely changes the visualization of the graph
// panel. Its like three panels in one. The main mode is the time series
// mode with time on the X-axis. The other two modes are a basic bar chart
// mode with series on the X-axis instead of time and a histogram mode.
// * 'time' - The X-axis represents time and that the data is grouped by
// time (for example, by hour, or by minute).
// * 'series' - The data is grouped by series and not by time. The Y-axis
// still represents the value.
// * 'histogram' - Converts the graph into a histogram. A histogram is a
// kind of bar chart that groups numbers into ranges, often called buckets
// or bins. Taller bars show that more data falls in that range.
mode: string | *"time"
// Name.
name: string
// Show or hide the axis.
show: bool | *true
// Values
values: [...number]
}
yaxes: [...{
// Defines how many decimals are displayed for Y value.
decimals: int
// The display unit for the Y value.
format: string | *"short"
// The Y axis label.
label: string
// The scale to use for the Y value - linear, or logarithmic.
// * 1 - linear
// * 2 - log (base 2)
// * 10 - log (base 10)
// * 32 - log (base 32)
// * 1024 - log (base 1024)
logBase: int | *1
// The maximum Y value.
max?: int
// The minimum Y value.
min?: int
// Show or hide the axis.
show: bool | *true
}]
yaxis: {
// Align left and right Y-axes by value.
align: bool | *false
// Available when align is true. Value to use for alignment of left and
// right Y-axes, starting from Y=0.
alignLevel: int | *0
}
}

View File

@@ -1,24 +0,0 @@
package panels
// A row is a logical divider within a dashboard. It is used
// to group panels together.
#Row: {
// Whether the row is collapsed or not.
collapsed: bool | *true
// Name of default data source.
datasource?: string
// Grid position.
gridPos?: _gridPos
// Dashboard panels.
panels?: [...{}]
// Name of template variable to repeat for.
repeat?: string
// Whether to display the title.
showTitle: bool | *true
// Title.
title?: string
// Size of title.
titleSize: string | *"h6"
// Panel type.
type: string | *"row"
}

View File

@@ -1,12 +0,0 @@
package panels
_gridPos: {
// Panel height.
h?: int > 0 | *9
// Panel width.
w?: int > 0 <= 24 | *12
// Panel x position.
x?: int >= 0 < 24 | *0
// Panel y position.
y?: int >= 0 | *0
}

View File

@@ -1,14 +0,0 @@
package panels
_link: {
// Link title.
title?: string
// Whether to open link in new browser tab.
targetBlank: bool | *true
// URL of link.
url: string
}
_panelLink: _link
_dataLink: _link

View File

@@ -1,11 +0,0 @@
package panels
_mapping: {
id: int
from: string
operator: string
to: string
text: string
type: int
value: string
}

View File

@@ -1,12 +0,0 @@
package panels
_override: {
matcher: {
id: string
options: string
}
properties: [...{
id: string
value: int
}]
}

View File

@@ -1,24 +0,0 @@
package panels
_panel: {
// Panel title.
title?: string
// Description.
description?: string
// Whether to display the panel without a background.
transparent: bool | *false
// Name of default datasource.
datasource?: string
// Grid position.
gridPos?: _gridPos
// Panel links.
links?: [..._panelLink]
// Name of template variable to repeat for.
repeat?: string
// Direction to repeat in if 'repeat' is set.
// "h" for horizontal, "v" for vertical.
repeatDirection: *"h" | "v"
// Panel targets - datasource and query configurations to use as
// a basis for vizualization.
targets?: [...{}]
}

View File

@@ -1,11 +0,0 @@
package panels
_thresholds: {
// Threshold mode.
mode: string | *"absolute"
// Threshold steps.
steps: [...{
color: string
value: number
}]
}

View File

@@ -1,19 +0,0 @@
package targets
#Prometheus: {
// Query expression.
expr: string
// Controls the name of the time series, using name or pattern.
legendFormat?: string
// Interval.
interval?: int | *1
// Target reference ID.
refId: string
// Perform an “instant” query, to return only the latest value that
// Prometheus has scraped for the requested time series.
instant: bool | *false
// Resolution.
intervalFactor?: int
// Format.
format: *"time_series" | "table" | "heat_map"
}

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