mirror of
https://github.com/grafana/grafana.git
synced 2025-12-24 05:44:14 +08:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91162f3542 | ||
|
|
70466c6cec | ||
|
|
cce7f11c35 | ||
|
|
acbd6d44b0 | ||
|
|
3c5bf4a0cf | ||
|
|
b33ac25f82 | ||
|
|
3a8306086b | ||
|
|
f14ad7445f | ||
|
|
946a6c7d59 | ||
|
|
990168c2af | ||
|
|
95ce4725fb | ||
|
|
7133cc1013 | ||
|
|
3600f0ec0b | ||
|
|
80c717cf6d | ||
|
|
9d58257be6 | ||
|
|
e1b554c61e | ||
|
|
a747ec349e | ||
|
|
d9f3c0931a | ||
|
|
f736e7aeb2 | ||
|
|
84d6e67e6b | ||
|
|
5ad76a29a0 | ||
|
|
5c6fd4f202 | ||
|
|
f13ffa3a52 | ||
|
|
55809ee92a | ||
|
|
a1db5561e0 | ||
|
|
3591e573f1 | ||
|
|
b29c2da7ef | ||
|
|
0f601dc4b1 | ||
|
|
5742c4d603 | ||
|
|
2226506a1d | ||
|
|
dcafc29bf2 | ||
|
|
1b16a1ae81 | ||
|
|
45e22da955 | ||
|
|
bc660ff3d5 | ||
|
|
426ae8bdd3 | ||
|
|
5bab016837 | ||
|
|
a7fcadd7c9 |
14
.babelrc
14
.babelrc
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"browsers": "last 3 versions"
|
||||
},
|
||||
"useBuiltIns": "entry",
|
||||
"modules": "false",
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
18
.bra.toml
18
.bra.toml
@@ -1,19 +1,17 @@
|
||||
[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", "build", "-o", "./bin/grafana-server", "./pkg/cmd/grafana-server"],
|
||||
["./bin/grafana-server", "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"]
|
||||
watch_exts = [".go", ".ini", ".toml"]
|
||||
build_delay = 1500
|
||||
cmds = [
|
||||
["go", "run", "build.go", "-dev", "build-server"],
|
||||
["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"]
|
||||
["go", "build", "-o", "./bin/grafana-server", "./pkg/cmd/grafana-server"],
|
||||
["./bin/grafana-server", "cfg:app_mode=development"]
|
||||
]
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
>1%,
|
||||
Chrome > 20
|
||||
last 4 versions,
|
||||
Firefox ESR
|
||||
1215
.circleci/config.yml
1215
.circleci/config.yml
File diff suppressed because it is too large
Load Diff
@@ -1,18 +0,0 @@
|
||||
.awcache
|
||||
.dockerignore
|
||||
.git
|
||||
.gitignore
|
||||
.github
|
||||
.vscode
|
||||
bin
|
||||
data*
|
||||
dist
|
||||
docker
|
||||
Dockerfile
|
||||
docs
|
||||
dump.rdb
|
||||
node_modules
|
||||
/local
|
||||
/tmp
|
||||
*.yml
|
||||
*.md
|
||||
@@ -1,8 +0,0 @@
|
||||
load('scripts/pr.star', 'pr_pipelines')
|
||||
load('scripts/master.star', 'master_pipelines')
|
||||
load('scripts/release.star', 'release_pipelines', 'test_release_pipelines')
|
||||
|
||||
def main(ctx):
|
||||
edition = 'oss'
|
||||
return pr_pipelines(edition=edition) + master_pipelines(edition=edition) + release_pipelines() + \
|
||||
test_release_pipelines()
|
||||
2249
.drone.yml
2249
.drone.yml
File diff suppressed because it is too large
Load Diff
@@ -16,15 +16,5 @@ 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
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
node_modules
|
||||
compiled
|
||||
build
|
||||
vendor
|
||||
devenv
|
||||
data
|
||||
dist
|
||||
13
.eslintrc
13
.eslintrc
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"extends": ["@grafana/eslint-config"],
|
||||
"root": true,
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["packages/grafana-ui/**/*/!(*.story).{ts,tsx}", "public/app/**/*.{ts,tsx}"],
|
||||
"rules": {
|
||||
"react-hooks/rules-of-hooks": "off",
|
||||
"react-hooks/exhaustive-deps": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
60
.github/CODEOWNERS
vendored
60
.github/CODEOWNERS
vendored
@@ -1,60 +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/ @oddlittlebird @achatterjee-grafana
|
||||
/contribute/ @oddlittlebird @marcusolsson @achatterjee-grafana
|
||||
/docs/sources/developers/plugins/ @marcusolsson
|
||||
|
||||
# Backend code
|
||||
*.go @grafana/backend-platform
|
||||
go.mod @grafana/backend-platform
|
||||
go.sum @grafana/backend-platform
|
||||
|
||||
/e2e @grafana/grafana-frontend-platform
|
||||
/packages @grafana/grafana-frontend-platform
|
||||
/plugins-bundled @grafana/grafana-frontend-platform
|
||||
/public @grafana/grafana-frontend-platform
|
||||
/scripts/build/release-packages.sh @grafana/grafana-frontend-platform
|
||||
/scripts/circle-release-next-packages.sh @grafana/grafana-frontend-platform
|
||||
/scripts/ci-frontend-metrics.sh @grafana/grafana-frontend-platform
|
||||
/scripts/grunt @grafana/grafana-frontend-platform
|
||||
/scripts/webpack @grafana/grafana-frontend-platform
|
||||
package.json @grafana/grafana-frontend-platform
|
||||
tsconfig.json @grafana/grafana-frontend-platform
|
||||
lerna.json @grafana/grafana-frontend-platform
|
||||
.babelrc @grafana/grafana-frontend-platform
|
||||
.prettierrc.js @grafana/grafana-frontend-platform
|
||||
.eslintrc @grafana/grafana-frontend-platform
|
||||
|
||||
# @grafana/ui component documentation
|
||||
*.mdx @marcusolsson @jessover9000 @grafana/grafana-frontend-platform
|
||||
|
||||
/public/app/features/explore/ @grafana/observability-squad
|
||||
/packages/jaeger-ui-components/ @grafana/observability-squad
|
||||
|
||||
# Core datasources
|
||||
/public/app/plugins/datasource/cloudwatch @grafana/backend-platform @grafana/observability-squad
|
||||
/public/app/plugins/datasource/elasticsearch @grafana/observability-squad
|
||||
/public/app/plugins/datasource/grafana-azure-monitor-datasource @grafana/backend-platform
|
||||
/public/app/plugins/datasource/graphite @grafana/observability-squad
|
||||
/public/app/plugins/datasource/influxdb @grafana/observability-squad
|
||||
/public/app/plugins/datasource/jaeger @grafana/observability-squad
|
||||
/public/app/plugins/datasource/loki @grafana/observability-squad
|
||||
/public/app/plugins/datasource/mssql @grafana/backend-platform
|
||||
/public/app/plugins/datasource/mysql @grafana/backend-platform
|
||||
/public/app/plugins/datasource/opentsdb @grafana/backend-platform
|
||||
/public/app/plugins/datasource/postgres @grafana/backend-platform
|
||||
/public/app/plugins/datasource/prometheus @grafana/observability-squad
|
||||
/public/app/plugins/datasource/cloud-monitoring @grafana/backend-platform
|
||||
/public/app/plugins/datasource/zipkin @grafana/observability-squad
|
||||
22
.github/CONTRIBUTING.md
vendored
Normal file
22
.github/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Follow the setup guide in README.md
|
||||
|
||||
### Rebuild frontend assets on source change
|
||||
```
|
||||
grunt && grunt watch
|
||||
```
|
||||
|
||||
### Rerun tests on source change
|
||||
```
|
||||
grunt karma:dev
|
||||
```
|
||||
|
||||
### Run tests for backend assets before commit
|
||||
```
|
||||
test -z "$(gofmt -s -l . | grep -v -E 'vendor/(github.com|golang.org|gopkg.in)' | tee /dev/stderr)"
|
||||
```
|
||||
|
||||
### Run tests for frontend assets before commit
|
||||
```
|
||||
npm test
|
||||
go test -v ./pkg/...
|
||||
```
|
||||
16
.github/ISSUE_TEMPLATE.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
Read before posting:
|
||||
|
||||
- Questions should be posted to https://community.grafana.com. Please search there and here on GitHub for similar issues before creating a new issue.
|
||||
- Checkout FAQ: https://community.grafana.com/c/howto/faq
|
||||
- Checkout How to troubleshoot metric query issues: https://community.grafana.com/t/how-to-troubleshoot-metric-query-issues/50
|
||||
|
||||
Please include this information:
|
||||
- What Grafana version are you using?
|
||||
- What datasource are you using?
|
||||
- What OS are you running grafana on?
|
||||
- What did you do?
|
||||
- What was the expected result?
|
||||
- What happened instead?
|
||||
- If related to metric query / data viz:
|
||||
- Include raw network request & response: get by opening Chrome Dev Tools (F12, Ctrl+Shift+I on windows, Cmd+Opt+I on Mac), go the network tab.
|
||||
|
||||
31
.github/ISSUE_TEMPLATE/1-bug_report.md
vendored
31
.github/ISSUE_TEMPLATE/1-bug_report.md
vendored
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report a bug you found when using Grafana
|
||||
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
|
||||
-->
|
||||
|
||||
**What happened**:
|
||||
|
||||
**What you expected to happen**:
|
||||
|
||||
**How to reproduce it (as minimally and precisely as possible)**:
|
||||
|
||||
**Anything else we need to know?**:
|
||||
|
||||
**Environment**:
|
||||
- Grafana version:
|
||||
- Data source type & version:
|
||||
- OS Grafana is installed on:
|
||||
- User OS & Browser:
|
||||
- Grafana plugins:
|
||||
- Others:
|
||||
11
.github/ISSUE_TEMPLATE/2-feature_request.md
vendored
11
.github/ISSUE_TEMPLATE/2-feature_request.md
vendored
@@ -1,11 +0,0 @@
|
||||
---
|
||||
name: Enhancement request
|
||||
about: Suggest an enhancement or new feature for the Grafana project
|
||||
labels: 'type: feature request'
|
||||
---
|
||||
|
||||
<!-- Please only use this template for submitting feature requests -->
|
||||
|
||||
**What would you like to be added**:
|
||||
|
||||
**Why is this needed**:
|
||||
26
.github/ISSUE_TEMPLATE/3-accessibility.md
vendored
26
.github/ISSUE_TEMPLATE/3-accessibility.md
vendored
@@ -1,26 +0,0 @@
|
||||
---
|
||||
name: Accessibility issue
|
||||
about: Help make Grafana be better at keyboard navigation, screen-readable and accessible to all.
|
||||
labels: 'type: accessibility'
|
||||
---
|
||||
|
||||
<!--
|
||||
Please only use this template for submitting accessibility issues.
|
||||
|
||||
This is a new feature area for Grafana that we want to improve. We have long way to go
|
||||
to really improve accessibility and would like your help to know where to start.
|
||||
-->
|
||||
|
||||
**Steps to reproduce**:
|
||||
|
||||
**Actual Result**:
|
||||
|
||||
**Expected Result**
|
||||
|
||||
**Relevant WCAG Criteria:** [#.#.# WCAG Criterion](link to https://www.w3.org/WAI/WCAG21/quickref/?versions=2.0)
|
||||
|
||||
**Environment**:
|
||||
- Grafana version:
|
||||
- Data source type & version:
|
||||
- User OS & Browser:
|
||||
- Others:
|
||||
39
.github/ISSUE_TEMPLATE/4-grafana_ui_component.md
vendored
39
.github/ISSUE_TEMPLATE/4-grafana_ui_component.md
vendored
@@ -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).
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -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.
|
||||
36
.github/PULL_REQUEST_TEMPLATE.md
vendored
36
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,34 +1,4 @@
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
|
||||
**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)"
|
||||
|
||||
-->
|
||||
|
||||
Fixes #
|
||||
|
||||
**Special notes for your reviewer**:
|
||||
* Link the PR to an issue for new features
|
||||
* Rebase your PR if it gets out of sync with master
|
||||
|
||||
**REMOVE THE TEXT ABOVE BEFORE CREATING THE PULL REQUEST**
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
FROM alpine
|
||||
RUN apk update
|
||||
RUN apk add rsync git bash
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
|
||||
21
.github/actions/gha-publish-to-git/LICENSE
vendored
21
.github/actions/gha-publish-to-git/LICENSE
vendored
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Sean Middleditch
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
60
.github/actions/gha-publish-to-git/README.md
vendored
60
.github/actions/gha-publish-to-git/README.md
vendored
@@ -1,60 +0,0 @@
|
||||
publish-to-git
|
||||
==============
|
||||
|
||||
[GitHub Action](https://github.com/features/actions) for publishing a directory
|
||||
and its contents to another git repository.
|
||||
|
||||
This can be especially useful for publishing static website, such as with
|
||||
[GitHub Pages](https://pages.github.com/), from built files in other job
|
||||
steps, such as [Doxygen](http://www.doxygen.nl/) generated HTML files.
|
||||
|
||||
> **Note:** GitHub currently requires the use of a Personal Access Token for
|
||||
pushing to other repositories. Pushing to the current repository should work
|
||||
with the always-available GitHub Token (available via
|
||||
`{{ secrets.GITHUB_TOKEN }}`. If pushing to another repository, a Personal
|
||||
Access Token will need to be [created](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) and assigned to the
|
||||
workflow [secrets](https://help.github.com/en/articles/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables).
|
||||
|
||||
Inputs
|
||||
------
|
||||
|
||||
- `repository`: Destination repository (default: current repository).
|
||||
- `branch`: Destination branch (required).
|
||||
- `host`: Destination git host (default: `github.com`).
|
||||
- `github_token`: GitHub Token (required; use `secrets.GITHUB_TOKEN`).
|
||||
- `github_pat`: Personal Access Token or other https credentials.
|
||||
- `source_folder`: Source folder in workspace to copy (default: workspace root).
|
||||
- `target_folder`: Target folder in destination branch to copy to (default: repository root).
|
||||
- `commit_author`: Override commit author (default: `{github.actor}@users.noreply.github.com`).
|
||||
- `commit_message`: Set commit message (default: `[workflow] Publish from [repository]:[branch]/[folder]`).
|
||||
- `dry_run`: Does not push if non-empty (default: empty).
|
||||
- `working_directory`: Location to checkout repository (default: random location in `${HOME}`)
|
||||
|
||||
Outputs
|
||||
-------
|
||||
|
||||
- `commit_hash`: SHA hash of the new commit.
|
||||
- `working_directory`: Working directory of git clone of repository.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT License. See [LICENSE](LICENSE) for details.
|
||||
|
||||
Usage Example
|
||||
-------------
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
publish:
|
||||
- uses: actions/checkout@master
|
||||
- run: |
|
||||
sh scripts/build-doxygen-html.sh --out static/html
|
||||
- uses: seanmiddleditch/gha-publish-to-git@master
|
||||
with:
|
||||
branch: gh-pages
|
||||
github_token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
github_pat: '${{ secrets.GH_PAT }}'
|
||||
source_folder: static/html
|
||||
if: success() && github.event == 'push'
|
||||
```
|
||||
60
.github/actions/gha-publish-to-git/action.yml
vendored
60
.github/actions/gha-publish-to-git/action.yml
vendored
@@ -1,60 +0,0 @@
|
||||
---
|
||||
name: publish-to-git
|
||||
description: 'Publish files to a git repository'
|
||||
branding:
|
||||
icon: 'git-commit'
|
||||
color: 'blue'
|
||||
inputs:
|
||||
repository:
|
||||
description: 'Destination repository (default: current repository)'
|
||||
default: ''
|
||||
branch:
|
||||
description: 'Destination branch'
|
||||
required: true
|
||||
host:
|
||||
description: 'Destination git host'
|
||||
default: 'github.com'
|
||||
github_token:
|
||||
description: 'GitHub Token (use `secrets.GITHUB_TOKEN`)'
|
||||
required: true
|
||||
github_pat:
|
||||
description: 'Personal Access Token or other https credentials'
|
||||
default: ''
|
||||
source_folder:
|
||||
description: 'Source folder in workspace to copy (default: workspace root)'
|
||||
defaault: ''
|
||||
target_folder:
|
||||
description: 'Target folder in destination branch to copy to (default: repository root)'
|
||||
default: ''
|
||||
commit_author:
|
||||
description: 'User Name <email@address> (default: [github.actor]@users.noreply.github.com)'
|
||||
default: ''
|
||||
commit_message:
|
||||
description: 'Commit message (default: [workflow] Publish from [repository]:[branch]/[folder])'
|
||||
default: ''
|
||||
dry_run:
|
||||
description: 'Do not push to repository (set to non-empty string to make dry-run)'
|
||||
default: ''
|
||||
working_directory:
|
||||
description: 'Working directory for clone (default: random location in `${HOME}`)'
|
||||
default: ''
|
||||
outputs:
|
||||
commit_hash:
|
||||
description: 'Hash of the new commit'
|
||||
working_directory:
|
||||
description: 'Working directory of temporary repository'
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'Dockerfile'
|
||||
args:
|
||||
- ${{ inputs.repository }}
|
||||
- ${{ inputs.branch }}
|
||||
- ${{ inputs.host }}
|
||||
- ${{ inputs.github_token }}
|
||||
- ${{ inputs.github_pat }}
|
||||
- ${{ inputs.source_folder }}
|
||||
- ${{ inputs.target_folder }}
|
||||
- ${{ inputs.commit_author }}
|
||||
- ${{ inputs.commit_message }}
|
||||
- ${{ inputs.dry_run }}
|
||||
- ${{ inputs.working_directory }}
|
||||
99
.github/actions/gha-publish-to-git/entrypoint.sh
vendored
99
.github/actions/gha-publish-to-git/entrypoint.sh
vendored
@@ -1,99 +0,0 @@
|
||||
#/bin/bash
|
||||
|
||||
# Name the Docker inputs.
|
||||
#
|
||||
INPUT_REPOSITORY="$1"
|
||||
INPUT_BRANCH="$2"
|
||||
INPUT_HOST="$3"
|
||||
INPUT_GITHUB_TOKEN="$4"
|
||||
INPUT_GITHUB_PAT="$5"
|
||||
INPUT_SOURCE_FOLDER="$6"
|
||||
INPUT_TARGET_FOLDER="$7"
|
||||
INPUT_COMMIT_AUTHOR="$8"
|
||||
INPUT_COMMIT_MESSAGE="$9"
|
||||
INPUT_DRYRUN="${10}"
|
||||
INPUT_WORKDIR="${11}"
|
||||
|
||||
# Check for required inputs.
|
||||
#
|
||||
[ -z "$INPUT_BRANCH" ] && echo >&2 "::error::'branch' is required" && exit 1
|
||||
[ -z "$INPUT_GITHUB_TOKEN" -a -z "$INPUT_GITHUB_PAT" ] && echo >&2 "::error::'github_token' or 'github_pat' is required" && exit 1
|
||||
|
||||
# Set state from inputs or defaults.
|
||||
#
|
||||
REPOSITORY="${INPUT_REPOSITORY:-${GITHUB_REPOSITORY}}"
|
||||
BRANCH="${INPUT_BRANCH}"
|
||||
HOST="${INPUT_GIT_HOST:-github.com}"
|
||||
TOKEN="${INPUT_GITHUB_PAT:-${INPUT_GITHUB_TOKEN}}"
|
||||
REMOTE="${INPUT_REMOTE:-https://${TOKEN}@${HOST}/${REPOSITORY}.git}"
|
||||
|
||||
SOURCE_FOLDER="${INPUT_SOURCE_FOLDER:-.}"
|
||||
TARGET_FOLDER="${INPUT_TARGET_FOLDER}"
|
||||
|
||||
REF="${GITHUB_BASE_REF:-${GITHUB_REF}}"
|
||||
REF_BRANCH=$(echo "${REF}" | rev | cut -d/ -f1 | rev)
|
||||
[ -z "$REF_BRANCH" ] && echo 2>&1 "No ref branch" && exit 1
|
||||
|
||||
COMMIT_AUTHOR="${INPUT_AUTHOR:-${GITHUB_ACTOR} <${GITHUB_ACTOR}@users.noreply.github.com>}"
|
||||
COMMIT_MESSAGE="${INPUT_COMMIT_MESSAGE:-[${GITHUB_WORKFLOW}] Publish from ${GITHUB_REPOSITORY}:${REF_BRANCH}/${SOURCE_FOLDER}}"
|
||||
|
||||
# Calculate the real source path.
|
||||
#
|
||||
SOURCE_PATH="$(realpath "${SOURCE_FOLDER}")"
|
||||
[ -z "${SOURCE_PATH}" ] && exit 1
|
||||
echo "::debug::SOURCE_PATH=${SOURCE_PATH}"
|
||||
|
||||
# Let's start doing stuff.
|
||||
echo "Publishing ${SOURCE_FOLDER} to ${REMOTE}:${BRANCH}/${TARGET_FOLDER}"
|
||||
|
||||
# Create a working directory; the workspace may be filled with other important
|
||||
# files.
|
||||
#
|
||||
WORK_DIR="${INPUT_WORKDIR:-$(mktemp -d "${HOME}/gitrepo.XXXXXX")}"
|
||||
[ -z "${WORK_DIR}" ] && echo >&2 "::error::Failed to create temporary working directory" && exit 1
|
||||
cd "${WORK_DIR}"
|
||||
|
||||
# Initialize git repo and configure for remote access.
|
||||
#
|
||||
echo "Initializing repository with remote ${REMOTE}"
|
||||
git init || exit 1
|
||||
git config --local user.email "${GITHUB_ACTOR}@users.noreply.github.com" || exit 1
|
||||
git config --local user.name "${GITHUB_ACTOR}" || exit 1
|
||||
git remote add origin "${REMOTE}" || exit 1
|
||||
git remote -v
|
||||
|
||||
# Fetch initial (current contents).
|
||||
#
|
||||
echo "Fetching ${REMOTE}:${BRANCH}"
|
||||
git fetch --depth 1 origin "${BRANCH}" || exit 1
|
||||
git checkout -b "${BRANCH}" || exit 1
|
||||
git pull origin "${BRANCH}" || exit 1
|
||||
|
||||
# Create the target directory (if necessary) and copy files from source.
|
||||
#
|
||||
TARGET_PATH="${WORK_DIR}/${TARGET_FOLDER}"
|
||||
echo "Populating ${TARGET_PATH}"
|
||||
mkdir -p "${TARGET_PATH}" || exit 1
|
||||
rsync -a --quiet --delete "${SOURCE_PATH}/" "${TARGET_PATH}" || exit 1
|
||||
|
||||
# Create commit with changes.
|
||||
#
|
||||
echo "Creating commit"
|
||||
git add "${TARGET_PATH}" || exit 1
|
||||
git commit -m "${COMMIT_MESSAGE}" --author "${COMMIT_AUTHOR}" || exit 1
|
||||
COMMIT_HASH="$(git rev-parse HEAD)"
|
||||
echo "Created commit ${COMMIT_HASH}"
|
||||
|
||||
# Publish output variables.
|
||||
#
|
||||
echo "::set-output name=commit_hash::${COMMIT_HASH}"
|
||||
echo "::set-output name=working_directory::${WORK_DIR}"
|
||||
|
||||
# Push if not a dry-run.
|
||||
#
|
||||
if [ -z "${INPUT_DRYRUN}" ] ; then
|
||||
echo "Pushing to ${REMOTE}:${BRANCH}"
|
||||
git push origin "${BRANCH}" || exit 1
|
||||
else
|
||||
echo "[DRY-RUN] Not pushing to ${REMOTE}:${BRANCH}"
|
||||
fi
|
||||
27
.github/commands.json
vendored
27
.github/commands.json
vendored
@@ -1,27 +0,0 @@
|
||||
[
|
||||
{
|
||||
"type": "label",
|
||||
"name": "type/question",
|
||||
"action": "close",
|
||||
"comment": "Please ask your question on [community.grafana.com/](https://community.grafana.com/). To avoid having your issue closed in the future, please read our [CONTRIBUTING](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md) guidelines.\n\nHappy graphing!"
|
||||
},
|
||||
{
|
||||
"type": "comment",
|
||||
"name": "duplicate",
|
||||
"allowUsers": [],
|
||||
"action": "updateLabels",
|
||||
"addLabel": "type/duplicate"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"name": "type/duplicate",
|
||||
"action": "close",
|
||||
"comment": "Thanks for creating this issue! It looks like this has already been reported by another user. We’ve closed this in favor of the existing one. Please consider adding any details you think is missing to that issue.\n\nTo avoid having your issue closed in the future, please read our [CONTRIBUTING](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md) guidelines.\n\nHappy graphing!"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"name": "no new info",
|
||||
"action": "close",
|
||||
"comment": "We've closed this issue since it needs more information and hasn't had any activity recently. We can re-open it after you you add more information. To avoid having your issue closed in the future, please read our [CONTRIBUTING](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md) guidelines.\n\nHappy graphing!"
|
||||
}
|
||||
]
|
||||
47
.github/stale.yml
vendored
47
.github/stale.yml
vendored
@@ -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.
|
||||
71
.github/workflows/codeql-analysis.yml
vendored
71
.github/workflows/codeql-analysis.yml
vendored
@@ -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
|
||||
25
.github/workflows/commands.yml
vendored
25
.github/workflows/commands.yml
vendored
@@ -1,25 +0,0 @@
|
||||
name: Run commands when issues are labeled or comments added
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: "grafana/grafana-github-actions"
|
||||
path: ./actions
|
||||
ref: main
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: Run Commands
|
||||
uses: ./actions/commands
|
||||
with:
|
||||
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
|
||||
token: ${{secrets.GH_BOT_ACCESS_TOKEN}}
|
||||
config-path: commands
|
||||
34
.github/workflows/metrics-collector.yml
vendored
34
.github/workflows/metrics-collector.yml
vendored
@@ -1,34 +0,0 @@
|
||||
#
|
||||
# When triggered by the cron job it will also collect metrics for:
|
||||
# * number of issues without label
|
||||
# * number of issues with "needs more info"
|
||||
# * number of issues with "needs investigation"
|
||||
# * number of issues with label type/bug
|
||||
# * number of open issues in current milestone
|
||||
#
|
||||
# https://github.com/grafana/grafana-github-actions/blob/main/metrics-collector/index.ts
|
||||
#
|
||||
name: Github issue metrics collection
|
||||
on:
|
||||
schedule:
|
||||
- cron: "*/10 * * * *"
|
||||
issues:
|
||||
types: [opened, closed]
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: "grafana/grafana-github-actions"
|
||||
path: ./actions
|
||||
ref: main
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: Run metrics collector
|
||||
uses: ./actions/metrics-collector
|
||||
with:
|
||||
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
|
||||
token: ${{secrets.GH_BOT_ACCESS_TOKEN}}
|
||||
38
.github/workflows/publish.yml
vendored
38
.github/workflows/publish.yml
vendored
@@ -1,38 +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
|
||||
- name: generate-packages-docs
|
||||
uses: actions/setup-node@v1
|
||||
id: generate-docs
|
||||
with:
|
||||
node-version: '12'
|
||||
- run: yarn install --pure-lockfile --no-progress
|
||||
- run: ./scripts/ci-reference-docs-build.sh
|
||||
- name: publish-to-git
|
||||
uses: ./.github/actions/gha-publish-to-git
|
||||
id: publish
|
||||
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
|
||||
- shell: bash
|
||||
run: |
|
||||
test -n "${{ steps.publish.outputs.commit_hash }}"
|
||||
test -n "${{ steps.publish.outputs.working_directory }}"
|
||||
71
.gitignore
vendored
71
.gitignore
vendored
@@ -1,28 +1,14 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
coverage/
|
||||
.aws-config.json
|
||||
awsconfig
|
||||
/.awcache
|
||||
/dist
|
||||
/public/build
|
||||
/public/views/index.html
|
||||
/public/views/error.html
|
||||
/emails/dist
|
||||
/reports
|
||||
/e2e/tmp
|
||||
.yarnrc
|
||||
.yarn/
|
||||
vendor/
|
||||
|
||||
# Enterprise emails
|
||||
/emails/templates/enterprise_*
|
||||
/public/emails/enterprise_*
|
||||
|
||||
# Enterprise devenv
|
||||
/devenv/docker/blocks/grafana-enterprise
|
||||
|
||||
/public_gen
|
||||
/public/vendor/npm
|
||||
/tmp
|
||||
tools/phantomjs/phantomjs
|
||||
tools/phantomjs/phantomjs.exe
|
||||
@@ -45,37 +31,25 @@ public/css/*.min.css
|
||||
*.tmp
|
||||
.DS_Store
|
||||
.vscode/
|
||||
.vs/
|
||||
.eslintcache
|
||||
|
||||
/data/*
|
||||
/bin/*
|
||||
|
||||
# devenv
|
||||
/devenv/docker-compose.yaml
|
||||
/devenv/.env
|
||||
|
||||
conf/custom.ini
|
||||
fig.yml
|
||||
docker-compose.yml
|
||||
docker-compose.yaml
|
||||
/conf/provisioning/**/custom.yaml
|
||||
/conf/provisioning/**/dev.yaml
|
||||
/conf/ldap_dev.toml
|
||||
/conf/ldap_freeipa.toml
|
||||
profile.cov
|
||||
/grafana
|
||||
/local
|
||||
.notouch
|
||||
/Makefile.local
|
||||
/pkg/cmd/grafana-cli/grafana-cli
|
||||
/pkg/cmd/grafana-server/grafana-server
|
||||
/pkg/cmd/grafana-server/debug
|
||||
/pkg/extensions/*
|
||||
!/pkg/extensions/main.go
|
||||
/public/app/extensions
|
||||
debug.test
|
||||
/examples/*/dist
|
||||
/packaging/**/*.rpm
|
||||
/packaging/**/*.deb
|
||||
/packaging/**/*.tar.gz
|
||||
|
||||
# Ignore OSX indexing
|
||||
.DS_Store
|
||||
@@ -85,36 +59,5 @@ debug.test
|
||||
/vendor/**/*.yml
|
||||
/vendor/**/*_test.go
|
||||
/vendor/**/.editorconfig
|
||||
*.orig
|
||||
|
||||
/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
|
||||
|
||||
# Ignoring frontend packages specifics
|
||||
/packages/**/dist
|
||||
/packages/**/compiled
|
||||
/packages/**/.rpt2_cache
|
||||
/packages/**/tsdoc-metadata.json
|
||||
|
||||
# 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
|
||||
/vendor/**/appengine*
|
||||
*.orig
|
||||
13
.jscs.json
Normal file
13
.jscs.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"disallowImplicitTypeConversion": ["string"],
|
||||
"disallowKeywords": ["with"],
|
||||
"disallowMultipleLineBreaks": true,
|
||||
"disallowMixedSpacesAndTabs": true,
|
||||
"disallowTrailingWhitespace": true,
|
||||
"requireSpacesInFunctionExpression": {
|
||||
"beforeOpeningCurlyBrace": true
|
||||
},
|
||||
"disallowSpacesInsideArrayBrackets": true,
|
||||
"disallowSpacesInsideParentheses": true,
|
||||
"validateIndentation": 2
|
||||
}
|
||||
37
.jshintrc
Normal file
37
.jshintrc
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"browser": true,
|
||||
"esversion": 6,
|
||||
"bitwise":false,
|
||||
"curly": true,
|
||||
"eqnull": true,
|
||||
"strict": false,
|
||||
"devel": true,
|
||||
"eqeqeq": true,
|
||||
"forin": false,
|
||||
"immed": true,
|
||||
"supernew": true,
|
||||
"expr": true,
|
||||
"indent": 2,
|
||||
"latedef": false,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"noempty": true,
|
||||
"undef": true,
|
||||
"boss": true,
|
||||
"trailing": true,
|
||||
"laxbreak": true,
|
||||
"laxcomma": true,
|
||||
"sub": true,
|
||||
"unused": true,
|
||||
"maxdepth": 6,
|
||||
"maxlen": 140,
|
||||
|
||||
"globals": {
|
||||
"System": true,
|
||||
"Promise": true,
|
||||
"define": true,
|
||||
"require": true,
|
||||
"Chromath": false,
|
||||
"setImmediate": true
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
.git
|
||||
.github
|
||||
dist/
|
||||
pkg/
|
||||
node_modules
|
||||
public/vendor/
|
||||
vendor/
|
||||
data/
|
||||
e2e/tmp
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
...require('@grafana/toolkit/src/config/prettier.plugin.config.json'),
|
||||
};
|
||||
3919
CHANGELOG.md
3919
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -2,25 +2,25 @@
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
# Contributing to Grafana
|
||||
|
||||
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).
|
||||
|
||||
This document is a guide to help you through the process of contributing to Grafana.
|
||||
|
||||
## Become a contributor
|
||||
|
||||
You can contribute to Grafana in several ways. Here are some examples:
|
||||
|
||||
- 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.
|
||||
|
||||
For more ways to contribute, check out the [Open Source Guides](https://opensource.guide/how-to-contribute/).
|
||||
|
||||
### Report bugs
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
#### Security issues
|
||||
|
||||
If you believe you've found a security vulnerability, please read our [security policy](https://github.com/grafana/grafana/security/policy) for more details.
|
||||
|
||||
### Suggest enhancements
|
||||
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
### Triage issues
|
||||
|
||||
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.
|
||||
|
||||
Read more about the ways you can [Triage issues](/contribute/triage-issues.md).
|
||||
|
||||
### Answering questions
|
||||
|
||||
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/).
|
||||
|
||||
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.
|
||||
|
||||
### Your first contribution
|
||||
|
||||
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.
|
||||
80
Dockerfile
80
Dockerfile
@@ -1,80 +0,0 @@
|
||||
FROM node:12.19.0-alpine3.12 as js-builder
|
||||
|
||||
WORKDIR /usr/src/app/
|
||||
|
||||
COPY package.json yarn.lock ./
|
||||
COPY packages packages
|
||||
|
||||
RUN yarn install --pure-lockfile --no-progress
|
||||
|
||||
COPY Gruntfile.js tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js ./
|
||||
COPY public public
|
||||
COPY tools tools
|
||||
COPY scripts scripts
|
||||
COPY emails emails
|
||||
|
||||
ENV NODE_ENV production
|
||||
RUN ./node_modules/.bin/grunt build
|
||||
|
||||
FROM golang:1.15.1-alpine3.12 as go-builder
|
||||
|
||||
RUN apk add --no-cache gcc g++
|
||||
|
||||
WORKDIR $GOPATH/src/github.com/grafana/grafana
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
|
||||
RUN go mod verify
|
||||
|
||||
COPY pkg pkg
|
||||
COPY build.go package.json ./
|
||||
|
||||
RUN go run build.go build
|
||||
|
||||
# Final stage
|
||||
FROM alpine:3.12
|
||||
|
||||
LABEL maintainer="Grafana team <hello@grafana.com>"
|
||||
|
||||
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
|
||||
|
||||
RUN apk add --no-cache ca-certificates bash tzdata && \
|
||||
apk add --no-cache openssl musl-utils
|
||||
|
||||
COPY conf ./conf
|
||||
|
||||
RUN mkdir -p "$GF_PATHS_HOME/.aws" && \
|
||||
addgroup -S -g $GF_GID grafana && \
|
||||
adduser -S -u $GF_UID -G grafana grafana && \
|
||||
mkdir -p "$GF_PATHS_PROVISIONING/datasources" \
|
||||
"$GF_PATHS_PROVISIONING/dashboards" \
|
||||
"$GF_PATHS_PROVISIONING/notifiers" \
|
||||
"$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:grafana "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \
|
||||
chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING"
|
||||
|
||||
COPY --from=go-builder /go/src/github.com/grafana/grafana/bin/linux-amd64/grafana-server /go/src/github.com/grafana/grafana/bin/linux-amd64/grafana-cli ./bin/
|
||||
COPY --from=js-builder /usr/src/app/public ./public
|
||||
COPY --from=js-builder /usr/src/app/tools ./tools
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
COPY ./packaging/docker/run.sh /run.sh
|
||||
|
||||
USER grafana
|
||||
ENTRYPOINT [ "/run.sh" ]
|
||||
@@ -1,76 +0,0 @@
|
||||
FROM node:12.19.0-slim AS js-builder
|
||||
|
||||
WORKDIR /usr/src/app/
|
||||
|
||||
COPY package.json yarn.lock ./
|
||||
COPY packages packages
|
||||
|
||||
RUN yarn install --pure-lockfile
|
||||
|
||||
COPY Gruntfile.js tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js ./
|
||||
COPY public public
|
||||
COPY tools tools
|
||||
COPY scripts scripts
|
||||
COPY emails emails
|
||||
|
||||
ENV NODE_ENV production
|
||||
RUN ./node_modules/.bin/grunt build
|
||||
|
||||
FROM golang:1.15.1 AS go-builder
|
||||
|
||||
WORKDIR /src/grafana
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
|
||||
RUN go mod verify
|
||||
|
||||
COPY build.go package.json ./
|
||||
COPY pkg pkg/
|
||||
|
||||
RUN go run build.go build
|
||||
|
||||
FROM ubuntu:20.04
|
||||
|
||||
LABEL maintainer="Grafana team <hello@grafana.com>"
|
||||
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_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" ]
|
||||
205
GOVERNANCE.md
205
GOVERNANCE.md
@@ -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 O’Carroll ([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
|
||||
638
Gopkg.lock
generated
Normal file
638
Gopkg.lock
generated
Normal file
@@ -0,0 +1,638 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "cloud.google.com/go"
|
||||
packages = ["compute/metadata"]
|
||||
revision = "767c40d6a2e058483c25fa193e963a22da17236d"
|
||||
version = "v0.18.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/BurntSushi/toml"
|
||||
packages = ["."]
|
||||
revision = "b26d9c308763d68093482582cea63d69be07a0f0"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/Unknwon/com"
|
||||
packages = ["."]
|
||||
revision = "7677a1d7c1137cd3dd5ba7a076d0c898a1ef4520"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/apache/thrift"
|
||||
packages = ["lib/go/thrift"]
|
||||
revision = "b2a4d4ae21c789b689dd162deb819665567f481c"
|
||||
version = "0.10.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/aws/aws-sdk-go"
|
||||
packages = [
|
||||
"aws",
|
||||
"aws/awserr",
|
||||
"aws/awsutil",
|
||||
"aws/client",
|
||||
"aws/client/metadata",
|
||||
"aws/corehandlers",
|
||||
"aws/credentials",
|
||||
"aws/credentials/ec2rolecreds",
|
||||
"aws/credentials/endpointcreds",
|
||||
"aws/credentials/stscreds",
|
||||
"aws/defaults",
|
||||
"aws/ec2metadata",
|
||||
"aws/endpoints",
|
||||
"aws/request",
|
||||
"aws/session",
|
||||
"aws/signer/v4",
|
||||
"internal/shareddefaults",
|
||||
"private/protocol",
|
||||
"private/protocol/ec2query",
|
||||
"private/protocol/query",
|
||||
"private/protocol/query/queryutil",
|
||||
"private/protocol/rest",
|
||||
"private/protocol/restxml",
|
||||
"private/protocol/xml/xmlutil",
|
||||
"service/cloudwatch",
|
||||
"service/ec2",
|
||||
"service/ec2/ec2iface",
|
||||
"service/s3",
|
||||
"service/sts"
|
||||
]
|
||||
revision = "decd990ddc5dcdf2f73309cbcab90d06b996ca28"
|
||||
version = "v1.12.67"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/benbjohnson/clock"
|
||||
packages = ["."]
|
||||
revision = "7dc76406b6d3c05b5f71a86293cbcf3c4ea03b19"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/beorn7/perks"
|
||||
packages = ["quantile"]
|
||||
revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/bmizerany/assert"
|
||||
packages = ["."]
|
||||
revision = "b7ed37b82869576c289d7d97fb2bbd8b64a0cb28"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/bradfitz/gomemcache"
|
||||
packages = ["memcache"]
|
||||
revision = "1952afaa557dc08e8e0d89eafab110fb501c1a2b"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/codahale/hdrhistogram"
|
||||
packages = ["."]
|
||||
revision = "3a0bb77429bd3a61596f5e8a3172445844342120"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/codegangsta/cli"
|
||||
packages = ["."]
|
||||
revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1"
|
||||
version = "v1.20.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fatih/color"
|
||||
packages = ["."]
|
||||
revision = "570b54cabe6b8eb0bc2dfce68d964677d63b5260"
|
||||
version = "v1.5.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-ini/ini"
|
||||
packages = ["."]
|
||||
revision = "32e4c1e6bc4e7d0d8451aa6b75200d19e37a536a"
|
||||
version = "v1.32.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-ldap/ldap"
|
||||
packages = ["."]
|
||||
revision = "bb7a9ca6e4fbc2129e3db588a34bc970ffe811a9"
|
||||
version = "v2.5.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-macaron/binding"
|
||||
packages = ["."]
|
||||
revision = "ac54ee249c27dca7e76fad851a4a04b73bd1b183"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-macaron/gzip"
|
||||
packages = ["."]
|
||||
revision = "cad1c6580a07c56f5f6bc52d66002a05985c5854"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-macaron/inject"
|
||||
packages = ["."]
|
||||
revision = "d8a0b8677191f4380287cfebd08e462217bac7ad"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-macaron/session"
|
||||
packages = [
|
||||
".",
|
||||
"memcache",
|
||||
"mysql",
|
||||
"postgres",
|
||||
"redis"
|
||||
]
|
||||
revision = "b8e286a0dba8f4999042d6b258daf51b31d08938"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
packages = ["."]
|
||||
revision = "2cc627ac8defc45d65066ae98f898166f580f9a4"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-stack/stack"
|
||||
packages = ["."]
|
||||
revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc"
|
||||
version = "v1.7.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-xorm/builder"
|
||||
packages = ["."]
|
||||
revision = "488224409dd8aa2ce7a5baf8d10d55764a913738"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-xorm/core"
|
||||
packages = ["."]
|
||||
revision = "da1adaf7a28ca792961721a34e6e04945200c890"
|
||||
version = "v0.5.7"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-xorm/xorm"
|
||||
packages = ["."]
|
||||
revision = "1933dd69e294c0a26c0266637067f24dbb25770c"
|
||||
version = "v0.6.4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
"ptypes",
|
||||
"ptypes/any",
|
||||
"ptypes/duration",
|
||||
"ptypes/timestamp"
|
||||
]
|
||||
revision = "c65a0412e71e8b9b3bfd22925720d23c0f054237"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/gopherjs/gopherjs"
|
||||
packages = ["js"]
|
||||
revision = "178c176a91fe05e3e6c58fa5c989bad19e6cdcb3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gorilla/websocket"
|
||||
packages = ["."]
|
||||
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gosimple/slug"
|
||||
packages = ["."]
|
||||
revision = "e9f42fa127660e552d0ad2b589868d403a9be7c6"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/grafana/grafana_plugin_model"
|
||||
packages = ["go/datasource"]
|
||||
revision = "dfe5dc0a6ce05825ba7fe2d0323d92e631bffa89"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-hclog"
|
||||
packages = ["."]
|
||||
revision = "5bcb0f17e36442247290887cc914a6e507afa5c4"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/hashicorp/go-plugin"
|
||||
packages = ["."]
|
||||
revision = "3e6d191694b5a3a2b99755f31b47fa209e4bcd09"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-version"
|
||||
packages = ["."]
|
||||
revision = "4fe82ae3040f80a03d04d2cccb5606a626b8e1ee"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/yamux"
|
||||
packages = ["."]
|
||||
revision = "683f49123a33db61abfb241b7ac5e4af4dc54d55"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/inconshreveable/log15"
|
||||
packages = ["."]
|
||||
revision = "0decfc6c20d9ca0ad143b0e89dcaa20f810b4fb3"
|
||||
version = "v2.13"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/jmespath/go-jmespath"
|
||||
packages = ["."]
|
||||
revision = "0b12d6b5"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/jtolds/gls"
|
||||
packages = ["."]
|
||||
revision = "77f18212c9c7edc9bd6a33d383a7b545ce62f064"
|
||||
version = "v4.2.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/klauspost/compress"
|
||||
packages = [
|
||||
"flate",
|
||||
"gzip"
|
||||
]
|
||||
revision = "6c8db69c4b49dd4df1fff66996cf556176d0b9bf"
|
||||
version = "v1.2.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/klauspost/cpuid"
|
||||
packages = ["."]
|
||||
revision = "ae7887de9fa5d2db4eaa8174a7eff2c1ac00f2da"
|
||||
version = "v1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/klauspost/crc32"
|
||||
packages = ["."]
|
||||
revision = "cb6bfca970f6908083f26f39a79009d608efd5cd"
|
||||
version = "v1.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/kr/pretty"
|
||||
packages = ["."]
|
||||
revision = "cfb55aafdaf3ec08f0db22699ab822c50091b1c4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/kr/text"
|
||||
packages = ["."]
|
||||
revision = "7cafcd837844e784b526369c9bce262804aebc60"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/lib/pq"
|
||||
packages = [
|
||||
".",
|
||||
"oid"
|
||||
]
|
||||
revision = "61fe37aa2ee24fabcdbe5c4ac1d4ac566f88f345"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-colorable"
|
||||
packages = ["."]
|
||||
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
|
||||
version = "v0.0.9"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-isatty"
|
||||
packages = ["."]
|
||||
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
|
||||
version = "v0.0.3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-sqlite3"
|
||||
packages = ["."]
|
||||
revision = "6c771bb9887719704b210e87e934f08be014bdb1"
|
||||
version = "v1.6.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/matttproud/golang_protobuf_extensions"
|
||||
packages = ["pbutil"]
|
||||
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mitchellh/go-testing-interface"
|
||||
packages = ["."]
|
||||
revision = "a61a99592b77c9ba629d254a693acffaeb4b7e28"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/opentracing/opentracing-go"
|
||||
packages = [
|
||||
".",
|
||||
"ext",
|
||||
"log"
|
||||
]
|
||||
revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38"
|
||||
version = "v1.0.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/patrickmn/go-cache"
|
||||
packages = ["."]
|
||||
revision = "a3647f8e31d79543b2d0f0ae2fe5c379d72cedc0"
|
||||
version = "v2.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
packages = [
|
||||
"api",
|
||||
"api/prometheus/v1",
|
||||
"prometheus",
|
||||
"prometheus/promhttp"
|
||||
]
|
||||
revision = "967789050ba94deca04a5e84cce8ad472ce313c1"
|
||||
version = "v0.9.0-pre1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/client_model"
|
||||
packages = ["go"]
|
||||
revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/common"
|
||||
packages = [
|
||||
"expfmt",
|
||||
"internal/bitbucket.org/ww/goautoneg",
|
||||
"model"
|
||||
]
|
||||
revision = "89604d197083d4781071d3c65855d24ecfb0a563"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/procfs"
|
||||
packages = [
|
||||
".",
|
||||
"internal/util",
|
||||
"nfsd",
|
||||
"xfs"
|
||||
]
|
||||
revision = "85fadb6e89903ef7cca6f6a804474cd5ea85b6e1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/rainycape/unidecode"
|
||||
packages = ["."]
|
||||
revision = "cb7f23ec59bec0d61b19c56cd88cee3d0cc1870c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/sergi/go-diff"
|
||||
packages = ["diffmatchpatch"]
|
||||
revision = "1744e2970ca51c86172c8190fadad617561ed6e7"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/smartystreets/assertions"
|
||||
packages = [
|
||||
".",
|
||||
"internal/go-render/render",
|
||||
"internal/oglematchers"
|
||||
]
|
||||
revision = "0b37b35ec7434b77e77a4bb29b79677cced992ea"
|
||||
version = "1.8.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/smartystreets/goconvey"
|
||||
packages = [
|
||||
"convey",
|
||||
"convey/gotest",
|
||||
"convey/reporting"
|
||||
]
|
||||
revision = "9e8dc3f972df6c8fcc0375ef492c24d0bb204857"
|
||||
version = "1.6.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/teris-io/shortid"
|
||||
packages = ["."]
|
||||
revision = "771a37caa5cf0c81f585d7b6df4dfc77e0615b5c"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/uber/jaeger-client-go"
|
||||
packages = [
|
||||
".",
|
||||
"config",
|
||||
"internal/baggage",
|
||||
"internal/baggage/remote",
|
||||
"internal/spanlog",
|
||||
"log",
|
||||
"rpcmetrics",
|
||||
"thrift-gen/agent",
|
||||
"thrift-gen/baggage",
|
||||
"thrift-gen/jaeger",
|
||||
"thrift-gen/sampling",
|
||||
"thrift-gen/zipkincore",
|
||||
"utils"
|
||||
]
|
||||
revision = "3ac96c6e679cb60a74589b0d0aa7c70a906183f7"
|
||||
version = "v2.11.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/uber/jaeger-lib"
|
||||
packages = ["metrics"]
|
||||
revision = "7f95f4f7e80028096410abddaae2556e4c61b59f"
|
||||
version = "v1.3.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/yudai/gojsondiff"
|
||||
packages = [
|
||||
".",
|
||||
"formatter"
|
||||
]
|
||||
revision = "7b1b7adf999dab73a6eb02669c3d82dbb27a3dd6"
|
||||
version = "1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/yudai/golcs"
|
||||
packages = ["."]
|
||||
revision = "ecda9a501e8220fae3b4b600c3db4b0ba22cfc68"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["pbkdf2"]
|
||||
revision = "3d37316aaa6bd9929127ac9a527abf408178ea7b"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"context",
|
||||
"context/ctxhttp",
|
||||
"http2",
|
||||
"http2/hpack",
|
||||
"idna",
|
||||
"internal/timeseries",
|
||||
"lex/httplex",
|
||||
"trace"
|
||||
]
|
||||
revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
packages = [
|
||||
".",
|
||||
"google",
|
||||
"internal",
|
||||
"jws",
|
||||
"jwt"
|
||||
]
|
||||
revision = "b28fcf2b08a19742b43084fb40ab78ac6c3d8067"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sync"
|
||||
packages = ["errgroup"]
|
||||
revision = "fd80eb99c8f653c847d294a001bdf2a3a6f768f5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "af50095a40f9041b3b38960738837185c26e9419"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/text"
|
||||
packages = [
|
||||
"collate",
|
||||
"collate/build",
|
||||
"internal/colltab",
|
||||
"internal/gen",
|
||||
"internal/tag",
|
||||
"internal/triegen",
|
||||
"internal/ucd",
|
||||
"language",
|
||||
"secure/bidirule",
|
||||
"transform",
|
||||
"unicode/bidi",
|
||||
"unicode/cldr",
|
||||
"unicode/norm",
|
||||
"unicode/rangetable"
|
||||
]
|
||||
revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/appengine"
|
||||
packages = [
|
||||
".",
|
||||
"cloudsql",
|
||||
"internal",
|
||||
"internal/app_identity",
|
||||
"internal/base",
|
||||
"internal/datastore",
|
||||
"internal/log",
|
||||
"internal/modules",
|
||||
"internal/remote_api",
|
||||
"internal/urlfetch",
|
||||
"urlfetch"
|
||||
]
|
||||
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
revision = "a8101f21cf983e773d0c1133ebc5424792003214"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/grpc"
|
||||
packages = [
|
||||
".",
|
||||
"balancer",
|
||||
"balancer/base",
|
||||
"balancer/roundrobin",
|
||||
"codes",
|
||||
"connectivity",
|
||||
"credentials",
|
||||
"encoding",
|
||||
"grpclb/grpc_lb_v1/messages",
|
||||
"grpclog",
|
||||
"health",
|
||||
"health/grpc_health_v1",
|
||||
"internal",
|
||||
"keepalive",
|
||||
"metadata",
|
||||
"naming",
|
||||
"peer",
|
||||
"resolver",
|
||||
"resolver/dns",
|
||||
"resolver/passthrough",
|
||||
"stats",
|
||||
"status",
|
||||
"tap",
|
||||
"transport"
|
||||
]
|
||||
revision = "6b51017f791ae1cfbec89c52efdf444b13b550ef"
|
||||
version = "v1.9.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "v3"
|
||||
name = "gopkg.in/alexcesaro/quotedprintable.v3"
|
||||
packages = ["."]
|
||||
revision = "2caba252f4dc53eaf6b553000885530023f54623"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/asn1-ber.v1"
|
||||
packages = ["."]
|
||||
revision = "379148ca0225df7a432012b8df0355c2a2063ac0"
|
||||
version = "v1.2"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/bufio.v1"
|
||||
packages = ["."]
|
||||
revision = "567b2bfa514e796916c4747494d6ff5132a1dfce"
|
||||
version = "v1"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/gomail.v2"
|
||||
packages = ["."]
|
||||
revision = "81ebce5c23dfd25c6c67194b37d3dd3f338c98b1"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/ini.v1"
|
||||
packages = ["."]
|
||||
revision = "32e4c1e6bc4e7d0d8451aa6b75200d19e37a536a"
|
||||
version = "v1.32.0"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/macaron.v1"
|
||||
packages = ["."]
|
||||
revision = "75f2e9b42e99652f0d82b28ccb73648f44615faa"
|
||||
version = "v1.2.4"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/redis.v2"
|
||||
packages = ["."]
|
||||
revision = "e6179049628164864e6e84e973cfb56335748dea"
|
||||
version = "v2.3.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "112ccff73f668c8c4dbe3d41c37ebee65fd7d839f5a4fa0665c593cae0095dad"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
197
Gopkg.toml
Normal file
197
Gopkg.toml
Normal file
@@ -0,0 +1,197 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
||||
ignored = [
|
||||
"github.com/grafana/grafana/data/*",
|
||||
"github.com/grafana/grafana/public/*",
|
||||
"github.com/grafana/grafana/node_modules/*"
|
||||
]
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/BurntSushi/toml"
|
||||
version = "0.3.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/Unknwon/com"
|
||||
#version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/aws/aws-sdk-go"
|
||||
version = "1.12.65"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/benbjohnson/clock"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/bmizerany/assert"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/codegangsta/cli"
|
||||
version = "1.20.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
version = "1.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/fatih/color"
|
||||
version = "1.5.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-ldap/ldap"
|
||||
version = "2.5.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/go-macaron/binding"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/go-macaron/gzip"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/go-macaron/session"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
revision = "2cc627ac8defc45d65066ae98f898166f580f9a4"
|
||||
#version = "1.3.0" //keeping this since we would rather depend on version then commit
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-stack/stack"
|
||||
version = "1.7.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-xorm/core"
|
||||
version = "0.5.7"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-xorm/xorm"
|
||||
version = "0.6.4"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gorilla/websocket"
|
||||
version = "1.2.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gosimple/slug"
|
||||
version = "1.1.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/grafana/grafana_plugin_model"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-hclog"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-version"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/inconshreveable/log15"
|
||||
version = "2.13.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/lib/pq"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/mattn/go-isatty"
|
||||
version = "0.0.3"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/mattn/go-sqlite3"
|
||||
version = "1.6.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/opentracing/opentracing-go"
|
||||
version = "1.0.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/patrickmn/go-cache"
|
||||
version = "2.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
version = "0.9.0-pre1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/client_model"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/common"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/smartystreets/goconvey"
|
||||
version = "1.6.3"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/uber/jaeger-client-go"
|
||||
version = "2.11.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/yudai/gojsondiff"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sync"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/gomail.v2"
|
||||
branch = "v2"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/ini.v1"
|
||||
version = "1.32.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/macaron.v1"
|
||||
version = "1.2.4"
|
||||
|
||||
[[constraint]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
|
||||
[prune]
|
||||
non-go = true
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/teris-io/shortid"
|
||||
37
Gruntfile.js
37
Gruntfile.js
@@ -1,5 +1,6 @@
|
||||
/* jshint node:true */
|
||||
'use strict';
|
||||
module.exports = function(grunt) {
|
||||
module.exports = function (grunt) {
|
||||
var os = require('os');
|
||||
var config = {
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
@@ -9,18 +10,8 @@ module.exports = function(grunt) {
|
||||
destDir: 'dist',
|
||||
tempDir: 'tmp',
|
||||
platform: process.platform.replace('win32', 'windows'),
|
||||
enterprise: false,
|
||||
libc: null,
|
||||
};
|
||||
|
||||
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 {
|
||||
@@ -31,10 +22,8 @@ module.exports = function(grunt) {
|
||||
}
|
||||
}
|
||||
|
||||
if (grunt.option('libc')) {
|
||||
config.libc = grunt.option('libc');
|
||||
}
|
||||
|
||||
config.coverage = grunt.option('coverage');
|
||||
config.phjs = grunt.option('phjsToRelease');
|
||||
config.pkg.version = grunt.option('pkgVer') || config.pkg.version;
|
||||
|
||||
console.log('Version', config.pkg.version);
|
||||
@@ -46,21 +35,19 @@ module.exports = function(grunt) {
|
||||
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));
|
||||
});
|
||||
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/');
|
||||
loadConfig(config,'./scripts/grunt/options/');
|
||||
// pass the config to grunt
|
||||
grunt.initConfig(config);
|
||||
};
|
||||
|
||||
346
ISSUE_TRIAGE.md
346
ISSUE_TRIAGE.md
@@ -1,346 +0,0 @@
|
||||
# Triage 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.
|
||||
|
||||
> **Note:** This information is for Grafana project Maintainers, Owners, and Admins. If you are a Contributor, then you will not be able to perform most of the tasks in this topic.
|
||||
|
||||
The core maintainers of the Grafana project are responsible for categorizing all incoming issues and delegating any critical or important issue to other maintainers. Currently one maintainer each week is responsible. Besides that part, triage provides an important way to contribute to an open source project.
|
||||
|
||||
Triage helps ensure issues resolve quickly by:
|
||||
|
||||
- Ensuring the issue's intent and purpose is conveyed precisely. This is necessary because it can be difficult for an issue to explain how an end user experiences a problem and what actions they took.
|
||||
- Giving a contributor the information they need before they commit to resolving an issue.
|
||||
- Lowering the issue count by preventing duplicate issues.
|
||||
- Streamlining the development process by preventing duplicate discussions.
|
||||
|
||||
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 -->
|
||||
```
|
||||
+--------------------------+
|
||||
+----------------+ New issue opened/ |
|
||||
| | more information added |
|
||||
| +-------------+------------+
|
||||
| Ask for more |
|
||||
| information +-------------+------------+
|
||||
| | All information needed |
|
||||
| +--------+ to categorize the issue? +--------+
|
||||
| | | | |
|
||||
| | NO +--------------------------+ YES |
|
||||
| | |
|
||||
+------+-------+-------------+ +------------+---------+ +----------------------------+
|
||||
| | | | | |
|
||||
| label: needs more info | | Needs investigation? +--YES---+ label: needs investigation |
|
||||
| | | | | |
|
||||
+----------------------------+ +----------------+-----+ +--------------+-------------+
|
||||
NO | |
|
||||
| Investigate |
|
||||
+-----------+----------+ |
|
||||
| label: type/* | |
|
||||
| label: area/* +------------------+
|
||||
| label: datasource/* |
|
||||
+-----|----------+-----+
|
||||
| |
|
||||
| |
|
||||
| +--+--------------------+ +--------------------+
|
||||
| | | | label: priority/* |
|
||||
| | Needs priority? +--YES---+| milestone? |
|
||||
| | | | |
|
||||
| +--------------------+--+ +----+---------------+
|
||||
| NO | |
|
||||
| | |
|
||||
+----+-------------+ +---+----------+ |
|
||||
| | | | |
|
||||
| Close issue +----------+ Done +------+
|
||||
| | | |
|
||||
+------------------+ +--------------+
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
### Subscribe to all notifications
|
||||
|
||||
The more advanced, but recommended way is to subscribe to all notifications from this repository which means that all new issues, pull requests, comments and important status changes are sent to your configured email address. Read this [guide](https://help.github.com/en/articles/watching-and-unwatching-repositories#watching-a-single-repository) for help with setting this up.
|
||||
|
||||
It's highly recommended that you setup filters to automatically remove emails from the inbox and label/categorize them accordingly to make it easy for you to understand when you need to act upon a notification or where to look for finding issues that haven't been triaged etc.
|
||||
|
||||
Instructions for setting up filters in Gmail can be found [here](#setting-up-gmail-filters). Another alternative is to use [Trailer](https://github.com/ptsochantaris/trailer) or similar software.
|
||||
|
||||
## 2. Ensure the issue contains basic information
|
||||
|
||||
Before triaging an issue very far, make sure that the issue's author provided the standard issue information. This will help you make an educated recommendation on how to categorize the issue. The Grafana project utilizes [GitHub issue templates](https://help.github.com/en/articles/creating-issue-templates-for-your-repository) to guide contributors to provide standard information that must be included for each type of template or type of issue.
|
||||
|
||||
### Standard issue information that must be included
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
- Data source type & version
|
||||
- Platform & OS Grafana is installed on
|
||||
- User OS & Browser + versions
|
||||
- Using docker + what environment
|
||||
- Which plugins
|
||||
- Configuration database in use (sqlite, mysql, postgres)
|
||||
- Reverse proxy in front of Grafana, what version and configuration
|
||||
- Non-default configuration settings
|
||||
- Development environment like Go and Node versions, if applicable
|
||||
|
||||
#### Enhancement requests
|
||||
|
||||
Should explain what enhancement or feature that the author wants to be added and why that is needed.
|
||||
|
||||
#### Accessibility issues
|
||||
|
||||
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
|
||||
|
||||
In general, if the issue description and title is perceived as a question no more information is needed.
|
||||
|
||||
### Good practices
|
||||
|
||||
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.
|
||||
|
||||
> **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?
|
||||
|
||||
Depending on the issue, you might not feel all this information is needed. Use your best judgement. If you cannot triage an issue using what its author provided, explain kindly to the author that they must provide the above information to clarify the problem. Label issue with `needs more detail` and add any related `area/*` or `datasource/*` labels.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
| 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. |
|
||||
|
||||
### Duplicate issues
|
||||
|
||||
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:
|
||||
|
||||
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
|
||||
3. Optionally add any related `area/*` or `datasource/*` labels.
|
||||
|
||||
### Bug reports
|
||||
|
||||
If it's not perfectly clear that it's an actual bug, quickly try to reproduce it.
|
||||
|
||||
**It's a bug/it can be reproduced:**
|
||||
|
||||
1. Add a comment describing detailed steps for how to reproduce it, if applicable.
|
||||
2. Label the issue `type/bug` and at least one `area/*` or `datasource/*` label.
|
||||
3. If you know that maintainers wont be able to put any resources into it for some time then label the issue with `help wanted` and optionally `beginner friendly` together with pointers on which code to update to fix the bug. This should signal to the community that we would appreciate any help we can get to resolve this.
|
||||
4. Move on to [prioritizing the issue](#4-prioritization-of-issues).
|
||||
|
||||
**It can't be reproduced:**
|
||||
1. Either [ask for more information](#2-ensure-the-issue-contains-basic-information) needed to investigate it more thoroughly.
|
||||
2. Either [delegate further investigations](#investigation-of-issues) to someone else.
|
||||
|
||||
**It works as intended/by design:**
|
||||
1. Kindly and politely add a comment explaining briefly why we think it works as intended and close the issue.
|
||||
2. Label the issue `type/works-as-intended`.
|
||||
|
||||
### Enhancement/feature?
|
||||
|
||||
1. Label the issue `type/feature-request` and at least one `area/*` or `datasource/*` label.
|
||||
2. Move on to [prioritizing the issue](#4-prioritization-of-issues).
|
||||
|
||||
### Documentation issue?
|
||||
|
||||
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.
|
||||
|
||||
Second, label the issue `type/docs` and at least one `area/*` or `datasource/*` label.
|
||||
|
||||
**Minor typo/error/lack of information:**
|
||||
|
||||
There's a minor typo/error/lack of information that adds a lot of confusion for users and given the amount of work is a big win to make sure fixing it:
|
||||
1. Either update the documentation yourself and open a pull request.
|
||||
2. Either delegate the work to someone else by assigning that person to the issue and add the issue to next major/minor milestone.
|
||||
|
||||
**Major error/lack of information:**
|
||||
|
||||
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
|
||||
|
||||
1. Label the issue `type/accessibility` and at least one `area/*` or `datasource/*` label.
|
||||
|
||||
### Support requests
|
||||
|
||||
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`.
|
||||
|
||||
## 4. Prioritization of issues
|
||||
|
||||
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.
|
||||
|
||||
In case there is an uncertainty around the prioritization 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. |
|
||||
|
||||
**Critical bugs**
|
||||
|
||||
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.
|
||||
|
||||
- Results in any data loss
|
||||
- Critical security or performance issues
|
||||
- Problem that makes a feature unusable
|
||||
- Multiple users experience a severe problem affecting their business, users etc.
|
||||
|
||||
2. Label the issue `priority/critical`.
|
||||
3. If applicable, label the issue `priority/support-subscription`.
|
||||
4. Add the issue to the next upcoming patch release milestone. Create a new milestone if there are none.
|
||||
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**
|
||||
|
||||
1. Label the issue `priority/important-soon`.
|
||||
2. If applicable, label the issue `priority/support-subscription`.
|
||||
3. Add the issue to the next upcoming patch or major/minor stable release milestone. Ask maintainers for help if unsure if it's a patch or not. Create a new milestone if there are none.
|
||||
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**
|
||||
|
||||
1. Label the issue `priority/important-longterm`.
|
||||
2. Consider requesting [help from the community](#5-requesting-help-from-the-community).
|
||||
|
||||
**Nice to have**
|
||||
|
||||
1. Label the issue `priority/nice-to-have`.
|
||||
2. Consider requesting [help from the community](#5-requesting-help-from-the-community).
|
||||
|
||||
**Not critical, but unsure?**
|
||||
|
||||
1. Label the issue `priority/unscheduled`.
|
||||
2. Consider requesting [help from the community](#5-requesting-help-from-the-community).
|
||||
|
||||
## 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.
|
||||
|
||||
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:
|
||||
|
||||
- Database setups
|
||||
- Authentication like OAuth providers and LDAP setups
|
||||
- Platform specific things
|
||||
- Reverse proxy setups
|
||||
- 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.
|
||||
- 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.
|
||||
4. If possible, try to estimate the amount of work by adding `effort/small`, `effort/medium` or `effort/large`.
|
||||
|
||||
## 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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Even if you don't have the time or knowledge to investigate an issue we highly recommend that you [upvote](https://help.github.com/en/articles/about-conversations-on-github#reacting-to-ideas-in-comments) the issue if you happen to have the same problem. If you have further details that may help investigating the issue please provide as much information as possible.
|
||||
|
||||
## Automation
|
||||
|
||||
We have some automation that triggers on comments or labels being added to issues. Many of these automated behaviors are defined in [commands.json](https://github.com/grafana/grafana/blob/master/.github/commands.json). Or in other [GitHub Actions](https://github.com/grafana/grafana/tree/master/.github/workflows)
|
||||
|
||||
* Add /duplicate `#<issue number>` to have Grafana label & close issue with an appropriate message.
|
||||
* Add `type/question` and the bot will close it with an appropriate message.
|
||||
|
||||
## External PRs
|
||||
|
||||
Part of issue triage should also be triaging of external PRs. Main goal should be to make sure PRs from external contributors have an owner/reviewer and are not forgotten.
|
||||
|
||||
1. Check new external PRs which do not have a reviewer.
|
||||
1. Check if there is a link to an existing issue.
|
||||
1. If not and you know which issue it is solving, add the link yourself, otherwise ask the author to link the issue or create one.
|
||||
1. 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.
|
||||
|
||||
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)
|
||||
2. In Gmail, go to Settings -> Filters and Blocked Addresses
|
||||
3. Import filters -> select xml file -> Open file
|
||||
4. Review filters
|
||||
5. Optional, Check Apply new filters to existing email
|
||||
6. Create filters
|
||||
|
||||
This will give you a structure of labels in the sidebar similar to the following:
|
||||
```
|
||||
- Inbox
|
||||
...
|
||||
- GitHub (mine)
|
||||
- activity
|
||||
- assigned
|
||||
- mentions
|
||||
- GitHub (other)
|
||||
- Grafana
|
||||
```
|
||||
|
||||
- All notifications you’ll need to read/take action on show up as unread in GitHub (mine) and its sub-labels.
|
||||
- All other notifications you don’t 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.
|
||||
202
LICENSE
202
LICENSE
@@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2015 Grafana Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -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
|
||||
169
Makefile
169
Makefile
@@ -1,164 +1,31 @@
|
||||
## 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 tidy-check test-go test-js test run run-frontend clean devenv devenv-down revive-strict protobuf help
|
||||
|
||||
GO = GO111MODULE=on go
|
||||
GO_FILES ?= ./pkg/...
|
||||
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 ## Install frontend dependencies.
|
||||
|
||||
deps: deps-js ## Install all dependencies.
|
||||
|
||||
node_modules: package.json yarn.lock ## Install node modules.
|
||||
@echo "install frontend dependencies"
|
||||
deps-js:
|
||||
yarn install --pure-lockfile --no-progress
|
||||
|
||||
##@ Building
|
||||
deps: deps-js
|
||||
|
||||
build-go: ## Build all Go binaries.
|
||||
@echo "build go files"
|
||||
$(GO) run build.go build
|
||||
build-go:
|
||||
go run build.go build
|
||||
|
||||
build-server: ## Build Grafana server.
|
||||
@echo "build server"
|
||||
$(GO) run build.go build-server
|
||||
build-js:
|
||||
npm run build
|
||||
|
||||
build-cli: ## Build Grafana CLI application.
|
||||
@echo "build in CI environment"
|
||||
$(GO) run build.go build-cli
|
||||
build: build-go build-js
|
||||
|
||||
build-js: ## Build frontend assets.
|
||||
@echo "build frontend"
|
||||
yarn run build
|
||||
yarn run plugins:build-bundled
|
||||
test-go:
|
||||
go test -v ./pkg/...
|
||||
|
||||
build: build-go build-js ## Build backend and frontend.
|
||||
test-js:
|
||||
npm test
|
||||
|
||||
scripts/go/bin/bra: scripts/go/go.mod
|
||||
@cd scripts/go; \
|
||||
$(GO) build -o ./bin/bra github.com/unknwon/bra
|
||||
test: test-go test-js
|
||||
|
||||
run: scripts/go/bin/bra ## Build and run web server on filesystem changes.
|
||||
@GO111MODULE=on scripts/go/bin/bra run
|
||||
run:
|
||||
./bin/grafana-server
|
||||
|
||||
run-frontend: deps-js ## Fetch js dependencies and watch frontend for rebuild
|
||||
yarn start
|
||||
|
||||
##@ Testing
|
||||
|
||||
test-go: ## Run tests for backend.
|
||||
@echo "test backend"
|
||||
$(GO) test -v ./pkg/...
|
||||
|
||||
test-js: ## Run tests for frontend.
|
||||
@echo "test frontend"
|
||||
yarn test
|
||||
|
||||
test: test-go test-js ## Run all tests.
|
||||
|
||||
##@ Linting
|
||||
|
||||
scripts/go/bin/revive: scripts/go/go.mod
|
||||
@cd scripts/go; \
|
||||
$(GO) build -o ./bin/revive github.com/mgechev/revive
|
||||
|
||||
revive: scripts/go/bin/revive
|
||||
@echo "lint via revive"
|
||||
@scripts/go/bin/revive \
|
||||
-formatter stylish \
|
||||
-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
|
||||
|
||||
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
|
||||
|
||||
golangci-lint: scripts/go/bin/golangci-lint
|
||||
@echo "lint via golangci-lint"
|
||||
@scripts/go/bin/golangci-lint run \
|
||||
--config ./scripts/go/configs/.golangci.toml \
|
||||
$(GO_FILES)
|
||||
|
||||
tidy-check:
|
||||
@echo "check whether go.mod and go.sum are consistent"
|
||||
@scripts/tidy-check.sh
|
||||
|
||||
lint-go: golangci-lint revive revive-strict tidy-check # Run all code checks for backend.
|
||||
|
||||
# with disabled SC1071 we are ignored some TCL,Expect `/usr/bin/env expect` scripts
|
||||
shellcheck: $(SH_FILES) ## Run checks for shell scripts.
|
||||
@docker run --rm -v "$$PWD:/mnt" koalaman/shellcheck:stable \
|
||||
$(SH_FILES) -e SC1071 -e SC2162
|
||||
|
||||
##@ 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
|
||||
|
||||
# create docker-compose file with provided sources and start them
|
||||
# example: make devenv sources=postgres,openldap
|
||||
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.
|
||||
$(eval targets := $(shell echo '$(sources)' | tr "," " "))
|
||||
|
||||
@cd devenv; \
|
||||
./create_docker_compose.sh $(targets) || \
|
||||
(rm -rf {docker-compose.yaml,conf.tmp,.env}; exit 1)
|
||||
|
||||
@cd devenv; \
|
||||
docker-compose up -d --build
|
||||
endif
|
||||
|
||||
devenv-down: ## Stop optional services.
|
||||
@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)
|
||||
protoc:
|
||||
protoc -I pkg/tsdb/models pkg/tsdb/models/*.proto --go_out=plugins=grpc:pkg/tsdb/models/.
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
Copyright 2014-2018 Grafana Labs
|
||||
Copyright 2014-2017 Grafana Labs
|
||||
|
||||
This software is based on Kibana:
|
||||
Copyright 2012-2013 Elasticsearch BV
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
# 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
|
||||
This document is not meant as complete guide for developing plugins but more as a changelog for changes in
|
||||
Grafana that can impact plugin development. When ever you as 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)
|
||||
- [Simple JSON datasource plugin](https://github.com/grafana/simple-json-datasource)
|
||||
- [Datasource plugin written in typescript](https://github.com/grafana/typescript-template-datasource)
|
||||
- [Simple json dataource plugin](https://github.com/grafana/simple-json-datasource)
|
||||
- [Plugin development guide](http://docs.grafana.org/plugins/developing/development/)
|
||||
|
||||
## 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 +24,5 @@ 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
|
||||
|
||||
### DashboardSrv.ts
|
||||
|
||||
If you utilize [DashboardSrv](https://github.com/grafana/grafana/commit/8574dca081002f36e482b572517d8f05fd44453f#diff-1ab99561f9f6a10e1fafcddc39bc1d65) in your plugin code, `dash` was renamed to `dashboard`.
|
||||
|
||||
136
README.md
136
README.md
@@ -1,46 +1,124 @@
|
||||

|
||||
[Grafana](https://grafana.com) [](https://circleci.com/gh/grafana/grafana) [](https://goreportcard.com/report/github.com/grafana/grafana) [](https://codecov.io/gh/grafana/grafana)
|
||||
================
|
||||
[Website](https://grafana.com) |
|
||||
[Twitter](https://twitter.com/grafana) |
|
||||
[Community & Forum](https://community.grafana.com)
|
||||
|
||||
The open-source platform for monitoring and observability.
|
||||
Grafana is an open source, feature rich metrics dashboard and graph editor for
|
||||
Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB.
|
||||
|
||||
[](LICENSE)
|
||||
[](https://circleci.com/gh/grafana/grafana)
|
||||
[](https://goreportcard.com/report/github.com/grafana/grafana)
|
||||

|
||||
|
||||
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:
|
||||
## Grafana v5 Alpha Preview
|
||||
Grafana master is now v5.0 alpha. This is going to be the biggest and most foundational release Grafana has ever had, coming with a ton of UX improvements, a new dashboard grid engine, dashboard folders, user teams and permissions. Checkout out this [video preview](https://www.youtube.com/watch?v=BC_YRNpqj5k) of Grafana v5.
|
||||
|
||||
- **Visualize:** Fast and flexible client side graphs with a multitude of options. Panel plugins for many different way 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
|
||||
Head to [docs.grafana.org](http://docs.grafana.org/installation/) and [download](https://grafana.com/get)
|
||||
the latest release.
|
||||
|
||||
## Get started
|
||||
If you have any problems please read the [troubleshooting guide](http://docs.grafana.org/installation/troubleshooting/).
|
||||
|
||||
- [Get Grafana](https://grafana.com/get)
|
||||
- [Installation guides](http://docs.grafana.org/installation/)
|
||||
## Documentation & Support
|
||||
Be sure to read the [getting started guide](http://docs.grafana.org/guides/gettingstarted/) and the other feature guides.
|
||||
|
||||
Unsure if Grafana is for you? Watch Grafana in action on [play.grafana.org](https://play.grafana.org/)!
|
||||
## Run from master
|
||||
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)
|
||||
|
||||
## Documentation
|
||||
### Dependencies
|
||||
|
||||
The Grafana documentation is available at [grafana.com/docs](https://grafana.com/docs/).
|
||||
- Go 1.9
|
||||
- NodeJS LTS
|
||||
|
||||
## Contributing
|
||||
### Building the backend
|
||||
```bash
|
||||
go get github.com/grafana/grafana
|
||||
cd ~/go/src/github.com/grafana/grafana
|
||||
go run build.go setup
|
||||
go run build.go build
|
||||
```
|
||||
|
||||
If you're interested in contributing to the Grafana project:
|
||||
### Building frontend assets
|
||||
|
||||
- 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).
|
||||
For this you need nodejs (v.6+).
|
||||
|
||||
## Get involved
|
||||
```bash
|
||||
npm install -g yarn
|
||||
yarn install --pure-lockfile
|
||||
npm run watch
|
||||
```
|
||||
|
||||
- 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.
|
||||
Run tests
|
||||
```bash
|
||||
npm run jest
|
||||
```
|
||||
|
||||
Run karma tests
|
||||
```bash
|
||||
npm run karma
|
||||
```
|
||||
|
||||
### Recompile backend on source change
|
||||
|
||||
To rebuild on source change.
|
||||
```bash
|
||||
go get github.com/Unknwon/bra
|
||||
bra run
|
||||
```
|
||||
|
||||
Open grafana in your browser (default: `http://localhost:3000`) and login with admin user (default: `user/pass = admin/admin`).
|
||||
|
||||
### 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
|
||||
npm run test
|
||||
```
|
||||
|
||||
Writing & watching frontend tests (we have two test runners)
|
||||
|
||||
- jest for all new tests that do not require browser context (React+more)
|
||||
- Start watcher: `npm run jest`
|
||||
- Jest will run all test files that end with the name ".jest.ts"
|
||||
- karma + mocha is used for testing angularjs components. We do want to migrate these test to jest over time (if possible).
|
||||
- Start watcher: `npm run karma`
|
||||
- Karma+Mocha runs all files that end with the name "_specs.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/...
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
If you have any idea for an improvement or found a bug, do not hesitate to open an issue.
|
||||
And if you have time clone this repo and submit a pull request and help me make Grafana
|
||||
the kickass metrics & devops dashboard we all dream about!
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
40
ROADMAP.md
40
ROADMAP.md
@@ -1,5 +1,39 @@
|
||||
# Roadmap
|
||||
# Roadmap (2018-02-22)
|
||||
|
||||
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.
|
||||
|
||||
### Short term (1-2 months)
|
||||
|
||||
- v5.1
|
||||
- Crossplatform builds & build speed improvements
|
||||
- Enterprise LDAP
|
||||
- New template interpolation syntax
|
||||
- Provisioning workflow
|
||||
- First login registration view
|
||||
- IFQL Initial support
|
||||
|
||||
To view the Roadmap, go to the Issues tab on GitHub. There you will find three roadmap issues pinned at the top.
|
||||
### Mid term (2-4 months)
|
||||
|
||||
- v5.2
|
||||
- Azure monitor backend rewrite
|
||||
- Elasticsearch alerting
|
||||
- Backend plugins? (alert notifiers, auth)
|
||||
|
||||
### Long term (4 - 8 months)
|
||||
|
||||
- Alerting improvements (silence, per series tracking, etc)
|
||||
- Progress on React migration
|
||||
- Change visualization (panel type) on the fly.
|
||||
- Multi stat panel (vertical version of singlestat with bars/graph mode with big number etc)
|
||||
- Repeat panel by query results
|
||||
|
||||
### In a distant future far far away
|
||||
|
||||
- Meta queries
|
||||
- Integrated light weight TSDB
|
||||
- Web socket & live data sources
|
||||
|
||||
### Outside contributions
|
||||
We know this is being worked on right now by contributors (and we hope to merge it when it's ready).
|
||||
|
||||
|
||||
20
SECURITY.md
20
SECURITY.md
@@ -1,20 +0,0 @@
|
||||
# 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:
|
||||
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
## 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).
|
||||
10
SUPPORT.md
10
SUPPORT.md
@@ -1,10 +0,0 @@
|
||||
# Get Grafana help
|
||||
------------------
|
||||
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.
|
||||
@@ -1,108 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## Go
|
||||
|
||||
- CircleCi
|
||||
- `grafana/build-container`
|
||||
- Appveyor
|
||||
- Dockerfile
|
||||
|
||||
## Node.js
|
||||
|
||||
- CircleCI
|
||||
- `grafana/build-container`
|
||||
- Appveyor
|
||||
- Dockerfile
|
||||
|
||||
## 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.
|
||||
|
||||
To add or update a new dependency, use the `go get` command:
|
||||
|
||||
```bash
|
||||
# The GO111MODULE variable can be omitted when the code isn't located in GOPATH.
|
||||
# Pick the latest tagged release.
|
||||
GO111MODULE=on go get example.com/some/module/pkg
|
||||
|
||||
# Pick a specific version.
|
||||
GO111MODULE=on go get example.com/some/module/pkg@vX.Y.Z
|
||||
```
|
||||
|
||||
Tidy up the `go.mod` and `go.sum` files:
|
||||
|
||||
```bash
|
||||
# The GO111MODULE variable can be omitted when the code isn't located in GOPATH.
|
||||
GO111MODULE=on go mod tidy
|
||||
```
|
||||
|
||||
You have to commit the changes to `go.mod` and `go.sum` before submitting the pull request.
|
||||
|
||||
## Node.js dependencies
|
||||
|
||||
Updated using `yarn`.
|
||||
|
||||
- `package.json`
|
||||
|
||||
## Where to make changes
|
||||
|
||||
### CircleCI
|
||||
|
||||
Our builds run on CircleCI through our build script.
|
||||
|
||||
#### Files
|
||||
|
||||
- `.circleci/config.yml`.
|
||||
|
||||
#### Dependencies
|
||||
|
||||
- nodejs
|
||||
- golang
|
||||
- grafana/build-container (our custom docker build container)
|
||||
|
||||
### grafana/build-container
|
||||
|
||||
The main build step (in CircleCI) is built using a custom build container that comes pre-baked with some of the necessary dependencies.
|
||||
|
||||
Link: [grafana/build-container](https://github.com/grafana/grafana/tree/master/scripts/build/ci-build)
|
||||
|
||||
#### Dependencies
|
||||
|
||||
- fpm
|
||||
- nodejs
|
||||
- golang
|
||||
- crosscompiling (several compilers)
|
||||
|
||||
### Appveyor
|
||||
|
||||
Master and release builds trigger test runs on Appveyors build environment so that tests will run on Windows.
|
||||
|
||||
#### Files:
|
||||
|
||||
- `appveyor.yml`
|
||||
|
||||
#### Dependencies
|
||||
|
||||
- nodejs
|
||||
- golang
|
||||
|
||||
### Dockerfile
|
||||
|
||||
There is a Docker build for Grafana in the root of the project that allows anyone to build Grafana just using Docker.
|
||||
|
||||
#### Files
|
||||
|
||||
- `Dockerfile`
|
||||
|
||||
#### Dependencies
|
||||
|
||||
- nodejs
|
||||
- golang
|
||||
|
||||
### Local developer environments
|
||||
|
||||
Please send out a notice in the grafana-dev slack channel when updating Go or Node.js to make it easier for everyone to update their local developer environments.
|
||||
73
WORKFLOW.md
73
WORKFLOW.md
@@ -1,73 +0,0 @@
|
||||
# Grafana workflow
|
||||
|
||||
This document is based on [GOVERNANCE.md](GOVERNANCE.md). We assume good faith and intend to keep all processes as lightweight as possible but as specific as required. In case of disagreements about anything in this document, GOVERNANCE.md applies.
|
||||
|
||||
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC2119](http://tools.ietf.org/html/rfc2119).
|
||||
|
||||
Git and [GitHub terminology](https://help.github.com/en/github/getting-started-with-github/github-glossary) are used throughout this document.
|
||||
|
||||
Team members and their access to repositories is maintained through [GitHub teams](https://help.github.com/en/github/setting-up-and-managing-organizations-and-teams/about-teams). Team maintainers add and remove team members as outlined in GOVERNANCE.md.
|
||||
|
||||
# Code changes
|
||||
|
||||
## Proposing changes
|
||||
|
||||
Examples of proposed changes are overarching architecture, component design, and specific code or graphical elements. Proposed changes SHOULD cover the big picture and intention, but individual parts SHOULD be split into the smallest possible changes. Changes SHOULD be based on and target the master branch. Depending on size of the proposed change, each change SHOULD be discussed, in increasing order of change size and complexity:
|
||||
- Directly in a RR (Pull Request) - this MAY be done, but SHOULD not be the common case.
|
||||
- Issue
|
||||
- Developer mailing list
|
||||
- Design document, shared via Google Docs, accessible to at least all team members.
|
||||
|
||||
Significant changes MUST be discussed and agreed upon with the relevant subsystem maintainers.
|
||||
|
||||
## Merging PRs (Pull Requests)
|
||||
|
||||
Depending on the size and complexity of a PR, different requirements MUST be applied. Any team member contributing substantially to a PR MUST NOT count against review requirements.
|
||||
Commits MUST be merged into master using PRs. They MUST NOT be merged into master directly.
|
||||
- Every merge MUST be approved by at least one team member.
|
||||
- Non-trivial changes MUST be approved by at least
|
||||
- two team members, or
|
||||
- one subsystem maintainer.
|
||||
- Significant changes MUST be approved by at least
|
||||
- two team members, AND
|
||||
- the relevant subsystem maintainer.
|
||||
|
||||
PRs MUST be [reviewed](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/reviewing-changes-in-pull-requests) and [approved](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/approving-a-pull-request-with-required-reviews) via GitHub’s review system.
|
||||
- Reviewers MAY write comments if approving
|
||||
- Reviewers MUST write comments if rejecting a PR or if requesting changes.
|
||||
|
||||
Once a PR is approved as per above, any team member MAY merge the PR.
|
||||
|
||||
# Release workflow
|
||||
|
||||
## Branch structure
|
||||
|
||||
Grafana uses trunk-based development.
|
||||
|
||||
In particular, we found that the following principles match how we work:
|
||||
- Master and release branches MUST always build without failure.
|
||||
- Branches SHOULD be merged often. Larger changes SHOULD be activated with feature flags until they are ready. Long-lived development branches SHOULD be avoided.
|
||||
- Changes MAY be enabled by default once they are in a complete state
|
||||
- Changes which span multiple PRs MUST be described in an overarching issue or Google Doc.
|
||||
|
||||
## Releases
|
||||
|
||||
Releases MUST follow [Semantic Versioning](https://semver.org/) in naming and SHOULD follow Semantic Versioning as closely as reasonably possible for non-library software.
|
||||
|
||||
Release branches MUST be split from the following branches.
|
||||
- MAJOR release branches MUST be based on master.
|
||||
- MINOR release branches MUST be based on master.
|
||||
- PATCH release branches MUST be split from the relevant MINOR release branch’s most current PATCH
|
||||
|
||||
Security releases follow the same process but MUST be prepared in secret. Security releases MUST NOT include changes which are not related to the security fix. Normal release processes MUST accommodate the security release process. SECURITY.md MUST be followed.
|
||||
|
||||
PRs intended for inclusion in the next PATCH release MUST be labeled with `cherry-pick-needed` so they can be picked up by automated release tooling.
|
||||
|
||||
Releases follow the following cadence
|
||||
- MAJOR: Yearly
|
||||
- MINOR: Every 4-6 weeks
|
||||
- PATCH: As needed
|
||||
|
||||
Releases SHOULD NOT be delayed by pending changes.
|
||||
|
||||
Releases MUST be coordinated with the relevant subsystem maintainers.
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
appveyor.yml
Normal file
53
appveyor.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
version: "{build}"
|
||||
|
||||
os: Windows Server 2012 R2
|
||||
|
||||
clone_folder: c:\gopath\src\github.com\grafana\grafana
|
||||
|
||||
environment:
|
||||
nodejs_version: "6"
|
||||
GOPATH: c:\gopath
|
||||
GOVERSION: 1.9.2
|
||||
|
||||
install:
|
||||
- rmdir c:\go /s /q
|
||||
# install nodejs and npm
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
- npm install -g yarn --silent
|
||||
- yarn install --pure-lockfile --no-progress
|
||||
- npm install -g grunt-cli
|
||||
- appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.zip
|
||||
- 7z x go%GOVERSION%.windows-amd64.zip -y -oC:\ > NUL
|
||||
# install gcc (needed for sqlite3)
|
||||
- choco install -y --limit-output mingw
|
||||
- set PATH=C:\tools\mingw64\bin;%PATH%
|
||||
- echo %PATH%
|
||||
- echo %GOPATH%
|
||||
- go version
|
||||
- go env
|
||||
# - go run build.go setup
|
||||
|
||||
build_script:
|
||||
- go run build.go build
|
||||
- grunt release
|
||||
- go run build.go sha-dist
|
||||
- cp dist/* .
|
||||
- go test -v ./pkg/...
|
||||
|
||||
artifacts:
|
||||
- path: grafana-*windows-*.*
|
||||
name: binzip
|
||||
type: zip
|
||||
|
||||
deploy:
|
||||
- provider: Environment
|
||||
name: GrafanaReleaseMaster
|
||||
on:
|
||||
buildType: master
|
||||
|
||||
- provider: Environment
|
||||
name: GrafanaReleaseRelease
|
||||
on:
|
||||
buildType: release
|
||||
|
||||
|
||||
383
build.go
383
build.go
@@ -9,7 +9,6 @@ import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@@ -17,78 +16,55 @@ import (
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
windows = "windows"
|
||||
linux = "linux"
|
||||
)
|
||||
|
||||
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"
|
||||
versionRe = regexp.MustCompile(`-[0-9]{1,3}-g[0-9a-f]{5,10}`)
|
||||
goarch string
|
||||
goos string
|
||||
gocc string
|
||||
gocxx string
|
||||
cgo string
|
||||
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"
|
||||
serverBinary string = "grafana-server"
|
||||
cliBinary string = "grafana-cli"
|
||||
binaries []string = []string{serverBinary, cliBinary}
|
||||
isDev bool = false
|
||||
enterprise bool = false
|
||||
skipRpmGen bool = false
|
||||
skipDebGen bool = false
|
||||
printGenVersion bool = false
|
||||
includeBuildNumber bool = true
|
||||
buildNumber int = 0
|
||||
binaries []string = []string{"grafana-server", "grafana-cli"}
|
||||
)
|
||||
|
||||
const minGoVersion = 1.8
|
||||
|
||||
func main() {
|
||||
log.SetOutput(os.Stdout)
|
||||
log.SetFlags(0)
|
||||
|
||||
var buildIdRaw string
|
||||
ensureGoPath()
|
||||
|
||||
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.BoolVar(&cgo, "cgo-enabled", cgo, "Enable cgo")
|
||||
flag.StringVar(&gocxx, "cxx", "", "CXX")
|
||||
flag.StringVar(&cgo, "cgo-enabled", "", "CGO_ENABLED")
|
||||
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")
|
||||
flag.StringVar(&buildIdRaw, "buildId", "0", "Build ID from CI system")
|
||||
flag.BoolVar(&isDev, "dev", isDev, "optimal for development, skips certain steps")
|
||||
flag.BoolVar(&skipRpmGen, "skipRpm", skipRpmGen, "skip rpm package generation (default: false)")
|
||||
flag.BoolVar(&skipDebGen, "skipDeb", skipDebGen, "skip deb package generation (default: false)")
|
||||
flag.BoolVar(&printGenVersion, "gen-version", printGenVersion, "generate Grafana version and output (default: false)")
|
||||
flag.BoolVar(&includeBuildNumber, "includeBuildNumber", includeBuildNumber, "IncludeBuildNumber in package name")
|
||||
flag.IntVar(&buildNumber, "buildNumber", 0, "Build number from CI system")
|
||||
flag.Parse()
|
||||
|
||||
buildId = shortenBuildId(buildIdRaw)
|
||||
|
||||
readVersionFromPackageJson()
|
||||
|
||||
if pkgArch == "" {
|
||||
pkgArch = goarch
|
||||
}
|
||||
|
||||
if printGenVersion {
|
||||
printGeneratedVersion()
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Version: %s, Linux Version: %s, Package Iteration: %s\n", version, linuxPackageVersion, linuxPackageIteration)
|
||||
|
||||
if flag.NArg() == 0 {
|
||||
@@ -103,42 +79,26 @@ func main() {
|
||||
case "setup":
|
||||
setup()
|
||||
|
||||
case "build-srv", "build-server":
|
||||
clean()
|
||||
doBuild("grafana-server", "./pkg/cmd/grafana-server", []string{})
|
||||
|
||||
case "build-cli":
|
||||
clean()
|
||||
doBuild("grafana-cli", "./pkg/cmd/grafana-cli", []string{})
|
||||
build("grafana-cli", "./pkg/cmd/grafana-cli", []string{})
|
||||
|
||||
case "build":
|
||||
//clean()
|
||||
clean()
|
||||
for _, binary := range binaries {
|
||||
doBuild(binary, "./pkg/cmd/"+binary, []string{})
|
||||
build(binary, "./pkg/cmd/"+binary, []string{})
|
||||
}
|
||||
|
||||
case "build-frontend":
|
||||
grunt(gruntBuildArg("build")...)
|
||||
|
||||
case "test":
|
||||
test("./pkg/...")
|
||||
grunt("test")
|
||||
|
||||
case "package":
|
||||
grunt(gruntBuildArg("build")...)
|
||||
grunt(gruntBuildArg("package")...)
|
||||
if goos == linux {
|
||||
grunt(gruntBuildArg("release")...)
|
||||
if runtime.GOOS != "windows" {
|
||||
createLinuxPackages()
|
||||
}
|
||||
|
||||
case "package-only":
|
||||
grunt(gruntBuildArg("package")...)
|
||||
if goos == linux {
|
||||
createLinuxPackages()
|
||||
}
|
||||
case "pkg-archive":
|
||||
grunt(gruntBuildArg("package")...)
|
||||
|
||||
case "pkg-rpm":
|
||||
grunt(gruntBuildArg("release")...)
|
||||
createRpmPackages()
|
||||
@@ -169,15 +129,9 @@ 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",
|
||||
".deb": "dist/grafana_latest_amd64.deb",
|
||||
".rpm": "dist/grafana-latest-1.x86_64.rpm",
|
||||
".tar.gz": "dist/grafana-latest.linux-x64.tar.gz",
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
@@ -217,9 +171,9 @@ func readVersionFromPackageJson() {
|
||||
}
|
||||
|
||||
// add timestamp to iteration
|
||||
if includeBuildId {
|
||||
if buildId != "0" {
|
||||
linuxPackageIteration = fmt.Sprintf("%s%s", buildId, linuxPackageIteration)
|
||||
if includeBuildNumber {
|
||||
if buildNumber != 0 {
|
||||
linuxPackageIteration = fmt.Sprintf("%d%s", buildNumber, linuxPackageIteration)
|
||||
} else {
|
||||
linuxPackageIteration = fmt.Sprintf("%d%s", time.Now().Unix(), linuxPackageIteration)
|
||||
}
|
||||
@@ -228,9 +182,7 @@ func readVersionFromPackageJson() {
|
||||
|
||||
type linuxPackageOptions struct {
|
||||
packageType string
|
||||
packageArch string
|
||||
homeDir string
|
||||
homeBinDir string
|
||||
binPath string
|
||||
serverBinPath string
|
||||
cliBinPath string
|
||||
@@ -241,26 +193,18 @@ type linuxPackageOptions struct {
|
||||
initdScriptFilePath string
|
||||
systemdServiceFilePath string
|
||||
|
||||
postinstSrc string
|
||||
initdScriptSrc string
|
||||
defaultFileSrc string
|
||||
systemdFileSrc string
|
||||
cliBinaryWrapperSrc string
|
||||
postinstSrc string
|
||||
initdScriptSrc string
|
||||
defaultFileSrc string
|
||||
systemdFileSrc 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",
|
||||
@@ -268,29 +212,19 @@ func createDebPackages() {
|
||||
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",
|
||||
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",
|
||||
|
||||
depends: []string{"adduser", "libfontconfig1"},
|
||||
depends: []string{"adduser", "libfontconfig"},
|
||||
})
|
||||
}
|
||||
|
||||
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",
|
||||
@@ -298,24 +232,18 @@ func createRpmPackages() {
|
||||
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",
|
||||
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",
|
||||
|
||||
depends: []string{"/sbin/service", "fontconfig", "freetype", "urw-fonts"},
|
||||
})
|
||||
}
|
||||
|
||||
func createLinuxPackages() {
|
||||
if !skipDebGen {
|
||||
createDebPackages()
|
||||
}
|
||||
|
||||
if !skipRpmGen {
|
||||
createRpmPackages()
|
||||
}
|
||||
createDebPackages()
|
||||
createRpmPackages()
|
||||
}
|
||||
|
||||
func createPackage(options linuxPackageOptions) {
|
||||
@@ -329,12 +257,10 @@ func createPackage(options linuxPackageOptions) {
|
||||
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 binary
|
||||
for _, binary := range binaries {
|
||||
runPrint("cp", "-p", filepath.Join(workingDir, "tmp/bin/"+binary), filepath.Join(packageRoot, "/usr/sbin/"+binary))
|
||||
}
|
||||
// copy init.d script
|
||||
runPrint("cp", "-p", options.initdScriptSrc, filepath.Join(packageRoot, options.initdScriptFilePath))
|
||||
// copy environment var file
|
||||
@@ -346,49 +272,23 @@ func createPackage(options linuxPackageOptions) {
|
||||
// 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,
|
||||
"--vendor", "Grafana",
|
||||
"--url", "https://grafana.com",
|
||||
"--license", "\"Apache 2.0\"",
|
||||
"--maintainer", "contact@grafana.com",
|
||||
"--config-files", options.initdScriptFilePath,
|
||||
"--config-files", options.etcDefaultFilePath,
|
||||
"--config-files", options.systemdServiceFilePath,
|
||||
"--after-install", options.postinstSrc,
|
||||
|
||||
"--name", "grafana",
|
||||
"--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"
|
||||
}
|
||||
|
||||
if !enterprise {
|
||||
args = append(args, "--license", "\"Apache 2.0\"")
|
||||
}
|
||||
|
||||
if options.packageType == "rpm" {
|
||||
args = append(args, "--rpm-posttrans", "packaging/rpm/control/posttrans")
|
||||
}
|
||||
@@ -397,15 +297,15 @@ func createPackage(options linuxPackageOptions) {
|
||||
args = append(args, "--deb-no-default-config-files")
|
||||
}
|
||||
|
||||
if options.packageArch != "" {
|
||||
args = append(args, "-a", options.packageArch)
|
||||
if pkgArch != "" {
|
||||
args = append(args, "-a", pkgArch)
|
||||
}
|
||||
|
||||
if linuxPackageIteration != "" {
|
||||
args = append(args, "--iteration", linuxPackageIteration)
|
||||
}
|
||||
|
||||
// add dependencies
|
||||
// add dependenciesj
|
||||
for _, dep := range options.depends {
|
||||
args = append(args, "--depends", dep)
|
||||
}
|
||||
@@ -416,71 +316,77 @@ func createPackage(options linuxPackageOptions) {
|
||||
runPrint("fpm", append([]string{"-t", options.packageType}, args...)...)
|
||||
}
|
||||
|
||||
func verifyGitRepoIsClean() {
|
||||
rs, err := runError("git", "ls-files", "--modified")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to check if git tree was clean, %v, %v\n", string(rs), err)
|
||||
return
|
||||
}
|
||||
count := len(string(rs))
|
||||
if count > 0 {
|
||||
log.Fatalf("Git repository has modified files, aborting")
|
||||
}
|
||||
|
||||
log.Println("Git repository is clean")
|
||||
}
|
||||
|
||||
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 ChangeWorkingDir(dir string) {
|
||||
os.Chdir(dir)
|
||||
}
|
||||
|
||||
func grunt(params ...string) {
|
||||
if runtime.GOOS == windows {
|
||||
if runtime.GOOS == "windows" {
|
||||
runPrint(`.\node_modules\.bin\grunt`, params...)
|
||||
} else {
|
||||
runPrint("./node_modules/.bin/grunt", params...)
|
||||
}
|
||||
}
|
||||
|
||||
func genPackageVersion() string {
|
||||
if includeBuildId {
|
||||
return fmt.Sprintf("%v-%v", linuxPackageVersion, linuxPackageIteration)
|
||||
} else {
|
||||
return version
|
||||
}
|
||||
}
|
||||
|
||||
func gruntBuildArg(task string) []string {
|
||||
args := []string{task}
|
||||
args = append(args, fmt.Sprintf("--pkgVer=%v", genPackageVersion()))
|
||||
if includeBuildNumber {
|
||||
args = append(args, fmt.Sprintf("--pkgVer=%v-%v", linuxPackageVersion, linuxPackageIteration))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("--pkgVer=%v", version))
|
||||
}
|
||||
if pkgArch != "" {
|
||||
args = append(args, fmt.Sprintf("--arch=%v", pkgArch))
|
||||
}
|
||||
if libc != "" {
|
||||
args = append(args, fmt.Sprintf("--libc=%s", libc))
|
||||
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", "get", "-v", "github.com/golang/dep")
|
||||
runPrint("go", "install", "-v", "./pkg/cmd/grafana-server")
|
||||
}
|
||||
|
||||
func printGeneratedVersion() {
|
||||
fmt.Print(genPackageVersion())
|
||||
}
|
||||
|
||||
func test(pkg string) {
|
||||
setBuildEnv()
|
||||
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)
|
||||
if isDev {
|
||||
//don't include os/arch/libc in output path in dev environment
|
||||
binary = fmt.Sprintf("./bin/%s", binaryName)
|
||||
}
|
||||
|
||||
if goos == windows {
|
||||
func build(binaryName, pkg string, tags []string) {
|
||||
binary := "./bin/" + binaryName
|
||||
if goos == "windows" {
|
||||
binary += ".exe"
|
||||
}
|
||||
|
||||
if !isDev {
|
||||
rmr(binary, binary+".md5")
|
||||
}
|
||||
rmr(binary, binary+".md5")
|
||||
args := []string{"build", "-ldflags", ldflags()}
|
||||
if len(tags) > 0 {
|
||||
args = append(args, "-tags", strings.Join(tags, ","))
|
||||
@@ -491,26 +397,16 @@ func doBuild(binaryName, pkg string, tags []string) {
|
||||
|
||||
args = append(args, "-o", binary)
|
||||
args = append(args, pkg)
|
||||
setBuildEnv()
|
||||
|
||||
if !isDev {
|
||||
setBuildEnv()
|
||||
runPrint("go", "version")
|
||||
libcPart := ""
|
||||
if libc != "" {
|
||||
libcPart = fmt.Sprintf("/%s", libc)
|
||||
}
|
||||
fmt.Printf("Targeting %s/%s%s\n", goos, goarch, libcPart)
|
||||
}
|
||||
|
||||
runPrint("go", "version")
|
||||
runPrint("go", args...)
|
||||
|
||||
if !isDev {
|
||||
// Create an md5 checksum of the binary, to be included in the archive for
|
||||
// automatic upgrades.
|
||||
err := md5File(binary)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Create an md5 checksum of the binary, to be included in the archive for
|
||||
// automatic upgrades.
|
||||
err := md5File(binary)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,10 +416,6 @@ func ldflags() string {
|
||||
b.WriteString(fmt.Sprintf(" -X main.version=%s", version))
|
||||
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()
|
||||
}
|
||||
|
||||
@@ -535,25 +427,13 @@ func rmr(paths ...string) {
|
||||
}
|
||||
|
||||
func clean() {
|
||||
if isDev {
|
||||
return
|
||||
}
|
||||
|
||||
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() {
|
||||
os.Setenv("GOOS", goos)
|
||||
if goos == windows {
|
||||
// require windows >=7
|
||||
os.Setenv("CGO_CFLAGS", "-D_WIN32_WINNT=0x0601")
|
||||
}
|
||||
if goarch != "amd64" || goos != linux {
|
||||
// needed for all other archs
|
||||
cgo = true
|
||||
}
|
||||
if strings.HasPrefix(goarch, "armv") {
|
||||
os.Setenv("GOARCH", "arm")
|
||||
os.Setenv("GOARM", goarch[4:])
|
||||
@@ -563,20 +443,15 @@ func setBuildEnv() {
|
||||
if goarch == "386" {
|
||||
os.Setenv("GO386", "387")
|
||||
}
|
||||
if cgo {
|
||||
os.Setenv("CGO_ENABLED", "1")
|
||||
if cgo != "" {
|
||||
os.Setenv("CGO_ENABLED", cgo)
|
||||
}
|
||||
if gocc != "" {
|
||||
os.Setenv("CC", gocc)
|
||||
}
|
||||
}
|
||||
|
||||
func getGitBranch() string {
|
||||
v, err := runError("git", "rev-parse", "--abbrev-ref", "HEAD")
|
||||
if err != nil {
|
||||
return "master"
|
||||
if gocxx != "" {
|
||||
os.Setenv("CXX", gocxx)
|
||||
}
|
||||
return string(v)
|
||||
}
|
||||
|
||||
func getGitSha() string {
|
||||
@@ -588,11 +463,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()
|
||||
@@ -601,6 +471,24 @@ func buildStamp() int64 {
|
||||
return s
|
||||
}
|
||||
|
||||
func buildArch() string {
|
||||
os := goos
|
||||
if os == "darwin" {
|
||||
os = "macosx"
|
||||
}
|
||||
return fmt.Sprintf("%s-%s", os, goarch)
|
||||
}
|
||||
|
||||
func run(cmd string, args ...string) []byte {
|
||||
bs, err := runError(cmd, args...)
|
||||
if err != nil {
|
||||
log.Println(cmd, strings.Join(args, " "))
|
||||
log.Println(string(bs))
|
||||
log.Fatal(err)
|
||||
}
|
||||
return bytes.TrimSpace(bs)
|
||||
}
|
||||
|
||||
func runError(cmd string, args ...string) ([]byte, error) {
|
||||
ecmd := exec.Command(cmd, args...)
|
||||
bs, err := ecmd.CombinedOutput()
|
||||
@@ -614,7 +502,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()
|
||||
@@ -655,7 +542,7 @@ func shaFilesInDist() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !strings.Contains(path, ".sha256") {
|
||||
if strings.Contains(path, ".sha256") == false {
|
||||
err := shaFile(path)
|
||||
if err != nil {
|
||||
log.Printf("Failed to create sha file. error: %v\n", err)
|
||||
@@ -690,11 +577,3 @@ func shaFile(file string) error {
|
||||
|
||||
return out.Close()
|
||||
}
|
||||
|
||||
func shortenBuildId(buildId string) string {
|
||||
buildId = strings.Replace(buildId, "-", "", -1)
|
||||
if len(buildId) < 9 {
|
||||
return buildId
|
||||
}
|
||||
return buildId[0:8]
|
||||
}
|
||||
|
||||
57
circle.yml
Normal file
57
circle.yml
Normal file
@@ -0,0 +1,57 @@
|
||||
machine:
|
||||
node:
|
||||
version: 6.11.4
|
||||
python:
|
||||
version: 2.7.3
|
||||
services:
|
||||
- docker
|
||||
environment:
|
||||
GOPATH: "/home/ubuntu/.go_workspace"
|
||||
ORG_PATH: "github.com/grafana"
|
||||
REPO_PATH: "${ORG_PATH}/grafana"
|
||||
GODIST: "go1.9.3.linux-amd64.tar.gz"
|
||||
post:
|
||||
- mkdir -p ~/download
|
||||
- mkdir -p ~/docker
|
||||
- test -e download/$GODIST || curl -o download/$GODIST https://storage.googleapis.com/golang/$GODIST
|
||||
- sudo rm -rf /usr/local/go
|
||||
- sudo tar -C /usr/local -xzf download/$GODIST
|
||||
|
||||
dependencies:
|
||||
cache_directories:
|
||||
- "~/docker"
|
||||
- "~/download"
|
||||
override:
|
||||
- rm -rf ${GOPATH}/src/${REPO_PATH}
|
||||
- mkdir -p ${GOPATH}/src/${ORG_PATH}
|
||||
- cp -r ~/grafana ${GOPATH}/src/${ORG_PATH}
|
||||
pre:
|
||||
- pip install awscli
|
||||
- sudo apt-get update; sudo apt-get install rpm; sudo apt-get install expect
|
||||
- ./scripts/build/build_container.sh
|
||||
|
||||
test:
|
||||
override:
|
||||
- bash scripts/circle-test-frontend.sh
|
||||
- bash scripts/circle-test-backend.sh
|
||||
|
||||
deployment:
|
||||
gh_branch:
|
||||
branch: master
|
||||
commands:
|
||||
- ./scripts/build/deploy.sh
|
||||
- ./scripts/build/sign_packages.sh
|
||||
- go run build.go sha-dist
|
||||
- aws s3 sync ./dist s3://$BUCKET_NAME/master
|
||||
- ./scripts/trigger_windows_build.sh ${APPVEYOR_TOKEN} ${CIRCLE_SHA1} master
|
||||
- ./scripts/trigger_docker_build.sh ${TRIGGER_GRAFANA_PACKER_CIRCLECI_TOKEN}
|
||||
- go run ./scripts/build/publish.go -apiKey ${GRAFANA_COM_API_KEY}
|
||||
gh_tag:
|
||||
tag: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/
|
||||
commands:
|
||||
- ./scripts/build/deploy.sh
|
||||
- ./scripts/build/sign_packages.sh
|
||||
- go run build.go sha-dist
|
||||
- aws s3 sync ./dist s3://$BUCKET_NAME/release
|
||||
- ./scripts/trigger_windows_build.sh ${APPVEYOR_TOKEN} ${CIRCLE_SHA1} release
|
||||
- ./scripts/trigger_docker_build.sh ${TRIGGER_GRAFANA_PACKER_CIRCLECI_TOKEN} ${CIRCLE_TAG}
|
||||
13
codecov.yml
Normal file
13
codecov.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "50...100"
|
||||
|
||||
status:
|
||||
project: yes
|
||||
patch: yes
|
||||
changes: no
|
||||
|
||||
comment:
|
||||
layout: "diff"
|
||||
behavior: "once"
|
||||
@@ -14,9 +14,6 @@ instance_name = ${HOSTNAME}
|
||||
# Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used)
|
||||
data = data
|
||||
|
||||
# Temporary files in `data` directory older than given duration will be removed
|
||||
temp_data_lifetime = 24h
|
||||
|
||||
# Directory where grafana can store logs
|
||||
logs = data/log
|
||||
|
||||
@@ -28,13 +25,13 @@ 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
|
||||
http_addr =
|
||||
|
||||
# The http port to use
|
||||
# The http port to use
|
||||
http_port = 3000
|
||||
|
||||
# The public facing domain name used to access grafana from a browser
|
||||
@@ -47,9 +44,6 @@ enforce_domain = false
|
||||
# The full public facing url
|
||||
root_url = %(protocol)s://%(domain)s:%(http_port)s/
|
||||
|
||||
# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons.
|
||||
serve_from_sub_path = false
|
||||
|
||||
# Log web requests
|
||||
router_logging = false
|
||||
|
||||
@@ -106,19 +100,36 @@ server_cert_name =
|
||||
# For "sqlite3" only, path relative to data_path setting
|
||||
path = grafana.db
|
||||
|
||||
# For "sqlite3" only. cache mode setting used for connecting to the database
|
||||
cache_mode = private
|
||||
#################################### Session #############################
|
||||
[session]
|
||||
# Either "memory", "file", "redis", "mysql", "postgres", "memcache", default is "file"
|
||||
provider = file
|
||||
|
||||
#################################### Cache server #############################
|
||||
[remote_cache]
|
||||
# Either "redis", "memcached" or "database" default is "database"
|
||||
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'.
|
||||
# Provider config options
|
||||
# memory: not have any config yet
|
||||
# file: session dir path, is relative to grafana data_path
|
||||
# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=grafana`
|
||||
# postgres: user=a password=b host=localhost port=5432 dbname=c sslmode=disable
|
||||
# mysql: go-sql-driver/mysql dsn config string, examples:
|
||||
# `user:password@tcp(127.0.0.1:3306)/database_name`
|
||||
# `user:password@unix(/var/run/mysqld/mysqld.sock)/database_name`
|
||||
# memcache: 127.0.0.1:11211
|
||||
connstr =
|
||||
|
||||
|
||||
provider_config = sessions
|
||||
|
||||
# Session cookie name
|
||||
cookie_name = grafana_sess
|
||||
|
||||
# If you use session in https only, default is false
|
||||
cookie_secure = false
|
||||
|
||||
# Session life time, default is 86400
|
||||
session_life_time = 86400
|
||||
gc_interval_time = 86400
|
||||
|
||||
# Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours)
|
||||
conn_max_lifetime = 14400
|
||||
|
||||
#################################### Data proxy ###########################
|
||||
[dataproxy]
|
||||
@@ -126,31 +137,6 @@ 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.
|
||||
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.
|
||||
send_user_header = false
|
||||
|
||||
#################################### Analytics ###########################
|
||||
[analytics]
|
||||
# Server reporting, sends usage counters to stats.grafana.org every 24 hours.
|
||||
@@ -174,18 +160,20 @@ 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
|
||||
|
||||
# default admin password, can be changed before first start of grafana, or in profile settings
|
||||
# default admin password, can be changed before first start of grafana, or in profile settings
|
||||
admin_password = admin
|
||||
|
||||
# used for signing
|
||||
secret_key = SW2YcwTIb9zpOOhoPsMm
|
||||
|
||||
# Auto-login remember days
|
||||
login_remember_days = 7
|
||||
cookie_username = grafana_user
|
||||
cookie_remember_name = grafana_remember
|
||||
|
||||
# disable gravatar profile images
|
||||
disable_gravatar = false
|
||||
|
||||
@@ -195,39 +183,6 @@ data_source_proxy_whitelist =
|
||||
# disable protection against brute force login attempts
|
||||
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"
|
||||
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.
|
||||
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.
|
||||
strict_transport_security = false
|
||||
|
||||
# Sets how long a browser should cache HSTS. Only applied if strict_transport_security is enabled.
|
||||
strict_transport_security_max_age_seconds = 86400
|
||||
|
||||
# Set to true if to enable HSTS preloading option. Only applied if strict_transport_security is enabled.
|
||||
strict_transport_security_preload = false
|
||||
|
||||
# Set to true if to enable the HSTS includeSubDomains option. Only applied if strict_transport_security is enabled.
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
#################################### Snapshots ###########################
|
||||
[snapshots]
|
||||
# snapshot sharing options
|
||||
@@ -235,10 +190,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
|
||||
|
||||
@@ -248,13 +199,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 =
|
||||
|
||||
#################################### Users ###############################
|
||||
[users]
|
||||
# disable user signup / registration
|
||||
@@ -266,9 +210,6 @@ allow_org_create = false
|
||||
# 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 auto_assign_org above is set to true)
|
||||
auto_assign_org_role = Viewer
|
||||
|
||||
@@ -277,7 +218,6 @@ verify_email_enabled = false
|
||||
|
||||
# Background text for the user field on the login page
|
||||
login_hint = email or username
|
||||
password_hint = password
|
||||
|
||||
# Default UI theme ("dark" or "light")
|
||||
default_theme = dark
|
||||
@@ -290,47 +230,13 @@ external_manage_info =
|
||||
# Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
|
||||
viewers_can_edit = false
|
||||
|
||||
# Editors can administrate dashboard, folders and teams they create
|
||||
editors_can_admin = false
|
||||
|
||||
# The duration in time a user invitation remains valid before expiring. This setting should be expressed as a duration. Examples: 6h (hours), 2d (days), 1w (week). Default is 24h (24 hours). The minimum supported duration is 15m (15 minutes).
|
||||
user_invite_max_lifetime_duration = 24h
|
||||
|
||||
[auth]
|
||||
# Login cookie name
|
||||
login_cookie_name = grafana_session
|
||||
|
||||
# The maximum lifetime (duration) an authenticated user can be inactive before being required to login at next visit. Default is 7 days (7d). This setting should be expressed as a duration, e.g. 5m (minutes), 6h (hours), 10d (days), 2w (weeks), 1M (month). The lifetime resets at each successful token rotation (token_rotation_interval_minutes).
|
||||
login_maximum_inactive_lifetime_duration =
|
||||
|
||||
# The 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 =
|
||||
|
||||
# How often should auth tokens be rotated for authenticated users when being active. The default is each 10 minutes.
|
||||
token_rotation_interval_minutes = 10
|
||||
|
||||
# Set to true to disable (hide) the login form, useful if you use OAuth
|
||||
disable_login_form = false
|
||||
|
||||
# Set to true to disable the signout link in the side menu. useful if you use auth.proxy
|
||||
disable_signout_menu = false
|
||||
|
||||
# URL to redirect the user to after sign out
|
||||
signout_redirect_url =
|
||||
|
||||
# Set to true to attempt login with OAuth automatically, skipping the login screen.
|
||||
# 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
|
||||
@@ -342,42 +248,25 @@ 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 =
|
||||
|
||||
#################################### GitLab Auth #########################
|
||||
[auth.gitlab]
|
||||
enabled = false
|
||||
allow_sign_up = true
|
||||
client_id = some_id
|
||||
client_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
|
||||
allow_sign_up = true
|
||||
client_id = some_client_id
|
||||
client_secret =
|
||||
client_secret = some_client_secret
|
||||
scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email
|
||||
auth_url = https://accounts.google.com/o/oauth2/auth
|
||||
token_url = https://accounts.google.com/o/oauth2/token
|
||||
@@ -391,7 +280,7 @@ hosted_domain =
|
||||
enabled = false
|
||||
allow_sign_up = true
|
||||
client_id = some_id
|
||||
client_secret =
|
||||
client_secret = some_secret
|
||||
scopes = user:email
|
||||
allowed_organizations =
|
||||
|
||||
@@ -399,61 +288,23 @@ 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 =
|
||||
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 =
|
||||
|
||||
#################################### Basic Auth ##########################
|
||||
[auth.basic]
|
||||
@@ -465,12 +316,8 @@ 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]
|
||||
@@ -478,11 +325,6 @@ enabled = false
|
||||
config_file = /etc/grafana/ldap.toml
|
||||
allow_sign_up = true
|
||||
|
||||
# LDAP backround sync (Enterprise only)
|
||||
# At 1 am every day
|
||||
sync_cron = "0 0 1 * * *"
|
||||
active_sync_enabled = true
|
||||
|
||||
#################################### SMTP / Emailing #####################
|
||||
[smtp]
|
||||
enabled = false
|
||||
@@ -496,7 +338,6 @@ skip_verify = false
|
||||
from_address = admin@grafana.localhost
|
||||
from_name = Grafana
|
||||
ehlo_identity =
|
||||
startTLS_policy =
|
||||
|
||||
[emails]
|
||||
welcome_email_on_sign_up = false
|
||||
@@ -504,7 +345,7 @@ templates_pattern = emails/*.html
|
||||
|
||||
#################################### Logging ##########################
|
||||
[log]
|
||||
# Either "console", "file", "syslog". Default is console and file
|
||||
# Either "console", "file", "syslog". Default is console and file
|
||||
# Use space to separate multiple modes, e.g. "console file"
|
||||
mode = console file
|
||||
|
||||
@@ -601,74 +442,11 @@ enabled = true
|
||||
# Makes it possible to turn off alert rule execution but alerting UI is visible
|
||||
execute_alerts = true
|
||||
|
||||
# Default setting for new alert rules. Defaults to categorize error and timeouts as alerting. (alerting, keep_state)
|
||||
error_or_timeout = alerting
|
||||
|
||||
# Default setting for how Grafana handles nodata or null values in alerting. (alerting, no_data, keep_state, ok)
|
||||
nodata_or_nullvalues = no_data
|
||||
|
||||
# Alert notifications can include images, but rendering many images at the same time can overload the server
|
||||
# This limit will protect the server from render overloading and make sure notifications are sent out quickly
|
||||
concurrent_render_limit = 5
|
||||
|
||||
# Default setting for alert calculation timeout. Default value is 30
|
||||
evaluation_timeout_seconds = 30
|
||||
|
||||
# Default setting for alert notification timeout. Default value is 30
|
||||
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.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
|
||||
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
|
||||
|
||||
#If both are set, basic auth will be required for the metrics endpoint.
|
||||
basic_auth_username =
|
||||
basic_auth_password =
|
||||
enabled = true
|
||||
interval_seconds = 10
|
||||
|
||||
# Send internal Grafana metrics to graphite
|
||||
[metrics.graphite]
|
||||
@@ -676,7 +454,6 @@ basic_auth_password =
|
||||
address =
|
||||
prefix = prod.grafana.%(instance_name)s.
|
||||
|
||||
#################################### Grafana.com integration ##########################
|
||||
[grafana_net]
|
||||
url = https://grafana.com
|
||||
|
||||
@@ -699,21 +476,13 @@ sampler_type = const
|
||||
# and indicates the initial sampling rate before the actual one
|
||||
# is received from the mothership
|
||||
sampler_param = 1
|
||||
# Whether or not to use Zipkin span 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
|
||||
|
||||
#################################### 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 =
|
||||
@@ -731,8 +500,6 @@ public_url =
|
||||
key_file =
|
||||
bucket =
|
||||
path =
|
||||
enable_signed_urls = false
|
||||
signed_url_expiration =
|
||||
|
||||
[external_image_storage.azure_blob]
|
||||
account_name =
|
||||
@@ -741,111 +508,3 @@ container_name =
|
||||
|
||||
[external_image_storage.local]
|
||||
# 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.
|
||||
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
|
||||
enable_alpha = false
|
||||
disable_sanitize_html = false
|
||||
|
||||
[plugins]
|
||||
enable_alpha = false
|
||||
app_tls_skip_verify_insecure = false
|
||||
# Enter a comma-separated list of plugin identifiers to identify plugins that are allowed to be loaded even if they lack a valid signature.
|
||||
allow_loading_unsigned_plugins =
|
||||
|
||||
#################################### Grafana Image Renderer Plugin ##########################
|
||||
[plugin.grafana-image-renderer]
|
||||
# Instruct headless browser instance to use a default timezone when not provided by Grafana, e.g. when rendering panel image of alert.
|
||||
# See ICU’s 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
|
||||
|
||||
@@ -15,9 +15,6 @@ start_tls = false
|
||||
ssl_skip_verify = false
|
||||
# set to the path to your root CA certificate or leave unset to use system defaults
|
||||
# root_ca_cert = "/path/to/certificate.crt"
|
||||
# Authentication against LDAP servers requiring client certificates
|
||||
# client_cert = "/path/to/client.crt"
|
||||
# client_key = "/path/to/client.key"
|
||||
|
||||
# Search user bind dn
|
||||
bind_dn = "cn=admin,dc=grafana,dc=org"
|
||||
@@ -31,11 +28,37 @@ search_filter = "(cn=%s)"
|
||||
# An array of base dns to search through
|
||||
search_base_dns = ["dc=grafana,dc=org"]
|
||||
|
||||
## For Posix or LDAP setups that does not support member_of attribute you can define the below settings
|
||||
## Please check grafana LDAP docs for examples
|
||||
# In POSIX LDAP schemas, without memberOf attribute a secondary query must be made for groups.
|
||||
# This is done by enabling group_search_filter below. You must also set member_of= "cn"
|
||||
# in [servers.attributes] below.
|
||||
|
||||
# Users with nested/recursive group membership and an LDAP server that supports LDAP_MATCHING_RULE_IN_CHAIN
|
||||
# can set group_search_filter, group_search_filter_user_attribute, group_search_base_dns and member_of
|
||||
# below in such a way that the user's recursive group membership is considered.
|
||||
#
|
||||
# Nested Groups + Active Directory (AD) Example:
|
||||
#
|
||||
# AD groups store the Distinguished Names (DNs) of members, so your filter must
|
||||
# recursively search your groups for the authenticating user's DN. For example:
|
||||
#
|
||||
# group_search_filter = "(member:1.2.840.113556.1.4.1941:=%s)"
|
||||
# group_search_filter_user_attribute = "distinguishedName"
|
||||
# group_search_base_dns = ["ou=groups,dc=grafana,dc=org"]
|
||||
#
|
||||
# [servers.attributes]
|
||||
# ...
|
||||
# member_of = "distinguishedName"
|
||||
|
||||
## Group search filter, to retrieve the groups of which the user is a member (only set if memberOf attribute is not available)
|
||||
# group_search_filter = "(&(objectClass=posixGroup)(memberUid=%s))"
|
||||
## Group search filter user attribute defines what user attribute gets substituted for %s in group_search_filter.
|
||||
## Defaults to the value of username in [server.attributes]
|
||||
## Valid options are any of your values in [servers.attributes]
|
||||
## If you are using nested groups you probably want to set this and member_of in
|
||||
## [servers.attributes] to "distinguishedName"
|
||||
# group_search_filter_user_attribute = "distinguishedName"
|
||||
## An array of the base DNs to search through for groups. Typically uses ou=groups
|
||||
# group_search_base_dns = ["ou=groups,dc=grafana,dc=org"]
|
||||
# group_search_filter_user_attribute = "uid"
|
||||
|
||||
# Specify names of the ldap attributes your ldap uses
|
||||
[servers.attributes]
|
||||
@@ -47,15 +70,13 @@ 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
|
||||
# The Grafana organization database id, optional, if left out the default org (id 1) will be used
|
||||
# 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]]
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
# --- First LDAP Server ---
|
||||
|
||||
[[servers]]
|
||||
host = "10.0.0.1"
|
||||
port = 389
|
||||
use_ssl = false
|
||||
start_tls = false
|
||||
ssl_skip_verify = false
|
||||
bind_dn = "cn=admin,dc=grafana,dc=org"
|
||||
bind_password = 'grafana'
|
||||
search_filter = "(cn=%s)"
|
||||
search_base_dns = ["ou=users,dc=grafana,dc=org"]
|
||||
|
||||
[servers.attributes]
|
||||
name = "givenName"
|
||||
surname = "sn"
|
||||
username = "cn"
|
||||
member_of = "memberOf"
|
||||
email = "email"
|
||||
|
||||
[[servers.group_mappings]]
|
||||
group_dn = "cn=admins,ou=groups,dc=grafana,dc=org"
|
||||
org_role = "Admin"
|
||||
grafana_admin = true
|
||||
|
||||
# --- Second LDAP Server ---
|
||||
|
||||
[[servers]]
|
||||
host = "10.0.0.2"
|
||||
port = 389
|
||||
use_ssl = false
|
||||
start_tls = false
|
||||
ssl_skip_verify = false
|
||||
|
||||
bind_dn = "cn=admin,dc=grafana,dc=org"
|
||||
bind_password = 'grafana'
|
||||
search_filter = "(cn=%s)"
|
||||
search_base_dns = ["ou=users,dc=grafana,dc=org"]
|
||||
|
||||
[servers.attributes]
|
||||
name = "givenName"
|
||||
surname = "sn"
|
||||
username = "cn"
|
||||
member_of = "memberOf"
|
||||
email = "email"
|
||||
|
||||
[[servers.group_mappings]]
|
||||
group_dn = "cn=editors,ou=groups,dc=grafana,dc=org"
|
||||
org_role = "Editor"
|
||||
|
||||
[[servers.group_mappings]]
|
||||
group_dn = "*"
|
||||
org_role = "Viewer"
|
||||
@@ -5,7 +5,6 @@ apiVersion: 1
|
||||
# - name: 'default'
|
||||
# orgId: 1
|
||||
# folder: ''
|
||||
# folderUid: ''
|
||||
# type: file
|
||||
# options:
|
||||
# path: /var/lib/grafana/dashboards
|
||||
|
||||
@@ -7,7 +7,7 @@ apiVersion: 1
|
||||
# orgId: 1
|
||||
|
||||
# # list of datasources to insert/update depending
|
||||
# # on what's available in the database
|
||||
# # on what's available in the datbase
|
||||
#datasources:
|
||||
# # <string, required> name of the datasource. Required
|
||||
# - name: Graphite
|
||||
@@ -40,14 +40,11 @@ apiVersion: 1
|
||||
# graphiteVersion: "1.1"
|
||||
# tlsAuth: true
|
||||
# tlsAuthWithCACert: true
|
||||
# httpHeaderName1: "Authorization"
|
||||
# # <string> json object of data that will be encrypted.
|
||||
# secureJsonData:
|
||||
# tlsCACert: "..."
|
||||
# tlsClientCert: "..."
|
||||
# tlsClientKey: "..."
|
||||
# # <openshift\kubernetes token example>
|
||||
# httpHeaderValue1: "Bearer xf5yhfkpsnmgo"
|
||||
# version: 1
|
||||
# # <bool> allow users to edit datasources from the UI.
|
||||
# editable: false
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# # config file version
|
||||
apiVersion: 1
|
||||
|
||||
# notifiers:
|
||||
# - name: default-slack-temp
|
||||
# type: slack
|
||||
# org_name: Main Org.
|
||||
# is_default: true
|
||||
# uid: notifier1
|
||||
# settings:
|
||||
# recipient: "XXX"
|
||||
# token: "xoxb"
|
||||
# uploadImage: true
|
||||
# url: https://slack.com
|
||||
# - name: default-email
|
||||
# type: email
|
||||
# org_id: 1
|
||||
# uid: notifier2
|
||||
# is_default: false
|
||||
# settings:
|
||||
# addresses: example11111@example.com
|
||||
# delete_notifiers:
|
||||
# - name: default-slack-temp
|
||||
# org_name: Main Org.
|
||||
# uid: notifier1
|
||||
@@ -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"
|
||||
514
conf/sample.ini
514
conf/sample.ini
@@ -4,19 +4,16 @@
|
||||
# change
|
||||
|
||||
# possible values : production, development
|
||||
;app_mode = production
|
||||
; app_mode = production
|
||||
|
||||
# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty
|
||||
;instance_name = ${HOSTNAME}
|
||||
; instance_name = ${HOSTNAME}
|
||||
|
||||
#################################### Paths ####################################
|
||||
[paths]
|
||||
# Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used)
|
||||
;data = /var/lib/grafana
|
||||
|
||||
# Temporary files in `data` directory older than given duration will be removed
|
||||
;temp_data_lifetime = 24h
|
||||
|
||||
# Directory where grafana can store logs
|
||||
;logs = /var/log/grafana
|
||||
|
||||
@@ -24,11 +21,11 @@
|
||||
;plugins = /var/lib/grafana/plugins
|
||||
|
||||
# folder that contains provisioning config files that grafana will apply on startup and while running.
|
||||
;provisioning = conf/provisioning
|
||||
; 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
|
||||
@@ -46,10 +43,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/
|
||||
|
||||
# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons.
|
||||
;serve_from_sub_path = false
|
||||
;root_url = http://localhost:3000
|
||||
|
||||
# Log web requests
|
||||
;router_logging = false
|
||||
@@ -70,7 +64,7 @@
|
||||
#################################### Database ####################################
|
||||
[database]
|
||||
# You can configure the database connection by specifying type, host, name, user and password
|
||||
# as separate properties or as on string using the url properties.
|
||||
# as seperate properties or as on string using the url propertie.
|
||||
|
||||
# Either "mysql", "postgres" or "sqlite3", it's your choice
|
||||
;type = sqlite3
|
||||
@@ -87,11 +81,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
|
||||
|
||||
@@ -105,21 +94,29 @@
|
||||
;conn_max_lifetime = 14400
|
||||
|
||||
# Set to true to log the sql calls and execution times.
|
||||
;log_queries =
|
||||
log_queries =
|
||||
|
||||
# For "sqlite3" only. cache mode setting used for connecting to the database. (private, shared)
|
||||
;cache_mode = private
|
||||
#################################### Session ####################################
|
||||
[session]
|
||||
# Either "memory", "file", "redis", "mysql", "postgres", default is "file"
|
||||
;provider = file
|
||||
|
||||
#################################### Cache server #############################
|
||||
[remote_cache]
|
||||
# Either "redis", "memcached" or "database" default is "database"
|
||||
;type = database
|
||||
# Provider config options
|
||||
# memory: not have any config yet
|
||||
# file: session dir path, is relative to grafana data_path
|
||||
# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=grafana`
|
||||
# mysql: go-sql-driver/mysql dsn config string, e.g. `user:password@tcp(127.0.0.1:3306)/database_name`
|
||||
# postgres: user=a password=b host=localhost port=5432 dbname=c sslmode=disable
|
||||
;provider_config = sessions
|
||||
|
||||
# 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'.
|
||||
# memcache: 127.0.0.1:11211
|
||||
;connstr =
|
||||
# Session cookie name
|
||||
;cookie_name = grafana_sess
|
||||
|
||||
# If you use session in https only, default is false
|
||||
;cookie_secure = false
|
||||
|
||||
# Session life time, default is 86400
|
||||
;session_life_time = 86400
|
||||
|
||||
#################################### Data proxy ###########################
|
||||
[dataproxy]
|
||||
@@ -127,30 +124,6 @@
|
||||
# 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.
|
||||
;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
|
||||
|
||||
#################################### Analytics ####################################
|
||||
[analytics]
|
||||
@@ -161,7 +134,7 @@
|
||||
;reporting_enabled = true
|
||||
|
||||
# Set to false to disable all checks to https://grafana.net
|
||||
# for new versions (grafana itself and plugins), check is used
|
||||
# for new vesions (grafana itself and plugins), check is used
|
||||
# in some UI views to notify that grafana or plugin update exists
|
||||
# This option does not cause any auto updates, nor send any information
|
||||
# only a GET request to http://grafana.com to get latest versions
|
||||
@@ -170,14 +143,8 @@
|
||||
# Google Analytics universal tracking code, only enabled if you specify an id here
|
||||
;google_analytics_ua_id =
|
||||
|
||||
# Google Tag Manager ID, only enabled if you specify an id here
|
||||
;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
|
||||
|
||||
@@ -187,6 +154,11 @@
|
||||
# used for signing
|
||||
;secret_key = SW2YcwTIb9zpOOhoPsMm
|
||||
|
||||
# Auto-login remember days
|
||||
;login_remember_days = 7
|
||||
;cookie_username = grafana_user
|
||||
;cookie_remember_name = grafana_remember
|
||||
|
||||
# disable gravatar profile images
|
||||
;disable_gravatar = false
|
||||
|
||||
@@ -196,38 +168,6 @@
|
||||
# disable protection against brute force login attempts
|
||||
;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"
|
||||
;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.
|
||||
;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.
|
||||
;strict_transport_security = false
|
||||
|
||||
# Sets how long a browser should cache HSTS. Only applied if strict_transport_security is enabled.
|
||||
;strict_transport_security_max_age_seconds = 86400
|
||||
|
||||
# Set to true if to enable HSTS preloading option. Only applied if strict_transport_security is enabled.
|
||||
;strict_transport_security_preload = false
|
||||
|
||||
# Set to true if to enable the HSTS includeSubDomains option. Only applied if strict_transport_security is enabled.
|
||||
;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
|
||||
|
||||
# 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
|
||||
|
||||
#################################### Snapshots ###########################
|
||||
[snapshots]
|
||||
# snapshot sharing options
|
||||
@@ -235,10 +175,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
|
||||
|
||||
@@ -247,13 +183,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
|
||||
@@ -265,18 +194,11 @@
|
||||
# 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
|
||||
|
||||
# Default UI theme ("dark" or "light")
|
||||
;default_theme = dark
|
||||
@@ -289,48 +211,14 @@
|
||||
# Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
|
||||
;viewers_can_edit = false
|
||||
|
||||
# Editors can administrate dashboard, folders and teams they create
|
||||
;editors_can_admin = false
|
||||
|
||||
# The duration in time a user invitation remains valid before expiring. This setting should be expressed as a duration. Examples: 6h (hours), 2d (days), 1w (week). Default is 24h (24 hours). The minimum supported duration is 15m (15 minutes).
|
||||
;user_invite_max_lifetime_duration = 24h
|
||||
|
||||
[auth]
|
||||
# Login cookie name
|
||||
;login_cookie_name = grafana_session
|
||||
|
||||
# The maximum lifetime (duration) an authenticated user can be inactive before being required to login at next visit. Default is 7 days (7d). This setting should be expressed as a duration, e.g. 5m (minutes), 6h (hours), 10d (days), 2w (weeks), 1M (month). The lifetime resets at each successful token rotation.
|
||||
;login_maximum_inactive_lifetime_duration =
|
||||
|
||||
# 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 =
|
||||
|
||||
# How often should auth tokens be rotated for authenticated users when being active. The default is each 10 minutes.
|
||||
;token_rotation_interval_minutes = 10
|
||||
|
||||
# Set to true to disable (hide) the login form, useful if you use OAuth, defaults to false
|
||||
;disable_login_form = false
|
||||
|
||||
# Set to true to disable the signout link in the side menu. useful if you use auth.proxy, defaults to false
|
||||
;disable_signout_menu = false
|
||||
|
||||
# URL to redirect the user to after sign out
|
||||
;signout_redirect_url =
|
||||
|
||||
# Set to true to attempt login with OAuth automatically, skipping the login screen.
|
||||
# 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 ######################
|
||||
#################################### Anonymous Auth ##########################
|
||||
[auth.anonymous]
|
||||
# enable anonymous access
|
||||
;enabled = false
|
||||
@@ -341,10 +229,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
|
||||
@@ -354,23 +239,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
|
||||
@@ -382,7 +253,20 @@
|
||||
;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 =
|
||||
|
||||
#################################### Grafana.com Auth ####################
|
||||
[auth.grafana_com]
|
||||
@@ -393,73 +277,18 @@
|
||||
;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 =
|
||||
;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]
|
||||
@@ -467,17 +296,12 @@
|
||||
;config_file = /etc/grafana/ldap.toml
|
||||
;allow_sign_up = true
|
||||
|
||||
# LDAP backround sync (Enterprise only)
|
||||
# At 1 am every day
|
||||
;sync_cron = "0 0 1 * * *"
|
||||
;active_sync_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 =
|
||||
@@ -486,12 +310,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]
|
||||
@@ -505,6 +326,7 @@
|
||||
# optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug
|
||||
;filters =
|
||||
|
||||
|
||||
# For "console" mode only
|
||||
[log.console]
|
||||
;level =
|
||||
@@ -550,40 +372,6 @@
|
||||
# Syslog tag. By default, the process' argv[0] is used.
|
||||
;tag =
|
||||
|
||||
#################################### 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]
|
||||
@@ -592,77 +380,14 @@
|
||||
# Makes it possible to turn off alert rule execution but alerting UI is visible
|
||||
;execute_alerts = true
|
||||
|
||||
# Default setting for new alert rules. Defaults to categorize error and timeouts as alerting. (alerting, keep_state)
|
||||
;error_or_timeout = alerting
|
||||
|
||||
# Default setting for how Grafana handles nodata or null values in alerting. (alerting, no_data, keep_state, ok)
|
||||
;nodata_or_nullvalues = no_data
|
||||
|
||||
# Alert notifications can include images, but rendering many images at the same time can overload the server
|
||||
# This limit will protect the server from render overloading and make sure notifications are sent out quickly
|
||||
;concurrent_render_limit = 5
|
||||
|
||||
|
||||
# Default setting for alert calculation timeout. Default value is 30
|
||||
;evaluation_timeout_seconds = 30
|
||||
|
||||
# Default setting for alert notification timeout. Default value is 30
|
||||
;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 a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month).
|
||||
;max_annotation_age =
|
||||
|
||||
# Configures max number of alert annotations that Grafana stores. Default value is 0, which keeps all alert annotations.
|
||||
;max_annotations_to_keep =
|
||||
|
||||
#################################### Annotations #########################
|
||||
|
||||
[annotations.dashboard]
|
||||
# Dashboard annotations means that annotations are associated with the dashboard they are created on.
|
||||
|
||||
# Configures how long dashboard annotations are stored. Default is 0, which keeps them forever.
|
||||
# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month).
|
||||
;max_age =
|
||||
|
||||
# Configures max number of dashboard annotations that Grafana stores. Default value is 0, which keeps all dashboard annotations.
|
||||
;max_annotations_to_keep =
|
||||
|
||||
[annotations.api]
|
||||
# API annotations means that the annotations have been created using the API without any
|
||||
# association with a dashboard.
|
||||
|
||||
# Configures how long Grafana stores API annotations. Default is 0, which keeps them forever.
|
||||
# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month).
|
||||
;max_age =
|
||||
|
||||
# Configures max number of API annotations that Grafana keeps. Default value is 0, which keeps all API annotations.
|
||||
;max_annotations_to_keep =
|
||||
|
||||
#################################### Explore #############################
|
||||
[explore]
|
||||
# Enable the Explore section
|
||||
;enabled = true
|
||||
|
||||
#################################### Internal Grafana Metrics ##########################
|
||||
# Metrics available at HTTP API Url /metrics
|
||||
[metrics]
|
||||
# Disable / Enable internal metrics
|
||||
;enabled = true
|
||||
# Graphite 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 =
|
||||
# Publish interval
|
||||
;interval_seconds = 10
|
||||
|
||||
# Send internal metrics to Graphite
|
||||
[metrics.graphite]
|
||||
@@ -670,11 +395,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)
|
||||
@@ -691,11 +411,11 @@
|
||||
# and indicates the initial sampling rate before the actual one
|
||||
# is received from the mothership
|
||||
;sampler_param = 1
|
||||
# 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 to import dashboards directly from Grafana.com
|
||||
[grafana_com]
|
||||
;url = https://grafana.com
|
||||
|
||||
#################################### External image storage ##########################
|
||||
[external_image_storage]
|
||||
@@ -704,8 +424,6 @@
|
||||
;provider =
|
||||
|
||||
[external_image_storage.s3]
|
||||
;endpoint =
|
||||
;path_style_access =
|
||||
;bucket =
|
||||
;region =
|
||||
;path =
|
||||
@@ -730,111 +448,3 @@
|
||||
|
||||
[external_image_storage.local]
|
||||
# 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.
|
||||
;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]
|
||||
# If set to true Grafana will allow script tags in text panels. Not recommended as it enable XSS vulnerabilities.
|
||||
;disable_sanitize_html = false
|
||||
|
||||
[plugins]
|
||||
;enable_alpha = false
|
||||
;app_tls_skip_verify_insecure = false
|
||||
# Enter a comma-separated list of plugin identifiers to identify plugins that are allowed to be loaded even if they lack a valid signature.
|
||||
;allow_loading_unsigned_plugins =
|
||||
|
||||
#################################### Grafana Image Renderer Plugin ##########################
|
||||
[plugin.grafana-image-renderer]
|
||||
# Instruct headless browser instance to use a default timezone when not provided by Grafana, e.g. when rendering panel image of alert.
|
||||
# See ICU’s 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
|
||||
|
||||
@@ -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.
|
||||
@@ -1,10 +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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
```
|
||||
@@ -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](http://gobook.io/read/github.com/go-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 the `SQLStore` 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,
|
||||
}))
|
||||
}
|
||||
```
|
||||
@@ -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.
|
||||
@@ -1,95 +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.
|
||||
|
||||
## 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.
|
||||
@@ -1,238 +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@12
|
||||
|
||||
npm install -g yarn
|
||||
```
|
||||
|
||||
## 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 Sqlite3 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).
|
||||
|
||||
## 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 jest
|
||||
```
|
||||
|
||||
### Run backend tests
|
||||
|
||||
If you're developing for the backend, run the tests with the standard Go tool:
|
||||
|
||||
```
|
||||
go test -v ./pkg/...
|
||||
```
|
||||
|
||||
### Run end-to-end tests
|
||||
|
||||
The end to end tests in Grafana use [Cypress](https://www.cypress.io/) to run automated scripts in a headless Chromium browser. Read more about our [e2e framework](/contribute/style-guides/e2e.md).
|
||||
|
||||
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).
|
||||
@@ -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 you’re 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 you’ve 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, you’re 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.
|
||||
@@ -1,41 +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.
|
||||
@@ -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;
|
||||
}
|
||||
```
|
||||
@@ -1,131 +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
|
||||
|
||||
Include images in a document using the following syntax:
|
||||
|
||||
**Example** \!\[Grafana Logo](/link/to/grafanalogo/logo.png)
|
||||
|
||||
This follows the format of "!", alt text wrapped in "[]" and the link URL wrapped in "()".
|
||||
|
||||
## 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 "()".
|
||||
@@ -1,229 +0,0 @@
|
||||
# Documentation style guide
|
||||
|
||||
This style guide applies to all documentation created for Grafana products.
|
||||
|
||||
For information about how to write technical documentation, we suggest reviewing the content of the [Google Technical Writing courses](https://developers.google.com/tech-writing).
|
||||
|
||||
The [Divio documentation system](https://documentation.divio.com/) site and the [Vue writing principles](https://v3.vuejs.org/guide/contributing/writing-guide.html#principles) are also good resources.
|
||||
|
||||
## 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 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
|
||||
|
||||
The [codespell](https://github.com/codespell-project/codespell) tool is run for every change to catch common misspellings.
|
||||
|
||||
## Inclusive language
|
||||
|
||||
This section provides guidelines on how to avoid using charged language in documentation.
|
||||
|
||||
### Allowing and blocking
|
||||
|
||||
Don't use "whitelist" or "blacklist" when referring to allowing or blocking content or traffic.
|
||||
|
||||
- When used as a noun, use "allowlist" or "blocklist".
|
||||
- When used as a verb, use "allow" or "block"
|
||||
|
||||
Example: _To **allow** outgoing traffic, add the IP to the **allowlist**._
|
||||
|
||||
### Leader and follower
|
||||
|
||||
Don't use "master" or "slave" to describe relationships between nodes or processes.
|
||||
|
||||
- Use "leader", "main" or "primary," instead of "master."
|
||||
- Use "follower" or "secondary," instead of "slave."
|
||||
|
||||
### Exceptions
|
||||
|
||||
When referring to a configuration or settings used by third-party libraries och technologies outside the Grafana project, prefer the original name to avoid confusion.
|
||||
|
||||
For example, use "master" when referring to the default Git branch.
|
||||
|
||||
## Grafana-specific style
|
||||
|
||||
The following sections provide general guidelines on topics specific to Grafana documentation. Note that for the most part, these are *guidelines*, not rigid rules. If you have questions, ask in the #docs channel of Grafana Slack.
|
||||
|
||||
### General
|
||||
|
||||
- Use active voice. Avoid passive voice.
|
||||
- Passive: The heatmap visualization is displayed.
|
||||
- Active: Grafana displays the heatmap visualization.
|
||||
- Write in the imperative second person. Examples: You can write a query. Click the panel. Close the window.
|
||||
- Write in present tense.
|
||||
- Not: The panel will open.
|
||||
- Use: The panel opens. Grafana opens the panel.
|
||||
- Do not use an ampersand (&) as an abbreviation for "and."
|
||||
- **Exceptions:** If an ampersand is used in the Grafana UI, then match the UI.
|
||||
- Avoid using internal slang and jargon in technical documentation.
|
||||
- Do not use two spaces after a period. Only add one space after each sentence. Do not add a space at the end of the paragraph.
|
||||
- Sentence length should be 25 words or less. If your thought is longer than 25 words, consider breaking up the sentence or changing the format to a list.
|
||||
- Paragraphs should be three sentences or fewer. Break up long paragraphs.
|
||||
|
||||
### File naming conventions
|
||||
|
||||
- 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
|
||||
|
||||
### 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
|
||||
- Avoid following one heading with another heading.
|
||||
- Avoid skipping heading levels. For example, an h1 should be followed by an h2 rather than an h3.
|
||||
- Avoid having just one lower-level heading. For example, h1, h2, h2, h3, h3, h2 is a good order. Do not go h1, h2, h3, h2, h3, h2.
|
||||
- Don't include parenthetical words like (Important!) in headings.
|
||||
|
||||
### 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.
|
||||
|
||||
### Capitalization
|
||||
|
||||
- Grafana, Loki, and Prometheus are always capitalized unless part of a code block.
|
||||
- API names are always Title Case, followed by "API"—for example, "Dashboard Permissions API"
|
||||
- Git is always capitalized, unless part of a code block.
|
||||
- Abbreviations are always capitalized (such as API, HTTP, ID, JSON, SQL, or URL) unless they are part of a code block.
|
||||
- Menu and submenu titles always use sentence case: capitalize the first word, and lowercase the rest.
|
||||
- "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.
|
||||
|
||||
### 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.
|
||||
|
||||
- **Wrong:** `$ sudo yum install grafana`
|
||||
- **Right:** `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.
|
||||
|
||||
#### 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.
|
||||
|
||||
#### 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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
```
|
||||
@@ -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.
|
||||
@@ -1,48 +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')]);
|
||||
```
|
||||
@@ -1,182 +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 [Storybook’s 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 don’t 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 component’s stories
|
||||
|
||||
To link a component’s 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 don’ts 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>;
|
||||
}
|
||||
```
|
||||
|
||||
### Knobs
|
||||
|
||||
Knobs is an [addon to Storybook](https://github.com/storybookjs/storybook/tree/master/addons/knobs) which can be used to easily switch values in the UI. A good use case for it is to try different props for the component. Using knobs is easy. Grafana is set up so knobs can be used straight out of the box. Here is an example of how you might use it.
|
||||
|
||||
```jsx
|
||||
// In MyComponent.story.tsx
|
||||
|
||||
import { number, text } from "@storybook/addon-knobs";
|
||||
|
||||
export const basicStory = () => (
|
||||
<MyComponent
|
||||
max={number("Max value", 10)}
|
||||
min={number("Min value", -10)}
|
||||
title={text("Title", "Look at the value!")}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
The general convention is that the first parameter of the knob is its name and the second is the default value. There are some more types:
|
||||
|
||||
| Knob | Description |
|
||||
| --------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `text` | Any text field |
|
||||
| `number` | Any number input. Also [available as range](https://github.com/storybookjs/storybook/tree/master/addons/knobs#number-bound-by-range) |
|
||||
| `boolean` | A switch between true/false |
|
||||
| `color` | Color picker |
|
||||
| `object` | JSON input or array. Good to use if the property requires more complex data structures. |
|
||||
| `array` | Array of strings separated by a comma |
|
||||
| `select` | Select a value from an options object. Good for trying different test cases. |
|
||||
| `options` | Configurable UI for selecting a range of options |
|
||||
| `files` | File selector |
|
||||
| `date` | Select date as stringified Unix timestamp |
|
||||
| `button` | Has a handler which is called when clicked |
|
||||
|
||||
## 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.
|
||||
@@ -1,109 +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.
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { useStyles } from '@grafana/ui';
|
||||
import { css } from 'emotion';
|
||||
|
||||
const getComponentStyles = (theme: GrafanaTheme) => css`
|
||||
padding: ${theme.spacing.md};
|
||||
`;
|
||||
|
||||
const Foo: FC<FooProps> = () => {
|
||||
const styles = useStyles(getComponentsStyles);
|
||||
|
||||
// Use styles with className
|
||||
};
|
||||
```
|
||||
|
||||
### Styling complex components
|
||||
|
||||
In more complex cases, especially when you need to style multiple DOM elements in one component, or when using styles that depend on properties and/or state, you should create a helper function that returns an object of styles. This function should also be wrapped in the `stylesFactory` helper function, which will provide basic memoization.
|
||||
|
||||
Let's say you need to style a component that has a different background depending on the theme:
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { selectThemeVariant, stylesFactory, useTheme } from '@grafana/ui';
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
const backgroundColor = selectThemeVariant({ light: theme.colors.red, dark: theme.colors.blue }, theme.type);
|
||||
|
||||
return {
|
||||
wrapper: css`
|
||||
background: ${backgroundColor};
|
||||
`,
|
||||
icon: css`
|
||||
font-size: ${theme.typography.size.sm};
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
const ComponentA = () => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyles(theme);
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
As red as you can get
|
||||
<i className={styles.icon} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
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>;
|
||||
};
|
||||
```
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -1,49 +0,0 @@
|
||||
# Set up your development environment
|
||||
|
||||
This folder contains useful scripts and configuration so you can:
|
||||
|
||||
- Configure data sources in Grafana for development.
|
||||
- Configure dashboards for development and test scenarios.
|
||||
- Create docker-compose file with databases and fake data.
|
||||
|
||||
## Install Docker
|
||||
|
||||
Grafana uses [Docker](https://docker.com) to make the task of setting up databases a little easier. If you do not have it already, make sure you [install Docker](https://docs.docker.com/docker-for-mac/install/) before proceeding to the next step.
|
||||
|
||||
## Developer dashboards and data sources
|
||||
|
||||
```bash
|
||||
./setup.sh
|
||||
```
|
||||
|
||||
After restarting the Grafana server, there should be a number of data sources named `gdev-<type>` provisioned as well as
|
||||
a dashboard folder named `gdev dashboards`. This folder contains dashboard and panel features tests dashboards.
|
||||
|
||||
Please update these dashboards or make new ones as new panels and dashboards features are developed or new bugs are
|
||||
found. The dashboards are located in the `devenv/dev-dashboards` folder.
|
||||
|
||||
## docker-compose with databases
|
||||
|
||||
This command creates a docker-compose file with specified databases configured and ready to run. Each database has
|
||||
a prepared image with some fake data ready to use. For available databases, see `docker/blocks` directory. Notice that
|
||||
for some databases there are multiple images, for example there is prometheus_mac specifically for Macs or different
|
||||
version.
|
||||
|
||||
```bash
|
||||
make devenv sources=influxdb,prometheus2,elastic5
|
||||
```
|
||||
|
||||
Some of the blocks support dynamic change of the image version used in the Docker file. The signature looks like this:
|
||||
|
||||
```bash
|
||||
make devenv sources=postgres,openldap,grafana postgres_version=9.2 grafana_version=6.7.0-beta1
|
||||
```
|
||||
|
||||
|
||||
### Notes per block
|
||||
|
||||
#### Grafana
|
||||
The grafana block is pre-configured with the dev-datasources and dashboards.
|
||||
|
||||
#### Jaeger
|
||||
Jaeger block runs both Jaeger and Loki container. Loki container sends traces to Jaeger and also logs its own logs into itself so it is possible to setup derived field for traceID from Loki to Jaeger. You need to install a docker plugin for the self logging to work, without it the container won't start. See https://github.com/grafana/loki/tree/master/cmd/docker-driver#plugin-installation for installation instructions.
|
||||
@@ -1,9 +0,0 @@
|
||||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: 'Bulk dashboards'
|
||||
folder: 'Bulk dashboards'
|
||||
type: file
|
||||
options:
|
||||
path: devenv/bulk-dashboards
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +0,0 @@
|
||||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: 'Bulk alerting dashboards'
|
||||
folder: 'Bulk alerting dashboards'
|
||||
type: file
|
||||
options:
|
||||
path: devenv/bulk_alerting_dashboards
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
{
|
||||
alertingDashboard(dashboardCounter, datasourceCounter):: {
|
||||
title: "alerting-title-" + dashboardCounter,
|
||||
editable: true,
|
||||
gnetId: null,
|
||||
graphTooltip: 0,
|
||||
id: null,
|
||||
links: [],
|
||||
panels: [
|
||||
{
|
||||
alert: {
|
||||
conditions: [
|
||||
{
|
||||
evaluator: {
|
||||
params: [
|
||||
65
|
||||
],
|
||||
type: "gt"
|
||||
},
|
||||
operator: {
|
||||
type: "and"
|
||||
},
|
||||
query: {
|
||||
params: [
|
||||
"A",
|
||||
"5m",
|
||||
"now"
|
||||
]
|
||||
},
|
||||
reducer: {
|
||||
params: [],
|
||||
type: "avg"
|
||||
},
|
||||
type: "query"
|
||||
}
|
||||
],
|
||||
executionErrorState: "alerting",
|
||||
frequency: "24h",
|
||||
handler: 1,
|
||||
name: "bulk alerting " + dashboardCounter,
|
||||
noDataState: "no_data",
|
||||
notifications: []
|
||||
},
|
||||
aliasColors: {},
|
||||
bars: false,
|
||||
dashLength: 10,
|
||||
dashes: false,
|
||||
datasource: "gfdev-bulkalerting-" + datasourceCounter,
|
||||
fill: 1,
|
||||
gridPos: {
|
||||
h: 9,
|
||||
w: 12,
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
id: 1,
|
||||
legend: {
|
||||
avg: false,
|
||||
current: false,
|
||||
max: false,
|
||||
min: false,
|
||||
show: true,
|
||||
total: false,
|
||||
values: false
|
||||
},
|
||||
lines: true,
|
||||
linewidth: 1,
|
||||
nullPointMode: "null",
|
||||
percentage: false,
|
||||
pointradius: 5,
|
||||
points: false,
|
||||
renderer: "flot",
|
||||
seriesOverrides: [],
|
||||
spaceLength: 10,
|
||||
stack: false,
|
||||
steppedLine: false,
|
||||
targets: [
|
||||
{
|
||||
expr: "go_goroutines",
|
||||
format: "time_series",
|
||||
intervalFactor: 1,
|
||||
refId: "A"
|
||||
}
|
||||
],
|
||||
thresholds: [
|
||||
{
|
||||
colorMode: "critical",
|
||||
fill: true,
|
||||
line: true,
|
||||
op: "gt",
|
||||
value: 50
|
||||
}
|
||||
],
|
||||
timeFrom: null,
|
||||
timeShift: null,
|
||||
title: "Panel Title",
|
||||
tooltip: {
|
||||
shared: true,
|
||||
sort: 0,
|
||||
value_type: "individual"
|
||||
},
|
||||
type: "graph",
|
||||
xaxis: {
|
||||
buckets: null,
|
||||
mode: "time",
|
||||
name: null,
|
||||
show: true,
|
||||
values: []
|
||||
},
|
||||
yaxes: [
|
||||
{
|
||||
format: "short",
|
||||
label: null,
|
||||
logBase: 1,
|
||||
max: null,
|
||||
min: null,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
format: "short",
|
||||
label: null,
|
||||
logBase: 1,
|
||||
max: null,
|
||||
min: null,
|
||||
show: true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
schemaVersion: 16,
|
||||
style: "dark",
|
||||
tags: [],
|
||||
templating: {
|
||||
list: []
|
||||
},
|
||||
time: {
|
||||
from: "now-6h",
|
||||
to: "now"
|
||||
},
|
||||
timepicker: {
|
||||
refresh_intervals: [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
time_options: [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
timezone: "",
|
||||
uid: null,
|
||||
version: 0
|
||||
},
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user