mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge remote-tracking branch 'upstream/master' into macroengine-interpolate
This commit is contained in:
commit
0f931f9e5e
@ -7,6 +7,7 @@ indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
max_line_length = 120
|
||||
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -10,8 +10,8 @@ awsconfig
|
||||
/public_gen
|
||||
/public/vendor/npm
|
||||
/tmp
|
||||
vendor/phantomjs/phantomjs
|
||||
vendor/phantomjs/phantomjs.exe
|
||||
tools/phantomjs/phantomjs
|
||||
tools/phantomjs/phantomjs.exe
|
||||
profile.out
|
||||
coverage.txt
|
||||
|
||||
@ -51,9 +51,13 @@ debug.test
|
||||
/packaging/**/*.rpm
|
||||
/packaging/**/*.deb
|
||||
|
||||
# Ignore OSX indexing
|
||||
.DS_Store
|
||||
|
||||
/vendor/**/*.py
|
||||
/vendor/**/*.xml
|
||||
/vendor/**/*.yml
|
||||
/vendor/**/*_test.go
|
||||
/vendor/**/.editorconfig
|
||||
/vendor/**/appengine*
|
||||
*.orig
|
@ -4,7 +4,7 @@
|
||||
"bitwise":false,
|
||||
"curly": true,
|
||||
"eqnull": true,
|
||||
"strict": true,
|
||||
"strict": false,
|
||||
"devel": true,
|
||||
"eqeqeq": true,
|
||||
"forin": false,
|
||||
|
122
CHANGELOG.md
122
CHANGELOG.md
@ -1,22 +1,87 @@
|
||||
# 5.0.0 (unreleased)
|
||||
# 5.0.0-stable (2018-03-01)
|
||||
|
||||
### WIP (in develop branch currently as its unstable or unfinished)
|
||||
- Dashboard folders
|
||||
- User groups
|
||||
- Dashboard permissions (on folder & dashboard level), permissions can be assigned to groups or individual users
|
||||
- UX changes to nav & side menu
|
||||
- New dashboard grid layout system
|
||||
### Fixes
|
||||
|
||||
# 4.7.0 (unreleased)
|
||||
- **oauth** Fix Github OAuth not working with private Organizations [#11028](https://github.com/grafana/grafana/pull/11028) [@lostick](https://github.com/lostick)
|
||||
- **kiosk** white area over bottom panels in kiosk mode [#11010](https://github.com/grafana/grafana/issues/11010)
|
||||
- **alerting** Fix OK state doesn't show up in Microsoft Teams [#11032](https://github.com/grafana/grafana/pull/11032), thx [@manacker](https://github.com/manacker)
|
||||
|
||||
# 5.0.0-beta5 (2018-02-26)
|
||||
|
||||
### Fixes
|
||||
|
||||
- **Orgs** Unable to switch org when too many orgs listed [#10774](https://github.com/grafana/grafana/issues/10774)
|
||||
- **Folders** Make it easier/explicit to access/modify folders using the API [#10630](https://github.com/grafana/grafana/issues/10630)
|
||||
- **Dashboard** Scrollbar works incorrectly in Grafana 5.0 Beta4 in some cases [#10982](https://github.com/grafana/grafana/issues/10982)
|
||||
- **ElasticSearch** Custom aggregation sizes no longer allowed for Elasticsearch [#10124](https://github.com/grafana/grafana/issues/10124)
|
||||
- **oauth** Github OAuth with allowed organizations fails to login [#10964](https://github.com/grafana/grafana/issues/10964)
|
||||
- **heatmap** Heatmap panel has partially hidden legend [#10793](https://github.com/grafana/grafana/issues/10793)
|
||||
- **snapshots** Expired snapshots not being cleaned up [#10996](https://github.com/grafana/grafana/pull/10996)
|
||||
|
||||
# 5.0.0-beta4 (2018-02-19)
|
||||
|
||||
### Fixes
|
||||
|
||||
- **Dashboard** Fixed dashboard overwrite permission issue [#10814](https://github.com/grafana/grafana/issues/10814)
|
||||
- **Keyboard shortcuts** Fixed Esc key when in panel edit/view mode [#10945](https://github.com/grafana/grafana/issues/10945)
|
||||
- **Save dashboard** Fixed issue with time range & variable reset after saving [#10946](https://github.com/grafana/grafana/issues/10946)
|
||||
|
||||
# 5.0.0-beta3 (2018-02-16)
|
||||
|
||||
### Fixes
|
||||
|
||||
- **MySQL** Fixed new migration issue with index length [#10931](https://github.com/grafana/grafana/issues/10931)
|
||||
- **Modal** Escape key no closes modals everywhere, fixes [#10887](https://github.com/grafana/grafana/issues/10887)
|
||||
- **Row repeats** Fix for repeating rows issue, fixes [#10932](https://github.com/grafana/grafana/issues/10932)
|
||||
- **Docs** Team api documented, fixes [#10832](https://github.com/grafana/grafana/issues/10832)
|
||||
- **Plugins** Plugin info page broken, fixes [#10943](https://github.com/grafana/grafana/issues/10943)
|
||||
|
||||
# 5.0.0-beta2 (2018-02-15)
|
||||
|
||||
### Fixes
|
||||
|
||||
- **Permissions** Fixed search permissions issues [#10822](https://github.com/grafana/grafana/issues/10822)
|
||||
- **Permissions** Fixed problem issues displaying permissions lists [#10864](https://github.com/grafana/grafana/issues/10864)
|
||||
- **PNG-Rendering** Fixed problem rendering legend to the right [#10526](https://github.com/grafana/grafana/issues/10526)
|
||||
- **Reset password** Fixed problem with reset password form [#10870](https://github.com/grafana/grafana/issues/10870)
|
||||
- **Light theme** Fixed problem with light theme in safari, [#10869](https://github.com/grafana/grafana/issues/10869)
|
||||
- **Provisioning** Now handles deletes when dashboard json files removed from disk [#10865](https://github.com/grafana/grafana/issues/10865)
|
||||
- **MySQL** Fixed issue with schema migration on old mysql (index too long) [#10779](https://github.com/grafana/grafana/issues/10779)
|
||||
- **Github OAuth** Fixed fetching github orgs from private github org [#10823](https://github.com/grafana/grafana/issues/10823)
|
||||
- **Embedding** Fixed issues embedding panel [#10787](https://github.com/grafana/grafana/issues/10787)
|
||||
|
||||
# 5.0.0-beta1 (2018-02-05)
|
||||
|
||||
Grafana v5.0 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=Izr0IBgoTZQ) of Grafana v5.
|
||||
|
||||
### New Major Features
|
||||
- **Dashboards** Dashboard folders, [#1611](https://github.com/grafana/grafana/issues/1611)
|
||||
- **Teams** User groups (teams) implemented. Can be used in folder & dashboard permission list.
|
||||
- **Dashboard grid**: Panels are now layed out in a two dimensional grid (with x, y, w, h). [#9093](https://github.com/grafana/grafana/issues/9093).
|
||||
- **Templating**: Vertical repeat direction for panel repeats.
|
||||
- **UX**: Major update to page header and navigation
|
||||
- **Dashboard settings**: Combine dashboard settings views into one with side menu, [#9750](https://github.com/grafana/grafana/issues/9750)
|
||||
- **Persistent dashboard url's**: New url's for dashboards that allows renaming dashboards without breaking links. [#7883](https://github.com/grafana/grafana/issues/7883)
|
||||
|
||||
## Breaking changes
|
||||
|
||||
`[dashboard.json]` have been replaced with [dashboard provisioning](http://docs.grafana.org/administration/provisioning/).
|
||||
* **[dashboard.json]** have been replaced with [dashboard provisioning](http://docs.grafana.org/administration/provisioning/).
|
||||
Config files for provisioning datasources as configuration have changed from `/conf/datasources` to `/conf/provisioning/datasources`.
|
||||
From `/etc/grafana/datasources` to `/etc/grafana/provisioning/datasources` when installed with deb/rpm packages.
|
||||
|
||||
Config files for provisioning datasources as configuration have changed from `/conf/datasources` to `/conf/provisioning/datasources`.
|
||||
From `/etc/grafana/datasources` to `/etc/grafana/provisioning/datasources` when installed with deb/rpm packages.
|
||||
* **Pagerduty** The notifier now defaults to not auto resolve incidents. More details at [#10222](https://github.com/grafana/grafana/issues/10222)
|
||||
|
||||
* **HTTP API**
|
||||
- `GET /api/alerts` property dashboardUri renamed to url and is now the full url (that is including app sub url).
|
||||
|
||||
## New Dashboard Grid
|
||||
|
||||
The new grid engine is a major upgrade for how you can position and move panels. It enables new layouts and a much easier dashboard building experience. The change is backward compatible. So you can upgrade your current version to 5.0 without breaking dashboards, but you cannot downgrade from 5.0 to previous versions. Grafana will automatically upgrade your dashboards to the new schema and position panels to match your existing layout. There might be minor differences in panel height. If you upgrade to 5.0 and for some reason want to rollback to the previous version you can restore dashboards to previous versions using dashboard history. But that should only be seen as an emergency solution.
|
||||
|
||||
Dashboard panels and rows are positioned using a gridPos object `{x: 0, y: 0, w: 24, h: 5}`. Units are in grid dimensions (24 columns, 1 height unit 30px). Rows and Panels objects exist (together) in a flat array directly on the dashboard root object. Rows are not needed for layouts anymore and are mainly there for backward compatibility. Some panel plugins that do not respect their panel height might require an update.
|
||||
|
||||
## New Features
|
||||
* **Alerting**: Add support for internal image store [#6922](https://github.com/grafana/grafana/issues/6922), thx [@FunkyM](https://github.com/FunkyM)
|
||||
* **Data Source Proxy**: Add support for whitelisting specified cookies that will be passed through to the data source when proxying data source requests [#5457](https://github.com/grafana/grafana/issues/5457), thanks [@robingustafsson](https://github.com/robingustafsson)
|
||||
* **Postgres/MySQL**: add __timeGroup macro for mysql [#9596](https://github.com/grafana/grafana/pull/9596), thanks [@svenklemm](https://github.com/svenklemm)
|
||||
* **Text**: Text panel are now edited in the ace editor. [#9698](https://github.com/grafana/grafana/pull/9698), thx [@mtanda](https://github.com/mtanda)
|
||||
@ -25,30 +90,53 @@ From `/etc/grafana/datasources` to `/etc/grafana/provisioning/datasources` when
|
||||
* **Graphite**: Query editor updated to support new query by tag features [#9230](https://github.com/grafana/grafana/issues/9230)
|
||||
* **Dashboard history**: New config file option versions_to_keep sets how many versions per dashboard to store, [#9671](https://github.com/grafana/grafana/issues/9671)
|
||||
* **Dashboard as cfg**: Load dashboards from file into Grafana on startup/change [#9654](https://github.com/grafana/grafana/issues/9654) [#5269](https://github.com/grafana/grafana/issues/5269)
|
||||
* **Prometheus**: Grafana can now send alerts to Prometheus Alertmanager while firing [#7481](https://github.com/grafana/grafana/issues/7481), thx [@Thib17](https://github.com/Thib17) and [@mtanda](https://github.com/mtanda)
|
||||
* **Table**: Support multiple table formated queries in table panel [#9170](https://github.com/grafana/grafana/issues/9170), thx [@davkal](https://github.com/davkal)
|
||||
* **Security**: Protect against brute force (frequent) login attempts [#7616](https://github.com/grafana/grafana/issues/7616)
|
||||
|
||||
## Minor
|
||||
* **Graph**: Don't hide graph display options (Lines/Points) when draw mode is unchecked [#9770](https://github.com/grafana/grafana/issues/9770), thx [@Jonnymcc](https://github.com/Jonnymcc)
|
||||
* **Prometheus**: Show label name in paren after by/without/on/ignoring/group_left/group_right [#9664](https://github.com/grafana/grafana/pull/9664), thx [@mtanda](https://github.com/mtanda)
|
||||
* **Alert panel**: Adds placeholder text when no alerts are within the time range [#9624](https://github.com/grafana/grafana/issues/9624), thx [@straend](https://github.com/straend)
|
||||
* **Mysql**: MySQL enable MaxOpenCon and MaxIdleCon regards how constring is configured. [#9784](https://github.com/grafana/grafana/issues/9784), thx [@dfredell](https://github.com/dfredell)
|
||||
* **Cloudwatch**: Fixes broken query inspector for cloudwatch [#9661](https://github.com/grafana/grafana/issues/9661), thx [@mtanda](https://github.com/mtanda)
|
||||
* **Dashboard**: Make it possible to start dashboards from search and dashboard list panel [#1871](https://github.com/grafana/grafana/issues/1871)
|
||||
* **Annotations**: Posting annotations now return the id of the annotation [#9798](https://github.com/grafana/grafana/issues/9798)
|
||||
* **Systemd**: Use systemd notification ready flag [#10024](https://github.com/grafana/grafana/issues/10024), thx [@jgrassler](https://github.com/jgrassler)
|
||||
* **Github**: Use organizations_url provided from github to verify user belongs in org. [#10111](https://github.com/grafana/grafana/issues/10111), thx [@adiletmaratov](https://github.com/adiletmaratov)
|
||||
|
||||
## Tech
|
||||
* **RabbitMq**: Remove support for publishing events to RabbitMQ [#9645](https://github.com/grafana/grafana/issues/9645)
|
||||
|
||||
* **Github**: Use organizations_url provided from github to verify user belongs in org. [#10111](https://github.com/grafana/grafana/issues/10111), thx
|
||||
[@adiletmaratov](https://github.com/adiletmaratov)
|
||||
* **Backend**: Fixed bug where Grafana exited before all sub routines where finished [#10131](https://github.com/grafana/grafana/issues/10131)
|
||||
* **Azure**: Adds support for Azure blob storage as external image stor [#8955](https://github.com/grafana/grafana/issues/8955), thx [@saada](https://github.com/saada)
|
||||
* **Telegram**: Add support for inline image uploads to telegram notifier plugin [#9967](https://github.com/grafana/grafana/pull/9967), thx [@rburchell](https://github.com/rburchell)
|
||||
|
||||
## Fixes
|
||||
* **Sensu**: Send alert message to sensu output [#9551](https://github.com/grafana/grafana/issues/9551), thx [@cjchand](https://github.com/cjchand)
|
||||
* **Singlestat**: suppress error when result contains no datapoints [#9636](https://github.com/grafana/grafana/issues/9636), thx [@utkarshcmu](https://github.com/utkarshcmu)
|
||||
* **Postgres/MySQL**: Control quoting in SQL-queries when using template variables [#9030](https://github.com/grafana/grafana/issues/9030), thanks [@svenklemm](https://github.com/svenklemm)
|
||||
* **Pagerduty**: Pagerduty dont auto resolve incidents by default anymore. [#10222](https://github.com/grafana/grafana/issues/10222)
|
||||
* **Cloudwatch**: Fix for multi-valued templated queries. [#9903](https://github.com/grafana/grafana/issues/9903)
|
||||
|
||||
# 4.6.3 (unreleased)
|
||||
## Tech
|
||||
* **RabbitMq**: Remove support for publishing events to RabbitMQ [#9645](https://github.com/grafana/grafana/issues/9645)
|
||||
|
||||
## Deprecation notes
|
||||
|
||||
### HTTP API
|
||||
The following operations have been deprecated and will be removed in a future release:
|
||||
- `GET /api/dashboards/db/:slug` -> Use `GET /api/dashboards/uid/:uid` instead
|
||||
- `DELETE /api/dashboards/db/:slug` -> Use `DELETE /api/dashboards/uid/:uid` instead
|
||||
|
||||
The following properties have been deprecated and will be removed in a future release:
|
||||
- `uri` property in `GET /api/search` -> Use new `url` or `uid` property instead
|
||||
- `meta.slug` property in `GET /api/dashboards/uid/:uid` and `GET /api/dashboards/db/:slug` -> Use new `meta.url` or `dashboard.uid` property instead
|
||||
|
||||
# 4.6.3 (2017-12-14)
|
||||
|
||||
## Fixes
|
||||
* **Gzip**: Fixes bug gravatar images when gzip was enabled [#5952](https://github.com/grafana/grafana/issues/5952)
|
||||
* **Alert list**: Now shows alert state changes even after adding manual annotations on dashboard [#9951](https://github.com/grafana/grafana/issues/9951)
|
||||
* **Alerting**: Fixes bug where rules evaluated as firing when all conditions was false and using OR operator. [#9318](https://github.com/grafana/grafana/issues/9318)
|
||||
* **Cloudwatch**: CloudWatch no longer display metrics' default alias [#10151](https://github.com/grafana/grafana/issues/10151), thx [@mtanda](https://github.com/mtanda)
|
||||
|
||||
# 4.6.2 (2017-11-16)
|
||||
|
||||
|
636
Gopkg.lock
generated
Normal file
636
Gopkg.lock
generated
Normal file
@ -0,0 +1,636 @@
|
||||
# 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 = "e8409d73255791843585964791443dbad877058c"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-xorm/xorm"
|
||||
packages = ["."]
|
||||
revision = "6687a2b4e824f4d87f2d65060ec5cb0d896dff1e"
|
||||
|
||||
[[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 = "4de68f1342ba98a637ec8ca7496aeeae2021bf9e4c7c80db7924e14709151a62"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
199
Gopkg.toml
Normal file
199
Gopkg.toml
Normal file
@ -0,0 +1,199 @@
|
||||
# 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"
|
||||
revision = "e8409d73255791843585964791443dbad877058c"
|
||||
#version = "0.5.7" //keeping this since we would rather depend on version then commit
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-xorm/xorm"
|
||||
revision = "6687a2b4e824f4d87f2d65060ec5cb0d896dff1e"
|
||||
#version = "0.6.4" //keeping this since we would rather depend on version then commit
|
||||
|
||||
[[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"
|
3
Makefile
3
Makefile
@ -26,3 +26,6 @@ test: test-go test-js
|
||||
|
||||
run:
|
||||
./bin/grafana-server
|
||||
|
||||
protoc:
|
||||
protoc -I pkg/tsdb/models pkg/tsdb/models/*.proto --go_out=plugins=grpc:pkg/tsdb/models/.
|
40
README.md
40
README.md
@ -9,6 +9,9 @@ Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB.
|
||||
|
||||

|
||||
|
||||
## 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.
|
||||
|
||||
## Installation
|
||||
Head to [docs.grafana.org](http://docs.grafana.org/installation/) and [download](https://grafana.com/get)
|
||||
the latest release.
|
||||
@ -19,7 +22,7 @@ If you have any problems please read the [troubleshooting guide](http://docs.gra
|
||||
Be sure to read the [getting started guide](http://docs.grafana.org/guides/gettingstarted/) and the other feature guides.
|
||||
|
||||
## 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
|
||||
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)
|
||||
|
||||
### Dependencies
|
||||
@ -42,23 +45,17 @@ For this you need nodejs (v.6+).
|
||||
```bash
|
||||
npm install -g yarn
|
||||
yarn install --pure-lockfile
|
||||
npm run build
|
||||
```
|
||||
|
||||
To rebuild frontend assets (typescript, sass etc) as you change them start the watcher via.
|
||||
|
||||
```bash
|
||||
npm run watch
|
||||
```
|
||||
|
||||
Run tests
|
||||
Run tests
|
||||
```bash
|
||||
npm run test
|
||||
npm run jest
|
||||
```
|
||||
|
||||
Run tests in watch mode
|
||||
Run karma tests
|
||||
```bash
|
||||
npm run watch-test
|
||||
npm run karma
|
||||
```
|
||||
|
||||
### Recompile backend on source change
|
||||
@ -83,8 +80,11 @@ In your custom.ini uncomment (remove the leading `;`) sign. And set `app_mode =
|
||||
|
||||
### Running tests
|
||||
|
||||
- You can run backend Golang tests using "go test ./pkg/...".
|
||||
- Execute all frontend tests with "npm run test"
|
||||
#### Frontend
|
||||
Execute all frontend tests
|
||||
```bash
|
||||
npm run test
|
||||
```
|
||||
|
||||
Writing & watching frontend tests (we have two test runners)
|
||||
|
||||
@ -95,9 +95,21 @@ Writing & watching frontend tests (we have two test runners)
|
||||
- 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.
|
||||
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!
|
||||
|
||||
|
27
ROADMAP.md
27
ROADMAP.md
@ -1,25 +1,28 @@
|
||||
# Roadmap (2017-10-31)
|
||||
# Roadmap (2018-02-22)
|
||||
|
||||
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-4 months)
|
||||
### Short term (1-2 months)
|
||||
|
||||
- Release Grafana v5
|
||||
- User groups
|
||||
- Dashboard folders
|
||||
- Dashboard & folder permissions (assigned to users or groups)
|
||||
- New Dashboard layout engine
|
||||
- New sidemenu & nav UX
|
||||
- v5.1
|
||||
- Crossplatform builds & build speed improvements
|
||||
- Enterprise LDAP
|
||||
- New template interpolation syntax
|
||||
- Provisioning workflow
|
||||
- First login registration view
|
||||
- IFQL Initial support
|
||||
|
||||
### Mid term (2-4 months)
|
||||
|
||||
- v5.2
|
||||
- Azure monitor backend rewrite
|
||||
- Elasticsearch alerting
|
||||
- React migration foundation (core components)
|
||||
- Graphite 1.1 Tags Support
|
||||
- Backend plugins? (alert notifiers, auth)
|
||||
|
||||
### Long term (4 - 8 months)
|
||||
|
||||
- Backend plugins to support more Auth options, Alerting data sources & notifications
|
||||
- Alerting improvements (silence, per series tracking, etc)
|
||||
- Dashboard as configuration and other automation / provisioning improvements
|
||||
- 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)
|
||||
|
12
build.go
12
build.go
@ -347,11 +347,11 @@ func ChangeWorkingDir(dir string) {
|
||||
}
|
||||
|
||||
func grunt(params ...string) {
|
||||
if runtime.GOOS == "windows" {
|
||||
runPrint(`.\node_modules\.bin\grunt`, params...)
|
||||
} else {
|
||||
runPrint("./node_modules/.bin/grunt", params...)
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
runPrint(`.\node_modules\.bin\grunt`, params...)
|
||||
} else {
|
||||
runPrint("./node_modules/.bin/grunt", params...)
|
||||
}
|
||||
}
|
||||
|
||||
func gruntBuildArg(task string) []string {
|
||||
@ -371,7 +371,7 @@ func gruntBuildArg(task string) []string {
|
||||
}
|
||||
|
||||
func setup() {
|
||||
runPrint("go", "get", "-v", "github.com/kardianos/govendor")
|
||||
runPrint("go", "get", "-v", "github.com/golang/dep")
|
||||
runPrint("go", "install", "-v", "./pkg/cmd/grafana-server")
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ machine:
|
||||
GOPATH: "/home/ubuntu/.go_workspace"
|
||||
ORG_PATH: "github.com/grafana"
|
||||
REPO_PATH: "${ORG_PATH}/grafana"
|
||||
GODIST: "go1.9.2.linux-amd64.tar.gz"
|
||||
GODIST: "go1.9.3.linux-amd64.tar.gz"
|
||||
post:
|
||||
- mkdir -p ~/download
|
||||
- mkdir -p ~/docker
|
||||
|
@ -174,6 +174,9 @@ disable_gravatar = false
|
||||
# data source proxy whitelist (ip_or_domain:port separated by spaces)
|
||||
data_source_proxy_whitelist =
|
||||
|
||||
# disable protection against brute force login attempts
|
||||
disable_brute_force_login_protection = false
|
||||
|
||||
#################################### Snapshots ###########################
|
||||
[snapshots]
|
||||
# snapshot sharing options
|
||||
@ -184,9 +187,6 @@ external_snapshot_name = Publish to snapshot.raintank.io
|
||||
# remove expired snapshot
|
||||
snapshot_remove_expired = true
|
||||
|
||||
# remove snapshots after 90 days
|
||||
snapshot_TTL_days = 90
|
||||
|
||||
#################################### Dashboards ##################
|
||||
|
||||
[dashboards]
|
||||
@ -221,6 +221,9 @@ external_manage_link_url =
|
||||
external_manage_link_name =
|
||||
external_manage_info =
|
||||
|
||||
# Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
|
||||
viewers_can_edit = false
|
||||
|
||||
[auth]
|
||||
# Set to true to disable (hide) the login form, useful if you use OAuth
|
||||
disable_login_form = false
|
||||
@ -245,7 +248,7 @@ enabled = false
|
||||
allow_sign_up = true
|
||||
client_id = some_id
|
||||
client_secret = some_secret
|
||||
scopes = user:email
|
||||
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
|
||||
@ -321,7 +324,7 @@ allow_sign_up = true
|
||||
enabled = false
|
||||
host = localhost:25
|
||||
user =
|
||||
# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;"""
|
||||
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
|
||||
password =
|
||||
cert_file =
|
||||
key_file =
|
||||
@ -470,7 +473,7 @@ sampler_param = 1
|
||||
|
||||
#################################### External Image Storage ##############
|
||||
[external_image_storage]
|
||||
# You can choose between (s3, webdav, gcs)
|
||||
# You can choose between (s3, webdav, gcs, azure_blob, local)
|
||||
provider =
|
||||
|
||||
[external_image_storage.s3]
|
||||
@ -490,4 +493,12 @@ public_url =
|
||||
[external_image_storage.gcs]
|
||||
key_file =
|
||||
bucket =
|
||||
path =
|
||||
path =
|
||||
|
||||
[external_image_storage.azure_blob]
|
||||
account_name =
|
||||
account_key =
|
||||
container_name =
|
||||
|
||||
[external_image_storage.local]
|
||||
# does not require any configuration
|
||||
|
@ -19,7 +19,7 @@ ssl_skip_verify = false
|
||||
# Search user bind dn
|
||||
bind_dn = "cn=admin,dc=grafana,dc=org"
|
||||
# Search user bind password
|
||||
# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;"""
|
||||
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
|
||||
bind_password = 'grafana'
|
||||
|
||||
# User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)"
|
||||
|
@ -1,6 +1,10 @@
|
||||
# # config file version
|
||||
apiVersion: 1
|
||||
|
||||
#providers:
|
||||
# - name: 'default'
|
||||
# org_id: 1
|
||||
# orgId: 1
|
||||
# folder: ''
|
||||
# type: file
|
||||
# options:
|
||||
# folder: /var/lib/grafana/dashboards
|
||||
# path: /var/lib/grafana/dashboards
|
||||
|
@ -1,10 +1,13 @@
|
||||
# # config file version
|
||||
apiVersion: 1
|
||||
|
||||
# # list of datasources that should be deleted from the database
|
||||
#delete_datasources:
|
||||
#deleteDatasources:
|
||||
# - name: Graphite
|
||||
# org_id: 1
|
||||
# orgId: 1
|
||||
|
||||
# # list of datasources to insert/update depending
|
||||
# # whats available in the datbase
|
||||
# # on what's available in the datbase
|
||||
#datasources:
|
||||
# # <string, required> name of the datasource. Required
|
||||
# - name: Graphite
|
||||
@ -12,8 +15,8 @@
|
||||
# type: graphite
|
||||
# # <string, required> access mode. direct or proxy. Required
|
||||
# access: proxy
|
||||
# # <int> org id. will default to org_id 1 if not specified
|
||||
# org_id: 1
|
||||
# # <int> org id. will default to orgId 1 if not specified
|
||||
# orgId: 1
|
||||
# # <string> url
|
||||
# url: http://localhost:8080
|
||||
# # <string> database password, if used
|
||||
@ -23,22 +26,22 @@
|
||||
# # <string> database name, if used
|
||||
# database:
|
||||
# # <bool> enable/disable basic auth
|
||||
# basic_auth:
|
||||
# basicAuth:
|
||||
# # <string> basic auth username
|
||||
# basic_auth_user:
|
||||
# basicAuthUser:
|
||||
# # <string> basic auth password
|
||||
# basic_auth_password:
|
||||
# basicAuthPassword:
|
||||
# # <bool> enable/disable with credentials headers
|
||||
# with_credentials:
|
||||
# withCredentials:
|
||||
# # <bool> mark as default datasource. Max one per org
|
||||
# is_default:
|
||||
# isDefault:
|
||||
# # <map> fields that will be converted to json and stored in json_data
|
||||
# json_data:
|
||||
# jsonData:
|
||||
# graphiteVersion: "1.1"
|
||||
# tlsAuth: true
|
||||
# tlsAuthWithCACert: true
|
||||
# # <string> json object of data that will be encrypted.
|
||||
# secure_json_data:
|
||||
# secureJsonData:
|
||||
# tlsCACert: "..."
|
||||
# tlsClientCert: "..."
|
||||
# tlsClientKey: "..."
|
||||
|
@ -71,7 +71,7 @@
|
||||
;host = 127.0.0.1:3306
|
||||
;name = grafana
|
||||
;user = root
|
||||
# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;"""
|
||||
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
|
||||
;password =
|
||||
|
||||
# Use either URL or the previous fields to configure the database
|
||||
@ -162,6 +162,9 @@ log_queries =
|
||||
# data source proxy whitelist (ip_or_domain:port separated by spaces)
|
||||
;data_source_proxy_whitelist =
|
||||
|
||||
# disable protection against brute force login attempts
|
||||
;disable_brute_force_login_protection = false
|
||||
|
||||
#################################### Snapshots ###########################
|
||||
[snapshots]
|
||||
# snapshot sharing options
|
||||
@ -172,9 +175,6 @@ log_queries =
|
||||
# remove expired snapshot
|
||||
;snapshot_remove_expired = true
|
||||
|
||||
# remove snapshots after 90 days
|
||||
;snapshot_TTL_days = 90
|
||||
|
||||
#################################### Dashboards History ##################
|
||||
[dashboards]
|
||||
# Number dashboard versions to keep (per dashboard). Default: 20, Minimum: 1
|
||||
@ -205,6 +205,9 @@ log_queries =
|
||||
;external_manage_link_name =
|
||||
;external_manage_info =
|
||||
|
||||
# Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
|
||||
;viewers_can_edit = false
|
||||
|
||||
[auth]
|
||||
# Set to true to disable (hide) the login form, useful if you use OAuth, defaults to false
|
||||
;disable_login_form = false
|
||||
@ -414,7 +417,7 @@ log_queries =
|
||||
#################################### 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)
|
||||
# you can choose between (s3, webdav, gcs, azure_blob, local)
|
||||
;provider =
|
||||
|
||||
[external_image_storage.s3]
|
||||
@ -433,4 +436,12 @@ log_queries =
|
||||
[external_image_storage.gcs]
|
||||
;key_file =
|
||||
;bucket =
|
||||
;path =
|
||||
;path =
|
||||
|
||||
[external_image_storage.azure_blob]
|
||||
;account_name =
|
||||
;account_key =
|
||||
;container_name =
|
||||
|
||||
[external_image_storage.local]
|
||||
# does not require any configuration
|
||||
|
4
docker/blocks/apache_proxy/Dockerfile
Normal file
4
docker/blocks/apache_proxy/Dockerfile
Normal file
@ -0,0 +1,4 @@
|
||||
FROM jmferrer/apache2-reverse-proxy:latest
|
||||
|
||||
COPY ports.conf /etc/apache2/sites-enabled
|
||||
COPY proxy.conf /etc/apache2/sites-enabled
|
9
docker/blocks/apache_proxy/docker-compose.yaml
Normal file
9
docker/blocks/apache_proxy/docker-compose.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
# This will proxy all requests for http://localhost:10081/grafana/ to
|
||||
# http://localhost:3000 (Grafana running locally)
|
||||
#
|
||||
# Please note that you'll need to change the root_url in the Grafana configuration:
|
||||
# root_url = %(protocol)s://%(domain)s:/grafana/
|
||||
|
||||
apacheproxy:
|
||||
build: blocks/apache_proxy
|
||||
network_mode: host
|
1
docker/blocks/apache_proxy/ports.conf
Normal file
1
docker/blocks/apache_proxy/ports.conf
Normal file
@ -0,0 +1 @@
|
||||
Listen 10081
|
4
docker/blocks/apache_proxy/proxy.conf
Normal file
4
docker/blocks/apache_proxy/proxy.conf
Normal file
@ -0,0 +1,4 @@
|
||||
<VirtualHost *:10081>
|
||||
ProxyPass /grafana/ http://localhost:3000/
|
||||
ProxyPassReverse /grafana/ http://localhost:3000/
|
||||
</VirtualHost>
|
@ -1,4 +1,4 @@
|
||||
graphite:
|
||||
graphite09:
|
||||
build: blocks/graphite
|
||||
ports:
|
||||
- "8080:80"
|
||||
|
549
docker/blocks/mysql/dashboard.json
Normal file
549
docker/blocks/mysql/dashboard.json
Normal file
@ -0,0 +1,549 @@
|
||||
{
|
||||
"__inputs": [
|
||||
{
|
||||
"name": "DS_MYSQL",
|
||||
"label": "Mysql",
|
||||
"description": "",
|
||||
"type": "datasource",
|
||||
"pluginId": "mysql",
|
||||
"pluginName": "MySQL"
|
||||
}
|
||||
],
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "5.0.0"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "graph",
|
||||
"name": "Graph",
|
||||
"version": ""
|
||||
},
|
||||
{
|
||||
"type": "datasource",
|
||||
"id": "mysql",
|
||||
"name": "MySQL",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "table",
|
||||
"name": "Table",
|
||||
"version": ""
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "A dashboard visualizing data generated from grafana/fake-data-gen",
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"iteration": 1518602729468,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {
|
||||
"total avg": "#6ed0e0"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "${DS_MYSQL}",
|
||||
"fill": 2,
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [
|
||||
{
|
||||
"alias": "total avg",
|
||||
"fill": 0,
|
||||
"pointradius": 3,
|
||||
"points": true
|
||||
}
|
||||
],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"rawSql": "SELECT\n $__timeGroup(createdAt,'$summarize') as time_sec,\n avg(value) as value,\n hostname as metric\nFROM \n grafana_metric\nWHERE\n $__timeFilter(createdAt) AND\n measurement = 'logins.count' AND\n hostname IN($host)\nGROUP BY 1, 3\nORDER BY 1",
|
||||
"refId": "A",
|
||||
"target": ""
|
||||
},
|
||||
{
|
||||
"alias": "",
|
||||
"format": "time_series",
|
||||
"rawSql": "SELECT\n $__timeGroup(createdAt,'$summarize') as time_sec,\n min(value) as value,\n 'total avg' as metric\nFROM \n grafana_metric\nWHERE\n $__timeFilter(createdAt) AND\n measurement = 'logins.count'\nGROUP BY 1\nORDER BY 1",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": "1h",
|
||||
"title": "Average logins / $summarize",
|
||||
"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
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "${DS_MYSQL}",
|
||||
"fill": 2,
|
||||
"gridPos": {
|
||||
"h": 18,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
"id": 4,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"format": "time_series",
|
||||
"rawSql": "SELECT\n $__timeGroup(createdAt,'$summarize') as time_sec,\n avg(value) as value,\n 'started' as metric\nFROM \n grafana_metric\nWHERE\n $__timeFilter(createdAt) AND\n measurement = 'payment.started'\nGROUP BY 1, 3\nORDER BY 1",
|
||||
"refId": "A",
|
||||
"target": ""
|
||||
},
|
||||
{
|
||||
"alias": "",
|
||||
"format": "time_series",
|
||||
"rawSql": "SELECT\n $__timeGroup(createdAt,'$summarize') as time_sec,\n avg(value) as value,\n 'ended' as \"metric\"\nFROM \n grafana_metric\nWHERE\n $__timeFilter(createdAt) AND\n measurement = 'payment.ended'\nGROUP BY 1, 3\nORDER BY 1",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": "1h",
|
||||
"title": "Average payments started/ended / $summarize",
|
||||
"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
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "${DS_MYSQL}",
|
||||
"fill": 2,
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 9
|
||||
},
|
||||
"id": 3,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"format": "time_series",
|
||||
"rawSql": "SELECT\n $__timeGroup(createdAt,'$summarize') as time_sec,\n max(value) as value,\n hostname as metric\nFROM \n grafana_metric\nWHERE\n $__timeFilter(createdAt) AND\n measurement = 'cpu' AND\n hostname IN($host)\nGROUP BY 1, 3\nORDER BY 1",
|
||||
"refId": "A",
|
||||
"target": ""
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": "1h",
|
||||
"title": "Max CPU / $summarize",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "percent",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"columns": [],
|
||||
"datasource": "${DS_MYSQL}",
|
||||
"fontSize": "100%",
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 18
|
||||
},
|
||||
"id": 6,
|
||||
"links": [],
|
||||
"pageSize": null,
|
||||
"scroll": true,
|
||||
"showHeader": true,
|
||||
"sort": {
|
||||
"col": 0,
|
||||
"desc": true
|
||||
},
|
||||
"styles": [
|
||||
{
|
||||
"alias": "Time",
|
||||
"dateFormat": "YYYY-MM-DD HH:mm:ss",
|
||||
"link": false,
|
||||
"pattern": "Time",
|
||||
"type": "date"
|
||||
},
|
||||
{
|
||||
"alias": "",
|
||||
"colorMode": null,
|
||||
"colors": [
|
||||
"rgba(245, 54, 54, 0.9)",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgba(50, 172, 45, 0.97)"
|
||||
],
|
||||
"decimals": 2,
|
||||
"pattern": "/.*/",
|
||||
"thresholds": [],
|
||||
"type": "number",
|
||||
"unit": "short"
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"format": "table",
|
||||
"rawSql": "SELECT createdAt as Time, source, datacenter, hostname, value FROM grafana_metric WHERE hostname in($host)",
|
||||
"refId": "A",
|
||||
"target": ""
|
||||
}
|
||||
],
|
||||
"timeShift": "1h",
|
||||
"title": "Values",
|
||||
"transform": "table",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 16,
|
||||
"style": "dark",
|
||||
"tags": [
|
||||
"fake-data-gen",
|
||||
"mysql"
|
||||
],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allValue": null,
|
||||
"current": {},
|
||||
"datasource": "${DS_MYSQL}",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "Datacenter",
|
||||
"multi": false,
|
||||
"name": "datacenter",
|
||||
"options": [],
|
||||
"query": "SELECT DISTINCT datacenter FROM grafana_metric",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"sort": 1,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
},
|
||||
{
|
||||
"allValue": null,
|
||||
"current": {},
|
||||
"datasource": "${DS_MYSQL}",
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"label": "Hostname",
|
||||
"multi": true,
|
||||
"name": "host",
|
||||
"options": [],
|
||||
"query": "SELECT DISTINCT hostname FROM grafana_metric WHERE datacenter='$datacenter'",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"sort": 1,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
},
|
||||
{
|
||||
"auto": false,
|
||||
"auto_count": 5,
|
||||
"auto_min": "10s",
|
||||
"current": {
|
||||
"selected": true,
|
||||
"text": "1m",
|
||||
"value": "1m"
|
||||
},
|
||||
"hide": 0,
|
||||
"label": "Summarize",
|
||||
"name": "summarize",
|
||||
"options": [
|
||||
{
|
||||
"selected": false,
|
||||
"text": "1s",
|
||||
"value": "1s"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "10s",
|
||||
"value": "10s"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "30s",
|
||||
"value": "30s"
|
||||
},
|
||||
{
|
||||
"selected": true,
|
||||
"text": "1m",
|
||||
"value": "1m"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "5m",
|
||||
"value": "5m"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "10m",
|
||||
"value": "10m"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "30m",
|
||||
"value": "30m"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "1h",
|
||||
"value": "1h"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "6h",
|
||||
"value": "6h"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "12h",
|
||||
"value": "12h"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "1d",
|
||||
"value": "1d"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "7d",
|
||||
"value": "7d"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "14d",
|
||||
"value": "14d"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "30d",
|
||||
"value": "30d"
|
||||
}
|
||||
],
|
||||
"query": "1s,10s,30s,1m,5m,10m,30m,1h,6h,12h,1d,7d,14d,30d",
|
||||
"refresh": 2,
|
||||
"type": "interval"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-1h",
|
||||
"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": "",
|
||||
"title": "Grafana Fake Data Gen - MySQL",
|
||||
"uid": "DGsCac3kz",
|
||||
"version": 6
|
||||
}
|
@ -12,3 +12,10 @@
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
command: [mysqld, --character-set-server=utf8mb4, --collation-server=utf8mb4_unicode_ci, --innodb_monitor_enable=all]
|
||||
|
||||
fake-mysql-data:
|
||||
image: grafana/fake-data-gen
|
||||
network_mode: bridge
|
||||
environment:
|
||||
FD_DATASOURCE: mysql
|
||||
FD_PORT: 3306
|
||||
|
||||
|
@ -7,4 +7,7 @@
|
||||
MYSQL_PASSWORD: password
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
tmpfs: /var/lib/mysql:rw
|
||||
|
3
docker/blocks/nginx_proxy/Dockerfile
Normal file
3
docker/blocks/nginx_proxy/Dockerfile
Normal file
@ -0,0 +1,3 @@
|
||||
FROM nginx:alpine
|
||||
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
9
docker/blocks/nginx_proxy/docker-compose.yaml
Normal file
9
docker/blocks/nginx_proxy/docker-compose.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
# This will proxy all requests for http://localhost:10080/grafana/ to
|
||||
# http://localhost:3000 (Grafana running locally)
|
||||
#
|
||||
# Please note that you'll need to change the root_url in the Grafana configuration:
|
||||
# root_url = %(protocol)s://%(domain)s:/grafana/
|
||||
|
||||
nginxproxy:
|
||||
build: blocks/nginx_proxy
|
||||
network_mode: host
|
19
docker/blocks/nginx_proxy/nginx.conf
Normal file
19
docker/blocks/nginx_proxy/nginx.conf
Normal file
@ -0,0 +1,19 @@
|
||||
events { worker_connections 1024; }
|
||||
|
||||
http {
|
||||
sendfile on;
|
||||
|
||||
proxy_redirect off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
|
||||
server {
|
||||
listen 10080;
|
||||
|
||||
location /grafana/ {
|
||||
proxy_pass http://localhost:3000/;
|
||||
}
|
||||
}
|
||||
}
|
547
docker/blocks/postgres/dashboard.json
Normal file
547
docker/blocks/postgres/dashboard.json
Normal file
@ -0,0 +1,547 @@
|
||||
{
|
||||
"__inputs": [
|
||||
{
|
||||
"name": "DS_POSTGRESQL",
|
||||
"label": "PostgreSQL",
|
||||
"description": "",
|
||||
"type": "datasource",
|
||||
"pluginId": "postgres",
|
||||
"pluginName": "PostgreSQL"
|
||||
}
|
||||
],
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "5.0.0"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "graph",
|
||||
"name": "Graph",
|
||||
"version": ""
|
||||
},
|
||||
{
|
||||
"type": "datasource",
|
||||
"id": "postgres",
|
||||
"name": "PostgreSQL",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "table",
|
||||
"name": "Table",
|
||||
"version": ""
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "A dashboard visualizing data generated from grafana/fake-data-gen",
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"iteration": 1518601837383,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {
|
||||
"total avg": "#6ed0e0"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "${DS_POSTGRESQL}",
|
||||
"fill": 2,
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [
|
||||
{
|
||||
"alias": "total avg",
|
||||
"fill": 0,
|
||||
"pointradius": 3,
|
||||
"points": true
|
||||
}
|
||||
],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"format": "time_series",
|
||||
"hide": false,
|
||||
"rawSql": "SELECT\n $__timeGroup(\"createdAt\",'$summarize'),\n avg(value) as \"value\",\n hostname as \"metric\"\nFROM \n grafana_metric\nWHERE\n $__timeFilter(\"createdAt\") AND\n measurement = 'logins.count' AND\n hostname IN($host)\nGROUP BY time, metric\nORDER BY time",
|
||||
"refId": "A",
|
||||
"target": ""
|
||||
},
|
||||
{
|
||||
"alias": "",
|
||||
"format": "time_series",
|
||||
"rawSql": "SELECT\n $__timeGroup(\"createdAt\",'$summarize'),\n min(value) as \"value\",\n 'total avg' as \"metric\"\nFROM \n grafana_metric\nWHERE\n $__timeFilter(\"createdAt\") AND\n measurement = 'logins.count'\nGROUP BY time",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Average logins / $summarize",
|
||||
"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
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "${DS_POSTGRESQL}",
|
||||
"fill": 2,
|
||||
"gridPos": {
|
||||
"h": 18,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
"id": 4,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"format": "time_series",
|
||||
"rawSql": "SELECT\n $__timeGroup(\"createdAt\",'$summarize'),\n avg(value) as \"value\",\n 'started' as \"metric\"\nFROM \n grafana_metric\nWHERE\n $__timeFilter(\"createdAt\") AND\n measurement = 'payment.started'\nGROUP BY time, metric\nORDER BY time",
|
||||
"refId": "A",
|
||||
"target": ""
|
||||
},
|
||||
{
|
||||
"alias": "",
|
||||
"format": "time_series",
|
||||
"rawSql": "SELECT\n $__timeGroup(\"createdAt\",'$summarize'),\n avg(value) as \"value\",\n 'ended' as \"metric\"\nFROM \n grafana_metric\nWHERE\n $__timeFilter(\"createdAt\") AND\n measurement = 'payment.ended'\nGROUP BY time, metric\nORDER BY time",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Average payments started/ended / $summarize",
|
||||
"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
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "${DS_POSTGRESQL}",
|
||||
"fill": 2,
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 9
|
||||
},
|
||||
"id": 3,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"format": "time_series",
|
||||
"rawSql": "SELECT\n $__timeGroup(\"createdAt\",'$summarize'),\n max(value) as \"value\",\n hostname as \"metric\"\nFROM \n grafana_metric\nWHERE\n $__timeFilter(\"createdAt\") AND\n measurement = 'cpu' AND\n hostname IN($host)\nGROUP BY time, metric\nORDER BY time",
|
||||
"refId": "A",
|
||||
"target": ""
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Max CPU / $summarize",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "percent",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"columns": [],
|
||||
"datasource": "${DS_POSTGRESQL}",
|
||||
"fontSize": "100%",
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 18
|
||||
},
|
||||
"id": 6,
|
||||
"links": [],
|
||||
"pageSize": null,
|
||||
"scroll": true,
|
||||
"showHeader": true,
|
||||
"sort": {
|
||||
"col": 0,
|
||||
"desc": true
|
||||
},
|
||||
"styles": [
|
||||
{
|
||||
"alias": "Time",
|
||||
"dateFormat": "YYYY-MM-DD HH:mm:ss",
|
||||
"link": false,
|
||||
"pattern": "Time",
|
||||
"type": "date"
|
||||
},
|
||||
{
|
||||
"alias": "",
|
||||
"colorMode": null,
|
||||
"colors": [
|
||||
"rgba(245, 54, 54, 0.9)",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgba(50, 172, 45, 0.97)"
|
||||
],
|
||||
"decimals": 2,
|
||||
"pattern": "/.*/",
|
||||
"thresholds": [],
|
||||
"type": "number",
|
||||
"unit": "short"
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"format": "table",
|
||||
"rawSql": "SELECT \"createdAt\" as \"Time\", source, datacenter, hostname, value FROM grafana_metric WHERE hostname in($host)",
|
||||
"refId": "A",
|
||||
"target": ""
|
||||
}
|
||||
],
|
||||
"title": "Values",
|
||||
"transform": "table",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 16,
|
||||
"style": "dark",
|
||||
"tags": [
|
||||
"fake-data-gen",
|
||||
"postgres"
|
||||
],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allValue": null,
|
||||
"current": {},
|
||||
"datasource": "${DS_POSTGRESQL}",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "Datacenter",
|
||||
"multi": false,
|
||||
"name": "datacenter",
|
||||
"options": [],
|
||||
"query": "SELECT DISTINCT datacenter FROM grafana_metric",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"sort": 1,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
},
|
||||
{
|
||||
"allValue": null,
|
||||
"current": {},
|
||||
"datasource": "${DS_POSTGRESQL}",
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"label": "Hostname",
|
||||
"multi": true,
|
||||
"name": "host",
|
||||
"options": [],
|
||||
"query": "SELECT DISTINCT hostname FROM grafana_metric WHERE datacenter='$datacenter'",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"sort": 1,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
},
|
||||
{
|
||||
"auto": false,
|
||||
"auto_count": 5,
|
||||
"auto_min": "10s",
|
||||
"current": {
|
||||
"text": "1m",
|
||||
"value": "1m"
|
||||
},
|
||||
"hide": 0,
|
||||
"label": "Summarize",
|
||||
"name": "summarize",
|
||||
"options": [
|
||||
{
|
||||
"selected": false,
|
||||
"text": "1s",
|
||||
"value": "1s"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "10s",
|
||||
"value": "10s"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "30s",
|
||||
"value": "30s"
|
||||
},
|
||||
{
|
||||
"selected": true,
|
||||
"text": "1m",
|
||||
"value": "1m"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "5m",
|
||||
"value": "5m"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "10m",
|
||||
"value": "10m"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "30m",
|
||||
"value": "30m"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "1h",
|
||||
"value": "1h"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "6h",
|
||||
"value": "6h"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "12h",
|
||||
"value": "12h"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "1d",
|
||||
"value": "1d"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "7d",
|
||||
"value": "7d"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "14d",
|
||||
"value": "14d"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "30d",
|
||||
"value": "30d"
|
||||
}
|
||||
],
|
||||
"query": "1s,10s,30s,1m,5m,10m,30m,1h,6h,12h,1d,7d,14d,30d",
|
||||
"refresh": 2,
|
||||
"type": "interval"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-1h",
|
||||
"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": "",
|
||||
"title": "Grafana Fake Data Gen - PostgreSQL",
|
||||
"uid": "JYola5qzz",
|
||||
"version": 1
|
||||
}
|
@ -7,3 +7,10 @@
|
||||
ports:
|
||||
- "5432:5432"
|
||||
command: postgres -c log_connections=on -c logging_collector=on -c log_destination=stderr -c log_directory=/var/log/postgresql
|
||||
|
||||
fake-postgres-data:
|
||||
image: grafana/fake-data-gen
|
||||
network_mode: bridge
|
||||
environment:
|
||||
FD_DATASOURCE: postgres
|
||||
FD_PORT: 5432
|
@ -1,3 +1,3 @@
|
||||
FROM prom/prometheus
|
||||
FROM prom/prometheus:v1.8.2
|
||||
ADD prometheus.yml /etc/prometheus/
|
||||
ADD alert.rules /etc/prometheus/
|
||||
|
25
docker/blocks/prometheus2/docker-compose.yaml
Normal file
25
docker/blocks/prometheus2/docker-compose.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
prometheus:
|
||||
build: blocks/prometheus2
|
||||
network_mode: host
|
||||
ports:
|
||||
- "9090:9090"
|
||||
|
||||
node_exporter:
|
||||
image: prom/node-exporter
|
||||
network_mode: host
|
||||
ports:
|
||||
- "9100:9100"
|
||||
|
||||
fake-prometheus-data:
|
||||
image: grafana/fake-data-gen
|
||||
network_mode: host
|
||||
ports:
|
||||
- "9091:9091"
|
||||
environment:
|
||||
FD_DATASOURCE: prom
|
||||
|
||||
alertmanager:
|
||||
image: quay.io/prometheus/alertmanager
|
||||
network_mode: host
|
||||
ports:
|
||||
- "9093:9093"
|
@ -9,5 +9,6 @@ FROM grafana/docs-base:latest
|
||||
|
||||
COPY config.toml /site
|
||||
COPY awsconfig /site
|
||||
COPY versions.json /site/static/js
|
||||
|
||||
VOLUME ["/site/content"]
|
||||
|
@ -1 +1 @@
|
||||
v4.3
|
||||
v5.0
|
||||
|
@ -10,17 +10,17 @@ weight = 8
|
||||
|
||||
# Grafana CLI
|
||||
|
||||
Grafana cli is a small executable that is bundled with grafana server and is suppose to be executed on the same machine as grafana runs.
|
||||
Grafana cli is a small executable that is bundled with Grafana-server and is supposed to be executed on the same machine Grafana-server is running on.
|
||||
|
||||
## Plugins
|
||||
|
||||
The CLI helps you install, upgrade and manage your plugins on the same machine it CLI is running.
|
||||
You can find more information about how to install and manage your plugins at the
|
||||
[plugin page]({{< relref "plugins/installation.md" >}}).
|
||||
The CLI allows you to install, upgrade and manage your plugins on the machine it is running on.
|
||||
You can find more information about how to install and manage your plugins in the
|
||||
[plugins page]({{< relref "plugins/installation.md" >}}).
|
||||
|
||||
## Admin
|
||||
|
||||
> This feature is only available in grafana 4.1 and above.
|
||||
> This feature is only available in Grafana 4.1 and above.
|
||||
|
||||
To show all admin commands:
|
||||
`grafana-cli admin`
|
||||
@ -39,7 +39,7 @@ then there are two flags that can be used to set homepath and the config file pa
|
||||
|
||||
`grafana-cli admin reset-admin-password --homepath "/usr/share/grafana" newpass`
|
||||
|
||||
If you have not lost the admin password then it is better to set in the Grafana UI. If you need to set the password in a script then the [Grafana API](http://docs.grafana.org/http_api/user/#change-password) can be used. Here is an example with curl using basic auth:
|
||||
If you have not lost the admin password then it is better to set in the Grafana UI. If you need to set the password in a script then the [Grafana API](http://docs.grafana.org/http_api/user/#change-password) can be used. Here is an example using curl with basic auth:
|
||||
|
||||
```bash
|
||||
curl -X PUT -H "Content-Type: application/json" -d '{
|
||||
|
@ -10,6 +10,6 @@ weight = 8
|
||||
|
||||
# Internal metrics
|
||||
|
||||
Grafana collects some metrics about it self internally. Currently Grafana supports pushing metrics to graphite and exposing them to be scraped by Prometheus.
|
||||
Grafana collects some metrics about itself internally. Currently, Grafana supports pushing metrics to Graphite or exposing them to be scraped by Prometheus.
|
||||
|
||||
To enabled internal metrics you have to enable it under the [metrics] section in your [grafana.ini](http://docs.grafana.org/installation/configuration/#enabled-6) config file.If you want to push metrics to graphite you have also have to configure the [metrics.graphite](http://docs.grafana.org/installation/configuration/#metrics-graphite) section.
|
||||
To emit internal metrics you have to enable the option under the [metrics] section in your [grafana.ini](http://docs.grafana.org/installation/configuration/#enabled-6) config file. If you want to push metrics to Graphite, you must also configure the [metrics.graphite](http://docs.grafana.org/installation/configuration/#metrics-graphite) section.
|
||||
|
118
docs/sources/administration/permissions.md
Normal file
118
docs/sources/administration/permissions.md
Normal file
@ -0,0 +1,118 @@
|
||||
+++
|
||||
title = "Permissions"
|
||||
description = "Grafana user permissions"
|
||||
keywords = ["grafana", "configuration", "documentation", "admin", "users", "permissions"]
|
||||
type = "docs"
|
||||
aliases = ["/reference/admin"]
|
||||
[menu.docs]
|
||||
name = "Permissions"
|
||||
parent = "admin"
|
||||
weight = 3
|
||||
+++
|
||||
|
||||
# Permissions
|
||||
|
||||
Grafana users have permissions that are determined by their:
|
||||
|
||||
- **Organization Role** (Admin, Editor, Viewer)
|
||||
- Via **Team** memberships where the **Team** has been assigned specific permissions.
|
||||
- Via permissions assigned directly to user (on folders or dashboards)
|
||||
- The Grafana Admin (i.e. Super Admin) user flag.
|
||||
|
||||
## Organization Roles
|
||||
|
||||
Users can be belong to one or more organizations. A user's organization membership is tied to a role that defines what the user is allowed to do
|
||||
in that organization.
|
||||
|
||||
### Admin Role
|
||||
|
||||
Can do everything scoped to the organization. For example:
|
||||
|
||||
- Add & Edit data sources.
|
||||
- Add & Edit organization users & teams.
|
||||
- Configure App plugins & set org settings.
|
||||
|
||||
### Editor Role
|
||||
|
||||
- Can create and modify dashboards & alert rules. This can be disabled on specific folders and dashboards.
|
||||
- **Cannot** create or edit data sources nor invite new users.
|
||||
|
||||
### Viewer Role
|
||||
|
||||
- View any dashboard. This can be disabled on specific folders and dashboards.
|
||||
- **Cannot** create or edit dashboards nor data sources.
|
||||
|
||||
This role can be tweaked via Grafana server setting [viewers_can_edit]({{< relref "installation/configuration.md#viewers-can-edit" >}}). If you set this to true users
|
||||
with **Viewer** can also make transient dashboard edits, meaning they can modify panels & queries but not save the changes (nor create new dashboards).
|
||||
Useful for public Grafana installations where you want anonymous users to be able to edit panels & queries but not save or create new dashboards.
|
||||
|
||||
## Grafana Admin
|
||||
|
||||
This admin flag makes a user a `Super Admin`. This means they can access the `Server Admin` views where all users and organizations can be administrated.
|
||||
|
||||
### Dashboard & Folder Permissions
|
||||
|
||||
> Introduced in Grafana v5.0
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v50/folder_permissions.png" max-width="500px" class="docs-image--right" >}}
|
||||
|
||||
For dashboards and dashboard folders there is a **Permissions** page that make it possible to
|
||||
remove the default role based permssions for Editors and Viewers. It's here you can add and assign permissions to specific **Users** and **Teams**.
|
||||
|
||||
You can assign & remove permissions for **Organization Roles**, **Users** and **Teams**.
|
||||
|
||||
Permission levels:
|
||||
|
||||
- **Admin**: Can edit & create dashboards and edit permissions.
|
||||
- **Edit**: Can edit & create dashboards. **Cannot** edit folder/dashboard permissions.
|
||||
- **View**: Can only view existing dashboards/folders.
|
||||
|
||||
#### Restricting Access
|
||||
|
||||
The highest permission always wins so if you for example want to hide a folder or dashboard from others you need to remove the **Organization Role** based permission from the Access Control List (ACL).
|
||||
|
||||
- You cannot override permissions for users with the **Org Admin Role**. Admins always have access to everything.
|
||||
- A more specific permission with a lower permission level will not have any effect if a more general rule exists with higher permission level. You need to remove or lower the permission level of the more general rule.
|
||||
|
||||
#### How Grafana Resolves Multiple Permissions - Examples
|
||||
|
||||
##### Example 1 (`user1` has the Editor Role)
|
||||
|
||||
Permissions for a dashboard:
|
||||
|
||||
- `Everyone with Editor Role Can Edit`
|
||||
- `user1 Can View`
|
||||
|
||||
Result: `user1` has Edit permission as the highest permission always wins.
|
||||
|
||||
##### Example 2 (`user1` has the Viewer Role and is a member of `team1`)
|
||||
|
||||
Permissions for a dashboard:
|
||||
|
||||
- `Everyone with Viewer Role Can View`
|
||||
- `user1 Can Edit`
|
||||
- `team1 Can Admin`
|
||||
|
||||
Result: `user1` has Admin permission as the highest permission always wins.
|
||||
|
||||
##### Example 3
|
||||
|
||||
Permissions for a dashboard:
|
||||
|
||||
- `user1 Can Admin (inherited from parent folder)`
|
||||
- `user1 Can Edit`
|
||||
|
||||
Result: You cannot override to a lower permission. `user1` has Admin permission as the highest permission always wins.
|
||||
|
||||
- **View**: Can only view existing dashboars/folders.
|
||||
- You cannot override permissions for users with **Org Admin Role**
|
||||
- A more specific permission with lower permission level will not have any effect if a more general rule exists with higher permission level. For example if "Everyone with Editor Role Can Edit" exists in the ACL list then **John Doe** will still have Edit permission even after you have specifically added a permission for this user with the permission set to **View**. You need to remove or lower the permission level of the more general rule.
|
||||
|
||||
### Data source permissions
|
||||
|
||||
Permissions on dashboards and folders **do not** include permissions on data sources. A user with `Viewer` role
|
||||
can still issue any possible query to a data source, not just those queries that exist on dashboards he/she has access to.
|
||||
We hope to add permissions on data sources in a future release. Until then **do not** view dashboard permissions as a secure
|
||||
way to restrict user data access. Dashboard permissions only limits what dashboards & folders a user can view & edit not which
|
||||
data sources a user can access nor what queries a user can issue.
|
||||
|
@ -3,6 +3,7 @@ title = "Provisioning"
|
||||
description = ""
|
||||
keywords = ["grafana", "provisioning"]
|
||||
type = "docs"
|
||||
aliases = ["/installation/provisioning"]
|
||||
[menu.docs]
|
||||
parent = "admin"
|
||||
weight = 8
|
||||
@ -12,7 +13,7 @@ weight = 8
|
||||
|
||||
## Config file
|
||||
|
||||
Checkout the [configuration](/installation/configuration) page for more information about what you can configure in `grafana.ini`
|
||||
Checkout the [configuration](/installation/configuration) page for more information on what you can configure in `grafana.ini`
|
||||
|
||||
### Config file locations
|
||||
|
||||
@ -35,7 +36,7 @@ GF_<SectionName>_<KeyName>
|
||||
```
|
||||
|
||||
Where the section name is the text within the brackets. Everything
|
||||
should be upper case, `.` should be replaced by `_`. For example, given these configuration settings:
|
||||
should be upper case and `.` should be replaced by `_`. For example, given these configuration settings:
|
||||
|
||||
```bash
|
||||
# default section
|
||||
@ -48,7 +49,7 @@ admin_user = admin
|
||||
client_secret = 0ldS3cretKey
|
||||
```
|
||||
|
||||
Then you can override them using:
|
||||
Overriding will be done like so:
|
||||
|
||||
```bash
|
||||
export GF_DEFAULT_INSTANCE_NAME=my-instance
|
||||
@ -60,34 +61,36 @@ export GF_AUTH_GOOGLE_CLIENT_SECRET=newS3cretKey
|
||||
|
||||
## Configuration management tools
|
||||
|
||||
Currently we do not provide any scripts/manifests for configuring Grafana. Rather then spending time learning and creating scripts/manifests for each tool, we think our time is better spent making Grafana easier to provision. Therefor, we heavily relay on the expertise of he community.
|
||||
Currently we do not provide any scripts/manifests for configuring Grafana. Rather than spending time learning and creating scripts/manifests for each tool, we think our time is better spent making Grafana easier to provision. Therefore, we heavily relay on the expertise of the community.
|
||||
|
||||
Tool | Project
|
||||
-----|------------
|
||||
Puppet | [https://forge.puppet.com/puppet/grafana](https://forge.puppet.com/puppet/grafana)
|
||||
Ansible | [https://github.com/cloudalchemy/ansible-grafana](https://github.com/cloudalchemy/ansible-grafana)
|
||||
Ansible | [https://github.com/picotrading/ansible-grafana](https://github.com/picotrading/ansible-grafana)
|
||||
Chef | [https://github.com/JonathanTron/chef-grafana](https://github.com/JonathanTron/chef-grafana)
|
||||
Saltstack | [https://github.com/salt-formulas/salt-formula-grafana](https://github.com/salt-formulas/salt-formula-grafana)
|
||||
|
||||
## Datasources
|
||||
## Datasources
|
||||
|
||||
> This feature is available from v5.0
|
||||
|
||||
It's possible to manage datasources in Grafana by adding one or more yaml config files in the [`provisioning/datasources`](/installation/configuration/#provisioning) directory. Each config file can contain a list of `datasources` that will be added or updated during start up. If the datasource already exists, Grafana will update it to match the configuration file. The config file can also contain a list of datasources that should be deleted. That list is called `delete_datasources`. Grafana will delete datasources listed in `delete_datasources` before inserting/updating those in the `datasource` list.
|
||||
|
||||
### Running multiple grafana instances.
|
||||
If you are running multiple instances of Grafana you might run into problems if they have different versions of the datasource.yaml configuration file. The best way to solve this problem is to add a version number to each datasource in the configuration and increase it when you update the config. Grafana will only update datasources with the same or lower version number than specified in the config. That way old configs cannot overwrite newer configs if they restart at the same time.
|
||||
### Running multiple Grafana instances.
|
||||
If you are running multiple instances of Grafana you might run into problems if they have different versions of the `datasource.yaml` configuration file. The best way to solve this problem is to add a version number to each datasource in the configuration and increase it when you update the config. Grafana will only update datasources with the same or lower version number than specified in the config. That way, old configs cannot overwrite newer configs if they restart at the same time.
|
||||
|
||||
### Example datasource config file
|
||||
```yaml
|
||||
# list of datasources that should be deleted from the database
|
||||
delete_datasources:
|
||||
- name: Graphite
|
||||
org_id: 1
|
||||
# config file version
|
||||
apiVersion: 1
|
||||
|
||||
# list of datasources to insert/update depending
|
||||
# whats available in the datbase
|
||||
# list of datasources that should be deleted from the database
|
||||
deleteDatasources:
|
||||
- name: Graphite
|
||||
orgId: 1
|
||||
|
||||
# list of datasources to insert/update depending
|
||||
# whats available in the database
|
||||
datasources:
|
||||
# <string, required> name of the datasource. Required
|
||||
- name: Graphite
|
||||
@ -95,8 +98,8 @@ datasources:
|
||||
type: graphite
|
||||
# <string, required> access mode. direct or proxy. Required
|
||||
access: proxy
|
||||
# <int> org id. will default to org_id 1 if not specified
|
||||
org_id: 1
|
||||
# <int> org id. will default to orgId 1 if not specified
|
||||
orgId: 1
|
||||
# <string> url
|
||||
url: http://localhost:8080
|
||||
# <string> database password, if used
|
||||
@ -106,22 +109,22 @@ datasources:
|
||||
# <string> database name, if used
|
||||
database:
|
||||
# <bool> enable/disable basic auth
|
||||
basic_auth:
|
||||
basicAuth:
|
||||
# <string> basic auth username
|
||||
basic_auth_user:
|
||||
basicAuthUser:
|
||||
# <string> basic auth password
|
||||
basic_auth_password:
|
||||
basicAuthPassword:
|
||||
# <bool> enable/disable with credentials headers
|
||||
with_credentials:
|
||||
withCredentials:
|
||||
# <bool> mark as default datasource. Max one per org
|
||||
is_default:
|
||||
isDefault:
|
||||
# <map> fields that will be converted to json and stored in json_data
|
||||
json_data:
|
||||
jsonData:
|
||||
graphiteVersion: "1.1"
|
||||
tlsAuth: true
|
||||
tlsAuthWithCACert: true
|
||||
# <string> json object of data that will be encrypted.
|
||||
secure_json_data:
|
||||
secureJsonData:
|
||||
tlsCACert: "..."
|
||||
tlsClientCert: "..."
|
||||
tlsClientKey: "..."
|
||||
@ -132,53 +135,72 @@ datasources:
|
||||
|
||||
#### Json data
|
||||
|
||||
Since all datasources dont have the same configuration settings we only have the most common ones as fields. The rest should be stored as a json blob in the `json_data` field. Here are the most common settings that the core datasources use.
|
||||
Since not all datasources have the same configuration settings we only have the most common ones as fields. The rest should be stored as a json blob in the `json_data` field. Here are the most common settings that the core datasources use.
|
||||
|
||||
| Name | Type | Datasource |Description |
|
||||
| ----| ---- | ---- | --- |
|
||||
| tlsAuth | boolean | *All* | Enable TLS authentication using client cert configured in secure json data |
|
||||
| tlsAuthWithCACert | boolean | *All* | Enable TLS authtication using CA cert |
|
||||
| tlsSkipVerify | boolean | *All* | Controls whether a client verifies the server's certificate chain and host name. |
|
||||
| graphiteVersion | string | Graphite | Graphite version |
|
||||
| timeInterval | string | Elastic, Influxdb & Prometheus | Lowest interval/step value that should be used for this data source |
|
||||
| esVersion | string | Elastic | Elasticsearch version |
|
||||
| timeField | string | Elastic | Which field that should be used as timestamp |
|
||||
| esVersion | string | Elastic | Elasticsearch version |
|
||||
| timeField | string | Elastic | Which field that should be used as timestamp |
|
||||
| interval | string | Elastic | Index date time format |
|
||||
| authType | string | Cloudwatch | Auth provider. keys/credentials/arn |
|
||||
| assumeRoleArn | string | Cloudwatch | ARN of Assume Role |
|
||||
| assumeRoleArn | string | Cloudwatch | ARN of Assume Role |
|
||||
| defaultRegion | string | Cloudwatch | AWS region |
|
||||
| customMetricsNamespaces | string | Cloudwatch | Namespaces of Custom Metrics |
|
||||
| customMetricsNamespaces | string | Cloudwatch | Namespaces of Custom Metrics |
|
||||
| tsdbVersion | string | OpenTsdb | Version |
|
||||
| tsdbResolution | string | OpenTsdb | Resolution |
|
||||
| sslmode | string | Postgre | SSLmode. 'disable', 'require', 'verify-ca' or 'verify-full' |
|
||||
| sslmode | string | Postgre | SSLmode. 'disable', 'require', 'verify-ca' or 'verify-full' |
|
||||
|
||||
|
||||
#### Secure Json data
|
||||
|
||||
{"authType":"keys","defaultRegion":"us-west-2","timeField":"@timestamp"}
|
||||
`{"authType":"keys","defaultRegion":"us-west-2","timeField":"@timestamp"}`
|
||||
|
||||
Secure json data is a map of settings that will be encrypted with [secret key](/installation/configuration/#secret-key) from the grafana config. The purpose of this is only to hide content from the users of the application. This should be used for storing TLS Cert and password that Grafana will append to request on the server side. All these settings are optional.
|
||||
Secure json data is a map of settings that will be encrypted with [secret key](/installation/configuration/#secret-key) from the Grafana config. The purpose of this is only to hide content from the users of the application. This should be used for storing TLS Cert and password that Grafana will append to the request on the server side. All of these settings are optional.
|
||||
|
||||
| Name | Type | Datasource | Description |
|
||||
| ----| ---- | ---- | --- |
|
||||
| tlsCACert | string | *All* |CA cert for out going requests |
|
||||
| tlsClientCert | string | *All* |TLS Client cert for outgoing requests |
|
||||
| tlsClientKey | string | *All* |TLS Client key for outgoing requests |
|
||||
| password | string | Postgre | password |
|
||||
| user | string | Postgre | user |
|
||||
| password | string | Postgre | password |
|
||||
| user | string | Postgre | user |
|
||||
| accessKey | string | Cloudwatch | Access key for connecting to Cloudwatch |
|
||||
| secretKey | string | Cloudwatch | Secret key for connecting to Cloudwatch |
|
||||
|
||||
### Dashboards
|
||||
|
||||
It's possible to manage dashboards in Grafana by adding one or more yaml config files in the [`provisioning/dashboards`](/installation/configuration/#provisioning) directory. Each config file can contain a list of `dashboards providers` that will load dashboards into grafana. Currently we only support reading dashboards from file but we will add more providers in the future.
|
||||
It's possible to manage dashboards in Grafana by adding one or more yaml config files in the [`provisioning/dashboards`](/installation/configuration/#provisioning) directory. Each config file can contain a list of `dashboards providers` that will load dashboards into Grafana from the local filesystem.
|
||||
|
||||
The dashboard provider config file looks like this
|
||||
The dashboard provider config file looks somewhat like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: 'default'
|
||||
org_id: 1
|
||||
orgId: 1
|
||||
folder: ''
|
||||
type: file
|
||||
disableDeletion: false
|
||||
editable: false
|
||||
options:
|
||||
folder: /var/lib/grafana/dashboards
|
||||
path: /var/lib/grafana/dashboards
|
||||
```
|
||||
|
||||
When grafana starts it will update/insert all dashboards available in the configured folders. If you modify the file the dashboard will also be updated.
|
||||
When Grafana starts, it will update/insert all dashboards available in the configured path. Then later on poll that path and look for updated json files and insert those update/insert those into the database.
|
||||
|
||||
### Reuseable dashboard urls
|
||||
|
||||
If the dashboard in the json file contains an [uid](/reference/dashboard/#json-fields), Grafana will force insert/update on that uid. This allows you to migrate dashboards betweens Grafana instances and provisioning Grafana from configuration without breaking the urls given since the new dashboard url uses the uid as identifer.
|
||||
When Grafana starts, it will update/insert all dashboards available in the configured folders. If you modify the file, the dashboard will also be updated.
|
||||
By default Grafana will delete dashboards in the database if the file is removed. You can disable this behavior using the `disableDeletion` setting.
|
||||
|
||||
> **Note.** Provisioning allows you to overwrite existing dashboards
|
||||
> which leads to problems if you re-use settings that are supposed to be unique.
|
||||
> Be careful not to re-use the same `title` multiple times within a folder
|
||||
> or `uid` within the same installation as this will cause weird behaviours.
|
||||
|
@ -13,7 +13,7 @@ weight = 2
|
||||
|
||||
> Alerting is only available in Grafana v4.0 and above.
|
||||
|
||||
The alert engine publishes some internal metrics about itself. You can read more about how Grafana published [internal metrics](/installation/configuration/#metrics).
|
||||
The alert engine publishes some internal metrics about itself. You can read more about how Grafana publishes [internal metrics](/installation/configuration/#metrics).
|
||||
|
||||
Description | Type | Metric name
|
||||
---------- | ----------- | ----------
|
||||
|
@ -14,23 +14,23 @@ weight = 2
|
||||
|
||||
> Alerting is only available in Grafana v4.0 and above.
|
||||
|
||||
When an alert changes state it sends out notifications. Each alert rule can have
|
||||
multiple notifications. But in order to add a notification to an alert rule you first need
|
||||
to add and configure a `notification` channel (can be email, Pagerduty or other integration). This is done from the Notification Channels page.
|
||||
When an alert changes state, it sends out notifications. Each alert rule can have
|
||||
multiple notifications. In order to add a notification to an alert rule you first need
|
||||
to add and configure a `notification` channel (can be email, PagerDuty or other integration). This is done from the Notification Channels page.
|
||||
|
||||
## Notification Channel Setup
|
||||
|
||||
{{< imgbox max-width="40%" img="/img/docs/v43/alert_notifications_menu.png" caption="Alerting Notification Channels" >}}
|
||||
{{< imgbox max-width="30%" img="/img/docs/v50/alerts_notifications_menu.png" caption="Alerting Notification Channels" >}}
|
||||
|
||||
On the Notification Channels page hit the `New Channel` button to go the page where you
|
||||
can configure and setup a new Notification Channel.
|
||||
|
||||
You specify name and type, and type specific options. You can also test the notification to make
|
||||
sure it's working and setup correctly.
|
||||
You specify a name and a type, and type specific options. You can also test the notification to make
|
||||
sure it's setup correctly.
|
||||
|
||||
### Send on all alerts
|
||||
|
||||
When checked this option will make this notification used for all alert rules, existing and new.
|
||||
When checked, this option will nofity for all alert rules - existing and new.
|
||||
|
||||
## Supported Notification Types
|
||||
|
||||
@ -38,39 +38,39 @@ Grafana ships with the following set of notification types:
|
||||
|
||||
### Email
|
||||
|
||||
To enable email notification you have to setup [SMTP settings](/installation/configuration/#smtp)
|
||||
in the Grafana config. Email notification will upload an image of the alert graph to an
|
||||
external image destination if available or fallback to attaching the image in the email.
|
||||
To enable email notifications you have to setup [SMTP settings](/installation/configuration/#smtp)
|
||||
in the Grafana config. Email notifications will upload an image of the alert graph to an
|
||||
external image destination if available or fallback to attaching the image to the email.
|
||||
|
||||
### Slack
|
||||
|
||||
{{< imgbox max-width="40%" img="/img/docs/v4/slack_notification.png" caption="Alerting Slack Notification" >}}
|
||||
|
||||
To set up slack you need to configure an incoming webhook url at slack. You can follow their guide for how
|
||||
to do that https://api.slack.com/incoming-webhooks If you want to include screenshots of the firing alerts
|
||||
in the slack messages you have to configure either the [external image destination](#external-image-store) in Grafana,
|
||||
To set up slack you need to configure an incoming webhook url at slack. You can follow their guide on how
|
||||
to do that [here](https://api.slack.com/incoming-webhooks). If you want to include screenshots of the firing alerts
|
||||
in the Slack messages you have to configure either the [external image destination](#external-image-store) in Grafana,
|
||||
or a bot integration via Slack Apps. Follow Slack's guide to set up a bot integration and use the token provided
|
||||
https://api.slack.com/bot-users, which starts with "xoxb".
|
||||
(https://api.slack.com/bot-users), which starts with "xoxb".
|
||||
|
||||
Setting | Description
|
||||
---------- | -----------
|
||||
Recipient | allows you to override the slack recipient.
|
||||
Mention | make it possible to include a mention in the slack notification sent by Grafana. Ex @here or @channel
|
||||
Recipient | allows you to override the Slack recipient.
|
||||
Mention | make it possible to include a mention in the Slack notification sent by Grafana. Ex @here or @channel
|
||||
Token | If provided, Grafana will upload the generated image via Slack's file.upload API method, not the external image destination.
|
||||
|
||||
### PagerDuty
|
||||
|
||||
To set up PagerDuty, all you have to do is to provide an api key.
|
||||
To set up PagerDuty, all you have to do is to provide an API key.
|
||||
|
||||
Setting | Description
|
||||
---------- | -----------
|
||||
Integration Key | Integration key for pagerduty.
|
||||
Auto resolve incidents | Resolve incidents in pagerduty once the alert goes back to ok
|
||||
Integration Key | Integration key for PagerDuty.
|
||||
Auto resolve incidents | Resolve incidents in PagerDuty once the alert goes back to ok
|
||||
|
||||
### Webhook
|
||||
|
||||
The webhook notification is a simple way to send information about an state change over HTTP to a custom endpoint.
|
||||
Using this notification you could integrate Grafana into any system you choose, by yourself.
|
||||
The webhook notification is a simple way to send information about a state change over HTTP to a custom endpoint.
|
||||
Using this notification you could integrate Grafana into a system of your choosing.
|
||||
|
||||
Example json body:
|
||||
|
||||
@ -117,45 +117,48 @@ Dingtalk supports the following "message type": `text`, `link` and `markdown`. O
|
||||
|
||||
### Kafka
|
||||
|
||||
Notifications can be sent to a Kafka topic from Grafana using [Kafka REST Proxy](https://docs.confluent.io/1.0/kafka-rest/docs/index.html).
|
||||
There are couple of configurations options which need to be set in Grafana UI under Kafka Settings:
|
||||
Notifications can be sent to a Kafka topic from Grafana using the [Kafka REST Proxy](https://docs.confluent.io/1.0/kafka-rest/docs/index.html).
|
||||
There are a couple of configuration options which need to be set up in Grafana UI under Kafka Settings:
|
||||
|
||||
1. Kafka REST Proxy endpoint.
|
||||
|
||||
2. Kafka Topic.
|
||||
|
||||
Once these two properties are set, you can send the alerts to Kafka for further processing or throttling them.
|
||||
Once these two properties are set, you can send the alerts to Kafka for further processing or throttling.
|
||||
|
||||
### Other Supported Notification Channels
|
||||
### All supported notifier
|
||||
|
||||
Grafana also supports the following Notification Channels:
|
||||
Name | Type |Support images
|
||||
-----|------------ | ------
|
||||
Slack | `slack` | yes
|
||||
Pagerduty | `pagerduty` | yes
|
||||
Email | `email` | yes
|
||||
Webhook | `webhook` | link
|
||||
Kafka | `kafka` | no
|
||||
Hipchat | `hipchat` | yes
|
||||
VictorOps | `victorops` | yes
|
||||
Sensu | `sensu` | yes
|
||||
OpsGenie | `opsgenie` | yes
|
||||
Threema | `threema` | yes
|
||||
Pushover | `pushover` | no
|
||||
Telegram | `telegram` | no
|
||||
Line | `line` | no
|
||||
Prometheus Alertmanager | `prometheus-alertmanager` | no
|
||||
|
||||
- HipChat
|
||||
|
||||
- VictorOps
|
||||
|
||||
- Sensu
|
||||
|
||||
- OpsGenie
|
||||
|
||||
- Threema
|
||||
|
||||
- Pushover
|
||||
|
||||
- Telegram
|
||||
|
||||
- LINE
|
||||
|
||||
# Enable images in notifications {#external-image-store}
|
||||
|
||||
Grafana can render the panel associated with the alert rule and include that in the notification. Most Notification Channels require that this image be publicly accessible (Slack and PagerDuty for example). In order to include images in alert notifications, Grafana can upload the image to an image store. It currently supports
|
||||
Amazon S3 and Webdav for this. So to set that up you need to configure the [external image uploader](/installation/configuration/#external-image-storage) in your grafana-server ini config file.
|
||||
Grafana can render the panel associated with the alert rule and include that in the notification. Most Notification Channels require that this image be publicly accessable (Slack and PagerDuty for example). In order to include images in alert notifications, Grafana can upload the image to an image store. It currently supports
|
||||
Amazon S3, Webdav, Google Cloud Storage and Azure Blob Storage. So to set that up you need to configure the [external image uploader](/installation/configuration/#external-image-storage) in your grafana-server ini config file.
|
||||
|
||||
Be aware that some notifiers requires public access to the image to be able to include it in the notification. So make sure to enable public access to the images. If your using local image uploader, your Grafana instance need to be accessible by the internet.
|
||||
|
||||
Currently only the Email Channels attaches images if no external image store is specified. To include images in alert notifications for other channels then you need to set up an external image store.
|
||||
|
||||
This is an optional requirement, you can get Slack and email notifications without setting this up.
|
||||
This is an optional requirement. You can get Slack and email notifications without setting this up.
|
||||
|
||||
# Configure the link back to Grafana from alert notifications
|
||||
|
||||
All alert notifications contains a link back to the triggered alert in the Grafana instance.
|
||||
All alert notifications contain a link back to the triggered alert in the Grafana instance.
|
||||
This url is based on the [domain](/installation/configuration/#domain) setting in Grafana.
|
||||
|
@ -13,7 +13,7 @@ weight = 10
|
||||
|
||||
# Using AWS CloudWatch in Grafana
|
||||
|
||||
Grafana ships with built in support for CloudWatch. You just have to add it as a data source and you will be ready to build dashboards for you CloudWatch metrics.
|
||||
Grafana ships with built in support for CloudWatch. You just have to add it as a data source and you will be ready to build dashboards for your CloudWatch metrics.
|
||||
|
||||
## Adding the data source to Grafana
|
||||
|
||||
@ -78,11 +78,14 @@ CloudWatch Datasource Plugin provides the following queries you can specify in t
|
||||
edit view. They allow you to fill a variable's options list with things like `region`, `namespaces`, `metric names`
|
||||
and `dimension keys/values`.
|
||||
|
||||
In place of `region` you can specify `default` to use the default region configured in the datasource for the query,
|
||||
e.g. `metrics(AWS/DynamoDB, default)` or `dimension_values(default, ..., ..., ...)`.
|
||||
|
||||
Name | Description
|
||||
------- | --------
|
||||
*regions()* | Returns a list of regions AWS provides their service.
|
||||
*namespaces()* | Returns a list of namespaces CloudWatch support.
|
||||
*metrics(namespace, [region])* | Returns a list of metrics in the namespace. (specify region for custom metrics)
|
||||
*metrics(namespace, [region])* | Returns a list of metrics in the namespace. (specify region or use "default" for custom metrics)
|
||||
*dimension_keys(namespace)* | Returns a list of dimension keys in the namespace.
|
||||
*dimension_values(region, namespace, metric, dimension_key)* | Returns a list of dimension values matching the specified `region`, `namespace`, `metric` and `dimension_key`.
|
||||
*ebs_volume_ids(region, instance_id)* | Returns a list of volume ids matching the specified `region`, `instance_id`.
|
||||
|
@ -45,7 +45,14 @@ To simplify syntax and to allow for dynamic parts, like date range filters, the
|
||||
|
||||
Macro example | Description
|
||||
------------ | -------------
|
||||
*$__time(dateColumn)* | Will be replaced by an expression to convert to a UNIX timestamp and rename the column to `time_sec`. For example, *UNIX_TIMESTAMP(dateColumn) as time_sec*
|
||||
*$__timeFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name. For example, *dateColumn > FROM_UNIXTIME(1494410783) AND dateColumn < FROM_UNIXTIME(1494497183)*
|
||||
*$__timeFrom()* | Will be replaced by the start of the currently active time selection. For example, *FROM_UNIXTIME(1494410783)*
|
||||
*$__timeTo()* | Will be replaced by the end of the currently active time selection. For example, *FROM_UNIXTIME(1494497183)*
|
||||
*$__timeGroup(dateColumn,'5m')* | Will be replaced by an expression usable in GROUP BY clause. For example, *cast(cast(UNIX_TIMESTAMP(dateColumn)/(300) as signed)*300 as signed) as time_sec,*
|
||||
*$__unixEpochFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name with times represented as unix timestamp. For example, *dateColumn > 1494410783 AND dateColumn < 1494497183*
|
||||
*$__unixEpochFrom()* | Will be replaced by the start of the currently active time selection as unix timestamp. For example, *1494410783*
|
||||
*$__unixEpochTo()* | Will be replaced by the end of the currently active time selection as unix timestamp. For example, *1494497183*
|
||||
|
||||
We plan to add many more macros. If you have suggestions for what macros you would like to see, please [open an issue](https://github.com/grafana/grafana) in our GitHub repo.
|
||||
|
||||
@ -99,6 +106,19 @@ GROUP BY metric1, UNIX_TIMESTAMP(time_date_time) DIV 300
|
||||
ORDER BY time_sec asc
|
||||
```
|
||||
|
||||
Example with $__timeGroup macro:
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
$__timeGroup(time_date_time,'5m') as time_sec,
|
||||
min(value_double) as value,
|
||||
metric_name as metric
|
||||
FROM test_data
|
||||
WHERE $__timeFilter(time_date_time)
|
||||
GROUP BY 1, metric_name
|
||||
ORDER BY 1
|
||||
```
|
||||
|
||||
Currently, there is no support for a dynamic group by time based on time range & panel width.
|
||||
This is something we plan to add.
|
||||
|
||||
|
@ -5,7 +5,7 @@ type = "docs"
|
||||
[menu.docs]
|
||||
name = "Features"
|
||||
identifier = "features"
|
||||
weight = 3
|
||||
weight = 4
|
||||
+++
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ The coloring options of the Singlestat Panel config allow you to dynamically cha
|
||||
2. **Thresholds**: Change the background and value colors dynamically within the panel, depending on the Singlestat value. The threshold field accepts **2 comma-separated** values which represent 3 ranges that correspond to the three colors directly to the right. For example: if the thresholds are 70, 90 then the first color represents < 70, the second color represents between 70 and 90 and the third color represents > 90.
|
||||
3. **Colors**: Select a color and opacity
|
||||
4. **Value**: This checkbox applies the configured thresholds and colors to the summary stat.
|
||||
5. **Invert order**: This link toggles the threshold color order.</br>For example: Green, Orange, Red (<img class="no-shadow" src="/img/docs(v1/gyr.png">) will become Red, Orange, Green (<img class="no-shadow" src="/img/docs/v1/ryg.png">).
|
||||
5. **Invert order**: This link toggles the threshold color order.</br>For example: Green, Orange, Red (<img class="no-shadow" src="/img/docs/v1/gyr.png">) will become Red, Orange, Green (<img class="no-shadow" src="/img/docs/v1/ryg.png">).
|
||||
|
||||
### Spark Lines
|
||||
|
||||
|
@ -8,7 +8,7 @@ weight = 7
|
||||
|
||||
# Keyboard shortcuts
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v4/shortcuts.png" max-width="20rem" class="docs-image--right" >}}
|
||||
{{< docs-imagebox img="/img/docs/v50/shortcuts.png" max-width="20rem" class="docs-image--right" >}}
|
||||
|
||||
Grafana v4 introduces a number of really powerful keyboard shortcuts. You can now focus a panel
|
||||
by hovering over it with your mouse. With a panel focused you can simple hit `e` to toggle panel
|
||||
@ -34,6 +34,8 @@ Hit `?` on your keyboard to open the shortcuts help modal.
|
||||
- `d` `s` Dashboard settings
|
||||
- `d` `v` Toggle in-active / view mode
|
||||
- `d` `k` Toggle kiosk mode (hides top nav)
|
||||
- `d` `E` Expand all rows
|
||||
- `d` `C` Collapse all rows
|
||||
- `mod+o` Toggle shared graph crosshair
|
||||
|
||||
### Focused Panel
|
||||
@ -42,12 +44,9 @@ Hit `?` on your keyboard to open the shortcuts help modal.
|
||||
- `p` `s` Open Panel Share Modal
|
||||
- `p` `r` Remove Panel
|
||||
|
||||
### Focused Row
|
||||
- `r` `c` Collapse Row
|
||||
- `r` `r` Remove Row
|
||||
|
||||
### Time Range
|
||||
- `t` `z` Zoom out time range
|
||||
- `t` Move time range back
|
||||
- `t` Move time range forward
|
||||
|
||||
mod = CTRL on windows or linux and CMD key on Mac
|
||||
|
@ -7,6 +7,7 @@ type = "docs"
|
||||
name = "Basic Concepts"
|
||||
identifier = "basic_concepts"
|
||||
parent = "guides"
|
||||
weight = 2
|
||||
+++
|
||||
|
||||
# Basic Concepts
|
||||
|
@ -8,6 +8,7 @@ aliases = ["/guides/gettingstarted"]
|
||||
name = "Getting Started"
|
||||
identifier = "getting_started_guide"
|
||||
parent = "guides"
|
||||
weight = 1
|
||||
+++
|
||||
|
||||
# Getting started
|
||||
@ -24,38 +25,38 @@ Read the [Basic Concepts](/guides/basic_concepts) document to get a crash course
|
||||
|
||||
### Top header
|
||||
|
||||
Let's start with creating a new Dashboard. You can find the new Dashboard link on the right side of the Dashboard picker. You now have a blank Dashboard.
|
||||
Let's start with creating a new Dashboard. You can find the new Dashboard link on the right side of the Dashboard picker. You now have a blank Dashboard.
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v45/top_nav_annotated.png">
|
||||
<img class="no-shadow" src="/img/docs/v50/top_nav_annotated.png" width="580px">
|
||||
|
||||
The image above shows you the top header for a Dashboard.
|
||||
|
||||
1. Side menubar toggle: This toggles the side menu, allowing you to focus on the data presented in the dashboard. The side menu provides access to features unrelated to a Dashboard such as Users, Organizations, and Data Sources.
|
||||
2. Dashboard dropdown: This dropdown shows you which Dashboard you are currently viewing, and allows you to easily switch to a new Dashboard. From here you can also create a new Dashboard, Import existing Dashboards, and manage Dashboard playlists.
|
||||
3. Star Dashboard: Star (or unstar) the current Dashboard. Starred Dashboards will show up on your own Home Dashboard by default, and are a convenient way to mark Dashboards that you're interested in.
|
||||
4. Share Dashboard: Share the current dashboard by creating a link or create a static Snapshot of it. Make sure the Dashboard is saved before sharing.
|
||||
5. Save dashboard: The current Dashboard will be saved with the current Dashboard name.
|
||||
6. Settings: Manage Dashboard settings and features such as Templating and Annotations.
|
||||
2. Dashboard dropdown: This dropdown shows you which Dashboard you are currently viewing, and allows you to easily switch to a new Dashboard. From here you can also create a new Dashboard or folder, Import existing Dashboards, and manage Dashboard playlists.
|
||||
3. Add Panel: Adds a new panel to the current Dashboard
|
||||
4. Star Dashboard: Star (or unstar) the current Dashboard. Starred Dashboards will show up on your own Home Dashboard by default, and are a convenient way to mark Dashboards that you're interested in.
|
||||
5. Share Dashboard: Share the current dashboard by creating a link or create a static Snapshot of it. Make sure the Dashboard is saved before sharing.
|
||||
6. Save dashboard: The current Dashboard will be saved with the current Dashboard name.
|
||||
7. Settings: Manage Dashboard settings and features such as Templating and Annotations.
|
||||
|
||||
## Dashboards, Panels, Rows, the building blocks of Grafana...
|
||||
## Dashboards, Panels, the building blocks of Grafana...
|
||||
|
||||
Dashboards are at the core of what Grafana is all about. Dashboards are composed of individual Panels arranged on a number of Rows. Grafana ships with a variety of Panels. Grafana makes it easy to construct the right queries, and customize the display properties so that you can create the perfect Dashboard for your need. Each Panel can interact with data from any configured Grafana Data Source (currently InfluxDB, Graphite, OpenTSDB, Prometheus and Cloudwatch). The [Basic Concepts](/guides/basic_concepts) guide explores these key ideas in detail.
|
||||
Dashboards are at the core of what Grafana is all about. Dashboards are composed of individual Panels arranged on a grid. Grafana ships with a variety of Panels. Grafana makes it easy to construct the right queries, and customize the display properties so that you can create the perfect Dashboard for your need. Each Panel can interact with data from any configured Grafana Data Source (currently InfluxDB, Graphite, OpenTSDB, Prometheus and Cloudwatch). The [Basic Concepts](/guides/basic_concepts) guide explores these key ideas in detail.
|
||||
|
||||
<img src="/img/docs/v45/dashboard_annotated.png" class="no-shadow">
|
||||
<img src="/img/docs/v50/dashboard_annotated.png" class="no-shadow" width="700px">
|
||||
|
||||
1. Zoom out time range
|
||||
2. Time picker dropdown. Here you can access relative time range options, auto refresh options and set custom absolute time ranges.
|
||||
3. Manual refresh button. Will cause all panels to refresh (fetch new data).
|
||||
4. Row controls menu. Via this menu you can add panels to the row, set row height and more.
|
||||
5. Dashboard panel. You edit panels by clicking the panel title.
|
||||
6. Graph legend. You can change series colors, y-axis and series visibility directly from the legend.
|
||||
4. Dashboard panel. You edit panels by clicking the panel title.
|
||||
5. Graph legend. You can change series colors, y-axis and series visibility directly from the legend.
|
||||
|
||||
|
||||
## Adding & Editing Graphs and Panels
|
||||
|
||||

|
||||
|
||||
1. You add panels via row menu. The row menu is the icon to the left of each row.
|
||||
1. You add panels by clicking the Add panel icon on the top menu.
|
||||
2. To edit the graph you click on the graph title to open the panel menu, then `Edit`.
|
||||
3. This should take you to the `Metrics` tab. In this tab you should see the editor for your default data source.
|
||||
|
||||
@ -63,7 +64,7 @@ When you click the `Metrics` tab, you are presented with a Query Editor that is
|
||||
|
||||
## Drag-and-Drop panels
|
||||
|
||||
You can Drag-and-Drop Panels within and between Rows. Click and hold the Panel title, and drag it to its new location. You can also easily resize panels by clicking the (-) and (+) icons.
|
||||
You can Drag-and-Drop Panels by simply clicking and holding the Panel title, and drag it to its new location. You can also easily resize panels by clicking the (-) and (+) icons.
|
||||
|
||||

|
||||
|
||||
|
@ -4,6 +4,6 @@ type = "docs"
|
||||
[menu.docs]
|
||||
name = "Getting Started"
|
||||
identifier = "guides"
|
||||
weight = 2
|
||||
weight = 3
|
||||
+++
|
||||
|
||||
|
@ -3,11 +3,6 @@ title = "What's New in Grafana v2.1"
|
||||
description = "Feature & improvement highlights for Grafana v2.1"
|
||||
keywords = ["grafana", "new", "documentation", "2.1"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Version 2.1"
|
||||
identifier = "v2.1"
|
||||
parent = "whatsnew"
|
||||
weight = 10
|
||||
+++
|
||||
|
||||
# What's new in Grafana v2.1
|
||||
|
@ -3,11 +3,6 @@ title = "What's New in Grafana v2.5"
|
||||
description = "Feature & improvement highlights for Grafana v2.5"
|
||||
keywords = ["grafana", "new", "documentation", "2.5"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Version 2.5"
|
||||
identifier = "v2.5"
|
||||
parent = "whatsnew"
|
||||
weight = 9
|
||||
+++
|
||||
|
||||
# What's new in Grafana v2.5
|
||||
|
@ -3,11 +3,6 @@ title = "What's New in Grafana v2.6"
|
||||
description = "Feature & improvement highlights for Grafana v2.6"
|
||||
keywords = ["grafana", "new", "documentation", "2.6"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Version 2.6"
|
||||
identifier = "v2.6"
|
||||
parent = "whatsnew"
|
||||
weight = 7
|
||||
+++
|
||||
|
||||
# What's new in Grafana v2.6
|
||||
|
@ -3,11 +3,6 @@ title = "What's New in Grafana v2.0"
|
||||
description = "Feature & improvement highlights for Grafana v2.0"
|
||||
keywords = ["grafana", "new", "documentation", "2.0"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Version 2.0"
|
||||
identifier = "v2.0"
|
||||
parent = "whatsnew"
|
||||
weight = 11
|
||||
+++
|
||||
|
||||
# What's New in Grafana v2.0
|
||||
|
@ -55,7 +55,7 @@ of another alert in your conditions, and `Time Of Day`.
|
||||
Alerting would not be very useful if there was no way to send notifications when rules trigger and change state. You
|
||||
can setup notifications of different types. We currently have `Slack`, `PagerDuty`, `Email` and `Webhook` with more in the
|
||||
pipe that will be added during beta period. The notifications can then be added to your alert rules.
|
||||
If you have configured an external image store in the grafana.ini config file (s3 and webdav options available)
|
||||
If you have configured an external image store in the grafana.ini config file (s3, webdav, and azure_blob options available)
|
||||
you can get very rich notifications with an image of the graph and the metric
|
||||
values all included in the notification.
|
||||
|
||||
|
154
docs/sources/guides/whats-new-in-v5.md
Normal file
154
docs/sources/guides/whats-new-in-v5.md
Normal file
@ -0,0 +1,154 @@
|
||||
+++
|
||||
title = "What's New in Grafana v5.0"
|
||||
description = "Feature & improvement highlights for Grafana v5.0"
|
||||
keywords = ["grafana", "new", "documentation", "5.0"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Version 5.0"
|
||||
identifier = "v5.0"
|
||||
parent = "whatsnew"
|
||||
weight = -6
|
||||
+++
|
||||
|
||||
# What's New in Grafana v5.0
|
||||
|
||||
> Out in beta: [Download now!](https://grafana.com/grafana/download/beta)
|
||||
|
||||
This is the most substantial update that Grafana has ever seen. This article will detail the major new features and enhancements.
|
||||
|
||||
- [New Dashboard Layout Engine]({{< relref "#new-dashboard-layout-engine" >}}) enables a much easier drag, drop and resize experience and new types of layouts.
|
||||
- [New UX]({{< relref "#new-ux-layout-engine" >}}). The UI has big improvements in both look and function.
|
||||
- [New Light Theme]({{< relref "#new-light-theme" >}}) is now looking really nice.
|
||||
- [Dashboard Folders]({{< relref "#dashboard-folders" >}}) helps you keep your dashboards organized.
|
||||
- [Permissions]({{< relref "#dashboard-folders" >}}) on folders and dashboards helps manage larger Grafana installations.
|
||||
- [Group users into teams]({{< relref "#teams" >}}) and use them in the new permission system.
|
||||
- [Datasource provisioning]({{< relref "#data-sources" >}}) makes it possible to setup datasources via config files.
|
||||
- [Dashboard provisioning]({{< relref "#dashboards" >}}) makes it possible to setup dashboards via config files.
|
||||
- [Persistent dashboard url's]({{< relref "#dashboard-model-persistent-url-s-and-api-changes" >}}) makes it possible to rename dashboards without breaking links.
|
||||
- [Graphite Tags & Integrated Function Docs]({{< relref "#graphite-tags-integrated-function-docs" >}}).
|
||||
|
||||
### Video showing new features
|
||||
|
||||
<iframe width="450" height="270" src="https://www.youtube.com/embed/Izr0IBgoTZQ?rel=0&" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
|
||||
<br />
|
||||
|
||||
## New Dashboard Layout Engine
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v50/new_grid.png" max-width="1000px" class="docs-image--right">}}
|
||||
|
||||
The new dashboard layout engine allows for much easier movement and sizing of panels, as other panels now move out of the way in
|
||||
a very intuitive way. Panels are sized independently, so rows are no longer necessary to create layouts. This opens
|
||||
up many new types of layouts where panels of different heights can be aligned easily. Checkout the new grid in the video
|
||||
above or on the [play site](http://play.grafana.org). All your existing dashboards will automatically migrate to the
|
||||
new position system and look close to identical. The new panel position makes dashboards saved in v5.0 incompatible
|
||||
with older versions of Grafana.
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
## New UX
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v50/new_ux_nav.png" max-width="1000px" class="docs-image--right" >}}
|
||||
|
||||
Almost every page has seen significant UX improvements. All pages (except dashboard pages) have a new tab-based layout that improves navigation between pages. The side menu has also changed quite a bit. You can still hide the side menu completely if you click on the Grafana logo.
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
## Dashboard Settings
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v50/dashboard_settings.png" max-width="1000px" class="docs-image--right" >}}
|
||||
Dashboard pages have a new header toolbar where buttons and actions are now all moved to the right. All the dashboard
|
||||
settings views have been combined with a side nav which allows you to easily move between different setting categories.
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
## New Light Theme
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v50/new_white_theme.png" max-width="1000px" class="docs-image--right" >}}
|
||||
|
||||
This theme has not seen a lot of love in recent years and we felt it was time to give it a major overhaul. We are very happy with the result.
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
## Dashboard Folders
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v50/new_search.png" max-width="1000px" class="docs-image--right" >}}
|
||||
|
||||
The big new feature that comes with Grafana v5.0 is dashboard folders. Now you can organize your dashboards in folders,
|
||||
which is very useful if you have a lot of dashboards or multiple teams.
|
||||
|
||||
- New search design adds expandable sections for each folder, starred and recently viewed dashboards.
|
||||
- New manage dashboard pages enable batch actions and views for folder settings and permissions.
|
||||
- Set permissions on folders and have dashboards inherit the permissions.
|
||||
|
||||
## Teams
|
||||
|
||||
A team is a new concept in Grafana v5. They are simply a group of users that can be used in the new permission system for dashboards and folders. Only an admin can create teams.
|
||||
We hope to do more with teams in future releases like integration with LDAP and a team landing page.
|
||||
|
||||
## Permissions
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v50/folder_permissions.png" max-width="1000px" class="docs-image--right" >}}
|
||||
|
||||
You can assign permissions to folders and dashboards. The default user role-based permissions can be removed and
|
||||
replaced with specific teams or users enabling more control over what a user can see and edit.
|
||||
|
||||
Dashboard permissions only limits what dashboards & folders a user can view & edit not which
|
||||
data sources a user can access nor what queries a user can issue.
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
## Provisioning from configuration
|
||||
|
||||
In previous versions of Grafana, you could only use the API for provisioning data sources and dashboards.
|
||||
But that required the service to be running before you started creating dashboards and you also needed to
|
||||
set up credentials for the HTTP API. In v5.0 we decided to improve this experience by adding a new active
|
||||
provisioning system that uses config files. This will make GitOps more natural as data sources and dashboards can
|
||||
be defined via files that can be version controlled. We hope to extend this system to later add support for users, orgs
|
||||
and alerts as well.
|
||||
|
||||
### Data sources
|
||||
|
||||
Data sources can now be setup using config files. These data sources are by default not editable from the Grafana GUI.
|
||||
It's also possible to update and delete data sources from the config file. More info in the [data source provisioning docs](/administration/provisioning/#datasources).
|
||||
|
||||
### Dashboards
|
||||
|
||||
We also deprecated the `[dashboard.json]` in favor of our new dashboard provisioner that keeps dashboards on disk
|
||||
in sync with dashboards in Grafana's database. The dashboard provisioner has multiple advantages over the old
|
||||
`[dashboard.json]` feature. Instead of storing the dashboard in memory we now insert the dashboard into the database,
|
||||
which makes it possible to star them, use one as the home dashboard, set permissions and other features in Grafana that
|
||||
expects the dashboards to exist in the database. More info in the [dashboard provisioning docs](/administration/provisioning/#dashboards)
|
||||
|
||||
|
||||
## Graphite Tags & Integrated Function Docs
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v50/graphite_tags.png" max-width="1000px" class="docs-image--right" >}}
|
||||
|
||||
The Graphite query editor has been updated to support the latest Graphite version (v1.2) that adds
|
||||
many new functions and support for querying by tags. You can now also view function documentation right in the query editor!
|
||||
|
||||
Read more on [Graphite Tag Support](http://graphite.readthedocs.io/en/latest/tags.html?highlight=tags).
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
## Dashboard model, persistent url's and API changes
|
||||
|
||||
We are introducing a new unique identifier (`uid`) in the dashboard JSON model. It's automatically
|
||||
generated if not provided when creating a dashboard and will have a length of 9-12 characters.
|
||||
|
||||
The unique identifier allows having persistent URL's for accessing dashboards, sharing them
|
||||
between instances and when using [dashboard provisioning](#dashboards). This means that dashboard can
|
||||
be renamed without breaking any links. We're changing the url format for dashboards
|
||||
from `/dashboard/db/:slug` to `/d/:uid/:slug`. We'll keep supporting the old slug-based url's for dashboards
|
||||
and redirects to the new one for backward compatibility. Please note that the old slug-based url's
|
||||
have been deprecated and will be removed in a future release.
|
||||
|
||||
Sharing dashboards between instances becomes much easier since the `uid` is unique (unique enough).
|
||||
This might seem like a small change, but we are incredibly excited about it since it will make it
|
||||
much easier to manage, collaborate and navigate between dashboards.
|
||||
|
||||
### API changes
|
||||
New uid-based routes in the dashboard API have been introduced to retrieve and delete dashboards.
|
||||
The corresponding slug-based routes have been deprecated and will be removed in a future release.
|
||||
|
||||
|
@ -61,7 +61,7 @@ Content-Type: application/json
|
||||
"client_id":"some_id",
|
||||
"client_secret":"************",
|
||||
"enabled":"false",
|
||||
"scopes":"user:email",
|
||||
"scopes":"user:email,read:org",
|
||||
"team_ids":"",
|
||||
"token_url":"https://github.com/login/oauth/access_token"
|
||||
},
|
||||
|
@ -62,7 +62,7 @@ Content-Type: application/json
|
||||
}
|
||||
"newStateDate": "2016-12-25",
|
||||
"executionError": "",
|
||||
"dashboardUri": "http://grafana.com/dashboard/db/sensors"
|
||||
"url": "http://grafana.com/dashboard/db/sensors"
|
||||
}
|
||||
]
|
||||
```
|
||||
@ -94,7 +94,7 @@ Content-Type: application/json
|
||||
"state": "alerting",
|
||||
"newStateDate": "2016-12-25",
|
||||
"executionError": "",
|
||||
"dashboardUri": "http://grafana.com/dashboard/db/sensors"
|
||||
"url": "http://grafana.com/dashboard/db/sensors"
|
||||
}
|
||||
```
|
||||
|
||||
@ -196,6 +196,8 @@ Content-Type: application/json
|
||||
|
||||
## Create alert notification
|
||||
|
||||
You can find the full list of [supported notifers](/alerting/notifications/#all-supported-notifier) at the alert notifiers page.
|
||||
|
||||
`POST /api/alert-notifications`
|
||||
|
||||
**Example Request**:
|
||||
@ -292,4 +294,4 @@ Content-Type: application/json
|
||||
{
|
||||
"message": "Notification deleted"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
@ -100,7 +100,7 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
JSON Body schema:
|
||||
|
||||
- **name** – The key name
|
||||
- **role** – Sets the access level/Grafana Role for the key. Can be one of the following values: `Viewer`, `Editor`, `Read Only Editor` or `Admin`.
|
||||
- **role** – Sets the access level/Grafana Role for the key. Can be one of the following values: `Viewer`, `Editor` or `Admin`.
|
||||
|
||||
**Example Response**:
|
||||
|
||||
|
@ -11,6 +11,17 @@ parent = "http_api"
|
||||
|
||||
# Dashboard API
|
||||
|
||||
## Identifier (id) vs unique identifier (uid)
|
||||
|
||||
The identifier (id) of a dashboard is an auto-incrementing numeric value and is only unique per Grafana install.
|
||||
|
||||
The unique identifier (uid) of a dashboard can be used for uniquely identify a dashboard between multiple Grafana installs.
|
||||
It's automatically generated if not provided when creating a dashboard. The uid allows having consistent URL's for accessing
|
||||
dashboards and when syncing dashboards between multiple Grafana installs, see [dashboard provisioning](/administration/provisioning/#dashboards)
|
||||
for more information. This means that changing the title of a dashboard will not break any bookmarked links to that dashboard.
|
||||
|
||||
The uid can have a maximum length of 40 characters.
|
||||
|
||||
## Create / Update dashboard
|
||||
|
||||
`POST /api/dashboards/db`
|
||||
@ -28,6 +39,7 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
{
|
||||
"dashboard": {
|
||||
"id": null,
|
||||
"uid": null,
|
||||
"title": "Production Overview",
|
||||
"tags": [ "templated" ],
|
||||
"timezone": "browser",
|
||||
@ -38,14 +50,18 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
"schemaVersion": 6,
|
||||
"version": 0
|
||||
},
|
||||
"folderId": 0,
|
||||
"overwrite": false
|
||||
}
|
||||
```
|
||||
|
||||
JSON Body schema:
|
||||
|
||||
- **dashboard** – The complete dashboard model, id = null to create a new dashboard
|
||||
- **overwrite** – Set to true if you want to overwrite existing dashboard with newer version or with same dashboard title.
|
||||
- **dashboard** – The complete dashboard model, id = null to create a new dashboard.
|
||||
- **dashboard.id** – id = null to create a new dashboard.
|
||||
- **dashboard.uid** – Optional [unique identifier](/http_api/dashboard/#identifier-id-vs-unique-identifier-uid) when creating a dashboard. uid = null will generate a new uid.
|
||||
- **folderId** – The id of the folder to save the dashboard in.
|
||||
- **overwrite** – Set to true if you want to overwrite existing dashboard with newer version, same dashboard title in folder or same dashboard uid.
|
||||
- **message** - Set a commit message for the version history.
|
||||
|
||||
**Example Response**:
|
||||
@ -56,9 +72,12 @@ Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 78
|
||||
|
||||
{
|
||||
"slug": "production-overview",
|
||||
"status": "success",
|
||||
"version": 1
|
||||
"id": 1,
|
||||
"uid": "cIBgcSjkk",
|
||||
"url": "/d/cIBgcSjkk/production-overview",
|
||||
"status": "success",
|
||||
"version": 1,
|
||||
"slug": "production-overview" //deprecated in Grafana v5.0
|
||||
}
|
||||
```
|
||||
|
||||
@ -67,10 +86,18 @@ Status Codes:
|
||||
- **200** – Created
|
||||
- **400** – Errors (invalid json, missing or invalid fields, etc)
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
- **412** – Precondition failed
|
||||
|
||||
The **412** status code is used when a newer dashboard already exists (newer, its version is greater than the version that was sent). The
|
||||
same status code is also used if another dashboard exists with the same title. The response body will look like this:
|
||||
The **412** status code is used for explaing that you cannot create the dashboard and why.
|
||||
There can be different reasons for this:
|
||||
|
||||
- The dashboard has been changed by someone else, `status=version-mismatch`
|
||||
- A dashboard with the same name in the folder already exists, `status=name-exists`
|
||||
- A dashboard with the same uid already exists, `status=name-exists`
|
||||
- The dashboard belongs to plugin `<plugin title>`, `status=plugin-dashboard`
|
||||
|
||||
The response body will have the following properties:
|
||||
|
||||
```http
|
||||
HTTP/1.1 412 Precondition Failed
|
||||
@ -83,18 +110,18 @@ Content-Length: 97
|
||||
}
|
||||
```
|
||||
|
||||
In in case of title already exists the `status` property will be `name-exists`.
|
||||
In case of title already exists the `status` property will be `name-exists`.
|
||||
|
||||
## Get dashboard
|
||||
## Get dashboard by uid
|
||||
|
||||
`GET /api/dashboards/db/:slug`
|
||||
`GET /api/dashboards/uid/:uid`
|
||||
|
||||
Will return the dashboard given the dashboard slug. Slug is the url friendly version of the dashboard title.
|
||||
Will return the dashboard given the dashboard unique identifier (uid).
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/dashboards/db/production-overview HTTP/1.1
|
||||
GET /api/dashboards/uid/cIBgcSjkk HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
@ -107,12 +134,9 @@ HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"meta": {
|
||||
"isStarred": false,
|
||||
"slug": "production-overview"
|
||||
},
|
||||
"dashboard": {
|
||||
"id": null,
|
||||
"id": 1,
|
||||
"uid": "cIBgcSjkk",
|
||||
"title": "Production Overview",
|
||||
"tags": [ "templated" ],
|
||||
"timezone": "browser",
|
||||
@ -122,20 +146,32 @@ Content-Type: application/json
|
||||
],
|
||||
"schemaVersion": 6,
|
||||
"version": 0
|
||||
},
|
||||
"meta": {
|
||||
"isStarred": false,
|
||||
"url": "/d/cIBgcSjkk/production-overview",
|
||||
"slug": "production-overview" //deprecated in Grafana v5.0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Delete dashboard
|
||||
Status Codes:
|
||||
|
||||
`DELETE /api/dashboards/db/:slug`
|
||||
- **200** – Found
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
- **404** – Not found
|
||||
|
||||
The above will delete the dashboard with the specified slug. The slug is the url friendly (unique) version of the dashboard title.
|
||||
## Delete dashboard by uid
|
||||
|
||||
`DELETE /api/dashboards/uid/:uid`
|
||||
|
||||
Will delete the dashboard given the specified unique identifier (uid).
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
DELETE /api/dashboards/db/test HTTP/1.1
|
||||
DELETE /api/dashboards/uid/cIBgcSjkk HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
@ -147,9 +183,16 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{"title": "Test"}
|
||||
{"title": "Production Overview"}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Deleted
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
- **404** – Not found
|
||||
|
||||
## Gets the home dashboard
|
||||
|
||||
`GET /api/dashboards/home`
|
||||
@ -172,15 +215,6 @@ HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"meta": {
|
||||
"isHome":true,
|
||||
"canSave":false,
|
||||
"canEdit":false,
|
||||
"canStar":false,
|
||||
"slug":"",
|
||||
"expires":"0001-01-01T00:00:00Z",
|
||||
"created":"0001-01-01T00:00:00Z"
|
||||
},
|
||||
"dashboard": {
|
||||
"editable":false,
|
||||
"hideControls":true,
|
||||
@ -206,13 +240,21 @@ Content-Type: application/json
|
||||
"timezone":"browser",
|
||||
"title":"Home",
|
||||
"version":5
|
||||
},
|
||||
"meta": {
|
||||
"isHome":true,
|
||||
"canSave":false,
|
||||
"canEdit":false,
|
||||
"canStar":false,
|
||||
"url":"",
|
||||
"expires":"0001-01-01T00:00:00Z",
|
||||
"created":"0001-01-01T00:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Tags for Dashboard
|
||||
|
||||
|
||||
`GET /api/dashboards/tags`
|
||||
|
||||
Get all tags of dashboards
|
||||
@ -244,21 +286,24 @@ Content-Type: application/json
|
||||
]
|
||||
```
|
||||
|
||||
## Search Dashboards
|
||||
## Dashboard Search
|
||||
See [Folder/Dashboard Search API](/http_api/folder_dashboard_search).
|
||||
|
||||
`GET /api/search/`
|
||||
## Deprecated resources
|
||||
Please note that these resource have been deprecated and will be removed in a future release.
|
||||
|
||||
Query parameters:
|
||||
### Get dashboard by slug
|
||||
**Deprecated starting from Grafana v5.0. Please update to use the new *Get dashboard by uid* resource instead**
|
||||
|
||||
- **query** – Search Query
|
||||
- **tag** – Tag to use
|
||||
- **starred** – Flag indicating if only starred Dashboards should be returned
|
||||
- **tagcloud** - Flag indicating if a tagcloud should be returned
|
||||
`GET /api/dashboards/db/:slug`
|
||||
|
||||
Will return the dashboard given the dashboard slug. Slug is the url friendly version of the dashboard title.
|
||||
If there exists multiple dashboards with the same slug, one of them will be returned in the response.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/search?query=Production%20Overview&starred=true&tag=prod HTTP/1.1
|
||||
GET /api/dashboards/db/production-overview HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
@ -270,14 +315,78 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
[
|
||||
{
|
||||
"id":1,
|
||||
"title":"Production Overview",
|
||||
"uri":"db/production-overview",
|
||||
"type":"dash-db",
|
||||
"tags":[prod],
|
||||
"isStarred":true
|
||||
{
|
||||
"dashboard": {
|
||||
"id": 1,
|
||||
"uid": "cIBgcSjkk",
|
||||
"title": "Production Overview",
|
||||
"tags": [ "templated" ],
|
||||
"timezone": "browser",
|
||||
"rows": [
|
||||
{
|
||||
}
|
||||
],
|
||||
"schemaVersion": 6,
|
||||
"version": 0
|
||||
},
|
||||
"meta": {
|
||||
"isStarred": false,
|
||||
"url": "/d/cIBgcSjkk/production-overview",
|
||||
"slug": "production-overview" // deprecated in Grafana v5.0
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Found
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
- **404** – Not found
|
||||
|
||||
### Delete dashboard by slug
|
||||
**Deprecated starting from Grafana v5.0. Please update to use the *Delete dashboard by uid* resource instead.**
|
||||
|
||||
`DELETE /api/dashboards/db/:slug`
|
||||
|
||||
Will delete the dashboard given the specified slug. Slug is the url friendly version of the dashboard title.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
DELETE /api/dashboards/db/test HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{"title": "Production Overview"}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Deleted
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access denied
|
||||
- **404** – Not found
|
||||
- **412** – Precondition failed
|
||||
|
||||
The **412** status code is used when there exists multiple dashboards with the same slug.
|
||||
The response body will look like this:
|
||||
|
||||
```http
|
||||
HTTP/1.1 412 Precondition Failed
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 97
|
||||
|
||||
{
|
||||
"message": "Multiple dashboards with the same slug exists",
|
||||
"status": "multiple-slugs-exists"
|
||||
}
|
||||
```
|
||||
|
149
docs/sources/http_api/dashboard_permissions.md
Normal file
149
docs/sources/http_api/dashboard_permissions.md
Normal file
@ -0,0 +1,149 @@
|
||||
+++
|
||||
title = "Dashboard Permissions HTTP API "
|
||||
description = "Grafana Dashboard Permissions HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "dashboard", "permission", "permissions", "acl"]
|
||||
aliases = ["/http_api/dashboardpermissions/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Dashboard Permissions"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
# Dashboard Permissions API
|
||||
|
||||
This API can be used to update/get the permissions for a dashboard.
|
||||
|
||||
Permissions with `dashboardId=-1` are the default permissions for users with the Viewer and Editor roles. Permissions can be set for a user, a team or a role (Viewer or Editor). Permissions cannot be set for Admins - they always have access to everything.
|
||||
|
||||
The permission levels for the permission field:
|
||||
|
||||
- 1 = View
|
||||
- 2 = Edit
|
||||
- 4 = Admin
|
||||
|
||||
## Get permissions for a dashboard
|
||||
|
||||
`GET /api/dashboards/id/:dashboardId/permissions`
|
||||
|
||||
Gets all existing permissions for the dashboard with the given `dashboardId`.
|
||||
|
||||
**Example request**:
|
||||
|
||||
```http
|
||||
GET /api/dashboards/id/1/permissions HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**
|
||||
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 551
|
||||
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"dashboardId": -1,
|
||||
"created": "2017-06-20T02:00:00+02:00",
|
||||
"updated": "2017-06-20T02:00:00+02:00",
|
||||
"userId": 0,
|
||||
"userLogin": "",
|
||||
"userEmail": "",
|
||||
"teamId": 0,
|
||||
"team": "",
|
||||
"role": "Viewer",
|
||||
"permission": 1,
|
||||
"permissionName": "View",
|
||||
"uid": "",
|
||||
"title": "",
|
||||
"slug": "",
|
||||
"isFolder": false,
|
||||
"url": ""
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"dashboardId": -1,
|
||||
"created": "2017-06-20T02:00:00+02:00",
|
||||
"updated": "2017-06-20T02:00:00+02:00",
|
||||
"userId": 0,
|
||||
"userLogin": "",
|
||||
"userEmail": "",
|
||||
"teamId": 0,
|
||||
"team": "",
|
||||
"role": "Editor",
|
||||
"permission": 2,
|
||||
"permissionName": "Edit",
|
||||
"uid": "",
|
||||
"title": "",
|
||||
"slug": "",
|
||||
"isFolder": false,
|
||||
"url": ""
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Access denied
|
||||
- **404** - Dashboard not found
|
||||
|
||||
## Update permissions for a dashboard
|
||||
|
||||
`POST /api/dashboards/id/:dashboardId/permissions`
|
||||
|
||||
Updates permissions for a dashboard. This operation will remove existing permissions if they're not included in the request.
|
||||
|
||||
**Example request**:
|
||||
|
||||
```http
|
||||
POST /api/dashboards/id/1/permissions
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
|
||||
"items": [
|
||||
{
|
||||
"role": "Viewer",
|
||||
"permission": 1
|
||||
},
|
||||
{
|
||||
"role": "Editor",
|
||||
"permission": 2
|
||||
},
|
||||
{
|
||||
"teamId": 1,
|
||||
"permission": 1
|
||||
},
|
||||
{
|
||||
"userId": 11,
|
||||
"permission": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
JSON body schema:
|
||||
|
||||
- **items** - The permission items to add/update. Items that are omitted from the list will be removed.
|
||||
|
||||
**Example response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 35
|
||||
|
||||
{"message":"Dashboard permissions updated"}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Access denied
|
||||
- **404** - Dashboard not found
|
317
docs/sources/http_api/folder.md
Normal file
317
docs/sources/http_api/folder.md
Normal file
@ -0,0 +1,317 @@
|
||||
+++
|
||||
title = "Folder HTTP API "
|
||||
description = "Grafana Folder HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "folder"]
|
||||
aliases = ["/http_api/folder/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Folder"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
# Folder API
|
||||
|
||||
## Identifier (id) vs unique identifier (uid)
|
||||
|
||||
The identifier (id) of a folder is an auto-incrementing numeric value and is only unique per Grafana install.
|
||||
|
||||
The unique identifier (uid) of a folder can be used for uniquely identify folders between multiple Grafana installs. It's automatically generated if not provided when creating a folder. The uid allows having consistent URL's for accessing folders and when syncing folders between multiple Grafana installs. This means that changing the title of a folder will not break any bookmarked links to that folder.
|
||||
|
||||
The uid can have a maximum length of 40 characters.
|
||||
|
||||
|
||||
## Get all folders
|
||||
|
||||
`GET /api/folders`
|
||||
|
||||
Returns all folders that the authenticated user has permission to view.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/folders?limit=10 HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
[
|
||||
{
|
||||
"id":1,
|
||||
"uid": "nErXDvCkzz",
|
||||
"title": "Departmenet ABC",
|
||||
"url": "/dashboards/f/nErXDvCkzz/department-abc",
|
||||
"hasAcl": false,
|
||||
"canSave": true,
|
||||
"canEdit": true,
|
||||
"canAdmin": true,
|
||||
"createdBy": "admin",
|
||||
"created": "2018-01-31T17:43:12+01:00",
|
||||
"updatedBy": "admin",
|
||||
"updated": "2018-01-31T17:43:12+01:00",
|
||||
"version": 1
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Get folder by uid
|
||||
|
||||
`GET /api/folders/:uid`
|
||||
|
||||
Will return the folder given the folder uid.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/folders/nErXDvCkzzh HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id":1,
|
||||
"uid": "nErXDvCkzz",
|
||||
"title": "Departmenet ABC",
|
||||
"url": "/dashboards/f/nErXDvCkzz/department-abc",
|
||||
"hasAcl": false,
|
||||
"canSave": true,
|
||||
"canEdit": true,
|
||||
"canAdmin": true,
|
||||
"createdBy": "admin",
|
||||
"created": "2018-01-31T17:43:12+01:00",
|
||||
"updatedBy": "admin",
|
||||
"updated": "2018-01-31T17:43:12+01:00",
|
||||
"version": 1
|
||||
}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Found
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access Denied
|
||||
- **404** – Folder not found
|
||||
|
||||
## Create folder
|
||||
|
||||
`POST /api/folders`
|
||||
|
||||
Creates a new folder.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
POST /api/folders HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
|
||||
{
|
||||
"uid": "nErXDvCkzz",
|
||||
"title": "Department ABC"
|
||||
}
|
||||
```
|
||||
|
||||
JSON Body schema:
|
||||
|
||||
- **uid** – Optional [unique identifier](/http_api/folder/#identifier-id-vs-unique-identifier-uid).
|
||||
- **title** – The title of the folder.
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id":1,
|
||||
"uid": "nErXDvCkzz",
|
||||
"title": "Departmenet ABC",
|
||||
"url": "/dashboards/f/nErXDvCkzz/department-abc",
|
||||
"hasAcl": false,
|
||||
"canSave": true,
|
||||
"canEdit": true,
|
||||
"canAdmin": true,
|
||||
"createdBy": "admin",
|
||||
"created": "2018-01-31T17:43:12+01:00",
|
||||
"updatedBy": "admin",
|
||||
"updated": "2018-01-31T17:43:12+01:00",
|
||||
"version": 1
|
||||
}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Created
|
||||
- **400** – Errors (invalid json, missing or invalid fields, etc)
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access Denied
|
||||
|
||||
## Update folder
|
||||
|
||||
`PUT /api/folders/:uid`
|
||||
|
||||
Updates an existing folder identified by uid.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
PUT /api/folders/nErXDvCkzz HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
|
||||
{
|
||||
"title":"Department DEF",
|
||||
"version": 1
|
||||
}
|
||||
```
|
||||
|
||||
JSON Body schema:
|
||||
|
||||
- **uid** – Provide another [unique identifier](/http_api/folder/#identifier-id-vs-unique-identifier-uid) than stored to change the unique identifier.
|
||||
- **title** – The title of the folder.
|
||||
- **version** – Provide the current version to be able to update the folder. Not needed if `overwrite=true`.
|
||||
- **overwrite** – Set to true if you want to overwrite existing folder with newer version.
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id":1,
|
||||
"uid": "nErXDvCkzz",
|
||||
"title": "Departmenet DEF",
|
||||
"url": "/dashboards/f/nErXDvCkzz/department-def",
|
||||
"hasAcl": false,
|
||||
"canSave": true,
|
||||
"canEdit": true,
|
||||
"canAdmin": true,
|
||||
"createdBy": "admin",
|
||||
"created": "2018-01-31T17:43:12+01:00",
|
||||
"updatedBy": "admin",
|
||||
"updated": "2018-01-31T17:43:12+01:00",
|
||||
"version": 1
|
||||
}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Updated
|
||||
- **400** – Errors (invalid json, missing or invalid fields, etc)
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access Denied
|
||||
- **404** – Folder not found
|
||||
- **412** – Precondition failed
|
||||
|
||||
The **412** status code is used for explaing that you cannot update the folder and why.
|
||||
There can be different reasons for this:
|
||||
|
||||
- The folder has been changed by someone else, `status=version-mismatch`
|
||||
|
||||
The response body will have the following properties:
|
||||
|
||||
```http
|
||||
HTTP/1.1 412 Precondition Failed
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 97
|
||||
|
||||
{
|
||||
"message": "The folder has been changed by someone else",
|
||||
"status": "version-mismatch"
|
||||
}
|
||||
```
|
||||
|
||||
## Delete folder
|
||||
|
||||
`DELETE /api/folders/:uid`
|
||||
|
||||
Deletes an existing folder identified by uid together with all dashboards stored in the folder, if any. This operation cannot be reverted.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
DELETE /api/folders/nErXDvCkzz HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"message":"Folder deleted"
|
||||
}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Deleted
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access Denied
|
||||
- **404** – Folder not found
|
||||
|
||||
## Get folder by id
|
||||
|
||||
`GET /api/folders/:id`
|
||||
|
||||
Will return the folder identified by id.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/folders/1 HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id":1,
|
||||
"uid": "nErXDvCkzz",
|
||||
"title": "Departmenet ABC",
|
||||
"url": "/dashboards/f/nErXDvCkzz/department-abc",
|
||||
"hasAcl": false,
|
||||
"canSave": true,
|
||||
"canEdit": true,
|
||||
"canAdmin": true,
|
||||
"createdBy": "admin",
|
||||
"created": "2018-01-31T17:43:12+01:00",
|
||||
"updatedBy": "admin",
|
||||
"updated": "2018-01-31T17:43:12+01:00",
|
||||
"version": 1
|
||||
}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** – Found
|
||||
- **401** – Unauthorized
|
||||
- **403** – Access Denied
|
||||
- **404** – Folder not found
|
98
docs/sources/http_api/folder_dashboard_search.md
Normal file
98
docs/sources/http_api/folder_dashboard_search.md
Normal file
@ -0,0 +1,98 @@
|
||||
+++
|
||||
title = "Folder/Dashboard Search HTTP API "
|
||||
description = "Grafana Folder/Dashboard Search HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "search", "folder", "dashboard"]
|
||||
aliases = ["/http_api/folder_dashboard_search/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Folder/dashboard search"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
# Folder/Dashboard Search API
|
||||
|
||||
## Search folders and dashboards
|
||||
|
||||
`GET /api/search/`
|
||||
|
||||
Query parameters:
|
||||
|
||||
- **query** – Search Query
|
||||
- **tag** – List of tags to search for
|
||||
- **type** – Type to search for, `dash-folder` or `dash-db`
|
||||
- **dashboardIds** – List of dashboard id's to search for
|
||||
- **folderIds** – List of folder id's to search in for dashboards
|
||||
- **starred** – Flag indicating if only starred Dashboards should be returned
|
||||
- **limit** – Limit the number of returned results
|
||||
|
||||
**Example request for retrieving folders and dashboards of the general folder**:
|
||||
|
||||
```http
|
||||
GET /api/search?folderIds=0&query=&starred=false HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example response for retrieving folders and dashboards of the general folder**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
[
|
||||
{
|
||||
"id": 163,
|
||||
"uid": "000000163",
|
||||
"title": "Folder",
|
||||
"url": "/dashboards/f/000000163/folder",
|
||||
"type": "dash-folder",
|
||||
"tags": [],
|
||||
"isStarred": false,
|
||||
"uri":"db/folder" // deprecated in Grafana v5.0
|
||||
},
|
||||
{
|
||||
"id":1,
|
||||
"uid": "cIBgcSjkk",
|
||||
"title":"Production Overview",
|
||||
"url": "/d/cIBgcSjkk/production-overview",
|
||||
"type":"dash-db",
|
||||
"tags":[prod],
|
||||
"isStarred":true,
|
||||
"uri":"db/production-overview" // deprecated in Grafana v5.0
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Example request searching for dashboards**:
|
||||
|
||||
```http
|
||||
GET /api/search?query=Production%20Overview&starred=true&tag=prod HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example response searching for dashboards**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
[
|
||||
{
|
||||
"id":1,
|
||||
"uid": "cIBgcSjkk",
|
||||
"title":"Production Overview",
|
||||
"url": "/d/cIBgcSjkk/production-overview",
|
||||
"type":"dash-db",
|
||||
"tags":[prod],
|
||||
"isStarred":true,
|
||||
"folderId": 2,
|
||||
"folderUid": "000000163",
|
||||
"folderTitle": "Folder",
|
||||
"folderUrl": "/dashboards/f/000000163/folder",
|
||||
"uri":"db/production-overview" // deprecated in Grafana v5.0
|
||||
}
|
||||
]
|
||||
```
|
149
docs/sources/http_api/folder_permissions.md
Normal file
149
docs/sources/http_api/folder_permissions.md
Normal file
@ -0,0 +1,149 @@
|
||||
+++
|
||||
title = "Folder Permissions HTTP API "
|
||||
description = "Grafana Folder Permissions HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "folder", "permission", "permissions", "acl"]
|
||||
aliases = ["/http_api/dashboardpermissions/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Folder Permissions"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
# Folder Permissions API
|
||||
|
||||
This API can be used to update/get the permissions for a folder.
|
||||
|
||||
Permissions with `folderId=-1` are the default permissions for users with the Viewer and Editor roles. Permissions can be set for a user, a team or a role (Viewer or Editor). Permissions cannot be set for Admins - they always have access to everything.
|
||||
|
||||
The permission levels for the permission field:
|
||||
|
||||
- 1 = View
|
||||
- 2 = Edit
|
||||
- 4 = Admin
|
||||
|
||||
## Get permissions for a folder
|
||||
|
||||
`GET /api/folders/:uid/permissions`
|
||||
|
||||
Gets all existing permissions for the folder with the given `uid`.
|
||||
|
||||
**Example request**:
|
||||
|
||||
```http
|
||||
GET /api/folders/nErXDvCkzz/permissions HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**
|
||||
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 551
|
||||
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"folderId": -1,
|
||||
"created": "2017-06-20T02:00:00+02:00",
|
||||
"updated": "2017-06-20T02:00:00+02:00",
|
||||
"userId": 0,
|
||||
"userLogin": "",
|
||||
"userEmail": "",
|
||||
"teamId": 0,
|
||||
"team": "",
|
||||
"role": "Viewer",
|
||||
"permission": 1,
|
||||
"permissionName": "View",
|
||||
"uid": "nErXDvCkzz",
|
||||
"title": "",
|
||||
"slug": "",
|
||||
"isFolder": false,
|
||||
"url": ""
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"dashboardId": -1,
|
||||
"created": "2017-06-20T02:00:00+02:00",
|
||||
"updated": "2017-06-20T02:00:00+02:00",
|
||||
"userId": 0,
|
||||
"userLogin": "",
|
||||
"userEmail": "",
|
||||
"teamId": 0,
|
||||
"team": "",
|
||||
"role": "Editor",
|
||||
"permission": 2,
|
||||
"permissionName": "Edit",
|
||||
"uid": "",
|
||||
"title": "",
|
||||
"slug": "",
|
||||
"isFolder": false,
|
||||
"url": ""
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Access denied
|
||||
- **404** - Folder not found
|
||||
|
||||
## Update permissions for a folder
|
||||
|
||||
`POST /api/folders/:uid/permissions`
|
||||
|
||||
Updates permissions for a folder. This operation will remove existing permissions if they're not included in the request.
|
||||
|
||||
**Example request**:
|
||||
|
||||
```http
|
||||
POST /api/folders/nErXDvCkzz/permissions
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
|
||||
"items": [
|
||||
{
|
||||
"role": "Viewer",
|
||||
"permission": 1
|
||||
},
|
||||
{
|
||||
"role": "Editor",
|
||||
"permission": 2
|
||||
},
|
||||
{
|
||||
"teamId": 1,
|
||||
"permission": 1
|
||||
},
|
||||
{
|
||||
"userId": 11,
|
||||
"permission": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
JSON body schema:
|
||||
|
||||
- **items** - The permission items to add/update. Items that are omitted from the list will be removed.
|
||||
|
||||
**Example response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Content-Length: 35
|
||||
|
||||
{"message":"Folder permissions updated"}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Access denied
|
||||
- **404** - Dashboard not found
|
@ -18,12 +18,19 @@ dashboards, creating users and updating data sources.
|
||||
## Supported HTTP APIs:
|
||||
|
||||
|
||||
* [Authentication API]({{< relref "auth.md" >}})
|
||||
* [Dashboard API]({{< relref "dashboard.md" >}})
|
||||
* [Data Source API]({{< relref "data_source.md" >}})
|
||||
* [Organisation API]({{< relref "org.md" >}})
|
||||
* [User API]({{< relref "user.md" >}})
|
||||
* [Admin API]({{< relref "admin.md" >}})
|
||||
* [Snapshot API]({{< relref "snapshot.md" >}})
|
||||
* [Preferences API]({{< relref "preferences.md" >}})
|
||||
* [Other API]({{< relref "other.md" >}})
|
||||
* [Authentication API]({{< relref "/http_api/auth.md" >}})
|
||||
* [Dashboard API]({{< relref "/http_api/dashboard.md" >}})
|
||||
* [Dashboard Versions API]({{< relref "http_api/dashboard_versions.md" >}})
|
||||
* [Dashboard Permissions API]({{< relref "http_api/dashboard_permissions.md" >}})
|
||||
* [Folder API]({{< relref "/http_api/folder.md" >}})
|
||||
* [Folder Permissions API]({{< relref "http_api/folder_permissions.md" >}})
|
||||
* [Folder/dashboard search API]({{< relref "/http_api/folder_dashboard_search.md" >}})
|
||||
* [Data Source API]({{< relref "http_api/data_source.md" >}})
|
||||
* [Organisation API]({{< relref "http_api/org.md" >}})
|
||||
* [Snapshot API]({{< relref "http_api/snapshot.md" >}})
|
||||
* [Annotations API]({{< relref "http_api/annotations.md" >}})
|
||||
* [Alerting API]({{< relref "http_api/alerting.md" >}})
|
||||
* [User API]({{< relref "http_api/user.md" >}})
|
||||
* [Admin API]({{< relref "http_api/admin.md" >}})
|
||||
* [Preferences API]({{< relref "http_api/preferences.md" >}})
|
||||
* [Other API]({{< relref "http_api/other.md" >}})
|
||||
|
316
docs/sources/http_api/team.md
Normal file
316
docs/sources/http_api/team.md
Normal file
@ -0,0 +1,316 @@
|
||||
+++
|
||||
title = "Team HTTP API "
|
||||
description = "Grafana Team HTTP API"
|
||||
keywords = ["grafana", "http", "documentation", "api", "team", "teams", "group"]
|
||||
aliases = ["/http_api/team/"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Teams"
|
||||
parent = "http_api"
|
||||
+++
|
||||
|
||||
# Team API
|
||||
|
||||
This API can be used to create/update/delete Teams and to add/remove users to Teams. All actions require that the user has the Admin role for the organization.
|
||||
|
||||
## Team Search With Paging
|
||||
|
||||
`GET /api/teams/search?perpage=50&page=1&query=mytea`
|
||||
|
||||
or
|
||||
|
||||
`GET /api/teams/search?name=myteam`
|
||||
|
||||
```http
|
||||
GET /api/teams/search?perpage=10&page=1&query=myteam HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
### Using the query parameter
|
||||
|
||||
Default value for the `perpage` parameter is `1000` and for the `page` parameter is `1`.
|
||||
|
||||
The `totalCount` field in the response can be used for pagination of the teams list E.g. if `totalCount` is equal to 100 teams and the `perpage` parameter is set to 10 then there are 10 pages of teams.
|
||||
|
||||
The `query` parameter is optional and it will return results where the query value is contained in the `name` field. Query values with spaces need to be url encoded e.g. `query=my%20team`.
|
||||
|
||||
### Using the name parameter
|
||||
|
||||
The `name` parameter returns a single team if the parameter matches the `name` field.
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
"totalCount": 1,
|
||||
"teams": [
|
||||
{
|
||||
"id": 1,
|
||||
"orgId": 1,
|
||||
"name": "MyTestTeam",
|
||||
"email": "",
|
||||
"avatarUrl": "\/avatar\/3f49c15916554246daa714b9bd0ee398",
|
||||
"memberCount": 1
|
||||
}
|
||||
],
|
||||
"page": 1,
|
||||
"perPage": 1000
|
||||
}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
- **404** - Team not found (if searching by name)
|
||||
|
||||
## Get Team By Id
|
||||
|
||||
`GET /api/teams/:id`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/teams/1 HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"orgId": 1,
|
||||
"name": "MyTestTeam",
|
||||
"email": "",
|
||||
"created": "2017-12-15T10:40:45+01:00",
|
||||
"updated": "2017-12-15T10:40:45+01:00"
|
||||
}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
- **404** - Team not found
|
||||
|
||||
## Add Team
|
||||
|
||||
The Team `name` needs to be unique. `name` is required and `email` is optional.
|
||||
|
||||
`POST /api/teams`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
POST /api/teams HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
|
||||
{
|
||||
"name": "MyTestTeam",
|
||||
"email": "email@test.com"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{"message":"Team created","teamId":2}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
- **409** - Team name is taken
|
||||
|
||||
## Update Team
|
||||
|
||||
There are two fields that can be updated for a team: `name` and `email`.
|
||||
|
||||
`PUT /api/teams/:id`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
PUT /api/teams/2 HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
|
||||
{
|
||||
"name": "MyTestTeam",
|
||||
"email": "email@test.com"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{"message":"Team updated"}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
- **404** - Team not found
|
||||
- **409** - Team name is taken
|
||||
|
||||
## Delete Team By Id
|
||||
|
||||
`DELETE /api/teams/:id`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
DELETE /api/teams/2 HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{"message":"Team deleted"}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
- **404** - Failed to delete Team. ID not found
|
||||
|
||||
## Get Team Members
|
||||
|
||||
`GET /api/teams/:teamId/members`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/teams/1/members HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
[
|
||||
{
|
||||
"orgId": 1,
|
||||
"teamId": 1,
|
||||
"userId": 3,
|
||||
"email": "user1@email.com",
|
||||
"login": "user1",
|
||||
"avatarUrl": "\/avatar\/1b3c32f6386b0185c40d359cdc733a79"
|
||||
},
|
||||
{
|
||||
"orgId": 1,
|
||||
"teamId": 1,
|
||||
"userId": 2,
|
||||
"email": "user2@email.com",
|
||||
"login": "user2",
|
||||
"avatarUrl": "\/avatar\/cad3c68da76e45d10269e8ef02f8e73e"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
|
||||
## Add Team Member
|
||||
|
||||
`POST /api/teams/:teamId/members`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
POST /api/teams/1/members HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
|
||||
{
|
||||
"userId": 2
|
||||
}
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{"message":"Member added to Team"}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **400** - User is already added to this team
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
- **404** - Team not found
|
||||
|
||||
## Remove Member From Team
|
||||
|
||||
`DELETE /api/teams/:teamId/members/:userId`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
DELETE /api/teams/2/members/3 HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{"message":"Team Member removed"}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
- **404** - Team not found/Team member not found
|
@ -156,7 +156,7 @@ HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"email": "user@mygraf.com"
|
||||
"email": "user@mygraf.com",
|
||||
"name": "admin",
|
||||
"login": "admin",
|
||||
"theme": "light",
|
||||
@ -409,4 +409,4 @@ HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{"message":"Dashboard unstarred"}
|
||||
```
|
||||
```
|
||||
|
@ -1,53 +1,107 @@
|
||||
+++
|
||||
title = "Docs Home"
|
||||
description = "Install guide for Grafana"
|
||||
title = "Grafana documentation"
|
||||
description = "Guides, Installation & Feature Documentation"
|
||||
keywords = ["grafana", "installation", "documentation"]
|
||||
type = "docs"
|
||||
aliases = ["v1.1", "guides/reference/admin"]
|
||||
[menu.docs]
|
||||
name = "Welcome to the Docs"
|
||||
identifier = "root"
|
||||
weight = -1
|
||||
+++
|
||||
|
||||
# Welcome to the Grafana Documentation
|
||||
# Grafana Documentation
|
||||
|
||||
Grafana is an open source metric analytics & visualization suite. It is most commonly used for
|
||||
visualizing time series data for infrastructure and application analytics but many use it in
|
||||
other domains including industrial sensors, home automation, weather, and process control.
|
||||
<h2>Installing Grafana</h2>
|
||||
<div class="nav-cards">
|
||||
<a href="{{< relref "installation/debian.md" >}}" class="nav-cards__item nav-cards__item--install">
|
||||
<div class="nav-cards__icon fa fa-linux">
|
||||
</div>
|
||||
<h5>Installing on Linux</h5>
|
||||
</a>
|
||||
<a href="{{< relref "installation/mac.md" >}}" class="nav-cards__item nav-cards__item--install">
|
||||
<div class="nav-cards__icon fa fa-apple">
|
||||
</div>
|
||||
<h5>Installing on Mac OS X</h5>
|
||||
</a>
|
||||
<a href="{{< relref "installation/windows.md" >}}" class="nav-cards__item nav-cards__item--install">
|
||||
<div class="nav-cards__icon fa fa-windows">
|
||||
</div>
|
||||
<h5>Installing on Windows</h5>
|
||||
</a>
|
||||
<a href="https://grafana.com/cloud/grafana" class="nav-cards__item nav-cards__item--install">
|
||||
<div class="nav-cards__icon fa fa-cloud">
|
||||
</div>
|
||||
<h5>Grafana Cloud</h5>
|
||||
</a>
|
||||
<a href="https://grafana.com/grafana/download" class="nav-cards__item nav-cards__item--install">
|
||||
<div class="nav-cards__icon fa fa-moon-o">
|
||||
</div>
|
||||
<h5>Nightly Builds</h5>
|
||||
</a>
|
||||
<div class="nav-cards__item nav-cards__item--install">
|
||||
<h5>For other platforms Read the <a href="{{< relref "project/building_from_source.md" >}}">build from source</a>
|
||||
instructions for more information.</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## Installing Grafana
|
||||
- [Installing on Debian / Ubuntu](installation/debian)
|
||||
- [Installing on RPM-based Linux (CentOS, Fedora, OpenSuse, RedHat)](installation/rpm)
|
||||
- [Installing on Mac OS X](installation/mac)
|
||||
- [Installing on Windows](installation/windows)
|
||||
- [Installing on Docker](installation/docker)
|
||||
- [Installing using Provisioning (Chef, Puppet, Salt, Ansible, etc)](installation/provisioning)
|
||||
- [Nightly Builds](https://grafana.com/grafana/download)
|
||||
<h2>Guides</h2>
|
||||
|
||||
For other platforms Read the [build from source]({{< relref "project/building_from_source.md" >}})
|
||||
instructions for more information.
|
||||
<div class="nav-cards">
|
||||
<a href="https://grafana.com/grafana" class="nav-cards__item nav-cards__item--guide">
|
||||
<h4>What is Grafana?</h4>
|
||||
<p>Grafana feature highlights.</p>
|
||||
</a>
|
||||
<a href="{{< relref "installation/configuration.md" >}}" class="nav-cards__item nav-cards__item--guide">
|
||||
<h4>Configure Grafana</h4>
|
||||
<p>Article on all the Grafana configuration and setup options.</p>
|
||||
</a>
|
||||
<a href="{{< relref "guides/getting_started.md" >}}" class="nav-cards__item nav-cards__item--guide">
|
||||
<h4>Getting Started</h4>
|
||||
<p>A guide that walks you through the basics of using Grafana</p>
|
||||
</a>
|
||||
<a href="{{< relref "administration/provisioning.md" >}}" class="nav-cards__item nav-cards__item--guide">
|
||||
<h4>Provisioning</h4>
|
||||
<p>A guide to help you automate your Grafana setup & configuration.</p>
|
||||
</a>
|
||||
<a href="{{< relref "guides/whats-new-in-v5.md" >}}" class="nav-cards__item nav-cards__item--guide">
|
||||
<h4>What's new in v5.0</h4>
|
||||
<p>Article on all the new cool features and enhancements in v5.0</p>
|
||||
</a>
|
||||
<a href="{{< relref "tutorials/screencasts.md" >}}" class="nav-cards__item nav-cards__item--guide">
|
||||
<h4>Screencasts</h4>
|
||||
<p>Video tutorials & guides</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Configuring Grafana
|
||||
|
||||
The back-end web server has a number of configuration options. Go the
|
||||
[Configuration]({{< relref "installation/configuration.md" >}}) page for details on all
|
||||
those options.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
- [Getting Started]({{< relref "guides/getting_started.md" >}})
|
||||
- [Basic Concepts]({{< relref "guides/basic_concepts.md" >}})
|
||||
- [Screencasts]({{< relref "tutorials/screencasts.md" >}})
|
||||
|
||||
## Data Source Guides
|
||||
|
||||
- [Graphite]({{< relref "features/datasources/graphite.md" >}})
|
||||
- [Elasticsearch]({{< relref "features/datasources/elasticsearch.md" >}})
|
||||
- [InfluxDB]({{< relref "features/datasources/influxdb.md" >}})
|
||||
- [Prometheus]({{< relref "features/datasources/prometheus.md" >}})
|
||||
- [OpenTSDB]({{< relref "features/datasources/opentsdb.md" >}})
|
||||
- [MySQL]({{< relref "features/datasources/mysql.md" >}})
|
||||
- [Postgres]({{< relref "features/datasources/postgres.md" >}})
|
||||
- [Cloudwatch]({{< relref "features/datasources/cloudwatch.md" >}})
|
||||
<h2>Data Source Guides</h2>
|
||||
<div class="nav-cards">
|
||||
<a href="{{< relref "features/datasources/graphite.md" >}}" class="nav-cards__item nav-cards__item--ds">
|
||||
<img src="/img/docs/logos/icon_graphite.svg" >
|
||||
<h5>Graphite</h5>
|
||||
</a>
|
||||
<a href="{{< relref "features/datasources/elasticsearch.md" >}}" class="nav-cards__item nav-cards__item--ds">
|
||||
<img src="/img/docs/logos/icon_elasticsearch.svg" >
|
||||
<h5>Elasticsearch</h5>
|
||||
</a>
|
||||
<a href="{{< relref "features/datasources/influxdb.md" >}}" class="nav-cards__item nav-cards__item--ds">
|
||||
<img src="/img/docs/logos/icon_influxdb.svg" >
|
||||
<h5>InfluxDB</h5>
|
||||
</a>
|
||||
<a href="{{< relref "features/datasources/prometheus.md" >}}" class="nav-cards__item nav-cards__item--ds">
|
||||
<img src="/img/docs/logos/icon_prometheus.svg" >
|
||||
<h5>Prometheus</h5>
|
||||
</a>
|
||||
<a href="{{< relref "features/datasources/opentsdb.md" >}}" class="nav-cards__item nav-cards__item--ds">
|
||||
<img src="/img/docs/logos/icon_opentsdb.png" >
|
||||
<h5>OpenTSDB</h5>
|
||||
</a>
|
||||
<a href="{{< relref "features/datasources/mysql.md" >}}" class="nav-cards__item nav-cards__item--ds">
|
||||
<img src="/img/docs/logos/icon_mysql.png" >
|
||||
<h5>MySQL</h5>
|
||||
</a>
|
||||
<a href="{{< relref "features/datasources/postgres.md" >}}" class="nav-cards__item nav-cards__item--ds">
|
||||
<img src="/img/docs/logos/icon_postgres.svg" >
|
||||
<h5>Postgres</h5>
|
||||
</a>
|
||||
<a href="{{< relref "features/datasources/cloudwatch.md" >}}" class="nav-cards__item nav-cards__item--ds">
|
||||
<img src="/img/docs/logos/icon_cloudwatch.svg">
|
||||
<h5>Cloudwatch</h5>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -69,4 +69,57 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
#### HAProxy configuration with sub path
|
||||
```bash
|
||||
frontend http-in
|
||||
bind *:80
|
||||
use_backend grafana_backend if { path /grafana } or { path_beg /grafana/ }
|
||||
|
||||
backend grafana_backend
|
||||
# Requires haproxy >= 1.6
|
||||
http-request set-path %[path,regsub(^/grafana/?,/)]
|
||||
|
||||
# Works for haproxy < 1.6
|
||||
# reqrep ^([^\ ]*\ /)grafana[/]?(.*) \1\2
|
||||
|
||||
server grafana localhost:3000
|
||||
```
|
||||
|
||||
### IIS URL Rewrite Rule (Windows) with Subpath
|
||||
|
||||
IIS requires that the URL Rewrite module is installed.
|
||||
|
||||
Given:
|
||||
|
||||
- subpath `grafana`
|
||||
- Grafana installed on `http://localhost:3000`
|
||||
- server config:
|
||||
|
||||
```bash
|
||||
[server]
|
||||
domain = localhost:8080
|
||||
root_url = %(protocol)s://%(domain)s:/grafana
|
||||
```
|
||||
|
||||
Create an Inbound Rule for the parent website (localhost:8080 in this example) in IIS Manager with the following settings:
|
||||
|
||||
- pattern: `grafana(/)?(.*)`
|
||||
- check the `Ignore case` checkbox
|
||||
- rewrite url set to `http://localhost:3000/{R:2}`
|
||||
- check the `Append query string` checkbox
|
||||
- check the `Stop processing of subsequent rules` checkbox
|
||||
|
||||
This is the rewrite rule that is generated in the `web.config`:
|
||||
|
||||
```xml
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="Grafana" enabled="true" stopProcessing="true">
|
||||
<match url="grafana(/)?(.*)" />
|
||||
<action type="Rewrite" url="http://localhost:3000/{R:2}" logRewrittenUrl="false" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
```
|
||||
|
||||
See the [tutorial on IIS Url Rewrites](http://docs.grafana.org/tutorials/iis/) for more in-depth instructions.
|
||||
|
@ -205,7 +205,7 @@ The database user (not applicable for `sqlite3`).
|
||||
|
||||
### password
|
||||
|
||||
The database user's password (not applicable for `sqlite3`). If the password contains `#` or `;` you have to wrap it with trippel quotes. Ex `"""#password;"""`
|
||||
The database user's password (not applicable for `sqlite3`). If the password contains `#` or `;` you have to wrap it with triple quotes. Ex `"""#password;"""`
|
||||
|
||||
### ssl_mode
|
||||
|
||||
@ -214,19 +214,19 @@ For MySQL, use either `true`, `false`, or `skip-verify`.
|
||||
|
||||
### ca_cert_path
|
||||
|
||||
(MySQL only) The path to the CA certificate to use. On many linux systems, certs can be found in `/etc/ssl/certs`.
|
||||
The path to the CA certificate to use. On many linux systems, certs can be found in `/etc/ssl/certs`.
|
||||
|
||||
### client_key_path
|
||||
|
||||
(MySQL only) The path to the client key. Only if server requires client authentication.
|
||||
The path to the client key. Only if server requires client authentication.
|
||||
|
||||
### client_cert_path
|
||||
|
||||
(MySQL only) The path to the client cert. Only if server requires client authentication.
|
||||
The path to the client cert. Only if server requires client authentication.
|
||||
|
||||
### server_cert_name
|
||||
|
||||
(MySQL only) The common name field of the certificate used by the `mysql` server. Not necessary if `ssl_mode` is set to `skip-verify`.
|
||||
The common name field of the certificate used by the `mysql` or `postgres` server. Not necessary if `ssl_mode` is set to `skip-verify`.
|
||||
|
||||
### max_idle_conn
|
||||
The maximum number of connections in the idle connection pool.
|
||||
@ -292,10 +292,14 @@ organization to be created for that new user.
|
||||
|
||||
The role new users will be assigned for the main organization (if the
|
||||
above setting is set to true). Defaults to `Viewer`, other valid
|
||||
options are `Admin` and `Editor` and `Read Only Editor`. e.g. :
|
||||
options are `Admin` and `Editor`. e.g. :
|
||||
|
||||
`auto_assign_org_role = Read Only Editor`
|
||||
`auto_assign_org_role = Viewer`
|
||||
|
||||
### viewers_can_edit
|
||||
|
||||
Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
|
||||
Defaults to `false`.
|
||||
|
||||
<hr>
|
||||
|
||||
@ -350,7 +354,7 @@ enabled = true
|
||||
allow_sign_up = true
|
||||
client_id = YOUR_GITHUB_APP_CLIENT_ID
|
||||
client_secret = YOUR_GITHUB_APP_CLIENT_SECRET
|
||||
scopes = user:email
|
||||
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
|
||||
@ -383,6 +387,7 @@ scopes = user:email,read:org
|
||||
team_ids = 150,300
|
||||
auth_url = https://github.com/login/oauth/authorize
|
||||
token_url = https://github.com/login/oauth/access_token
|
||||
api_url = https://api.github.com/user
|
||||
allow_sign_up = true
|
||||
```
|
||||
|
||||
@ -401,6 +406,7 @@ client_secret = YOUR_GITHUB_APP_CLIENT_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
|
||||
allow_sign_up = true
|
||||
# space-delimited organization names
|
||||
allowed_organizations = github google
|
||||
@ -492,7 +498,7 @@ name = BitBucket
|
||||
enabled = true
|
||||
allow_sign_up = true
|
||||
client_id = <client id>
|
||||
client_secret = <secret>
|
||||
client_secret = <client secret>
|
||||
scopes = account email
|
||||
auth_url = https://bitbucket.org/site/oauth2/authorize
|
||||
token_url = https://bitbucket.org/site/oauth2/access_token
|
||||
@ -501,6 +507,105 @@ team_ids =
|
||||
allowed_organizations =
|
||||
```
|
||||
|
||||
### Set up oauth2 with OneLogin
|
||||
|
||||
1. Create a new Custom Connector with the following settings:
|
||||
- Name: Grafana
|
||||
- Sign On Method: OpenID Connect
|
||||
- Redirect URI: `https://<grafana domain>/login/generic_oauth`
|
||||
- Signing Algorithm: RS256
|
||||
- Login URL: `https://<grafana domain>/login/generic_oauth`
|
||||
|
||||
then:
|
||||
2. Add an App to the Grafana Connector:
|
||||
- Display Name: Grafana
|
||||
|
||||
then:
|
||||
3. Under the SSO tab on the Grafana App details page you'll find the Client ID and Client Secret.
|
||||
|
||||
Your OneLogin Domain will match the url you use to access OneLogin.
|
||||
|
||||
Configure Grafana as follows:
|
||||
|
||||
```bash
|
||||
[auth.generic_oauth]
|
||||
name = OneLogin
|
||||
enabled = true
|
||||
allow_sign_up = true
|
||||
client_id = <client id>
|
||||
client_secret = <client secret>
|
||||
scopes = openid email name
|
||||
auth_url = https://<onelogin domain>.onelogin.com/oidc/auth
|
||||
token_url = https://<onelogin domain>.onelogin.com/oidc/token
|
||||
api_url = https://<onelogin domain>.onelogin.com/oidc/me
|
||||
team_ids =
|
||||
allowed_organizations =
|
||||
```
|
||||
|
||||
### Set up oauth2 with Auth0
|
||||
|
||||
1. Create a new Client in Auth0
|
||||
- Name: Grafana
|
||||
- Type: Regular Web Application
|
||||
|
||||
2. Go to the Settings tab and set:
|
||||
- Allowed Callback URLs: `https://<grafana domain>/login/generic_oauth`
|
||||
|
||||
3. Click Save Changes, then use the values at the top of the page to configure Grafana:
|
||||
|
||||
```bash
|
||||
[auth.generic_oauth]
|
||||
enabled = true
|
||||
allow_sign_up = true
|
||||
team_ids =
|
||||
allowed_organizations =
|
||||
name = Auth0
|
||||
client_id = <client id>
|
||||
client_secret = <client secret>
|
||||
scopes = openid profile email
|
||||
auth_url = https://<domain>/authorize
|
||||
token_url = https://<domain>/oauth/token
|
||||
api_url = https://<domain>/userinfo
|
||||
```
|
||||
|
||||
### Set up oauth2 with Azure Active Directory
|
||||
|
||||
1. Log in to portal.azure.com and click "Azure Active Directory" in the side menu, then click the "Properties" sub-menu item.
|
||||
|
||||
2. Copy the "Directory ID", this is needed for setting URLs later
|
||||
|
||||
3. Click "App Registrations" and add a new application registration:
|
||||
- Name: Grafana
|
||||
- Application type: Web app / API
|
||||
- Sign-on URL: `https://<grafana domain>/login/generic_oauth`
|
||||
|
||||
4. Click the name of the new application to open the application details page.
|
||||
|
||||
5. Note down the "Application ID", this will be the OAuth client id.
|
||||
|
||||
6. Click "Settings", then click "Keys" and add a new entry under Passwords
|
||||
- Key Description: Grafana OAuth
|
||||
- Duration: Never Expires
|
||||
|
||||
7. Click Save then copy the key value, this will be the OAuth client secret.
|
||||
|
||||
8. Configure Grafana as follows:
|
||||
|
||||
```bash
|
||||
[auth.generic_oauth]
|
||||
name = Azure AD
|
||||
enabled = true
|
||||
allow_sign_up = true
|
||||
client_id = <application id>
|
||||
client_secret = <key value>
|
||||
scopes = openid email name
|
||||
auth_url = https://login.microsoftonline.com/<directory id>/oauth2/authorize
|
||||
token_url = https://login.microsoftonline.com/<directory id>/oauth2/token
|
||||
api_url =
|
||||
team_ids =
|
||||
allowed_organizations =
|
||||
```
|
||||
|
||||
<hr>
|
||||
|
||||
## [auth.basic]
|
||||
@ -568,31 +673,6 @@ session provider you have configured.
|
||||
- **memcache:** ex: 127.0.0.1:11211
|
||||
- **redis:** ex: `addr=127.0.0.1:6379,pool_size=100,prefix=grafana`
|
||||
|
||||
If you use MySQL or Postgres as the session store you need to create the
|
||||
session table manually.
|
||||
|
||||
Mysql Example:
|
||||
|
||||
```bash
|
||||
CREATE TABLE `session` (
|
||||
`key` CHAR(16) NOT NULL,
|
||||
`data` BLOB,
|
||||
`expiry` INT(11) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`key`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
```
|
||||
|
||||
Postgres Example:
|
||||
|
||||
```bash
|
||||
CREATE TABLE session (
|
||||
key CHAR(16) NOT NULL,
|
||||
data BYTEA,
|
||||
expiry INTEGER NOT NULL,
|
||||
PRIMARY KEY (key)
|
||||
);
|
||||
```
|
||||
|
||||
Postgres valid `sslmode` are `disable`, `require`, `verify-ca`, and `verify-full` (default).
|
||||
|
||||
### cookie_name
|
||||
@ -717,17 +797,14 @@ Set root url to a Grafana instance where you want to publish external snapshots
|
||||
### external_snapshot_name
|
||||
Set name for external snapshot button. Defaults to `Publish to snapshot.raintank.io`
|
||||
|
||||
### remove expired snapshot
|
||||
### snapshot_remove_expired
|
||||
Enabled to automatically remove expired snapshots
|
||||
|
||||
### remove snapshots after 90 days
|
||||
Time to live for snapshots.
|
||||
|
||||
## [external_image_storage]
|
||||
These options control how images should be made public so they can be shared on services like slack.
|
||||
|
||||
### provider
|
||||
You can choose between (s3, webdav, gcs). If left empty Grafana will ignore the upload action.
|
||||
You can choose between (s3, webdav, gcs, azure_blob, local). If left empty Grafana will ignore the upload action.
|
||||
|
||||
## [external_image_storage.s3]
|
||||
|
||||
@ -782,6 +859,17 @@ Bucket Name on Google Cloud Storage.
|
||||
### path
|
||||
Optional extra path inside bucket
|
||||
|
||||
## [external_image_storage.azure_blob]
|
||||
|
||||
### account_name
|
||||
Storage account name
|
||||
|
||||
### account_key
|
||||
Storage account key
|
||||
|
||||
### container_name
|
||||
Container name where to store "Blob" images with random names. Creating the blob container beforehand is required. Only public containers are supported.
|
||||
|
||||
## [alerting]
|
||||
|
||||
### enabled
|
||||
@ -789,6 +877,4 @@ Defaults to true. Set to false to disable alerting engine and hide Alerting from
|
||||
|
||||
### execute_alerts
|
||||
|
||||
### execute_alerts = true
|
||||
|
||||
Makes it possible to turn off alert rule execution.
|
||||
|
@ -15,9 +15,7 @@ weight = 1
|
||||
|
||||
Description | Download
|
||||
------------ | -------------
|
||||
Stable for Debian-based Linux | [grafana_4.6.2_amd64.deb](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.6.2_amd64.deb)
|
||||
|
||||
<!-- Beta for Debian-based Linux | [grafana_4.5.0-beta1_amd64.deb](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.5.0-beta1_amd64.deb) -->
|
||||
Stable for Debian-based Linux | [grafana_5.0.0_amd64.deb](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_5.0.0_amd64.deb)
|
||||
|
||||
Read [Upgrading Grafana]({{< relref "installation/upgrading.md" >}}) for tips and guidance on updating an existing
|
||||
installation.
|
||||
@ -26,21 +24,11 @@ installation.
|
||||
|
||||
|
||||
```bash
|
||||
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.6.2_amd64.deb
|
||||
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_5.0.0_amd64.deb
|
||||
sudo apt-get install -y adduser libfontconfig
|
||||
sudo dpkg -i grafana_4.6.2_amd64.deb
|
||||
sudo dpkg -i grafana_5.0.0_amd64.deb
|
||||
```
|
||||
|
||||
<!--
|
||||
## Install Latest Beta
|
||||
|
||||
```bash
|
||||
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.5.2-beta1_amd64.deb
|
||||
sudo apt-get install -y adduser libfontconfig
|
||||
sudo dpkg -i grafana_4.5.2-beta1_amd64.deb
|
||||
```
|
||||
-->
|
||||
|
||||
## APT Repository
|
||||
|
||||
Add the following line to your `/etc/apt/sources.list` file.
|
||||
|
@ -7,6 +7,7 @@ aliases = ["installation/installation/", "v2.1/installation/install/"]
|
||||
[menu.docs]
|
||||
name = "Installation"
|
||||
identifier = "installation"
|
||||
weight = 1
|
||||
+++
|
||||
|
||||
## Installing Grafana
|
||||
|
@ -43,7 +43,7 @@ ssl_skip_verify = false
|
||||
# Search user bind dn
|
||||
bind_dn = "cn=admin,dc=grafana,dc=org"
|
||||
# Search user bind password
|
||||
# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;"""
|
||||
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
|
||||
bind_password = 'grafana'
|
||||
|
||||
# User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)"
|
||||
|
@ -15,9 +15,8 @@ weight = 2
|
||||
|
||||
Description | Download
|
||||
------------ | -------------
|
||||
Stable for CentOS / Fedora / OpenSuse / Redhat Linux | [4.6.2 (x86-64 rpm)](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.6.2-1.x86_64.rpm)
|
||||
Stable for CentOS / Fedora / OpenSuse / Redhat Linux | [5.0.0 (x86-64 rpm)](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.0.0-1.x86_64.rpm)
|
||||
|
||||
<!-- Latest Beta for CentOS / Fedora / OpenSuse / Redhat Linux | [4.5.0-beta1 (x86-64 rpm)](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.5.0-beta1.x86_64.rpm) -->
|
||||
|
||||
Read [Upgrading Grafana]({{< relref "installation/upgrading.md" >}}) for tips and guidance on updating an existing
|
||||
installation.
|
||||
@ -27,7 +26,7 @@ installation.
|
||||
You can install Grafana using Yum directly.
|
||||
|
||||
```bash
|
||||
$ sudo yum install https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.6.2-1.x86_64.rpm
|
||||
$ sudo yum install https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.0.0-1.x86_64.rpm
|
||||
```
|
||||
|
||||
Or install manually using `rpm`.
|
||||
@ -35,15 +34,15 @@ Or install manually using `rpm`.
|
||||
#### On CentOS / Fedora / Redhat:
|
||||
|
||||
```bash
|
||||
$ wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.6.2-1.x86_64.rpm
|
||||
$ wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.0.0-1.x86_64.rpm
|
||||
$ sudo yum install initscripts fontconfig
|
||||
$ sudo rpm -Uvh grafana-4.6.2-1.x86_64.rpm
|
||||
$ sudo rpm -Uvh grafana-5.0.0-1.x86_64.rpm
|
||||
```
|
||||
|
||||
#### On OpenSuse:
|
||||
|
||||
```bash
|
||||
$ sudo rpm -i --nodeps grafana-4.6.2-1.x86_64.rpm
|
||||
$ sudo rpm -i --nodeps grafana-5.0.0-1.x86_64.rpm
|
||||
```
|
||||
|
||||
## Install via YUM Repository
|
||||
|
@ -101,3 +101,11 @@ as this will make upgrades easier without risking losing your config changes.
|
||||
## Upgrading from 2.x
|
||||
|
||||
We are not aware of any issues upgrading directly from 2.x to 4.x but to be on the safe side go via 3.x => 4.x.
|
||||
|
||||
## Upgrading to v5.0
|
||||
|
||||
The dashboard grid layout engine has changed. All dashboards will be automatically upgraded to new
|
||||
positioning system when you load them in v5. Dashboards saved in v5 will not work in older versions of Grafana. Some
|
||||
external panel plugins might need to be updated to work properly.
|
||||
|
||||
For more details on the new panel positioning system, [click here]({{< relref "reference/dashboard.md#panel-size-position" >}})
|
||||
|
@ -13,7 +13,7 @@ weight = 3
|
||||
|
||||
Description | Download
|
||||
------------ | -------------
|
||||
Latest stable package for Windows | [grafana.4.6.2.windows-x64.zip](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.6.2.windows-x64.zip)
|
||||
Latest stable package for Windows | [grafana-5.0.0.windows-x64.zip](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.0.0.windows-x64.zip)
|
||||
|
||||
Read [Upgrading Grafana]({{< relref "installation/upgrading.md" >}}) for tips and guidance on updating an existing
|
||||
installation.
|
||||
@ -30,9 +30,9 @@ on windows. Edit `custom.ini` and uncomment the `http_port`
|
||||
configuration option (`;` is the comment character in ini files) and change it to something like `8080` or similar.
|
||||
That port should not require extra Windows privileges.
|
||||
|
||||
Start Grafana by executing `grafana-server.exe`, preferably from the
|
||||
Start Grafana by executing `grafana-server.exe`, located in the `bin` directory, preferably from the
|
||||
command line. If you want to run Grafana as windows service, download
|
||||
[NSSM](https://nssm.cc/). It is very easy add Grafana as a Windows
|
||||
[NSSM](https://nssm.cc/). It is very easy to add Grafana as a Windows
|
||||
service using that tool.
|
||||
|
||||
Read more about the [configuration options]({{< relref "configuration.md" >}}).
|
||||
@ -42,7 +42,3 @@ Read more about the [configuration options]({{< relref "configuration.md" >}}).
|
||||
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).
|
||||
|
||||
Copy `conf/sample.ini` to a file named `conf/custom.ini` and change the
|
||||
web server port to something like 8080. The default Grafana port, 3000,
|
||||
requires special privileges on Windows.
|
||||
|
@ -84,15 +84,15 @@ An array of:
|
||||
{
|
||||
"target":"upper_75",
|
||||
"datapoints":[
|
||||
[622,1450754160000],
|
||||
[365,1450754220000]
|
||||
[622, 1450754160000],
|
||||
[365, 1450754220000]
|
||||
]
|
||||
},
|
||||
{
|
||||
"target":"upper_90",
|
||||
"datapoints":[
|
||||
[861,1450754160000],
|
||||
[767,1450754220000]
|
||||
[861, 1450754160000],
|
||||
[767, 1450754220000]
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -57,7 +57,7 @@ For this you need nodejs (v.6+).
|
||||
```bash
|
||||
npm install -g yarn
|
||||
yarn install --pure-lockfile
|
||||
npm run build
|
||||
npm run watch
|
||||
```
|
||||
|
||||
## Running Grafana Locally
|
||||
|
@ -1,42 +0,0 @@
|
||||
+++
|
||||
title = "Admin Roles"
|
||||
description = "Users & Organization permission and administration"
|
||||
keywords = ["grafana", "configuration", "documentation", "admin", "users", "permissions"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Admin Roles"
|
||||
parent = "admin"
|
||||
weight = 3
|
||||
+++
|
||||
|
||||
# Administration
|
||||
|
||||
Grafana has two levels of administrators:
|
||||
|
||||
* Organizational administrators: These admins can manage users within specific organizations in a particular Grafana installation
|
||||
* Grafana administrators: These super admins can manage users across all organizations in a Grafana installation. They can also change and access system-wide settings.
|
||||
|
||||
## Organizational Administrators
|
||||
|
||||
As an Organizational administrator, you can add `Data Sources`, add Users to your Organization and
|
||||
modify Organization details and options.
|
||||
|
||||
> *Note*: If Grafana is configured with `users.allow_org_create = true`, any User of any Organization will be able to
|
||||
> start their own Organization and become the administrator of that Organization.
|
||||
|
||||
|
||||
## Grafana Administrators
|
||||
|
||||
<img src="/img/v2/admin_sidenav.png" class="pull-right" style="margin-left: 15px">
|
||||
As a Grafana Administrator, you have complete access to any Organization or User in that instance of Grafana.
|
||||
When performing actions as a Grafana admin, the sidebar will change it's appearance as below to indicate you are performing global server administration.
|
||||
|
||||
From the Grafana Server Admin page, you can access the System Info page which summarizes all of the backend configuration settings of the Grafana server.
|
||||
|
||||
## Why would I have multiple Organizations?
|
||||
|
||||
Organizations in Grafana are best suited for a **multi-tenant deployment**. In a multi-tenant deployment,
|
||||
Organizations can be used to provide a full Grafana experience to different sets of users from a single Grafana instance,
|
||||
at the convenience of the Grafana Administrator.
|
||||
|
||||
In most cases, a Grafana installation will only have **one** Organization. Since dashboards, data sources and other configuration items are not shared between organizations, there's no need to create multiple Organizations if you want all your users to have access to the same set of dashboards and data.
|
@ -54,7 +54,8 @@ Annotation events are fetched via annotation queries. To add a new annotation qu
|
||||
open the dashboard settings menu, then select `Annotations`. This will open the dashboard annotations
|
||||
settings view. To create a new annotation query hit the `New` button.
|
||||
|
||||

|
||||
<!---->
|
||||
{{< docs-imagebox img="/img/docs/v50/annotation_new_query.png" max-width="600px" >}}
|
||||
|
||||
Specify a name for the annotation query. This name is given to the toggle (checkbox) that will allow
|
||||
you to enable/disable showing annotation events from this query. For example you might have two
|
||||
|
@ -10,7 +10,7 @@ weight = 100
|
||||
|
||||
# Dashboard JSON
|
||||
|
||||
A dashboard in Grafana is represented by a JSON object, which stores metadata of its dashboard. Dashboard metadata includes dashboard properties, metadata from rows, panels, template variables, panel queries, etc.
|
||||
A dashboard in Grafana is represented by a JSON object, which stores metadata of its dashboard. Dashboard metadata includes dashboard properties, metadata from panels, template variables, panel queries, etc.
|
||||
|
||||
To view the JSON of a dashboard, follow the steps mentioned below:
|
||||
|
||||
@ -27,6 +27,7 @@ When a user creates a new dashboard, a new dashboard JSON object is initialized
|
||||
```json
|
||||
{
|
||||
"id": null,
|
||||
"uid": "cLV5GDCkz",
|
||||
"title": "New dashboard",
|
||||
"tags": [],
|
||||
"style": "dark",
|
||||
@ -34,7 +35,7 @@ When a user creates a new dashboard, a new dashboard JSON object is initialized
|
||||
"editable": true,
|
||||
"hideControls": false,
|
||||
"graphTooltip": 1,
|
||||
"rows": [],
|
||||
"panels": [],
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
@ -49,7 +50,7 @@ When a user creates a new dashboard, a new dashboard JSON object is initialized
|
||||
"annotations": {
|
||||
"list": []
|
||||
},
|
||||
"schemaVersion": 7,
|
||||
"schemaVersion": 16,
|
||||
"version": 0,
|
||||
"links": []
|
||||
}
|
||||
@ -58,224 +59,56 @@ Each field in the dashboard JSON is explained below with its usage:
|
||||
|
||||
| Name | Usage |
|
||||
| ---- | ----- |
|
||||
| **id** | unique dashboard id, an integer |
|
||||
| **id** | unique numeric identifier for the dashboard. (generated by the db) |
|
||||
| **uid** | unique dashboard identifier that can be generated by anyone. string (8-40) |
|
||||
| **title** | current title of dashboard |
|
||||
| **tags** | tags associated with dashboard, an array of strings |
|
||||
| **style** | theme of dashboard, i.e. `dark` or `light` |
|
||||
| **timezone** | timezone of dashboard, i.e. `utc` or `browser` |
|
||||
| **editable** | whether a dashboard is editable or not |
|
||||
| **hideControls** | whether row controls on the left in green are hidden or not |
|
||||
| **graphTooltip** | 0 for no shared crosshair or tooltip (default), 1 for shared crosshair, 2 for shared crosshair AND shared tooltip |
|
||||
| **rows** | row metadata, see [rows section](#rows) for details |
|
||||
| **time** | time range for dashboard, i.e. last 6 hours, last 7 days, etc |
|
||||
| **timepicker** | timepicker metadata, see [timepicker section](#timepicker) for details |
|
||||
| **templating** | templating metadata, see [templating section](#templating) for details |
|
||||
| **annotations** | annotations metadata, see [annotations section](#annotations) for details |
|
||||
| **schemaVersion** | TODO |
|
||||
| **version** | TODO |
|
||||
| **links** | TODO |
|
||||
| **schemaVersion** | version of the JSON schema (integer), incremented each time a Grafana update brings changes to the said schema |
|
||||
| **version** | version of the dashboard (integer), incremented each time the dashboard is updated |
|
||||
| **panels** | panels array, see below for detail. |
|
||||
|
||||
### rows
|
||||
## Panels
|
||||
|
||||
`rows` field consists of an array of JSON object representing each row in a dashboard, such as shown below:
|
||||
|
||||
```json
|
||||
"rows": [
|
||||
{
|
||||
"collapse": false,
|
||||
"editable": true,
|
||||
"height": "200px",
|
||||
"panels": [],
|
||||
"title": "New row"
|
||||
},
|
||||
{
|
||||
"collapse": true,
|
||||
"editable": true,
|
||||
"height": "300px",
|
||||
"panels": [],
|
||||
"title": "New row"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Usage of the fields is explained below:
|
||||
|
||||
| Name | Usage |
|
||||
| ---- | ----- |
|
||||
| **collapse** | whether row is collapsed or not |
|
||||
| **editable** | whether a row is editable or not |
|
||||
| **height** | height of the row in pixels |
|
||||
| **panels** | panels metadata, see [panels section](#panels) for details |
|
||||
| **title** | title of row |
|
||||
|
||||
#### panels
|
||||
|
||||
Panels are the building blocks a dashboard. It consists of datasource queries, type of graphs, aliases, etc. Panel JSON consists of an array of JSON objects, each representing a different panel in a row. Most of the fields are common for all panels but some fields depends on the panel type. Following is an example of panel JSON representing a `graph` panel type:
|
||||
Panels are the building blocks a dashboard. It consists of datasource queries, type of graphs, aliases, etc. Panel JSON consists of an array of JSON objects, each representing a different panel. Most of the fields are common for all panels but some fields depends on the panel type. Following is an example of panel JSON of a text panel.
|
||||
|
||||
```json
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"datasource": null,
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 0,
|
||||
"grid": {
|
||||
"leftLogBase": 1,
|
||||
"leftMax": null,
|
||||
"leftMin": null,
|
||||
"rightLogBase": 1,
|
||||
"rightMax": null,
|
||||
"rightMin": null,
|
||||
"threshold1": null,
|
||||
"threshold1Color": "rgba(216, 200, 27, 0.27)",
|
||||
"threshold2": null,
|
||||
"threshold2Color": "rgba(234, 112, 112, 0.22)"
|
||||
},
|
||||
"id": 1,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"span": 4,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"aggregator": "max",
|
||||
"alias": "$tag_instance_id",
|
||||
"currentTagKey": "",
|
||||
"currentTagValue": "",
|
||||
"downsampleAggregator": "avg",
|
||||
"downsampleInterval": "",
|
||||
"errors": {},
|
||||
"metric": "memory.percent-used",
|
||||
"refId": "A",
|
||||
"shouldComputeRate": false,
|
||||
"tags": {
|
||||
"app": "$app",
|
||||
"env": "stage",
|
||||
"instance_id": "*"
|
||||
}
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Memory Utilization",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"x-axis": true,
|
||||
"y-axis": true,
|
||||
"y_formats": [
|
||||
"percent",
|
||||
"short"
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"datasource": null,
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 0,
|
||||
"grid": {
|
||||
"leftLogBase": 1,
|
||||
"leftMax": null,
|
||||
"leftMin": null,
|
||||
"rightLogBase": 1,
|
||||
"rightMax": null,
|
||||
"rightMin": null,
|
||||
"threshold1": null,
|
||||
"threshold1Color": "rgba(216, 200, 27, 0.27)",
|
||||
"threshold2": null,
|
||||
"threshold2Color": "rgba(234, 112, 112, 0.22)"
|
||||
},
|
||||
"id": 2,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"span": 4,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"aggregator": "avg",
|
||||
"alias": "$tag_instance_id",
|
||||
"currentTagKey": "",
|
||||
"currentTagValue": "",
|
||||
"downsampleAggregator": "avg",
|
||||
"downsampleInterval": "",
|
||||
"errors": {},
|
||||
"metric": "memory.percent-cached",
|
||||
"refId": "A",
|
||||
"shouldComputeRate": false,
|
||||
"tags": {
|
||||
"app": "$app",
|
||||
"env": "prod",
|
||||
"instance_id": "*"
|
||||
}
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Memory Cached",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"x-axis": true,
|
||||
"y-axis": true,
|
||||
"y_formats": [
|
||||
"short",
|
||||
"short"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"title": "Panel Title",
|
||||
"gridPos": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 12,
|
||||
"h": 9
|
||||
},
|
||||
"id": 4,
|
||||
"mode": "markdown",
|
||||
"content": "# title"
|
||||
}
|
||||
```
|
||||
|
||||
Usage of each field is explained below:
|
||||
### Panel size & position
|
||||
|
||||
| Name | Usage |
|
||||
| ---- | ----- |
|
||||
| TODO | TODO |
|
||||
The gridPos property describes the panel size and position in grid coordinates.
|
||||
|
||||
- `w` 1-24 (the width of the dashboard is divided into 24 columns)
|
||||
- `h` In grid height units, each represents 30 pixels.
|
||||
- `x` The x position, in same unit as `w`.
|
||||
- `y` The y position, in same unit as `h`.
|
||||
|
||||
The grid has a negative gravity that moves panels up if there i empty space above a panel.
|
||||
|
||||
### timepicker
|
||||
|
||||
Description: TODO
|
||||
|
||||
```json
|
||||
"timepicker": {
|
||||
"collapse": false,
|
||||
@ -416,7 +249,3 @@ Usage of the above mentioned fields in the templating section is explained below
|
||||
| **refresh** | TODO |
|
||||
| **regex** | TODO |
|
||||
| **type** | type of variable, i.e. `custom`, `query` or `interval` |
|
||||
|
||||
### annotations
|
||||
|
||||
TODO
|
||||
|
52
docs/sources/reference/dashboard_folders.md
Normal file
52
docs/sources/reference/dashboard_folders.md
Normal file
@ -0,0 +1,52 @@
|
||||
+++
|
||||
title = "Dashboard Folders"
|
||||
keywords = ["grafana", "dashboard", "dashboard folders", "folder", "folders", "documentation", "guide"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Folders"
|
||||
parent = "dashboard_features"
|
||||
weight = 3
|
||||
+++
|
||||
|
||||
# Dashboard Folders
|
||||
|
||||
Folders are a way to organize and group dashboards - very useful if you have a lot of dashboards or multiple teams using the same Grafana instance.
|
||||
|
||||
## How To Create A Folder
|
||||
|
||||
- Create a folder by using the Create Folder link in the side menu (under the create menu (+ icon))
|
||||
- Use the create Folder button on the Manage Dashboards page.
|
||||
- When saving a dashboard, you can either choose a folder for the dashboard to be saved in or create a new folder
|
||||
|
||||
On the Create Folder page, fill in a unique name for the folder and press Create.
|
||||
|
||||
## Manage Dashboards
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v50/manage_dashboard_menu.png" max-width="300px" class="docs-image--right" >}}
|
||||
|
||||
There is a new Manage Dashboards page where you can carry out a variety of tasks:
|
||||
|
||||
- create a folder
|
||||
- create a dashboard
|
||||
- move dashboards into folders
|
||||
- delete multiple dashboards
|
||||
- navigate to a folder page (where you can set permissions for a folder and/or its dashboards)
|
||||
|
||||
## Dashboard Folder Page
|
||||
|
||||
You reach the dashboard folder page by clicking on the cog icon that appears when you hover
|
||||
over a folder in the dashboard list in the search result or on the Manage dashboards page.
|
||||
|
||||
The Dashboard Folder Page is similar to the Manage Dashboards page and is where you can carry out the following tasks:
|
||||
|
||||
- Allows you to move or delete dashboards in a folder.
|
||||
- Rename a folder (under the Settings tab).
|
||||
- Set permissions for the folder (inherited by dashboards in the folder).
|
||||
|
||||
## Permissions
|
||||
|
||||
Permissions can assigned to a folder and inherited by the containing dashboards. An Access Control List (ACL) is used where
|
||||
**Organization Role**, **Team** and Individual **User** can be assigned permissions. Read the
|
||||
[Dashboard & Folder Permissions]({{< relref "administration/permissions.md#dashboard-folder-permissions" >}}) docs for more detail
|
||||
on the permission system.
|
||||
|
@ -15,9 +15,9 @@ Grafana Dashboards can easily be exported and imported, either from the UI or fr
|
||||
|
||||
Dashboards are exported in Grafana JSON format, and contain everything you need (layout, variables, styles, data sources, queries, etc)to import the dashboard at a later time.
|
||||
|
||||
The export feature is accessed from the share menu.
|
||||
The export feature is accessed in the share window which you open by clicking the share button in the dashboard menu.
|
||||
|
||||
<img src="/img/docs/v31/export_menu.png">
|
||||
{{< docs-imagebox img="/img/docs/v50/export_modal.png" max-width="700px" >}}
|
||||
|
||||
### Making a dashboard portable
|
||||
|
||||
@ -31,12 +31,12 @@ the dashboard, and will also be added as an required input when the dashboard is
|
||||
|
||||
To import a dashboard open dashboard search and then hit the import button.
|
||||
|
||||
<img src="/img/docs/v31/import_step1.png">
|
||||
{{< docs-imagebox img="/img/docs/v50/import_step1.png" max-width="700px" >}}
|
||||
|
||||
From here you can upload a dashboard json file, paste a [Grafana.com](https://grafana.com) dashboard
|
||||
url or paste dashboard json text directly into the text area.
|
||||
|
||||
<img src="/img/docs/v31/import_step2.png">
|
||||
{{< docs-imagebox img="/img/docs/v50/import_step2.png" max-width="700px" >}}
|
||||
|
||||
In step 2 of the import process Grafana will let you change the name of the dashboard, pick what
|
||||
data source you want the dashboard to use and specify any metric prefixes (if the dashboard use any).
|
||||
@ -45,7 +45,7 @@ data source you want the dashboard to use and specify any metric prefixes (if th
|
||||
|
||||
Find dashboards for common server applications at [Grafana.com/dashboards](https://grafana.com/dashboards).
|
||||
|
||||
<img src="/img/docs/v31/gnet_dashboards_list.png">
|
||||
{{< docs-imagebox img="/img/docs/v50/gcom_dashboard_list.png" max-width="700px" >}}
|
||||
|
||||
## Import & Sharing with Grafana 2.x or 3.0
|
||||
|
||||
|
@ -16,7 +16,7 @@ Since Grafana automatically scales Dashboards to any resolution they're perfect
|
||||
|
||||
## Creating a Playlist
|
||||
|
||||
{{< docs-imagebox img="/img/docs/v3/playlist.png" max-width="25rem" class="docs-image--right">}}
|
||||
{{< docs-imagebox img="/img/docs/v50/playlist.png" max-width="25rem" class="docs-image--right">}}
|
||||
|
||||
The Playlist feature can be accessed from Grafana's sidemenu, in the Dashboard submenu.
|
||||
|
||||
|
@ -10,22 +10,22 @@ weight = 5
|
||||
|
||||
# Dashboard Search
|
||||
|
||||
Dashboards can be searched by the dashboard name, filtered by one (or many) tags or filtered by starred status. The dashboard search is accessed through the dashboard picker, available in the dashboard top nav area.
|
||||
Dashboards can be searched by the dashboard name, filtered by one (or many) tags or filtered by starred status. The dashboard search is accessed through the dashboard picker, available in the dashboard top nav area. The dashboard search can also be opened by using the shortcut `F`.
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v2/dashboard_search.png">
|
||||
<img class="no-shadow" src="/img/docs/v50/dashboard_search_annotated.png" width="700px">
|
||||
|
||||
1. `Dashboard Picker`: The Dashboard Picker is your primary navigation tool to move between dashboards. It is present on all dashboards, and open the Dashboard Search. The dashboard picker also doubles as the title of the current dashboard.
|
||||
2. `Search Bar`: The search bar allows you to enter any string and search both database and file based dashboards in real-time.
|
||||
3. `Starred`: The starred link allows you to filter the list to display only starred dashboards.
|
||||
4. `Tags`: The tags filter allows you to filter the list by dashboard tags.
|
||||
1. `Search Bar`: The search bar allows you to enter any string and search both database and file based dashboards in real-time.
|
||||
2. `Starred`: Here you find all your starred dashboards.
|
||||
3. `Recent`: Here you find the latest created dashboards.
|
||||
4. `Folders`: The tags filter allows you to filter the list by dashboard tags.
|
||||
5. `Root`: The root contains all dashboards that are not placed in a folder.
|
||||
6. `Tags`: The tags filter allows you to filter the list by dashboard tags.
|
||||
|
||||
When using only a keyboard, you can use your keyboard arrow keys to navigate the results, hit enter to open the selected dashboard.
|
||||
|
||||
## Find by dashboard name
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v2/dashboard_search_text.gif">
|
||||
|
||||
To search and load dashboards click the open folder icon in the header or use the shortcut `CTRL`+`F`. Begin typing any part of the desired dashboard names. Search will return results for for any partial string match in real-time, as you type.
|
||||
Begin typing any part of the desired dashboard names in the search bar. Search will return results for for any partial string match in real-time, as you type.
|
||||
|
||||
Dashboard search is:
|
||||
- Real-time
|
||||
@ -38,21 +38,8 @@ Tags are a great way to organize your dashboards, especially as the number of da
|
||||
|
||||
To filter the dashboard list by tag, click on any tag appearing in the right column. The list may be further filtered by clicking on additional tags:
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v2/dashboard_search_tag_filtering.gif">
|
||||
|
||||
Alternately, to see a list of all available tags, click the tags link in the search bar. All tags will be shown, and when a tag is selected, the dashboard search will be instantly filtered:
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v2/dashboard_search_tags_all_filtering.gif">
|
||||
Alternately, to see a list of all available tags, click the tags dropdown menu. All tags will be shown, and when a tag is selected, the dashboard search will be instantly filtered:
|
||||
|
||||
When using only a keyboard: `tab` to focus on the *tags* link, `▼` down arrow key to find a tag and select with the `Enter` key.
|
||||
|
||||
**Note**: When multiple tags are selected, Grafana will show dashboards that include **all**.
|
||||
|
||||
|
||||
## Filter by Starred
|
||||
|
||||
Starring is a great way to organize and find commonly used dashboards. To show only starred dashboards in the list, click the *starred* link in the search bar:
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v2/dashboard_search_starred_filtering.gif">
|
||||
|
||||
When using only a keyboard: `tab` to focus on the *stars* link, `▼` down arrow key to find a tag and select with the `Enter` key.
|
||||
**Note**: When multiple tags are selected, Grafana will show dashboards that include **all**.
|
@ -24,7 +24,7 @@ A dashboard snapshot is an instant way to share an interactive dashboard publicl
|
||||
(metric, template and annotation) and panel links, leaving only the visible metric data and series names embedded into your dashboard. Dashboard
|
||||
snapshots can be accessed by anyone who has the link and can reach the URL.
|
||||
|
||||

|
||||
{{< docs-imagebox img="/img/docs/v50/share_panel_modal.png" max-width="700px" >}}
|
||||
|
||||
### Publish snapshots
|
||||
|
||||
@ -39,7 +39,7 @@ Click a panel title to open the panel menu, then click share in the panel menu t
|
||||
|
||||
### Direct Link Rendered Image
|
||||
|
||||
You also get a link to service side rendered PNG of the panel. Useful if you want to share an image of the panel. Please note that for OSX and Windows, you will need to ensure that a `phantomjs` binary is available under `vendor/phantomjs/phantomjs`. For Linux, a `phantomjs` binary is included - however, you should ensure that any requisite libraries (e.g. libfontconfig) are available.
|
||||
You also get a link to service side rendered PNG of the panel. Useful if you want to share an image of the panel. Please note that for OSX and Windows, you will need to ensure that a `phantomjs` binary is available under `tools/phantomjs/phantomjs`. For Linux, a `phantomjs` binary is included - however, you should ensure that any requisite libraries (e.g. libfontconfig) are available.
|
||||
|
||||
Example of a link to a server-side rendered PNG:
|
||||
|
||||
@ -70,9 +70,9 @@ Below there should be an interactive Grafana graph embedded in an iframe:
|
||||
|
||||
### Export Panel Data
|
||||
|
||||

|
||||
{{< docs-imagebox img="/img/docs/v50/export_panel_data.png" max-width="500px" >}}
|
||||
|
||||
The submenu for a panel can be found by clicking on the title of a panel and then on the hamburger (three horizontal lines) submenu on the left of the context menu.
|
||||
The submenu for a panel can be found by clicking on the title of a panel and then on the More submenu.
|
||||
|
||||
This menu contains two options for exporting data:
|
||||
|
||||
|
@ -1,20 +1,20 @@
|
||||
+++
|
||||
title = "Templating"
|
||||
title = "Variables"
|
||||
keywords = ["grafana", "templating", "documentation", "guide"]
|
||||
type = "docs"
|
||||
[menu.docs]
|
||||
name = "Templating"
|
||||
name = "Variables"
|
||||
parent = "dashboard_features"
|
||||
weight = 1
|
||||
+++
|
||||
|
||||
# Templating
|
||||
# Variables
|
||||
|
||||
Templating allows for more interactive and dynamic dashboards. Instead of hard-coding things like server, application
|
||||
Variables allows for more interactive and dynamic dashboards. Instead of hard-coding things like server, application
|
||||
and sensor name in you metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of
|
||||
the dashboard. These dropdowns make it easy to change the data being displayed in your dashboard.
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v4/templated_dash.png">
|
||||
{{< docs-imagebox img="/img/docs/v50/variables_dashboard.png" >}}
|
||||
|
||||
## What is a variable?
|
||||
|
||||
@ -43,7 +43,7 @@ is the set of values you can choose from.
|
||||
|
||||
## Adding a variable
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v4/templating_var_list.png">
|
||||
{{< docs-imagebox img="/img/docs/v50/variables_var_list.png" max-width="800px" >}}
|
||||
|
||||
You add variables via Dashboard cogs menu > Templating. This opens up a list of variables and a `New` button to create a new variable.
|
||||
|
||||
@ -133,7 +133,7 @@ Option | Description
|
||||
*Tags query* | Data source query that should return a list of tags
|
||||
*Tag values query* | Data source query that should return a list of values for a specified tag key. Use `$tag` in the query to refer the currently selected tag.
|
||||
|
||||

|
||||
{{< docs-imagebox img="/img/docs/v50/variable_dropdown_tags.png" max-width="300px" >}}
|
||||
|
||||
### Interval variables
|
||||
|
||||
|
@ -13,7 +13,7 @@ weight = 7
|
||||
|
||||
Grafana provides numerous ways to manage the time ranges of the data being visualized, both at the Dashboard-level and the Panel-level.
|
||||
|
||||
<img class="no-shadow" src="/img/docs/whatsnew_2_5/timepicker.png">
|
||||
<img class="no-shadow" src="/img/docs/v50/timepicker.png" width="700px">
|
||||
|
||||
In the top right, you have the master Dashboard time picker (it's in between the 'Zoom out' and the 'Refresh' links).
|
||||
|
||||
@ -39,11 +39,11 @@ Week to date | `now/w` | `now`
|
||||
Previous Month | `now-1M/M` | `now-1M/M`
|
||||
|
||||
|
||||
## Dashboard-Level Time Picker Settings
|
||||
## Dashboard Time Options
|
||||
|
||||
There are two settings available from the Dashboard Settings area, allowing customization of the auto-refresh intervals and the definition of `now`.
|
||||
There are two settings available in the Dashboard Settings General tab, allowing customization of the auto-refresh intervals and the definition of `now`.
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v2/TimePicker-TimeOptions.png">
|
||||
<img class="no-shadow" src="/img/docs/v50/time_options.png" width="500px">
|
||||
|
||||
### Auto-Refresh Options
|
||||
|
||||
@ -59,11 +59,11 @@ Users often ask, [when will then be now](https://www.youtube.com/watch?v=VeZ9HhH
|
||||
|
||||
You can override the relative time range for individual panels, causing them to be different than what is selected in the Dashboard time picker in the upper right. This allows you to show metrics from different time periods or days at the same time.
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v2/panel_time_override.jpg">
|
||||
{{< docs-imagebox img="/img/docs/v50/panel_time_override.png" max-width="500px" >}}
|
||||
|
||||
You control these overrides in panel editor mode and the tab `Time Range`.
|
||||
|
||||
<img class="no-shadow" src="/img/docs/v2/time_range_tab.jpg">
|
||||
{{< docs-imagebox img="/img/docs/v50/time_range_tab.png" max-width="500px" >}}
|
||||
|
||||
When you zoom or change the Dashboard time to a custom absolute time range, all panel overrides will be disabled. The panel relative time override is only active when the dashboard time is also relative. The panel timeshift override is always active, even when the dashboard time is absolute.
|
||||
|
||||
|
89
docs/sources/tutorials/iis.md
Normal file
89
docs/sources/tutorials/iis.md
Normal file
@ -0,0 +1,89 @@
|
||||
+++
|
||||
title = "Grafana with IIS Reverse Proxy on Windows"
|
||||
type = "docs"
|
||||
keywords = ["grafana", "tutorials", "proxy", "IIS", "windows"]
|
||||
[menu.docs]
|
||||
parent = "tutorials"
|
||||
weight = 10
|
||||
+++
|
||||
|
||||
# How to Use IIS with URL Rewrite as a Reverse Proxy for Grafana on Windows
|
||||
|
||||
If you want Grafana to be a subpath or subfolder under a website in IIS then the URL Rewrite module for ISS can be used to support this.
|
||||
|
||||
Example:
|
||||
|
||||
- Parent site: http://localhost:8080
|
||||
- Grafana: http://localhost:3000
|
||||
|
||||
Grafana as a subpath: http://localhost:8080/grafana
|
||||
|
||||
## Setup
|
||||
|
||||
If you have not already done it, then a requirement is to install URL Rewrite module for IIS.
|
||||
|
||||
Download and install the URL Rewrite module for IIS: https://www.iis.net/downloads/microsoft/url-rewrite
|
||||
|
||||
## Grafana Config
|
||||
|
||||
The Grafana config can be set by creating a file named `custom.ini` in the `conf` subdirectory of your Grafana installation. See the [installation instructions](http://docs.grafana.org/installation/windows/#configure) for more details.
|
||||
|
||||
Given that the subpath should be `grafana` and the parent site is `localhost:8080` then add this to the `custom.ini` config file:
|
||||
|
||||
```bash
|
||||
[server]
|
||||
domain = localhost:8080
|
||||
root_url = %(protocol)s://%(domain)s:/grafana
|
||||
```
|
||||
|
||||
Restart the Grafana server after changing the config file.
|
||||
|
||||
## IIS Config
|
||||
|
||||
1. Open the IIS Manager and click on the parent website
|
||||
2. In the admin console for this website, double click on the Url Rewrite option:
|
||||
{{< docs-imagebox img="/img/docs/tutorials/IIS_admin_console.png" max-width= "800px" >}}
|
||||
|
||||
3. Click on the `Add Rule(s)...` action
|
||||
4. Choose the Blank Rule template for an Inbound Rule
|
||||
{{< docs-imagebox img="/img/docs/tutorials/IIS_add_inbound_rule.png" max-width= "800px" >}}
|
||||
|
||||
5. Create an Inbound Rule for the parent website (localhost:8080 in this example) with the following settings:
|
||||
- pattern: `grafana(/)?(.*)`
|
||||
- check the `Ignore case` checkbox
|
||||
- rewrite url set to `http://localhost:3000/{R:2}`
|
||||
- check the `Append query string` checkbox
|
||||
- check the `Stop processing of subsequent rules` checkbox
|
||||
|
||||
{{< docs-imagebox img="/img/docs/tutorials/IIS_url_rewrite.png" max-width= "800px" >}}
|
||||
|
||||
Finally, navigate to `http://localhost:8080/grafana` (replace `http://localhost:8080` with your parent domain) and you should come to the Grafana login page.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### 404 error
|
||||
|
||||
When navigating to the grafana url (`http://localhost:8080/grafana` in the example above) and a `HTTP Error 404.0 - Not Found` error is returned then either:
|
||||
|
||||
- the pattern for the Inbound Rule is incorrect. Edit the rule, click on the `Test pattern...` button, test the part of the url after `http://localhost:8080/` and make sure it matches. For `grafana/login` the test should return 3 capture groups: {R:0}: `grafana` {R:1}: `/` and {R:2}: `login`.
|
||||
- The `root_url` setting in the Grafana config file does not match the parent url with subpath.
|
||||
|
||||
### Grafana Website only shows text with no images or css
|
||||
|
||||
{{< docs-imagebox img="/img/docs/tutorials/IIS_proxy_error.png" max-width= "800px" >}}
|
||||
|
||||
1. The `root_url` setting in the Grafana config file does not match the parent url with subpath. This could happen if the root_url is commented out by mistake (`;` is used for commenting out a line in .ini files):
|
||||
|
||||
`; root_url = %(protocol)s://%(domain)s:/grafana`
|
||||
|
||||
2. or if the subpath in the `root_url` setting does not match the subpath used in the pattern in the Inbound Rule in IIS:
|
||||
|
||||
`root_url = %(protocol)s://%(domain)s:/grafana`
|
||||
|
||||
pattern in Inbound Rule: `wrongsubpath(/)?(.*)`
|
||||
|
||||
3. or if the Rewrite Url in the Inbound Rule is incorrect.
|
||||
|
||||
The Rewrite Url should not include the subpath.
|
||||
|
||||
The Rewrite Url should contain the capture group from the pattern matching that returns the part of the url after the subpath. The pattern used above returns 3 capture groups and the third one {R:2} returns the part of the url after `http://localhost:8080/grafana/`.
|
@ -3,7 +3,7 @@ title = "What's New in Grafana"
|
||||
[menu.docs]
|
||||
name = "What's New In Grafana"
|
||||
identifier = "whatsnew"
|
||||
weight = 2
|
||||
weight = 3
|
||||
+++
|
||||
|
||||
|
9
docs/versions.json
Normal file
9
docs/versions.json
Normal file
@ -0,0 +1,9 @@
|
||||
[
|
||||
{ "version": "v5.0", "path": "/", "archived": false, "current": true },
|
||||
{ "version": "v4.6", "path": "/v4.6", "archived": true },
|
||||
{ "version": "v4.5", "path": "/v4.5", "archived": true },
|
||||
{ "version": "v4.4", "path": "/v4.4", "archived": true },
|
||||
{ "version": "v4.3", "path": "/v4.3", "archived": true },
|
||||
{ "version": "v4.1", "path": "/v4.1", "archived": true },
|
||||
{ "version": "v3.1", "path": "/v3.1", "archived": true }
|
||||
]
|
@ -1,6 +1,6 @@
|
||||
|
||||
module.exports = {
|
||||
verbose: true,
|
||||
verbose: false,
|
||||
"globals": {
|
||||
"ts-jest": {
|
||||
"tsConfigFile": "tsconfig.json"
|
||||
@ -24,5 +24,6 @@ module.exports = {
|
||||
"setupFiles": [
|
||||
"./public/test/jest-shim.ts",
|
||||
"./public/test/jest-setup.ts"
|
||||
]
|
||||
],
|
||||
"snapshotSerializers": ["enzyme-to-json/serializer"],
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"stable": "4.6.2",
|
||||
"testing": "4.6.2"
|
||||
"stable": "5.0.0",
|
||||
"testing": "5.0.0"
|
||||
}
|
||||
|
75
package.json
75
package.json
@ -4,7 +4,7 @@
|
||||
"company": "Grafana Labs"
|
||||
},
|
||||
"name": "grafana",
|
||||
"version": "4.7.0-pre1",
|
||||
"version": "5.0.1-pre1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/grafana/grafana.git"
|
||||
@ -14,17 +14,19 @@
|
||||
"@types/enzyme": "^2.8.9",
|
||||
"@types/jest": "^21.1.4",
|
||||
"@types/node": "^8.0.31",
|
||||
"@types/react": "^16.0.5",
|
||||
"@types/react-dom": "^15.5.4",
|
||||
"@types/react": "^16.0.25",
|
||||
"@types/react-dom": "^16.0.3",
|
||||
"angular-mocks": "^1.6.6",
|
||||
"autoprefixer": "^6.4.0",
|
||||
"awesome-typescript-loader": "^3.2.3",
|
||||
"axios": "^0.17.1",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"css-loader": "^0.28.7",
|
||||
"enzyme": "^3.1.0",
|
||||
"enzyme-adapter-react-16": "^1.0.1",
|
||||
"enzyme-to-json": "^3.3.0",
|
||||
"es6-promise": "^3.0.2",
|
||||
"es6-shim": "^0.35.3",
|
||||
"expect.js": "~0.2.0",
|
||||
@ -54,7 +56,7 @@
|
||||
"html-loader": "^0.5.1",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"husky": "^0.14.3",
|
||||
"jest": "^21.2.1",
|
||||
"jest": "^22.0.4",
|
||||
"jshint-stylish": "~2.2.1",
|
||||
"json-loader": "^0.5.7",
|
||||
"karma": "1.7.0",
|
||||
@ -65,8 +67,9 @@
|
||||
"karma-sinon": "^1.0.5",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-webpack": "^2.0.4",
|
||||
"lint-staged": "^4.2.3",
|
||||
"lint-staged": "^6.0.0",
|
||||
"load-grunt-tasks": "3.5.2",
|
||||
"mobx-react-devtools": "^4.2.15",
|
||||
"mocha": "^4.0.1",
|
||||
"ng-annotate-loader": "^0.6.1",
|
||||
"ng-annotate-webpack-plugin": "^0.2.1-pre",
|
||||
@ -76,19 +79,19 @@
|
||||
"postcss-browser-reporter": "^0.5.0",
|
||||
"postcss-loader": "^2.0.6",
|
||||
"postcss-reporter": "^5.0.0",
|
||||
"prettier": "1.7.3",
|
||||
"prettier": "1.9.2",
|
||||
"react-test-renderer": "^16.0.0",
|
||||
"sass-lint": "^1.10.2",
|
||||
"sass-loader": "^6.0.6",
|
||||
"sinon": "1.17.6",
|
||||
"systemjs": "0.20.19",
|
||||
"systemjs-plugin-css": "^0.1.36",
|
||||
"ts-jest": "^21.1.3",
|
||||
"ts-loader": "^2.3.7",
|
||||
"tslint": "^5.7.0",
|
||||
"ts-jest": "^22.0.0",
|
||||
"ts-loader": "^3.2.0",
|
||||
"tslint": "^5.8.0",
|
||||
"tslint-loader": "^3.5.3",
|
||||
"typescript": "^2.5.2",
|
||||
"webpack": "^3.6.0",
|
||||
"typescript": "^2.6.2",
|
||||
"webpack": "^3.10.0",
|
||||
"webpack-bundle-analyzer": "^2.9.0",
|
||||
"webpack-cleanup-plugin": "^0.5.1",
|
||||
"webpack-merge": "^4.1.0",
|
||||
@ -103,34 +106,66 @@
|
||||
"lint": "tslint -c tslint.json --project tsconfig.json --type-check",
|
||||
"karma": "node ./node_modules/grunt-cli/bin/grunt karma:dev",
|
||||
"jest": "node ./node_modules/jest-cli/bin/jest.js --notify --watch",
|
||||
"precommit": "node ./node_modules/grunt-cli/bin/grunt precommit"
|
||||
"api-tests": "node ./node_modules/jest-cli/bin/jest.js --notify --watch --config=tests/api/jest.js",
|
||||
"precommit": "lint-staged && node ./node_modules/grunt-cli/bin/grunt precommit"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
],
|
||||
"*.scss": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
],
|
||||
"*.go": [
|
||||
"gofmt -w -s",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"prettier": {
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": true,
|
||||
"printWidth": 120
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"angular": "^1.6.6",
|
||||
"angular-bindonce": "^0.3.1",
|
||||
"angular-mocks": "^1.6.6",
|
||||
"angular-native-dragdrop": "^1.2.2",
|
||||
"angular-route": "^1.6.6",
|
||||
"angular-sanitize": "^1.6.6",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"brace": "^0.10.0",
|
||||
"classnames": "^2.2.5",
|
||||
"clipboard": "^1.7.1",
|
||||
"d3": "^4.11.0",
|
||||
"d3-scale-chromatic": "^1.1.1",
|
||||
"eventemitter3": "^2.0.3",
|
||||
"file-saver": "^1.3.3",
|
||||
"jquery": "^3.2.1",
|
||||
"lodash": "^4.17.4",
|
||||
"mobx": "^3.4.1",
|
||||
"mobx-react": "^4.3.5",
|
||||
"mobx-state-tree": "^1.3.1",
|
||||
"moment": "^2.18.1",
|
||||
"mousetrap": "^1.6.0",
|
||||
"ngreact": "^0.4.1",
|
||||
"react": "^16.0.0",
|
||||
"react-dom": "^16.0.0",
|
||||
"mousetrap-global-bind": "^1.1.0",
|
||||
"perfect-scrollbar": "^1.2.0",
|
||||
"prop-types": "^15.6.0",
|
||||
"react": "^16.2.0",
|
||||
"react-dom": "^16.2.0",
|
||||
"react-grid-layout-grafana": "0.16.0",
|
||||
"react-highlight-words": "^0.10.0",
|
||||
"react-popper": "^0.7.5",
|
||||
"react-select": "^1.1.0",
|
||||
"react-sizeme": "^2.3.6",
|
||||
"react-transition-group": "^2.2.1",
|
||||
"remarkable": "^1.7.1",
|
||||
"rst2html": "github:thoward/rst2html#990cb89",
|
||||
"rxjs": "^5.4.3",
|
||||
"tether": "^1.4.0",
|
||||
"tether-drop": "https://github.com/torkelo/drop",
|
||||
"tinycolor2": "^1.4.1",
|
||||
"d3": "^4.11.0",
|
||||
"d3-scale-chromatic": "^1.1.1"
|
||||
"tether-drop": "https://github.com/torkelo/drop/tarball/master",
|
||||
"tinycolor2": "^1.4.1"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#! /usr/bin/env bash
|
||||
version=4.6.2
|
||||
version=4.6.3
|
||||
|
||||
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_${version}_amd64.deb
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#! /usr/bin/env bash
|
||||
deb_ver=4.6.0-beta1
|
||||
rpm_ver=4.6.0-beta1
|
||||
deb_ver=5.0.0-beta5
|
||||
rpm_ver=5.0.0-beta5
|
||||
|
||||
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_${deb_ver}_amd64.deb
|
||||
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
)
|
||||
|
||||
func ValidateOrgAlert(c *middleware.Context) {
|
||||
@ -51,6 +52,7 @@ func GetAlerts(c *middleware.Context) Response {
|
||||
DashboardId: c.QueryInt64("dashboardId"),
|
||||
PanelId: c.QueryInt64("panelId"),
|
||||
Limit: c.QueryInt64("limit"),
|
||||
User: c.SignedInUser,
|
||||
}
|
||||
|
||||
states := c.QueryStrings("state")
|
||||
@ -62,43 +64,11 @@ func GetAlerts(c *middleware.Context) Response {
|
||||
return ApiError(500, "List alerts failed", err)
|
||||
}
|
||||
|
||||
dashboardIds := make([]int64, 0)
|
||||
alertDTOs := make([]*dtos.AlertRule, 0)
|
||||
for _, alert := range query.Result {
|
||||
dashboardIds = append(dashboardIds, alert.DashboardId)
|
||||
alertDTOs = append(alertDTOs, &dtos.AlertRule{
|
||||
Id: alert.Id,
|
||||
DashboardId: alert.DashboardId,
|
||||
PanelId: alert.PanelId,
|
||||
Name: alert.Name,
|
||||
Message: alert.Message,
|
||||
State: alert.State,
|
||||
NewStateDate: alert.NewStateDate,
|
||||
ExecutionError: alert.ExecutionError,
|
||||
EvalData: alert.EvalData,
|
||||
})
|
||||
alert.Url = models.GetDashboardUrl(alert.DashboardUid, alert.DashboardSlug)
|
||||
}
|
||||
|
||||
dashboardsQuery := models.GetDashboardsQuery{
|
||||
DashboardIds: dashboardIds,
|
||||
}
|
||||
|
||||
if len(alertDTOs) > 0 {
|
||||
if err := bus.Dispatch(&dashboardsQuery); err != nil {
|
||||
return ApiError(500, "List alerts failed", err)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: should be possible to speed this up with lookup table
|
||||
for _, alert := range alertDTOs {
|
||||
for _, dash := range dashboardsQuery.Result {
|
||||
if alert.DashboardId == dash.Id {
|
||||
alert.DashbboardUri = "db/" + dash.Slug
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Json(200, alertDTOs)
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
// POST /api/alerts/test
|
||||
@ -155,24 +125,6 @@ func GetAlert(c *middleware.Context) Response {
|
||||
return Json(200, &query.Result)
|
||||
}
|
||||
|
||||
// DEL /api/alerts/:id
|
||||
func DelAlert(c *middleware.Context) Response {
|
||||
alertId := c.ParamsInt64(":alertId")
|
||||
|
||||
if alertId == 0 {
|
||||
return ApiError(401, "Failed to parse alertid", nil)
|
||||
}
|
||||
|
||||
cmd := models.DeleteAlertCommand{AlertId: alertId}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return ApiError(500, "Failed to delete alert", err)
|
||||
}
|
||||
|
||||
var resp = map[string]interface{}{"alertId": alertId}
|
||||
return Json(200, resp)
|
||||
}
|
||||
|
||||
func GetAlertNotifiers(c *middleware.Context) Response {
|
||||
return Json(200, alerting.GetNotifiers())
|
||||
}
|
||||
@ -267,6 +219,22 @@ func NotificationTest(c *middleware.Context, dto dtos.NotificationTestCommand) R
|
||||
//POST /api/alerts/:alertId/pause
|
||||
func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
|
||||
alertId := c.ParamsInt64("alertId")
|
||||
|
||||
query := models.GetAlertByIdQuery{Id: alertId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Get Alert failed", err)
|
||||
}
|
||||
|
||||
guardian := guardian.New(query.Result.DashboardId, c.OrgId, c.SignedInUser)
|
||||
if canEdit, err := guardian.CanEdit(); err != nil || !canEdit {
|
||||
if err != nil {
|
||||
return ApiError(500, "Error while checking permissions for Alert", err)
|
||||
}
|
||||
|
||||
return ApiError(403, "Access denied to this dashboard and alert", nil)
|
||||
}
|
||||
|
||||
cmd := models.PauseAlertCommand{
|
||||
OrgId: c.OrgId,
|
||||
AlertIds: []int64{alertId},
|
||||
@ -278,7 +246,7 @@ func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
|
||||
}
|
||||
|
||||
var response models.AlertStateType = models.AlertStatePending
|
||||
pausedState := "un paused"
|
||||
pausedState := "un-paused"
|
||||
if cmd.Paused {
|
||||
response = models.AlertStatePaused
|
||||
pausedState = "paused"
|
||||
@ -287,7 +255,7 @@ func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
|
||||
result := map[string]interface{}{
|
||||
"alertId": alertId,
|
||||
"state": response,
|
||||
"message": "alert " + pausedState,
|
||||
"message": "Alert " + pausedState,
|
||||
}
|
||||
|
||||
return Json(200, result)
|
||||
|
97
pkg/api/alerting_test.go
Normal file
97
pkg/api/alerting_test.go
Normal file
@ -0,0 +1,97 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestAlertingApiEndpoint(t *testing.T) {
|
||||
Convey("Given an alert in a dashboard with an acl", t, func() {
|
||||
|
||||
singleAlert := &m.Alert{Id: 1, DashboardId: 1, Name: "singlealert"}
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetAlertByIdQuery) error {
|
||||
query.Result = singleAlert
|
||||
return nil
|
||||
})
|
||||
|
||||
viewerRole := m.ROLE_VIEWER
|
||||
editorRole := m.ROLE_EDITOR
|
||||
|
||||
aclMockResp := []*m.DashboardAclInfoDTO{}
|
||||
bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
|
||||
query.Result = aclMockResp
|
||||
return nil
|
||||
})
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
|
||||
query.Result = []*m.Team{}
|
||||
return nil
|
||||
})
|
||||
|
||||
Convey("When user is editor and not in the ACL", func() {
|
||||
Convey("Should not be able to pause the alert", func() {
|
||||
cmd := dtos.PauseAlertCommand{
|
||||
AlertId: 1,
|
||||
Paused: true,
|
||||
}
|
||||
postAlertScenario("When calling POST on", "/api/alerts/1/pause", "/api/alerts/:alertId/pause", m.ROLE_EDITOR, cmd, func(sc *scenarioContext) {
|
||||
CallPauseAlert(sc)
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When user is editor and dashboard has default ACL", func() {
|
||||
aclMockResp = []*m.DashboardAclInfoDTO{
|
||||
{Role: &viewerRole, Permission: m.PERMISSION_VIEW},
|
||||
{Role: &editorRole, Permission: m.PERMISSION_EDIT},
|
||||
}
|
||||
|
||||
Convey("Should be able to pause the alert", func() {
|
||||
cmd := dtos.PauseAlertCommand{
|
||||
AlertId: 1,
|
||||
Paused: true,
|
||||
}
|
||||
postAlertScenario("When calling POST on", "/api/alerts/1/pause", "/api/alerts/:alertId/pause", m.ROLE_EDITOR, cmd, func(sc *scenarioContext) {
|
||||
CallPauseAlert(sc)
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func CallPauseAlert(sc *scenarioContext) {
|
||||
bus.AddHandler("test", func(cmd *m.PauseAlertCommand) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
}
|
||||
|
||||
func postAlertScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.PauseAlertCommand, fn scenarioFunc) {
|
||||
Convey(desc+" "+url, func() {
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(url)
|
||||
sc.defaultHandler = wrap(func(c *middleware.Context) Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = TestUserID
|
||||
sc.context.OrgId = TestOrgID
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return PauseAlert(c, cmd)
|
||||
})
|
||||
|
||||
sc.m.Post(routePattern, sc.defaultHandler)
|
||||
|
||||
fn(sc)
|
||||
})
|
||||
}
|
@ -7,7 +7,9 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/annotations"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
@ -51,6 +53,10 @@ func (e *CreateAnnotationError) Error() string {
|
||||
}
|
||||
|
||||
func PostAnnotation(c *middleware.Context, cmd dtos.PostAnnotationsCmd) Response {
|
||||
if canSave, err := canSaveByDashboardId(c, cmd.DashboardId); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
repo := annotations.GetRepository()
|
||||
|
||||
if cmd.Text == "" {
|
||||
@ -178,6 +184,10 @@ func UpdateAnnotation(c *middleware.Context, cmd dtos.UpdateAnnotationsCmd) Resp
|
||||
|
||||
repo := annotations.GetRepository()
|
||||
|
||||
if resp := canSave(c, repo, annotationId); resp != nil {
|
||||
return resp
|
||||
}
|
||||
|
||||
item := annotations.Item{
|
||||
OrgId: c.OrgId,
|
||||
UserId: c.UserId,
|
||||
@ -228,6 +238,10 @@ func DeleteAnnotationById(c *middleware.Context) Response {
|
||||
repo := annotations.GetRepository()
|
||||
annotationId := c.ParamsInt64(":annotationId")
|
||||
|
||||
if resp := canSave(c, repo, annotationId); resp != nil {
|
||||
return resp
|
||||
}
|
||||
|
||||
err := repo.Delete(&annotations.DeleteParams{
|
||||
Id: annotationId,
|
||||
})
|
||||
@ -243,6 +257,10 @@ func DeleteAnnotationRegion(c *middleware.Context) Response {
|
||||
repo := annotations.GetRepository()
|
||||
regionId := c.ParamsInt64(":regionId")
|
||||
|
||||
if resp := canSave(c, repo, regionId); resp != nil {
|
||||
return resp
|
||||
}
|
||||
|
||||
err := repo.Delete(&annotations.DeleteParams{
|
||||
RegionId: regionId,
|
||||
})
|
||||
@ -253,3 +271,50 @@ func DeleteAnnotationRegion(c *middleware.Context) Response {
|
||||
|
||||
return ApiSuccess("Annotation region deleted")
|
||||
}
|
||||
|
||||
func canSaveByDashboardId(c *middleware.Context, dashboardId int64) (bool, error) {
|
||||
if dashboardId == 0 && !c.SignedInUser.HasRole(m.ROLE_EDITOR) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if dashboardId > 0 {
|
||||
guardian := guardian.New(dashboardId, c.OrgId, c.SignedInUser)
|
||||
if canEdit, err := guardian.CanEdit(); err != nil || !canEdit {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func canSave(c *middleware.Context, repo annotations.Repository, annotationId int64) Response {
|
||||
items, err := repo.Find(&annotations.ItemQuery{AnnotationId: annotationId, OrgId: c.OrgId})
|
||||
|
||||
if err != nil || len(items) == 0 {
|
||||
return ApiError(500, "Could not find annotation to update", err)
|
||||
}
|
||||
|
||||
dashboardId := items[0].DashboardId
|
||||
|
||||
if canSave, err := canSaveByDashboardId(c, dashboardId); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func canSaveByRegionId(c *middleware.Context, repo annotations.Repository, regionId int64) Response {
|
||||
items, err := repo.Find(&annotations.ItemQuery{RegionId: regionId, OrgId: c.OrgId})
|
||||
|
||||
if err != nil || len(items) == 0 {
|
||||
return ApiError(500, "Could not find annotation to update", err)
|
||||
}
|
||||
|
||||
dashboardId := items[0].DashboardId
|
||||
|
||||
if canSave, err := canSaveByDashboardId(c, dashboardId); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
242
pkg/api/annotations_test.go
Normal file
242
pkg/api/annotations_test.go
Normal file
@ -0,0 +1,242 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/annotations"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestAnnotationsApiEndpoint(t *testing.T) {
|
||||
Convey("Given an annotation without a dashboard id", t, func() {
|
||||
cmd := dtos.PostAnnotationsCmd{
|
||||
Time: 1000,
|
||||
Text: "annotation text",
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
IsRegion: false,
|
||||
}
|
||||
|
||||
updateCmd := dtos.UpdateAnnotationsCmd{
|
||||
Time: 1000,
|
||||
Text: "annotation text",
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
IsRegion: false,
|
||||
}
|
||||
|
||||
Convey("When user is an Org Viewer", func() {
|
||||
role := m.ROLE_VIEWER
|
||||
Convey("Should not be allowed to save an annotation", func() {
|
||||
postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
|
||||
putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
|
||||
sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
|
||||
sc.handlerFunc = DeleteAnnotationById
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
|
||||
sc.handlerFunc = DeleteAnnotationRegion
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When user is an Org Editor", func() {
|
||||
role := m.ROLE_EDITOR
|
||||
Convey("Should be able to save an annotation", func() {
|
||||
postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
|
||||
putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
|
||||
sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
|
||||
sc.handlerFunc = DeleteAnnotationById
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
|
||||
sc.handlerFunc = DeleteAnnotationRegion
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Given an annotation with a dashboard id and the dashboard does not have an acl", t, func() {
|
||||
cmd := dtos.PostAnnotationsCmd{
|
||||
Time: 1000,
|
||||
Text: "annotation text",
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
IsRegion: false,
|
||||
DashboardId: 1,
|
||||
PanelId: 1,
|
||||
}
|
||||
|
||||
updateCmd := dtos.UpdateAnnotationsCmd{
|
||||
Time: 1000,
|
||||
Text: "annotation text",
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
IsRegion: false,
|
||||
Id: 1,
|
||||
}
|
||||
|
||||
viewerRole := m.ROLE_VIEWER
|
||||
editorRole := m.ROLE_EDITOR
|
||||
|
||||
aclMockResp := []*m.DashboardAclInfoDTO{
|
||||
{Role: &viewerRole, Permission: m.PERMISSION_VIEW},
|
||||
{Role: &editorRole, Permission: m.PERMISSION_EDIT},
|
||||
}
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
|
||||
query.Result = aclMockResp
|
||||
return nil
|
||||
})
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
|
||||
query.Result = []*m.Team{}
|
||||
return nil
|
||||
})
|
||||
|
||||
Convey("When user is an Org Viewer", func() {
|
||||
role := m.ROLE_VIEWER
|
||||
Convey("Should not be allowed to save an annotation", func() {
|
||||
postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
|
||||
putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
|
||||
sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
|
||||
sc.handlerFunc = DeleteAnnotationById
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
|
||||
sc.handlerFunc = DeleteAnnotationRegion
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When user is an Org Editor", func() {
|
||||
role := m.ROLE_EDITOR
|
||||
Convey("Should be able to save an annotation", func() {
|
||||
postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
|
||||
putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
|
||||
sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
|
||||
sc.handlerFunc = DeleteAnnotationById
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
|
||||
sc.handlerFunc = DeleteAnnotationRegion
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
type fakeAnnotationsRepo struct {
|
||||
}
|
||||
|
||||
func (repo *fakeAnnotationsRepo) Delete(params *annotations.DeleteParams) error {
|
||||
return nil
|
||||
}
|
||||
func (repo *fakeAnnotationsRepo) Save(item *annotations.Item) error {
|
||||
item.Id = 1
|
||||
return nil
|
||||
}
|
||||
func (repo *fakeAnnotationsRepo) Update(item *annotations.Item) error {
|
||||
return nil
|
||||
}
|
||||
func (repo *fakeAnnotationsRepo) Find(query *annotations.ItemQuery) ([]*annotations.ItemDTO, error) {
|
||||
annotations := []*annotations.ItemDTO{{Id: 1}}
|
||||
return annotations, nil
|
||||
}
|
||||
|
||||
var fakeAnnoRepo *fakeAnnotationsRepo
|
||||
|
||||
func postAnnotationScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.PostAnnotationsCmd, fn scenarioFunc) {
|
||||
Convey(desc+" "+url, func() {
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(url)
|
||||
sc.defaultHandler = wrap(func(c *middleware.Context) Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = TestUserID
|
||||
sc.context.OrgId = TestOrgID
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return PostAnnotation(c, cmd)
|
||||
})
|
||||
|
||||
fakeAnnoRepo = &fakeAnnotationsRepo{}
|
||||
annotations.SetRepository(fakeAnnoRepo)
|
||||
|
||||
sc.m.Post(routePattern, sc.defaultHandler)
|
||||
|
||||
fn(sc)
|
||||
})
|
||||
}
|
||||
|
||||
func putAnnotationScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.UpdateAnnotationsCmd, fn scenarioFunc) {
|
||||
Convey(desc+" "+url, func() {
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(url)
|
||||
sc.defaultHandler = wrap(func(c *middleware.Context) Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = TestUserID
|
||||
sc.context.OrgId = TestOrgID
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return UpdateAnnotation(c, cmd)
|
||||
})
|
||||
|
||||
fakeAnnoRepo = &fakeAnnotationsRepo{}
|
||||
annotations.SetRepository(fakeAnnoRepo)
|
||||
|
||||
sc.m.Put(routePattern, sc.defaultHandler)
|
||||
|
||||
fn(sc)
|
||||
})
|
||||
}
|
@ -15,6 +15,8 @@ func (hs *HttpServer) registerRoutes() {
|
||||
reqGrafanaAdmin := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true, ReqGrafanaAdmin: true})
|
||||
reqEditorRole := middleware.RoleAuth(m.ROLE_EDITOR, m.ROLE_ADMIN)
|
||||
reqOrgAdmin := middleware.RoleAuth(m.ROLE_ADMIN)
|
||||
redirectFromLegacyDashboardUrl := middleware.RedirectFromLegacyDashboardUrl()
|
||||
redirectFromLegacyDashboardSoloUrl := middleware.RedirectFromLegacyDashboardSoloUrl()
|
||||
quota := middleware.Quota
|
||||
bind := binding.Bind
|
||||
|
||||
@ -40,9 +42,14 @@ func (hs *HttpServer) registerRoutes() {
|
||||
r.Get("/datasources/", reqSignedIn, Index)
|
||||
r.Get("/datasources/new", reqSignedIn, Index)
|
||||
r.Get("/datasources/edit/*", reqSignedIn, Index)
|
||||
r.Get("/org/users/", reqSignedIn, Index)
|
||||
r.Get("/org/users", reqSignedIn, Index)
|
||||
r.Get("/org/users/new", reqSignedIn, Index)
|
||||
r.Get("/org/users/invite", reqSignedIn, Index)
|
||||
r.Get("/org/teams", reqSignedIn, Index)
|
||||
r.Get("/org/teams/*", reqSignedIn, Index)
|
||||
r.Get("/org/apikeys/", reqSignedIn, Index)
|
||||
r.Get("/dashboard/import/", reqSignedIn, Index)
|
||||
r.Get("/configuration", reqGrafanaAdmin, Index)
|
||||
r.Get("/admin", reqGrafanaAdmin, Index)
|
||||
r.Get("/admin/settings", reqGrafanaAdmin, Index)
|
||||
r.Get("/admin/users", reqGrafanaAdmin, Index)
|
||||
@ -58,10 +65,15 @@ func (hs *HttpServer) registerRoutes() {
|
||||
r.Get("/plugins/:id/edit", reqSignedIn, Index)
|
||||
r.Get("/plugins/:id/page/:page", reqSignedIn, Index)
|
||||
|
||||
r.Get("/dashboard/*", reqSignedIn, Index)
|
||||
r.Get("/d/:uid/:slug", reqSignedIn, Index)
|
||||
r.Get("/dashboard/db/:slug", reqSignedIn, redirectFromLegacyDashboardUrl, Index)
|
||||
r.Get("/dashboard/script/*", reqSignedIn, Index)
|
||||
r.Get("/dashboard-solo/snapshot/*", Index)
|
||||
r.Get("/dashboard-solo/*", reqSignedIn, Index)
|
||||
r.Get("/d-solo/:uid/:slug", reqSignedIn, Index)
|
||||
r.Get("/dashboard-solo/db/:slug", reqSignedIn, redirectFromLegacyDashboardSoloUrl, Index)
|
||||
r.Get("/dashboard-solo/script/*", reqSignedIn, Index)
|
||||
r.Get("/import/dashboard", reqSignedIn, Index)
|
||||
r.Get("/dashboards/", reqSignedIn, Index)
|
||||
r.Get("/dashboards/*", reqSignedIn, Index)
|
||||
|
||||
r.Get("/playlists/", reqSignedIn, Index)
|
||||
@ -94,7 +106,7 @@ func (hs *HttpServer) registerRoutes() {
|
||||
r.Post("/api/snapshots/", bind(m.CreateDashboardSnapshotCommand{}), CreateDashboardSnapshot)
|
||||
r.Get("/api/snapshot/shared-options/", GetSharingOptions)
|
||||
r.Get("/api/snapshots/:key", GetDashboardSnapshot)
|
||||
r.Get("/api/snapshots-delete/:key", reqEditorRole, DeleteDashboardSnapshot)
|
||||
r.Get("/api/snapshots-delete/:key", reqEditorRole, wrap(DeleteDashboardSnapshot))
|
||||
|
||||
// api renew session based on remember cookie
|
||||
r.Get("/api/login/ping", quota("session"), LoginApiPing)
|
||||
@ -134,6 +146,18 @@ func (hs *HttpServer) registerRoutes() {
|
||||
usersRoute.Post("/:id/using/:orgId", wrap(UpdateUserActiveOrg))
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
// team (admin permission required)
|
||||
apiRoute.Group("/teams", func(teamsRoute RouteRegister) {
|
||||
teamsRoute.Get("/:teamId", wrap(GetTeamById))
|
||||
teamsRoute.Get("/search", wrap(SearchTeams))
|
||||
teamsRoute.Post("/", quota("teams"), bind(m.CreateTeamCommand{}), wrap(CreateTeam))
|
||||
teamsRoute.Put("/:teamId", bind(m.UpdateTeamCommand{}), wrap(UpdateTeam))
|
||||
teamsRoute.Delete("/:teamId", wrap(DeleteTeamById))
|
||||
teamsRoute.Get("/:teamId/members", wrap(GetTeamMembers))
|
||||
teamsRoute.Post("/:teamId/members", quota("teams"), bind(m.AddTeamMemberCommand{}), wrap(AddTeamMember))
|
||||
teamsRoute.Delete("/:teamId/members/:userId", wrap(RemoveTeamMember))
|
||||
}, reqOrgAdmin)
|
||||
|
||||
// org information available to all users.
|
||||
apiRoute.Group("/org", func(orgRoute RouteRegister) {
|
||||
orgRoute.Get("/", wrap(GetOrgCurrent))
|
||||
@ -222,21 +246,49 @@ func (hs *HttpServer) registerRoutes() {
|
||||
apiRoute.Any("/datasources/proxy/:id/*", reqSignedIn, hs.ProxyDataSourceRequest)
|
||||
apiRoute.Any("/datasources/proxy/:id", reqSignedIn, hs.ProxyDataSourceRequest)
|
||||
|
||||
// Folders
|
||||
apiRoute.Group("/folders", func(folderRoute RouteRegister) {
|
||||
folderRoute.Get("/", wrap(GetFolders))
|
||||
folderRoute.Get("/id/:id", wrap(GetFolderById))
|
||||
folderRoute.Post("/", bind(m.CreateFolderCommand{}), wrap(CreateFolder))
|
||||
|
||||
folderRoute.Group("/:uid", func(folderUidRoute RouteRegister) {
|
||||
folderUidRoute.Get("/", wrap(GetFolderByUid))
|
||||
folderUidRoute.Put("/", bind(m.UpdateFolderCommand{}), wrap(UpdateFolder))
|
||||
folderUidRoute.Delete("/", wrap(DeleteFolder))
|
||||
|
||||
folderUidRoute.Group("/permissions", func(folderPermissionRoute RouteRegister) {
|
||||
folderPermissionRoute.Get("/", wrap(GetFolderPermissionList))
|
||||
folderPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), wrap(UpdateFolderPermissions))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Dashboard
|
||||
apiRoute.Group("/dashboards", func(dashboardRoute RouteRegister) {
|
||||
dashboardRoute.Get("/db/:slug", GetDashboard)
|
||||
dashboardRoute.Delete("/db/:slug", reqEditorRole, DeleteDashboard)
|
||||
dashboardRoute.Get("/uid/:uid", wrap(GetDashboard))
|
||||
dashboardRoute.Delete("/uid/:uid", wrap(DeleteDashboardByUid))
|
||||
|
||||
dashboardRoute.Get("/id/:dashboardId/versions", wrap(GetDashboardVersions))
|
||||
dashboardRoute.Get("/id/:dashboardId/versions/:id", wrap(GetDashboardVersion))
|
||||
dashboardRoute.Post("/id/:dashboardId/restore", reqEditorRole, bind(dtos.RestoreDashboardVersionCommand{}), wrap(RestoreDashboardVersion))
|
||||
dashboardRoute.Get("/db/:slug", wrap(GetDashboard))
|
||||
dashboardRoute.Delete("/db/:slug", wrap(DeleteDashboard))
|
||||
|
||||
dashboardRoute.Post("/calculate-diff", bind(dtos.CalculateDiffOptions{}), wrap(CalculateDashboardDiff))
|
||||
|
||||
dashboardRoute.Post("/db", reqEditorRole, bind(m.SaveDashboardCommand{}), wrap(PostDashboard))
|
||||
dashboardRoute.Post("/db", bind(m.SaveDashboardCommand{}), wrap(PostDashboard))
|
||||
dashboardRoute.Get("/home", wrap(GetHomeDashboard))
|
||||
dashboardRoute.Get("/tags", GetDashboardTags)
|
||||
dashboardRoute.Post("/import", bind(dtos.ImportDashboardCommand{}), wrap(ImportDashboard))
|
||||
|
||||
dashboardRoute.Group("/id/:dashboardId", func(dashIdRoute RouteRegister) {
|
||||
dashIdRoute.Get("/versions", wrap(GetDashboardVersions))
|
||||
dashIdRoute.Get("/versions/:id", wrap(GetDashboardVersion))
|
||||
dashIdRoute.Post("/restore", bind(dtos.RestoreDashboardVersionCommand{}), wrap(RestoreDashboardVersion))
|
||||
|
||||
dashIdRoute.Group("/permissions", func(dashboardPermissionRoute RouteRegister) {
|
||||
dashboardPermissionRoute.Get("/", wrap(GetDashboardPermissionList))
|
||||
dashboardPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), wrap(UpdateDashboardPermissions))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Dashboard snapshots
|
||||
@ -291,8 +343,8 @@ func (hs *HttpServer) registerRoutes() {
|
||||
annotationsRoute.Delete("/:annotationId", wrap(DeleteAnnotationById))
|
||||
annotationsRoute.Put("/:annotationId", bind(dtos.UpdateAnnotationsCmd{}), wrap(UpdateAnnotation))
|
||||
annotationsRoute.Delete("/region/:regionId", wrap(DeleteAnnotationRegion))
|
||||
annotationsRoute.Post("/graphite", bind(dtos.PostGraphiteAnnotationsCmd{}), wrap(PostGraphiteAnnotation))
|
||||
}, reqEditorRole)
|
||||
annotationsRoute.Post("/graphite", reqEditorRole, bind(dtos.PostGraphiteAnnotationsCmd{}), wrap(PostGraphiteAnnotation))
|
||||
})
|
||||
|
||||
// error test
|
||||
r.Get("/metrics/error", wrap(GenerateError))
|
||||
|
@ -25,6 +25,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
gocache "github.com/patrickmn/go-cache"
|
||||
)
|
||||
|
||||
var gravatarSource string
|
||||
@ -92,7 +94,7 @@ func (this *Avatar) Update() (err error) {
|
||||
|
||||
type CacheServer struct {
|
||||
notFound *Avatar
|
||||
cache map[string]*Avatar
|
||||
cache *gocache.Cache
|
||||
}
|
||||
|
||||
func (this *CacheServer) mustInt(r *http.Request, defaultValue int, keys ...string) (v int) {
|
||||
@ -110,7 +112,9 @@ func (this *CacheServer) Handler(ctx *macaron.Context) {
|
||||
|
||||
var avatar *Avatar
|
||||
|
||||
if avatar, _ = this.cache[hash]; avatar == nil {
|
||||
if obj, exist := this.cache.Get(hash); exist {
|
||||
avatar = obj.(*Avatar)
|
||||
} else {
|
||||
avatar = New(hash)
|
||||
}
|
||||
|
||||
@ -124,7 +128,7 @@ func (this *CacheServer) Handler(ctx *macaron.Context) {
|
||||
if avatar.notFound {
|
||||
avatar = this.notFound
|
||||
} else {
|
||||
this.cache[hash] = avatar
|
||||
this.cache.Add(hash, avatar, gocache.DefaultExpiration)
|
||||
}
|
||||
|
||||
ctx.Resp.Header().Add("Content-Type", "image/jpeg")
|
||||
@ -146,18 +150,18 @@ func NewCacheServer() *CacheServer {
|
||||
|
||||
return &CacheServer{
|
||||
notFound: newNotFound(),
|
||||
cache: make(map[string]*Avatar),
|
||||
cache: gocache.New(time.Hour, time.Hour*2),
|
||||
}
|
||||
}
|
||||
|
||||
func newNotFound() *Avatar {
|
||||
avatar := &Avatar{notFound: true}
|
||||
|
||||
// load transparent png into buffer
|
||||
path := filepath.Join(setting.StaticRootPath, "img", "transparent.png")
|
||||
// load user_profile png into buffer
|
||||
path := filepath.Join(setting.StaticRootPath, "img", "user_profile.png")
|
||||
|
||||
if data, err := ioutil.ReadFile(path); err != nil {
|
||||
log.Error(3, "Failed to read transparent.png, %v", path)
|
||||
log.Error(3, "Failed to read user_profile.png, %v", path)
|
||||
} else {
|
||||
avatar.data = bytes.NewBuffer(data)
|
||||
}
|
||||
|
105
pkg/api/common_test.go
Normal file
105
pkg/api/common_test.go
Normal file
@ -0,0 +1,105 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/go-macaron/session"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
macaron "gopkg.in/macaron.v1"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func loggedInUserScenario(desc string, url string, fn scenarioFunc) {
|
||||
loggedInUserScenarioWithRole(desc, "GET", url, url, models.ROLE_EDITOR, fn)
|
||||
}
|
||||
|
||||
func loggedInUserScenarioWithRole(desc string, method string, url string, routePattern string, role models.RoleType, fn scenarioFunc) {
|
||||
Convey(desc+" "+url, func() {
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(url)
|
||||
sc.defaultHandler = wrap(func(c *middleware.Context) Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = TestUserID
|
||||
sc.context.OrgId = TestOrgID
|
||||
sc.context.OrgRole = role
|
||||
if sc.handlerFunc != nil {
|
||||
return sc.handlerFunc(sc.context)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
switch method {
|
||||
case "GET":
|
||||
sc.m.Get(routePattern, sc.defaultHandler)
|
||||
case "DELETE":
|
||||
sc.m.Delete(routePattern, sc.defaultHandler)
|
||||
}
|
||||
|
||||
fn(sc)
|
||||
})
|
||||
}
|
||||
|
||||
func (sc *scenarioContext) fakeReq(method, url string) *scenarioContext {
|
||||
sc.resp = httptest.NewRecorder()
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
So(err, ShouldBeNil)
|
||||
sc.req = req
|
||||
|
||||
return sc
|
||||
}
|
||||
|
||||
func (sc *scenarioContext) fakeReqWithParams(method, url string, queryParams map[string]string) *scenarioContext {
|
||||
sc.resp = httptest.NewRecorder()
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
q := req.URL.Query()
|
||||
for k, v := range queryParams {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
So(err, ShouldBeNil)
|
||||
sc.req = req
|
||||
|
||||
return sc
|
||||
}
|
||||
|
||||
type scenarioContext struct {
|
||||
m *macaron.Macaron
|
||||
context *middleware.Context
|
||||
resp *httptest.ResponseRecorder
|
||||
handlerFunc handlerFunc
|
||||
defaultHandler macaron.Handler
|
||||
req *http.Request
|
||||
url string
|
||||
}
|
||||
|
||||
func (sc *scenarioContext) exec() {
|
||||
sc.m.ServeHTTP(sc.resp, sc.req)
|
||||
}
|
||||
|
||||
type scenarioFunc func(c *scenarioContext)
|
||||
type handlerFunc func(c *middleware.Context) Response
|
||||
|
||||
func setupScenarioContext(url string) *scenarioContext {
|
||||
sc := &scenarioContext{
|
||||
url: url,
|
||||
}
|
||||
viewsPath, _ := filepath.Abs("../../public/views")
|
||||
|
||||
sc.m = macaron.New()
|
||||
sc.m.Use(macaron.Renderer(macaron.RenderOptions{
|
||||
Directory: viewsPath,
|
||||
Delims: macaron.Delims{Left: "[[", Right: "]]"},
|
||||
}))
|
||||
|
||||
sc.m.Use(middleware.GetContextHandler())
|
||||
sc.m.Use(middleware.Sessioner(&session.Options{}))
|
||||
|
||||
return sc
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user