Compare commits

...

379 Commits

Author SHA1 Message Date
Daniel Lee
c114c46119 update version to 4.5.1 2017-09-15 10:05:51 +02:00
Torkel Ödegaard
bbe191a975 graphite: do not show error for cancelled requests, fixes #9249 2017-09-15 09:59:23 +02:00
Torkel Ödegaard
f8326c29f9 mysql: fix query editor not showing issue, fixes #9247 2017-09-14 20:30:01 +02:00
bergquist
491e6897e7 metrics: set summary unit
we have to use milleseconds since graphite
doesnt support float64
2017-09-14 19:28:54 +02:00
Andrew Prokhorenkov
5b74bea476 add Ukrainian hryvnia sign 2017-09-14 19:06:25 +02:00
bergquist
314bff1b78 adds grafana_ prefix for none standard metrics 2017-09-14 14:26:32 +02:00
bergquist
9c30bf53cf introduce concept of named middleware 2017-09-14 14:26:32 +02:00
bergquist
4bc6ecb241 adds metric middlware to route register 2017-09-14 14:26:32 +02:00
bergquist
6372e22180 migrate handlers to new register 2017-09-14 14:26:32 +02:00
bergquist
f842265388 add custom route register 2017-09-14 14:26:32 +02:00
bergquist
bf138d1845 adds small docs page metrics 2017-09-14 14:26:32 +02:00
bergquist
c177a9a77a make bridge prefix backwards compatible 2017-09-14 14:26:32 +02:00
bergquist
6d22a67a30 return /metrics before session middleware 2017-09-14 14:26:32 +02:00
bergquist
6b1ae1a8a8 use internal init for settings 2017-09-14 14:26:32 +02:00
bergquist
dd9d4ecfbe update stat gauges first run to avoid gaps 2017-09-14 14:26:32 +02:00
bergquist
fca80ff525 add support for deltas in histogram and summaries 2017-09-14 14:26:32 +02:00
bergquist
2de94d6548 convert old metrics to prom metrics 2017-09-14 14:26:32 +02:00
bergquist
788f677ed7 remove old internal metrics lib 2017-09-14 14:26:32 +02:00
bergquist
d6b8c6a2d2 add graphite bridge that support delta counters 2017-09-14 14:26:32 +02:00
Torkel Ödegaard
c1ef89d3bf Update CHANGELOG.md 2017-09-14 11:55:44 +02:00
Torkel Ödegaard
aa24839ac9 Update CHANGELOG.md 2017-09-14 11:55:07 +02:00
Patrick O'Carroll
337fb9bdfa fixed some images (#9237) 2017-09-14 11:04:01 +02:00
Torkel Ödegaard
512535e8ff release: bumped version to v4.5.0 stable 2017-09-14 10:51:21 +02:00
Torkel Ödegaard
4e719aa0c1 docs: minor update 2017-09-14 10:50:34 +02:00
Daniel Lee
29de6387cb plugins: add styles for ol tags in markdown 2017-09-13 17:13:53 +02:00
Torkel Ödegaard
a76f3fba2e docs: minor fixes to images 2017-09-13 17:11:10 +02:00
Patrick O'Carroll
d71456b96f Docs image updates (#9225)
* replaced old images and gifs with new ones

* replaced images, changed some text especially for column styles

* replaced and added images and gifs
2017-09-13 16:29:53 +02:00
Torkel Ödegaard
85bd1861d6 fix: improve behavior when switching back and forth between x-axis modes, fixes #9229 2017-09-13 14:38:22 +02:00
Torkel Ödegaard
1a53d6453b Merge branch 'v4.4.x' 2017-09-13 10:02:04 +02:00
Torkel Ödegaard
10f058036c Merge branch 'master' of github.com:grafana/grafana 2017-09-13 09:48:56 +02:00
Torkel Ödegaard
73248d6687 fixes for metrics tab when data source was not found 2017-09-13 09:48:50 +02:00
Mitsuhiro Tanda
b349b3ef55 provide ace editor for external datasource plugin (#9224) 2017-09-13 09:29:53 +02:00
Torkel Ödegaard
dd67c9d420 Merge branch 'master' of github.com:grafana/grafana 2017-09-12 11:36:47 +02:00
Torkel Ödegaard
968ba30fa5 ux: increased code editor auto complete width from 320px to 550px, fixes #9203 2017-09-12 11:36:30 +02:00
Daniel Lee
379f984293 docs: windows - add note about ini comments 2017-09-12 11:08:28 +02:00
Torkel Ödegaard
3c16230158 prometheus: added completer unit test, #9208 2017-09-12 11:05:32 +02:00
Torkel Ödegaard
fd76c855f9 Merge branch 'master' of github.com:grafana/grafana 2017-09-12 10:32:02 +02:00
Torkel Ödegaard
e16cadaa27 docs: minor update 2017-09-12 10:31:53 +02:00
Daniel Lee
665fef0114 docs: kiosk mode options add to playlist doc 2017-09-12 10:31:13 +02:00
Daniel Lee
ff4cd1aef6 influxdb: small css fix for order by in query editor 2017-09-12 09:24:54 +02:00
Torkel Ödegaard
0e18c82d95 style: corrected indentation in sass file 2017-09-12 09:21:17 +02:00
Patrick O'Carroll
a7b0a01b13 replaced old images and gifs with new ones (#9217) 2017-09-12 09:07:36 +02:00
Torkel Ödegaard
18cfe1b192 Merge branch 'master' of github.com:grafana/grafana 2017-09-12 09:05:47 +02:00
Torkel Ödegaard
f6100dd8eb ux: success/error alerts refactoring, #9214 2017-09-12 09:05:32 +02:00
bergquist
ee4bbf61a9 remove node restriction from package.json
yarn requires correct node version in package.json
and wont install with 4.x. removing since we dont
care about it.
2017-09-12 08:15:48 +02:00
Torkel Ödegaard
7164183739 Merge branch 'master' of github.com:grafana/grafana 2017-09-12 08:01:51 +02:00
Patrick O'Carroll
90602942f5 New alert design (#9214)
* ux: updated alert design

* fixed bg-color for alerts

* more changes to alerts, index fixed
2017-09-12 08:01:44 +02:00
Torkel Ödegaard
6e344f6eea api: tsdb api orgId fix 2017-09-12 08:01:34 +02:00
bergquist
057b8a6b2d improve error message for timeouts
closes #9220
2017-09-11 20:07:57 +02:00
Torkel Ödegaard
e5f84484eb prometheus: another prometheus syntax highlight fix, #9212, #9167 2017-09-11 16:36:53 +02:00
Alexander Zobnin
b1580bf385 ace: fix braces highlight in prometheus (#9212) 2017-09-11 15:49:15 +02:00
Torkel Ödegaard
293daf2ca1 fix: removed text option from text panel edit options, was by mistake not removed from settings dropdown, fixes #9204 2017-09-11 10:45:00 +02:00
Torkel Ödegaard
75c4c4d8b5 fix: query ctrl unit tests now pass as before 2017-09-08 13:52:28 +02:00
Torkel Ödegaard
2953d64429 prometheus: minor update to focus editor PR, #9201 2017-09-08 11:43:29 +02:00
Torkel Ödegaard
4b851de648 Merge branch 'prom_give_focus' of https://github.com/mtanda/grafana into mtanda-prom_give_focus 2017-09-08 10:55:50 +02:00
Alin Sinpalean
1076b75a21 Fix rounding of intervals (#9197)
* Prometheus: Fix actual step computation logic when a min_step is specified and the range is longer than min_step * 11000.

* Fix kbn.round_interval for exact intervals.

* Remove redundant 1d return, fix a couple of comments.

* Be more cautious with values close to 1d not rounding up to 1d. They may, because of the way the calculation uses 2 potentially different current time values.
2017-09-08 10:37:57 +02:00
Daniel Lee
b1506a2b09 securejson: decrypt should not modify src
When decrypting a source securejson byte array, should not
modify the source and now passes back a new dest byte array.
2017-09-08 10:19:07 +02:00
Mitsuhiro Tanda
e13575eaef add AWS/NATGateway metrics (#9202) 2017-09-08 09:04:15 +02:00
Mitsuhiro Tanda
7c566a6539 fix to focus first query 2017-09-08 12:33:36 +09:00
Mitsuhiro Tanda
d971eddc7a copy from give-focus 2017-09-08 11:49:44 +09:00
Mitsuhiro Tanda
ce0de35a6c set give focus in code editor 2017-09-08 11:49:41 +09:00
Torkel Ödegaard
93be16b106 docs: minor docs update 2017-09-07 16:55:36 +02:00
Torkel Ödegaard
8ec33574a1 docs: added v4.4 to docs archive 2017-09-07 16:44:41 +02:00
Patrick O'Carroll
de647c4100 docs: uppdated getting started with images and text, added info on query inspector to version45 and trouble shooting (#9193) 2017-09-07 16:32:55 +02:00
bergquist
51d021a337 reduce readme to be about the code 2017-09-07 16:08:38 +02:00
bergquist
7dc6d67d46 adds note about closing #8876 2017-09-07 14:29:25 +02:00
Carl Bergquist
62979916ad Merge pull request #8876 from mtanda/shortcut_new_dashboard
add new dashboard shortcut
2017-09-07 14:26:05 +02:00
Carl Bergquist
4670c74942 Merge pull request #9022 from adriangarza/master
added CloudWatch data source API documentation
2017-09-07 14:10:53 +02:00
Torkel Ödegaard
c9a30ef149 build: fixed broken build 2017-09-07 13:05:26 +02:00
Carl Bergquist
9dac602e98 Merge pull request #9191 from wgliang/master
Optimize some wrong usage and spelling
2017-09-07 12:04:45 +02:00
wangguoliang
652fce7e76 Optimize some wrong usage and spelling
Signed-off-by: wgliang <liangcszzu@163.com>
2017-09-07 17:50:11 +08:00
Mitsuhiro Tanda
e98254e1e3 show only label name in label matcher (#9167) 2017-09-07 10:10:52 +02:00
Mitsuhiro Tanda
4446e95155 (prometheus) cache metric suggest query result (#9182)
* (prometheus) cache metric suggest query result

* add test
2017-09-07 10:09:59 +02:00
Alin Sinpalean
5d4b8b5a5c Have 'Hide series with only zeros' ignore nulls (#9179)
* Prometheus: Fix actual step computation logic when a min_step is specified and the range is longer than min_step * 11000.

* Have the 'Hide series with only zeros' option also apply to series with some null values.
2017-09-06 16:50:55 +02:00
Patrick O'Carroll
095ac80d19 docs: updated image in docs (#9184) 2017-09-06 16:31:17 +02:00
Torkel Ödegaard
9451e6af39 Merge branch 'master' of github.com:grafana/grafana 2017-09-06 14:20:53 +02:00
Torkel Ödegaard
82d365bdb8 fix: graph right y label is now correctly possitioned, fixes #9172 2017-09-05 21:57:32 +02:00
Sergey Korobov
ec64dc8fae Fix sortByName and percentileOfSeries in gfunc.js (#9169)
Fixing type of parameters from "select" to "boolean" for working with carbonapi (like it was done in summarize function) + some commas prettify.
2017-09-05 19:34:55 +02:00
Torkel Ödegaard
b333ad9481 docs: updated docs with v4.5 beta links 2017-09-05 16:01:28 +02:00
Torkel Ödegaard
22be9436f7 Update CHANGELOG.md 2017-09-05 15:16:04 +02:00
Torkel Ödegaard
bc690232fb version bump to v4.5-beta1 2017-09-05 10:39:55 +02:00
Torkel Ödegaard
0005f8e7b3 fix: fixed jshint issue 2017-09-05 10:17:24 +02:00
Torkel Ödegaard
4e387ed47a fix: Elasticsearch and adhoc filters fix, fixes #9165 2017-09-05 10:16:17 +02:00
Daniel Lee
52676161bb docs: update to http api admin section
Make it clearer that it only works with basic auth
2017-09-05 10:04:01 +02:00
bergquist
01e2729dba spring clean! 2017-09-04 23:19:09 +02:00
Carl Bergquist
a1faa6d4d9 Merge pull request #9164 from summic/master
Add the missing step of "grunt build" to the README.md
2017-09-04 23:06:42 +02:00
Allen
1a3d34b918 Add the missing step of grunt build to the readme 2017-09-05 01:56:52 +08:00
Torkel Ödegaard
5d3c3a6889 packaging: changed how pid directory is created for systemd systems, #9133 2017-09-04 16:41:07 +02:00
Torkel Ödegaard
4eabf6ce81 Update CHANGELOG.md 2017-09-04 14:49:51 +02:00
Torkel Ödegaard
2789c4f1e1 dsfix: include routes in plugin model 2017-09-04 14:09:02 +02:00
Torkel Ödegaard
9bafb108f7 docs: added docs archive for v4.3 2017-09-04 13:38:46 +02:00
Torkel Ödegaard
88e4b6ee75 docs: update changelog 2017-09-04 13:34:33 +02:00
Torkel Ödegaard
2fc67da69a Merge branch 'metrics-tab-v3' 2017-09-04 13:27:44 +02:00
Torkel Ödegaard
6e4090abf2 feat: finished work on the interval changes #9161 2017-09-04 13:27:28 +02:00
Torkel Ödegaard
284cacf560 logging: write pid file path and pid during startup 2017-09-04 12:44:54 +02:00
mxlxm
c5400ffe76 mysql: use collation instead of charset (#9156)
- use charset would issue additional 'SET NAMES <VALUE>' queries, set
collation would be better. see: https://github.com/go-sql-driver/mysql#charset
2017-09-04 12:32:07 +02:00
Torkel Ödegaard
c3cffeb10c packaging: fixed issue with pid file on systemd systems, fixes #9133 2017-09-04 10:43:04 +02:00
bergquist
ce6050f5d6 fix(graphite): jsonData is not always present. 2017-09-04 10:28:48 +02:00
Torkel Ödegaard
07e192ff47 change: more work on changing default group by time interval to min interval setting 2017-09-01 15:57:02 +02:00
Torkel Ödegaard
e8e1f1bc6d updated graphite help 2017-09-01 11:15:39 +02:00
Marcel Anacker
40c008f870 Cloudwatch Datasource: changed namespace of Web Application Firewall (#9128) 2017-09-01 10:43:23 +02:00
Nevins
66441650cd changing ordering so AWS API is only called if cache has expired (#9136) 2017-09-01 07:24:05 +02:00
Jesse White
91fb3f2224 fix: cancel the initial timer when changing the auto-refresh interval, fixes #9139 (#9140) 2017-09-01 07:19:51 +02:00
Torkel Ödegaard
7b1473649b Update README.md 2017-09-01 07:16:42 +02:00
Torkel Ödegaard
eb0f5cc900 ux: progress on metrics tab changes 2017-08-31 16:38:49 +02:00
Torkel Ödegaard
84d4958a3c plugin change: make interval, cache timeout & max data points options in plugin.json, remove query.options component feature, add help markdown feature and toggle for data sources 2017-08-31 14:05:52 +02:00
Torkel Ödegaard
40ae2cef38 docs: updated changelog with #9131 2017-08-31 09:54:45 +02:00
Torkel Ödegaard
52177a45d9 influxdb: use paranthesis for influxdb queries in frontend query builder, #9131 2017-08-31 09:52:32 +02:00
Jonathan A. Sternberg
bdfbc2453f Use parenthesis to surround the selected tags for influxdb queries (#9131)
The generated queries when selecting multiple tags are incorrect. In
InfluxQL, `AND` has a higher precedence than `OR` so the condition:

    WHERE "hostname" = 'server1' OR "hostname" = 'server2' AND time > now() - 5m

This is parsed as if it were:

    WHERE "hostname" = 'server1' OR ("hostname" = 'server2' AND time > now() - 5m)

But the intention is to write a query like this:

    WHERE ("hostname" = 'server1' OR "hostname" = 'server2') AND time > now() - 5m

This change modifies the generated query so it surrounds a query with
multiple conditions in parenthesis so it doesn't conflict with the time
expression in an unexpected way.

This is currently not an issue because InfluxDB doesn't actually
evaluate the condition for the time expression correctly. It just looks
through the AST for anything that looks like a time expression and then
assumes the proper format of `AND` was used rather than validating that
it was used correctly.
2017-08-31 09:33:03 +02:00
Torkel Ödegaard
9b60a63778 ux: metrics tab v3 2017-08-30 16:39:00 +02:00
Daniel Lee
abeaef71cc DashExport: fix View JSON in export menu
ref #9002
2017-08-30 09:56:49 +02:00
Torkel Ödegaard
54129b1340 Merge branch 'master' of github.com:grafana/grafana
: Please enter a commit message to explain why this merge is necessary,
2017-08-29 15:52:17 +02:00
Torkel Ödegaard
dda1cf1a88 Merge branch 'ace-editor' 2017-08-29 15:52:03 +02:00
Torkel Ödegaard
bdb1cfb008 ace: minor fixes for ace editor 2017-08-29 15:51:54 +02:00
Torkel Ödegaard
c5c5fa0db3 Update ROADMAP.md 2017-08-29 15:45:59 +02:00
Torkel Ödegaard
78ea1ea76e Updated master version to v4.5 2017-08-29 10:13:16 +02:00
Alin Sinpalean
bdd239e933 Prometheus: Fix actual step computation logic when a min_step is specified and the range is longer than min_step * 11000. (#9109) 2017-08-29 09:57:45 +02:00
Torkel Ödegaard
aef4eca254 fix: removed code intented to test/replicate an issue 2017-08-29 08:57:34 +02:00
Callum Loh
74ddebc8ea Fix spelling for Hipchat notifier (#9112) 2017-08-29 08:08:51 +02:00
Torkel Ödegaard
546f903141 ds: minor fix that resets data source model when switching data source type 2017-08-28 15:29:31 +02:00
Torkel Ödegaard
c2b05341e5 Merge branch 'master' of github.com:grafana/grafana 2017-08-28 13:29:36 +02:00
Torkel Ödegaard
c92317bafa fix: fixed gofmt formating for #9091 2017-08-28 13:29:24 +02:00
Torkel Ödegaard
407f1ad475 Merge branch 'master' of https://github.com/pdoan017/grafana 2017-08-28 13:28:13 +02:00
Torkel Ödegaard
ead7ae7635 Update CHANGELOG.md 2017-08-28 11:46:54 +02:00
Torkel Ödegaard
311fa66590 Update CHANGELOG.md 2017-08-28 11:46:13 +02:00
Torkel Ödegaard
72690b3962 Update CHANGELOG.md 2017-08-28 11:45:25 +02:00
Torkel Ödegaard
62f5770908 fix: changed modal to fixed positioned, this change makes modal maintain scroll position, fixes #8800 2017-08-28 11:34:44 +02:00
Torkel Ödegaard
bf110d02d1 fix: form dropdown, escape autocomplete dropdown items, fixes #9089 2017-08-28 11:00:42 +02:00
Torkel Ödegaard
e91cf28f8d elasticsearch: changed ad hoc filters from using term filters to using phrase match queries, closing #9095 2017-08-28 10:52:10 +02:00
Torkel Ödegaard
3b9fbd60d8 ux: fix for showing pending invitations tab, fixes #9094 2017-08-28 09:52:53 +02:00
Dmitry Bedrin
ad14ccf4bd non_negative_difference() function in InfluxDB 1.3 (#9104)
Add support of non_negative_difference() function from InfluxDB 1.3
https://docs.influxdata.com/influxdb/v1.3/administration/differences/#functions
2017-08-28 08:53:41 +02:00
Alexander Zobnin
9375441991 ace: add default light theme 2017-08-26 13:46:39 +03:00
Alexander Zobnin
ef3c543620 ace: fix directive docs 2017-08-26 12:52:32 +03:00
Alexander Zobnin
54f932e960 ace: fix error when getCompleter() wasn't passed 2017-08-26 12:48:37 +03:00
Alexander Zobnin
451ecce4ab ace: styles tweak 2017-08-26 12:36:08 +03:00
Alexander Zobnin
ef162c3dc7 ace: minor css refactor 2017-08-26 12:14:45 +03:00
pdoan017
3eea5d235d Added import for container/list 2017-08-24 15:42:54 -04:00
pdoan017
d6085755c4 Added series order according to query results
Raw query results would return as expected. But when appending new series to pointsBySeries map, order of keys is random. So I've added a list to keep track of series order. Should implement FIFO rules.
2017-08-24 15:38:36 -04:00
Alexander Zobnin
a0cb744746 ace: reduce docs lines width 2017-08-24 13:58:26 +03:00
Alexander Zobnin
dc7616e560 ace: prometheus functions docs 2017-08-24 13:56:22 +03:00
Alexander Zobnin
f7ec8e0de0 Merge branch 'master' into ace-editor 2017-08-24 12:37:18 +03:00
Torkel Ödegaard
47f8145246 Merge branch 'master' of github.com:grafana/grafana 2017-08-24 11:18:44 +02:00
Torkel Ödegaard
71c22fdbff dataproxy: removed some logging, closes #9078 2017-08-24 11:18:06 +02:00
Torkel Ödegaard
71c9582944 data source with token auth is starting to work, #9078 2017-08-24 11:07:37 +02:00
Jason Stangroome
632a5e9b97 Support Azure MySQL (#8618)
Azure's MySQL implementation appears to always respond with an Authentication Method Switch Request Packet requesting `mysql_native_password` auth even though the client's initial Handshake Response already included the native password credentials.

Most MySQL client libraries support this but Golang's go-sql-driver/mysql requires the `allowNativePasswords` DSN parameter set to enable it. Without this parameter, Grafana fails to authenticate to the database with the error message "this user requires mysql native password authentication."

References:

* https://web.archive.org/web/20160814002743/http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
* https://web.archive.org/web/20160814002743/http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
* https://github.com/go-sql-driver/mysql#user-content-allownativepasswords
2017-08-24 10:24:10 +02:00
Torkel Ödegaard
3c9798bec9 datasource-proxy: token exchange 2017-08-23 17:18:43 +02:00
Daniel Lee
bf4ffe41b0 Merge branch 'v4.4.x' 2017-08-23 15:19:51 +02:00
Daniel Lee
e763104a6f csv: add toggle for export to Excel
Adds back feature that adds 'sep=;' text that excel needs in a csv file.
Also adds toggle to make this optional if exporting to other spreadsheet
programs. Fixes #9083.
2017-08-23 15:17:53 +02:00
Torkel Ödegaard
4f9fbcc211 dataproxy: added caching of datasources when doing data proxy requests, #9078 2017-08-23 13:31:26 +02:00
Torkel Ödegaard
bcb3dfac9f Merge branch 'master' of github.com:grafana/grafana 2017-08-23 10:52:56 +02:00
Torkel Ödegaard
8bf49c51b9 dataproxy: refactoring data source proxy to support route templates and wrote more tests for data proxy code, #9078 2017-08-23 10:52:31 +02:00
jenlersadnie
0ba5706400 Fixing a minor typo under Selection Options (#9082)
Mulit => Multi
2017-08-23 08:50:22 +02:00
Torkel Ödegaard
63d6ab476a feat: data source proxy refactoring and route handling, #9078 2017-08-22 17:14:15 +02:00
Daniel Lee
d19aa89ec0 docs: .ini file semicolon is comment
ref #7725
2017-08-21 21:28:49 +02:00
Daniel Lee
bbf9d7677b Merge branch 'v4.4.x' 2017-08-21 21:05:43 +02:00
Daniel Lee
a31d0df897 shortcuts: fixes expand/collapse all rows
Fixes #9069
2017-08-21 21:04:20 +02:00
Daniel Lee
5c2958023d Merge branch 'v4.4.x' 2017-08-21 13:45:04 +02:00
Daniel Lee
7b5019482e mysqlds: add placeholder/typeahead for localhost connection strings
for the host field on the data source config page. Fixes #9046
2017-08-21 13:44:33 +02:00
Daniel Lee
649122b4fb mysqlds: add placeholder/typeahead for localhost connection strings
for the host field on the data source config page. Fixes #9046
2017-08-21 13:43:09 +02:00
Torkel Ödegaard
e3bd51e38d fix: remove duplicate set-cookie when logging in, fixes #9013 2017-08-21 11:10:59 +02:00
ericslaw
73f0bd3b4b fix link to opentsdb templating (#9039) 2017-08-16 16:57:27 +02:00
Andrei Burd
3222677493 Datasource Print the received error (#9043) 2017-08-16 16:56:51 +02:00
Matt Toback
020aae1427 Updated Grafana.net to .com 2017-08-14 11:05:28 +02:00
Torkel Ödegaard
17cb3f6e6a fix: graph fix for decimals, bug introduced by #61313478063b0e0721f204847f3c0298ea8f593f 2017-08-11 16:20:36 +02:00
Torkel Ödegaard
d4dd0222fa fix: prometheus does not have two editor modes, fixes #9025 2017-08-11 12:33:56 +02:00
Daniel Lee
167995776f docs: update to tag alias
ref #9024
2017-08-11 11:30:30 +02:00
Daniel Lee
02248273ae mysqlds: remove alpha state from plugin.json 2017-08-11 10:25:37 +02:00
Daniel Lee
c4feef2541 docs: http api /users - corrections + adds missing method 2017-08-11 10:24:54 +02:00
Adrian Garza
5420f271f1 added CloudWatch data source API documentation
access and secret keys are base64-encoded gibberish
2017-08-10 16:03:42 -07:00
Alexander Zobnin
776e6e2c3f ace: redefine completions for prometheus and add initial docs for functions 2017-08-10 19:58:59 +03:00
Alexander Zobnin
679ddc9696 ace: example snippet for prometheus 2017-08-10 16:49:09 +03:00
Daniel Lee
b716a2595a mysqlds: add support for key/value template variables
If the template variable query has two columns named __text and __value
then return a list of key values. The value is used when the variable is
interpolated in the query. Allows mapping of texts to ids.
2017-08-10 14:42:27 +02:00
Alexander Zobnin
d8d59fd8d4 ace: add custom behaviour for prometheus 2017-08-10 15:28:40 +03:00
Torkel Ödegaard
c7959ff06e fix: Using table cell links and ad hoc filters together now works & looks correct, fixes #8052 2017-08-10 14:12:31 +02:00
Torkel Ödegaard
d2437d3cf1 fix: ad-hoc filters now works with data source variables, fixes #8052 2017-08-10 12:04:46 +02:00
Alexander Zobnin
b260a642e7 ace: fix broken karma tests (error loading ace.js ) 2017-08-10 12:33:53 +03:00
Alexander Zobnin
e75b39376a ace: minor refactor 2017-08-10 11:53:55 +03:00
Alexander Zobnin
6b5400bdb6 ace: fix loading text snippets error 2017-08-10 11:23:32 +03:00
Torkel Ödegaard
149e694ce6 ace: prometheus completion improvements 2017-08-10 10:08:09 +02:00
Torkel Ödegaard
0b2cc404ff ace: working on editor completion stuff 2017-08-10 09:33:17 +02:00
Torkel Ödegaard
b9540e4c49 ace: minor ace theme tweaks 2017-08-09 21:12:15 +02:00
Daniel Lee
43fa852cc1 mysql: change logging from into to debug for scan 2017-08-09 19:33:09 +02:00
Daniel Lee
1105bb371f mysqlds: adds support for template variables
Fixes #8855
2017-08-09 19:32:53 +02:00
Daniel Lee
59513ff963 tempvar: bug fix for duplicate template var
and a fix for when selecting the same value twice in
a template variable if it is not multi select. It threw an
exception on the second selection
2017-08-09 14:28:23 +02:00
Torkel Ödegaard
459a8ed695 ace: minor changes to ace directive 2017-08-09 11:43:02 +02:00
Torkel Ödegaard
80f5c914e8 ace: removed the old text areas 2017-08-09 11:06:21 +02:00
Torkel Ödegaard
68cac6ccb5 Merge branch 'master' into ace-editor 2017-08-09 10:51:31 +02:00
Torkel Ödegaard
668cb3c1ef Merge branch 'v4.4.x' 2017-08-09 10:37:06 +02:00
Torkel Ödegaard
e8a20643d6 feat: store last seen date for users and present in stats and user lists, closes #9007 2017-08-09 10:36:41 +02:00
Alexander Zobnin
5c0773023f code-editor: increase autocomplete popup size 2017-08-09 11:23:05 +03:00
Alexander Zobnin
1c8c746956 code-editor: prometheus metrics autocomplete 2017-08-09 10:58:00 +03:00
Torkel Ödegaard
eac0d30e99 Merge branch 'v4.4.x' 2017-08-09 07:20:52 +02:00
Torkel Ödegaard
26ad025705 feat: added os to stats 2017-08-09 07:20:37 +02:00
Alexander Zobnin
aa670244f1 code-editor: initial prometheus syntax definition 2017-08-08 22:27:47 +03:00
Alexander Zobnin
e0bbb74b0c code-editor: test editors for MySQL and prometheus 2017-08-08 18:42:26 +03:00
Alexander Zobnin
0e0e60317e code-editor: tabSize option 2017-08-08 18:41:11 +03:00
Alexander Zobnin
152c4170da code-editor: onChange option and usage docs 2017-08-08 18:31:13 +03:00
Torkel Ödegaard
1652426dfe :Merge branch 'master' of github.com:grafana/grafana 2017-08-08 17:08:49 +02:00
Torkel Ödegaard
68c4ce34d5 fix: templating issue with data source variables, can now be used right away in other query variables and panels (without page reload), fixes #7510 2017-08-08 17:08:35 +02:00
Torkel Ödegaard
fec41cf038 Update CHANGELOG.md 2017-08-08 16:21:20 +02:00
Torkel Ödegaard
fee1e6df41 Merge branch 'master' of github.com:grafana/grafana 2017-08-08 16:18:26 +02:00
Torkel Ödegaard
addeccb4f0 Merge branch 'v4.4.x' 2017-08-08 16:18:08 +02:00
Torkel Ödegaard
a47b31ac62 fix: MySQL/Postgress max_idle_conn default was wrongly set to zero, which does not mean unlimited but zero, which in practice disables connection pooling, not good. now max idle conn is set to golang's default which is 2, fixes #8513 2017-08-08 16:17:52 +02:00
Alexander Zobnin
cd16db4d09 code-editor: use data- attributes for editor options 2017-08-08 16:28:51 +03:00
Daniel Lee
563795245a mysqlds: support for more column types
Includes integration test for most column types. Fixes #8918
2017-08-08 15:24:41 +02:00
Alexander Zobnin
59d1654df4 code-editor: adjust editor styles 2017-08-08 16:05:15 +03:00
Daniel Lee
2fb25d8fa4 mysqlds: add tests for new macros 2017-08-08 14:40:27 +02:00
Brad Lhotsky
a8ac215039 Add a few more MySQL macros:
* $__timeFrom() -> Returns the dashboard 'from' suitable for use querying
  against a MySQL TIMESTAMP field.
* $__timeTo() -> Returns the dashboard 'to' suitable for use querying
  against a MySQL TIMESTAMP field.
* $__unixEpochFiler(column) -> If you store timestamps as UNIX epoch's,
  this builds: column > 'from' AND column < 'to'
* $__unixEpochFrom() -> Returns the dashboard 'from' suitable for use querying
  against a MySQL integer field (UNIX epochs)
* $__unixEpochTo() -> Returns the dashboard 'to' suitable for use querying
  against a MySQL integer field (UNIX epochs)
2017-08-08 14:40:27 +02:00
Alexander Zobnin
eb944551c0 code-editor: add autocomplete styles 2017-08-08 15:32:23 +03:00
Alexander Zobnin
928fedaad7 code-editor: minor refactor 2017-08-08 15:19:15 +03:00
Torkel Ödegaard
d3680d290c fix: graphite issue with metricFind and sending from/until in normal format, fixes #8997 2017-08-08 13:51:54 +02:00
Torkel Ödegaard
83beff300b Merge branch 'v4.4.x' 2017-08-08 11:26:45 +02:00
Torkel Ödegaard
64b5153e7d fix: change view json to use the grafana built json viewer, fixes #9002 2017-08-08 11:26:16 +02:00
Torkel Ödegaard
781dd25c82 Merge branch 'elasticsearch-filtering' 2017-08-08 11:09:00 +02:00
Torkel Ödegaard
f979e95820 tablepanel: minor update to table panel, #8052 2017-08-08 11:08:51 +02:00
Torkel Ödegaard
1507c02ebb Merge branch 'feat-8539' of https://github.com/alexanderzobnin/grafana 2017-08-08 09:33:23 +02:00
Torkel Ödegaard
7c14ade623 Merge branch 'v4.4.x' 2017-08-08 09:28:41 +02:00
Torkel Ödegaard
7031f7e772 fix: sqlite3 and storing/displaying dates used wrong timezone, fixes #8996 2017-08-08 09:28:16 +02:00
Alexander Zobnin
bf8171fd63 code-editor: initial autocomplete 2017-08-07 21:30:36 +03:00
Alexander Zobnin
b74fe05fec code-editor: support language mode 2017-08-07 20:19:15 +03:00
Alexander Zobnin
ecb66e7678 code-editor: disable depreacation warning 2017-08-07 19:43:58 +03:00
Alexander Zobnin
e4dabb657c code-editor: initial directive for rich code editor (ace) 2017-08-07 19:31:50 +03:00
Torkel Ödegaard
48fa642727 Update CHANGELOG.md 2017-08-07 16:03:03 +02:00
Torkel Ödegaard
3e392ef921 ux: added minor help tip to graphite ds settings 2017-08-07 15:55:05 +02:00
Torkel Ödegaard
0e2b809f7e docker: added graphite v1.x docker block 2017-08-07 15:12:12 +02:00
Alexander Zobnin
4fe79edd40 Graphite 1.0 functions (#8987)
* graphite-ds: add graphite version to config editor

* graphite-ds: modify add-graphite-function to show only version-related functions

* graphite-ds: refactor, move func filtering to gfunc.js

* graphite-ds: add new functions for graphite 1.0.x

* graphite-ds: fix unit tests (add jsonData)
2017-08-07 15:10:59 +02:00
Alexander
35522c475f Fix #8998 by not overriding GOMAXPROCS (#8999) 2017-08-07 15:02:04 +02:00
Daniel Lee
92f71136e6 Update CHANGELOG.md 2017-08-07 13:40:25 +02:00
Daniel Lee
ee835242ca Merge branch 'v4.4.x' 2017-08-07 13:14:24 +02:00
Daniel Lee
def45f55da docs: update installation for version 4.4.3 2017-08-07 13:11:57 +02:00
Daniel Lee
54c79c5648 updated version to v4.4.3 2017-08-07 10:50:18 +02:00
Daniel Lee
649fe7e462 Merge branch 'v4.4.x' 2017-08-07 10:47:23 +02:00
Daniel Lee
0d25357367 build: remove downloaded pkg files after publish 2017-08-07 10:46:37 +02:00
Daniel Lee
aa889e59a1 tests: fix after interface change 2017-08-07 10:20:46 +02:00
Torkel Ödegaard
d285045ff6 removed unused images 2017-08-07 10:11:39 +02:00
Torkel Ödegaard
132cd36b0c Delete fav16.png
fixes #8989
2017-08-07 10:10:37 +02:00
Daniel Lee
1e5778174c login: regenerates session id on login 2017-08-07 10:00:29 +02:00
Patrick Tescher
c082372ffe Add a Safari Pinned Tab Icon (#8983)
Icon adopted from grafana_icon.svg

Reference document:
https://developer.apple.com/library/content/documentation/AppleApplicati
ons/Reference/SafariWebContent/pinnedTabs/pinnedTabs.html
2017-08-07 09:39:36 +02:00
Torkel Ödegaard
4f9cfcd632 Update CHANGELOG.md 2017-08-07 09:35:32 +02:00
Torkel Ödegaard
0bd03098ea Update CHANGELOG.md 2017-08-07 09:31:31 +02:00
Torkel Ödegaard
ee297487a5 Update CHANGELOG.md 2017-08-07 09:31:04 +02:00
Torkel Ödegaard
8930e04f2b Update CHANGELOG.md 2017-08-07 09:29:54 +02:00
Louis Ventre
97d1676fe8 Add time extremity with InfluxDB (#8722) 2017-08-07 09:26:32 +02:00
Jesse White
f547c93a4f fix: hide modals when pressing Esc, fixes #8988 (#8994) 2017-08-07 09:23:33 +02:00
Torkel Ödegaard
58528a951a Merge branch 'master' of github.com:grafana/grafana 2017-08-04 14:05:00 +02:00
Torkel Ödegaard
6e0f767af7 Update CHANGELOG.md 2017-08-04 14:04:16 +02:00
Torkel Ödegaard
0a23f3dd28 Merge branch 'master' of github.com:grafana/grafana 2017-08-04 14:02:18 +02:00
Torkel Ödegaard
26766ddb27 Merge branch 'v4.4.x' 2017-08-04 14:02:01 +02:00
Torkel Ödegaard
c0b0a54a8f fix: search bug where search was hidden when you click starred or tags filter links, fixes #8981 2017-08-04 14:01:09 +02:00
Sébastien Fievet
8e618bc169 Fix some typos in alerting documentation (#8986) 2017-08-04 10:08:41 +01:00
Daniel Lee
6131347806 graph: adds decimals option for y-axis
Fixes #8187
2017-08-03 17:57:04 +02:00
Daniel Lee
ef0c90b9ca graph: change tick decimal calculation for y-axis
Fixes #8872. Use the automatic calculation by Flot to get the
number of decimal places for ticks on the y-axis rather than
the number of decimal places for the min value.
2017-08-03 16:58:31 +02:00
Daniel Lee
1ce134cc6f docs: fixes #8972. Note on clustering and alerting. 2017-08-03 15:37:04 +02:00
David Wittman
8f5fbb4254 Fix typo in PagerDuty notifier options template (#8978) 2017-08-03 08:57:59 +02:00
Torkel Ödegaard
c7ca4830a8 Merge branch 'v4.4.x' 2017-08-03 08:56:46 +02:00
Torkel Ödegaard
1372d2e517 fix: update user permissions validation was not working properly, fixes #8977 2017-08-03 08:56:34 +02:00
Alexander Zobnin
77b7f4b376 heatmap: add unit tests for convertToCards() 2017-08-02 21:27:10 +03:00
Alexander Zobnin
c7e8b98d14 heatmap: minor refactor, don't repeat cards stats calculation 2017-08-02 21:24:59 +03:00
Torkel Ödegaard
8d7186d40d Merge branch 'v4.4.x' 2017-08-02 17:33:19 +02:00
Torkel Ödegaard
3dc9d76b38 fix: viewer role fix, fixes #8976 2017-08-02 17:33:06 +02:00
Torkel Ödegaard
a5bdfec0de ES: return .raw fields in field lookups, closes #8975 2017-08-02 16:52:43 +02:00
Daniel Lee
b5017d1e18 docs: var in singlestat panel. Fixes #8563 2017-08-02 16:44:43 +02:00
Daniel Lee
b241b98196 singlestat: fix for variable
in the prefix or postfix fields and when adding a gauge.
Previously the template variable substition was only done
when not rendering the gauge.
2017-08-02 16:40:26 +02:00
Torkel Ödegaard
a5d5f3d82f feat: add ad hoc filters directly from table panel cells, kibana 3 style, #8052 2017-08-02 16:15:22 +02:00
Torkel Ödegaard
c17b5d1306 table: minor table options improvement 2017-08-02 12:34:36 +02:00
Torkel Ödegaard
ede827f5c0 feat: Elasticsearch change to how queries without date histogram are transformed into Grafana data stucture, now it is processed into a table structure instead of json structure 2017-08-02 12:15:39 +02:00
Torkel Ödegaard
6224a25e42 feat: Elasticsearch filtering wip, moved to typescript 2017-08-02 11:16:37 +02:00
Alexander Zobnin
f7ea08dba7 heatmap: fix rendering tests 2017-08-01 16:51:55 +03:00
Phil Porada
814d164e5b Typo fix (#8966) 2017-08-01 14:44:57 +01:00
Alexander Zobnin
663a3293ee heatmap: some legend fixes 2017-08-01 16:23:01 +03:00
Alexander Zobnin
b01a4e6583 heatmap: use the same color for selection as for graph 2017-08-01 16:21:40 +03:00
Alexander Zobnin
f64ebf538c heatmap: minor legend fixes 2017-08-01 15:25:52 +03:00
Alexander Zobnin
91a921e12d heatmap: add show legend option 2017-08-01 14:07:52 +03:00
Alexander Zobnin
e72baca4a7 heatmap: fix black selection area 2017-08-01 13:54:09 +03:00
Alexander Zobnin
2aa26c98b6 heatmap: initial legend 2017-08-01 13:53:16 +03:00
Torkel Ödegaard
ae3e869d70 updated download links in docs 2017-08-01 10:18:48 +02:00
Torkel Ödegaard
deab5a54bf Merge branch 'master' of github.com:grafana/grafana 2017-08-01 09:49:37 +02:00
Torkel Ödegaard
ecfe28d7ac packaging: added strech to publish script, closes #8737 2017-08-01 09:49:26 +02:00
Torkel Ödegaard
9fb22ef86c Update CHANGELOG.md 2017-08-01 09:44:45 +02:00
Torkel Ödegaard
5d2054323b Merge branch 'aws-instance-attribute-tags' of https://github.com/paco3346/grafana into paco3346-aws-instance-attribute-tags 2017-08-01 09:38:58 +02:00
Torkel Ödegaard
1e4b0f01d6 Merge branch 'v4.4.x' 2017-08-01 09:18:39 +02:00
Torkel Ödegaard
6d9cbdd59e updated version to v4.4.2 2017-08-01 09:14:49 +02:00
Torkel Ödegaard
c4eadb576e fix: graphite bug fix introduced in recent commit 2017-07-31 22:39:56 +02:00
Torkel Ödegaard
7de1c0eaa2 Update CHANGELOG.md 2017-07-31 22:37:11 +02:00
Torkel Ödegaard
73a1a262ef Merge branch 'v4.4.x' 2017-07-31 22:33:36 +02:00
Torkel Ödegaard
e9989cb690 fix: make it easier to close search by clicking outside result container, fixes #8848 2017-07-31 22:33:22 +02:00
Torkel Ödegaard
0fcc87010a fix: cloudwatch fix for templating namespace argument to metrics tempalting function, fixes #8965 2017-07-31 22:30:49 +02:00
Mitsuhiro Tanda
91a533d948 (cloudwatch) high resolution custom metrics (#8958)
* support 1 second resolution Custom Metrics

* upgrade to aws-sdk-go v1.10.18

* simplify period calculation

* add test

* fix period calculation bug
2017-07-31 21:19:19 +02:00
squain
ede6d71e72 Fix typo in alert_howto.html (#8964) 2017-07-31 21:16:39 +02:00
Torkel Ödegaard
4d82a1076a Create CODE_OF_CONDUCT.md (#8960) 2017-07-31 17:31:05 +02:00
Torkel Ödegaard
44fbd3ec9f feat: calls to Graphite api /metrics/find now include panel or dashboard time ranges in some scenarios, closes #8055 2017-07-31 17:21:25 +02:00
Alexander Zobnin
c79a68dcd1 heatmap: refactor, build cards before rendering 2017-07-31 18:15:03 +03:00
Alexander Zobnin
55b24be115 heatmap: refactor, directive for color legend 2017-07-31 17:45:05 +03:00
Torkel Ödegaard
bf7516d9bf Update CHANGELOG.md 2017-07-31 16:06:29 +02:00
Torkel Ödegaard
81dc64d4ec Update CHANGELOG.md 2017-07-31 16:05:56 +02:00
Torkel Ödegaard
c7c5730c40 Merge branch 'v4.4.x' 2017-07-31 16:04:31 +02:00
Torkel Ödegaard
34cda65998 fix: png rendering api & timeout parameter now works as it should AND default render timeout increased from 30 to 60 seconds, fixes #8710 2017-07-31 16:04:04 +02:00
Torkel Ödegaard
61d8eb1fac Merge branch 'v4.4.x' 2017-07-31 15:07:22 +02:00
Torkel Ödegaard
d630f3d59e Merge branch 'external-user-mng' into v4.4.x 2017-07-31 15:07:01 +02:00
Torkel Ödegaard
06e87c151f feat: added settings to sample ini #8768 2017-07-31 15:04:47 +02:00
Torkel Ödegaard
73563d087c feat: more work on #8768 2017-07-31 14:39:33 +02:00
Torkel Ödegaard
23558c61d4 feat: wip work on #8768 2017-07-31 13:03:42 +02:00
Alexander Zobnin
ef9dd014c7 heatmap: add color scale options, issue #8539 2017-07-31 14:03:03 +03:00
Torkel Ödegaard
5406481e7b Update CHANGELOG.md 2017-07-31 12:17:46 +02:00
Torkel Ödegaard
510ad001b4 Update CHANGELOG.md 2017-07-31 12:16:29 +02:00
Dave Hall
0c70d271dc Support large github organisations (#8846)
* Add new HttpGetResponse struct type
* Modify HttpGet() return to use HttpGetResponse
* Look up _all_ the teams the user is a member of
2017-07-31 12:13:29 +02:00
Cedric Cellier
417c5163dd Fix typos (#8954)
Some being user visible.
2017-07-31 12:12:28 +02:00
Fredrik Wendt
5542309170 fixed incorrect header text (#8952)
Status code now replaced with Query parameters
2017-07-29 15:34:22 +01:00
Fredrik Wendt
6b344d0158 removed incorrect HTTP response data (#8949)
the example response body contained incorrect out-of-place data, presumably from a copy-paste operation
2017-07-28 09:25:30 +02:00
Daniel Lee
22758d5112 Merge branch 'v4.4.x' 2017-07-27 14:40:33 +02:00
Daniel Lee
7b768bca3f singlestat: change threshold check in flot gauge
Fixes #5515. Flot gauge has its own threshold check that is different
from the threshold check in singlestat. This changes the flot check to
be exclusive (same as the singlestat check). E.g. if the threshold is
10, then the value 10 is over the threshold.
2017-07-27 14:34:29 +02:00
amitkumar912
c4683f1ae8 Opentsdb datasource labeling fix (#8929)
* Fix Labeling issue when hiding Queries.

Issue #8928

* Fix spacing.

* Replacing tabs with spaces.

* Fix for jshint
2017-07-26 21:27:42 +02:00
Alexander Zobnin
cb8ecb2d5f Heatmap fixes (adapted for v4.4.x branch) (#8920)
* heatmap: fix converting error when series contains 0 and log scale is selected, issue #8884

* heatmap: fix app crash when Y min set to 0 with log scale

* heatmap: fix tooltip for 'zero' buckets in log scale

* heatmap: fix tooltip histogram for log scales

* heatmap: fix flicker of the highlighted element

this was caused by too often fired mouseenter/mouseleave events

* heatmap: fix missing X axis option for log scales

* heatmap: fix missing zero bucket in tooltip histogram
2017-07-25 16:28:29 +02:00
Torkel Ödegaard
ce4939bd56 Update CHANGELOG.md 2017-07-24 12:40:35 +02:00
Torkel Ödegaard
d46fd890a5 Merge branch 'v4.4.x' 2017-07-24 12:38:39 +02:00
Torkel Ödegaard
8ca08d65e7 docs: updated configuration docs with new defaults, #8743 2017-07-24 12:37:58 +02:00
Torkel Ödegaard
f5ed5c6529 settings(change): changed default value for allow sign up to false, closes #8743, and changed default option allow_org_create to false 2017-07-24 12:36:42 +02:00
Torkel Ödegaard
9825cd1ebb Update CHANGELOG.md 2017-07-24 12:32:22 +02:00
Torkel Ödegaard
0f33ac9e10 Merge branch 'master' of github.com:grafana/grafana 2017-07-24 12:30:43 +02:00
Torkel Ödegaard
24a79a6bea Merge branch 'v4.4.x' 2017-07-24 12:30:28 +02:00
Torkel Ödegaard
723f5bc9e8 fix: dsahboard_version data column type changed to MEDIUMTEXT, fixes #8813 2017-07-24 12:30:13 +02:00
Torkel Ödegaard
287c222fc7 Update CHANGELOG.md 2017-07-24 12:25:49 +02:00
Torkel Ödegaard
6956110497 Merge branch 'master' of github.com:grafana/grafana 2017-07-24 12:23:33 +02:00
Torkel Ödegaard
f500dfd1e5 Update CHANGELOG.md 2017-07-24 12:23:07 +02:00
Torkel Ödegaard
cd0e1a8978 Merge branch 'v4.4.x' 2017-07-24 12:21:43 +02:00
Torkel Ödegaard
2d2800e710 fix: url did not update correctly when closing settings view by using ESC key, fixes #8869 2017-07-24 12:21:30 +02:00
Daniel Lee
4a678c2884 influxdb: fix for adding math query part
Fixes #8870. Fixes out of bound exception on adding a math query part
when there is no group by interval (or only one query part).
2017-07-22 01:31:26 +02:00
Nicholas Nadeau
1a25b78ef2 homogenized docker run command (#8907)
There are three locations where the `docker run` command is referenced:
- 2x http://docs.grafana.org/installation/docker/
- 1x https://grafana.com/grafana/download?platform=docker

The fix syncs the given `docker run` command arguments with the other two.
2017-07-21 21:46:54 +02:00
Kakuya Ando
bbfdfc012f fix(prometheus) when tag value duplicate, tags not working. (#8040) 2017-07-21 09:51:25 +02:00
Mitsuhiro Tanda
b16b649c9b (cloudwatch) add new elb metrics (#8894) 2017-07-20 14:12:56 +02:00
Mitsuhiro Tanda
9d50ab8fb5 (cloudwatch) check auth type before assume role (#8895) 2017-07-20 14:11:51 +02:00
Alexander Zobnin
af56cc4c28 Panel Alertlist: use dashboard timezone (#8880)
* panel-alertlist: use dashboard timezone, fixes #8874

* alert state history: use dashboard timezone, issue #8874

* alert state history: minor refactor
2017-07-19 20:45:57 +02:00
Mitsuhiro Tanda
e8157f01ec add new dashboard shortcut 2017-07-19 17:54:34 +09:00
Mitsuhiro Tanda
aecc6860e3 set focus on text field when opening panel/query editor (#8879)
* (prometheus) set focus to top expression when opening editor

* (text panel) set focus to top expression when opening editor
2017-07-19 10:33:04 +02:00
Alexander Zobnin
9bbc942534 table-panel: clickable cell link - draft (#8738)
* table-panel: clickable cell link - draft

* table-panel: clickable cell link - fix link target option

* table-panel: fix undefined columnStyle.link

* table-panel: option to highlight cell with link

* table-panel: render variables for all cells in row

* table-panel: remove cell highlighting

* table-panel: add help for URL field

* linkPopover directive for link info in table panel

* table-panel: add link info popover to cells

* table-panel: use native popover instead directive

* table-panel: link drop refactor, remove unused code

* table-panel: fix unclickable link when drop is opened

* refactoring: minor refactoring to #8738, do not think we need a full blown popover for the links, simple tooltip is enough and more efficient, sadly we do not have a modern tooltip framework, still using old bootstrap 2.3 tooltip

* table-panel: add tests for link rendering
2017-07-18 20:59:34 +02:00
Torkel Ödegaard
13c966c178 Update CHANGELOG.md 2017-07-18 20:59:16 +02:00
Alexander Gängel
4073949af0 add templating for prometheus monitoring other promethues (#8845) 2017-07-18 19:52:29 +02:00
Mitsuhiro Tanda
a6920eb2ff (prometheus) replace each by for (#8881) 2017-07-18 19:50:44 +02:00
Mitsuhiro Tanda
32f9a42d5e Fix performance degradation by always setting fill = 0.001 (#8868)
* add benchmark

* fix, prevent plotLineArea() call if fill == 0

* remove benchmark
2017-07-17 20:50:58 +02:00
Daniel Koehler
c5f6cf0809 fix for wrong locale and text issues #8840 (#8854)
fixes https://github.com/grafana/grafana/issues/8840
by setting a default locale. Also uses fromNow(true) to work arround the replace.
2017-07-14 21:58:27 +02:00
Matt Toback
a045f175b6 Fixed typo 2017-07-14 12:20:04 -04:00
Adam Johnson
17d57ab074 docs(testdata): add missing word (#8856) 2017-07-13 19:52:59 +02:00
Torkel Ödegaard
74984f8da6 Update latest.json 2017-07-12 10:19:02 +02:00
Torkel Ödegaard
e4950c2dc1 fix: elasticsearch with template variable with terms agg on IP field, fixes #8662 2017-07-12 07:43:30 +02:00
bergquist
4844bf9be3 docs(prometheus): updates invalid template example 2017-07-12 07:37:44 +02:00
ajrnz
43974898c1 Interpolate the field property in elastic search term queries (#8663)
* Interpolate the field property in elastic search term queries

* more defensive interpolation of query.field in ES templates
2017-07-12 07:25:56 +02:00
Torkel Ödegaard
bb3bcbe6a1 fix: for issue in graph panel axes labels when iframe embedding, fixes #8827 2017-07-12 07:12:05 +02:00
gomlgs
228c210379 Cloudwatch: Fix bug with obtaining IAM roles within ECS containers. (#8766)
Fixes #8750.
2017-07-12 06:55:59 +02:00
Alexander Gängel
92937c591f upgrade grunt-sass to 2.0.0 (#8808) 2017-07-12 06:55:15 +02:00
Denis Doria
89822acf38 More precise detection for self reference variable on templates (#8814)
This should close the bug #8773
2017-07-12 06:54:32 +02:00
Moody Saada
2d99518f90 Update annotations.md typo (#8830) 2017-07-12 06:53:28 +02:00
Alin Sinpalean
5bffdfe9a4 When converting Prometheus results to table, handle the case where the returned series have non-uniform sets of labels. (#8826) 2017-07-12 06:52:59 +02:00
Liang Jiameng
f8d22385ce add a placeholder to DingTalk Url (#8820) 2017-07-10 16:51:03 +02:00
Daniel Lee
1dedc886f2 docs: DingDing notifier 2017-07-10 12:22:21 +02:00
Daniel Lee
1ccfca109f docs: instructions for DingDing notifier 2017-07-10 12:16:40 +02:00
Daniel Lee
68e7219135 docs: add missing parameter api call 2017-07-09 02:00:50 +02:00
Daniel Lee
3a075be7e9 cloudwatch: make dimension text in alias popover clearer 2017-07-07 18:17:05 +02:00
Daniel Lee
fc82de1543 docs: style fix 2017-07-07 13:00:13 +02:00
Daniel Lee
c296e73b83 docs: x-axis mode for graph panel 2017-07-07 12:25:42 +02:00
0x6875790d0a
a622c55b1b (feat) Add image to LINE notify (#8771) 2017-07-07 11:20:27 +02:00
Daniel Lee
e6f9546a7c api: add no cache headers for IE11
Adds pragma and expires headers for API calls so that IE11 does not
cache GET calls. Ref #5356
2017-07-06 18:56:22 +02:00
Daniel Lee
fe3bcd3678 Merge branch 'v4.4.x' 2017-07-06 10:11:07 +02:00
Torkel Ödegaard
cff1c37064 fix: InfluxDB direct access with normal inflxudb credentials was not sent correctly, fixes #8789 2017-07-06 09:46:31 +02:00
Torkel Ödegaard
e5b499a958 fix: Text area css issue prevented scrolling, fixes #8797 2017-07-06 09:36:57 +02:00
Torkel Ödegaard
1994b767d3 fix: InfluxDB direct access with normal inflxudb credentials was not sent correctly, fixes #8789 2017-07-05 22:15:28 +02:00
Daniel Lee
eca11e862e docs: update for panel sharing options 2017-07-05 22:14:04 +02:00
Min-Zhong "John" Lu
fbff905c57 Fix broken table row in prometheus.md (#8779)
"Metric Lookup" row in Query editor was broken :(
2017-07-05 22:14:03 +02:00
Daniel Lee
a4266319ad packaging: v4.4.1 2017-07-05 22:14:03 +02:00
Daniel Lee
49113c1ccb Add v4.4.1 patch release 2017-07-05 22:14:03 +02:00
Daniel Lee
6d4c29ea9b migrations: dashboard version migration handles nulls
If a dashboard has a null value for updated_by then the migration
for the dashboard version table fails. This change uses coalesce to
set -1 instead of null when inserting into the created_by column
which has a non-null constraint. Fixes #8783.
2017-07-05 22:14:03 +02:00
Daniel Lee
ab53b05c39 docs: fixes #8785 2017-07-05 22:14:03 +02:00
Daniel Lee
ba1c79b7a8 package.json to v5.0.0-pre1 2017-07-05 22:14:03 +02:00
Daniel Lee
de9ebc9a74 packaging: updates for v4.4.0 2017-07-05 22:12:51 +02:00
Daniel Lee
9341412acc release: v4.4.1 2017-07-05 22:06:00 +02:00
Daniel Lee
16cda723d3 migrations: dashboard version migration handles nulls
If a dashboard has a null value for updated_by then the migration
for the dashboard version table fails. This change uses coalesce to
set -1 instead of null when inserting into the created_by column
which has a non-null constraint. Fixes #8783.
2017-07-05 22:06:00 +02:00
Daniel Lee
36a1ab48c5 packaging: updates for v4.4.0 2017-07-05 22:04:27 +02:00
Michael Ambrose
aa3a737fea Updated cloudwatch doc to be more clear on ec2_instance_attribute usage and added Tag selection example 2017-06-07 16:58:01 -04:00
Michael Ambrose
f0169656ba Added test to for Cloudwatch EC2 tag selection 2017-06-07 16:53:49 -04:00
Michael Ambrose
525da95f49 Updated cloudwatch plugin to allow specific tag selection
Tags come back from AWS as a key value pair inside an array
This array is now converted to an object
Tags can be selected when using the 'ec2_instance_attribute' query
Example: `ec2_instance_attribute(us-east-1, Tags.Name, { "tag:Grafana": [ "true" ] })`
2017-06-07 16:53:49 -04:00
577 changed files with 44396 additions and 11296 deletions

3
.floo
View File

@@ -1,3 +0,0 @@
{
"url": "https://floobits.com/raintank/grafana"
}

View File

@@ -1,12 +0,0 @@
#*
*.o
*.pyc
*.pyo
*~
extern/
node_modules/
tmp/
data/
vendor/
public_gen/
dist/

2
.gitignore vendored
View File

@@ -39,3 +39,5 @@ profile.cov
/pkg/cmd/grafana-cli/grafana-cli
/pkg/cmd/grafana-server/grafana-server
/examples/*/dist
/packaging/**/*.rpm
/packaging/**/*.deb

View File

@@ -1,4 +1,82 @@
# 4.4.0 (unreleased)
# 5.0.0 (unreleased)
### 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
# 4.5.0 (2017-09-14)
## Fixes & Enhancements since beta1
* **Security**: Security fix for api vulnerability (in multiple org setups).
* **Shortcuts**: Adds shortcut for creating new dashboard [#8876](https://github.com/grafana/grafana/pull/8876) thx [@mtanda](https://github.com/mtanda)
* **Graph**: Right Y-Axis label position fixed [#9172](https://github.com/grafana/grafana/pull/9172)
* **General**: Improve rounding of time intervals [#9197](https://github.com/grafana/grafana/pull/9197), thx [@alin-amana](https://github.com/alin-amana)
# 4.5.0-beta1 (2017-09-05)
## New Features
* **Table panel**: Render cell values as links that can have an url template that uses variables from current table row. [#3754](https://github.com/grafana/grafana/issues/3754)
* **Elasticsearch**: Add ad hoc filters directly by clicking values in table panel [#8052](https://github.com/grafana/grafana/issues/8052).
* **MySQL**: New rich query editor with syntax highlighting
* **Prometheus**: New rich query editor with syntax highlighting, metric & range auto complete and integrated function docs. [#5117](https://github.com/grafana/grafana/issues/5117)
## Enhancements
* **GitHub OAuth**: Support for GitHub organizations with 100+ teams. [#8846](https://github.com/grafana/grafana/issues/8846), thx [@skwashd](https://github.com/skwashd)
* **Graphite**: Calls to Graphite api /metrics/find now include panel or dashboad time range (from & until) in most cases, [#8055](https://github.com/grafana/grafana/issues/8055)
* **Graphite**: Added new graphite 1.0 functions, available if you set version to 1.0.x in data source settings. New Functions: mapSeries, reduceSeries, isNonNull, groupByNodes, offsetToZero, grep, weightedAverage, removeEmptySeries, aggregateLine, averageOutsidePercentile, delay, exponentialMovingAverage, fallbackSeries, integralByInterval, interpolate, invert, linearRegression, movingMin, movingMax, movingSum, multiplySeriesWithWildcards, pow, powSeries, removeBetweenPercentile, squareRoot, timeSlice, closes [#8261](https://github.com/grafana/grafana/issues/8261)
- **Elasticsearch**: Ad-hoc filters now use query phrase match filters instead of term filters, works on non keyword/raw fields [#9095](https://github.com/grafana/grafana/issues/9095).
### Breaking change
* **InfluxDB/Elasticsearch**: The panel & data source option named "Group by time interval" is now named "Min time interval" and does now always define a lower limit for the auto group by time. Without having to use `>` prefix (that prefix still works). This should in theory have close to zero actual impact on existing dashboards. It does mean that if you used this setting to define a hard group by time interval of, say "1d", if you zoomed to a time range wide enough the time range could increase above the "1d" range as the setting is now always considered a lower limit.
## Changes
* **InfluxDB**: Change time range filter for absolute time ranges to be inclusive instead of exclusive [#8319](https://github.com/grafana/grafana/issues/8319), thx [@Oxydros](https://github.com/Oxydros)
* **InfluxDB**: Added paranthesis around tag filters in queries [#9131](https://github.com/grafana/grafana/pull/9131)
## Bug Fixes
* **Modals**: Maintain scroll position after opening/leaving modal [#8800](https://github.com/grafana/grafana/issues/8800)
* **Templating**: You cannot select data source variables as data source for other template variables [#7510](https://github.com/grafana/grafana/issues/7510)
* **MySQL/Postgres**: Fix for max_idle_conn option default which was wrongly set to zero which does not mean unlimited but means zero, which in practice kind of disables connection pooling, which is not good. Fixes [#8513](https://github.com/grafana/grafana/issues/8513)
# 4.4.3 (2017-08-07)
## Bug Fixes
* **Search**: Fix for issue that casued search view to hide when you clicked starred or tags filters, fixes [#8981](https://github.com/grafana/grafana/issues/8981)
* **Modals**: ESC key now closes modal again, fixes [#8981](https://github.com/grafana/grafana/issues/8988), thx [@j-white](https://github.com/j-white)
# 4.4.2 (2017-08-01)
## Bug Fixes
* **GrafanaDB(mysql)**: Fix for dashboard_version.data column type, now changed to MEDIUMTEXT, fixes [#8813](https://github.com/grafana/grafana/issues/8813)
* **Dashboard(settings)**: Closing setting views using ESC key did not update url correctly, fixes [#8869](https://github.com/grafana/grafana/issues/8869)
* **InfluxDB**: Wrong username/password parameter name when using direct access, fixes [#8789](https://github.com/grafana/grafana/issues/8789)
* **Forms(TextArea)**: Bug fix for no scroll in text areas [#8797](https://github.com/grafana/grafana/issues/8797)
* **Png Render API**: Bug fix for timeout url parameter. It now works as it should. Default value was also increased from 30 to 60 seconds [#8710](https://github.com/grafana/grafana/issues/8710)
* **Search**: Fix for not being able to close search by clicking on right side of search result container, [8848](https://github.com/grafana/grafana/issues/8848)
* **Cloudwatch**: Fix for using variables in templating metrics() query, [8965](https://github.com/grafana/grafana/issues/8965)
## Changes
* **Settings(defaults)**: allow_sign_up default changed from true to false [#8743](https://github.com/grafana/grafana/issues/8743)
* **Settings(defaults)**: allow_org_create default changed from true to false
# 4.4.1 (2017-07-05)
## Bug Fixes
* **Migrations**: migration fails where dashboard.created_by is null [#8783](https://github.com/grafana/grafana/issues/8783)
# 4.4.0 (2017-07-04)
## New Features
**Dashboard History**: View dashboard version history, compare any two versions (summary & json diffs), restore to old version. This big feature

46
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@grafana.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -1,4 +1,4 @@
[Grafana](https://grafana.com) [![Circle CI](https://circleci.com/gh/grafana/grafana.svg?style=svg)](https://circleci.com/gh/grafana/grafana)
[Grafana](https://grafana.com) [![Circle CI](https://circleci.com/gh/grafana/grafana.svg?style=svg)](https://circleci.com/gh/grafana/grafana) [![Go Report Card](https://goreportcard.com/badge/github.com/grafana/grafana)](https://goreportcard.com/report/github.com/grafana/grafana)
================
[Website](https://grafana.com) |
[Twitter](https://twitter.com/grafana) |
@@ -9,64 +9,8 @@ Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB.
![](http://docs.grafana.org/assets/img/features/dashboard_ex1.png)
- [Install instructions](http://docs.grafana.org/installation/)
- [What's New in Grafana 2.0](http://docs.grafana.org/guides/whats-new-in-v2/)
- [What's New in Grafana 2.1](http://docs.grafana.org/guides/whats-new-in-v2-1/)
- [What's New in Grafana 2.5](http://docs.grafana.org/guides/whats-new-in-v2-5/)
- [What's New in Grafana 3.0](http://docs.grafana.org/guides/whats-new-in-v3/)
- [What's New in Grafana 4.0](http://docs.grafana.org/guides/whats-new-in-v4/)
- [What's New in Grafana 4.1](http://docs.grafana.org/guides/whats-new-in-v4-1/)
- [What's New in Grafana 4.2](http://docs.grafana.org/guides/whats-new-in-v4-2/)
- [What's New in Grafana 4.3](http://docs.grafana.org/guides/whats-new-in-v4-3/)
## Features
### Graphing
- Fast rendering, even over large timespans
- Click and drag to zoom
- Multiple Y-axis, logarithmic scales
- Bars, Lines, Points
- Smart Y-axis formatting
- Series toggles & color selector
- Legend values, and formatting options
- Grid thresholds, axis labels
- [Annotations](http://docs.grafana.org/reference/annotations/)
- Any panel can be rendered to PNG (server side using phantomjs)
### Dashboards
- Create, edit, save & search dashboards
- Change column spans and row heights
- Drag and drop panels to rearrange
- [Templating](http://docs.grafana.org/reference/templating/)
- [Scripted dashboards](http://docs.grafana.org/reference/scripting/)
- [Dashboard playlists](http://docs.grafana.org/reference/playlist/)
- [Time range controls](http://docs.grafana.org/reference/timerange/)
- [Share snapshots publicly](http://docs.grafana.org/v2.0/reference/sharing/)
### InfluxDB
- Use InfluxDB as a metric data source, annotation source
- Query editor with field and tag typeahead, easy group by and function selection
### Graphite
- Graphite target expression parser
- Feature rich query composer
- Quickly add and edit functions & parameters
- Templated queries
- [See it in action](http://docs.grafana.org/datasources/graphite/)
### Elasticsearch, Prometheus & OpenTSDB
- Feature rich query editor UI
### Alerting
- Define alert rules using graphs & query conditions
- Schedule & evalute alert rules, send notifications to Slack, Hipchat, Email, PagerDuty, etc.
## Requirements
There are no dependencies except an external time series data store. For dashboards and user accounts Grafana can use an embedded
database (sqlite3) or you can use an external SQL data base like MySQL or Postgres.
## Installation
Head to [grafana.org](http://docs.grafana.org/installation/) and [download](https://grafana.com/get)
Head to [docs.grafana.org](http://docs.grafana.org/installation/) and [download](https://grafana.com/get)
the latest release.
If you have any problems please read the [troubleshooting guide](http://docs.grafana.org/installation/troubleshooting/).
@@ -83,27 +27,10 @@ the latest master builds [here](https://grafana.com/grafana/download)
- Go 1.8.1
- NodeJS LTS
### Get Code
```bash
go get github.com/grafana/grafana
```
Since imports of dependencies use the absolute path `github.com/grafana/grafana` within the `$GOPATH`,
you will need to put your version of the code in `$GOPATH/src/github.com/grafana/grafana` to be able
to develop and build grafana on a cloned repository. To do so, you can clone your forked repository
directly to `$GOPATH/src/github.com/grafana` or you can create a symbolic link from your version
of the code to `$GOPATH/src/github.com/grafana/grafana`. The last options makes it possible to change
easily the grafana repository you want to build.
```bash
go get github.com/*your_account*/grafana
mkdir $GOPATH/src/github.com/grafana
ln -s $GOPATH/src/github.com/*your_account*/grafana $GOPATH/src/github.com/grafana/grafana
```
### Building the backend
```bash
cd $GOPATH/src/github.com/grafana/grafana
go get github.com/grafana/grafana
cd ~/go/src/github.com/grafana/grafana
go run build.go setup
go run build.go build
```
@@ -122,8 +49,7 @@ npm run build
To build the frontend assets only on changes:
```bash
sudo npm install -g grunt-cli # to do only once to install grunt command line interface
grunt watch
npm run dev
```
### Recompile backend on source change
@@ -133,11 +59,6 @@ go get github.com/Unknwon/bra
bra run
```
### Running
```bash
./bin/grafana-server
```
Open grafana in your browser (default: `http://localhost:3000`) and login with admin user (default: `user/pass = admin/admin`).
### Dev config
@@ -148,9 +69,6 @@ You only need to add the options you want to override. Config files are applied
1. grafana.ini
1. custom.ini
## Create a pull request
Before or after you create a pull request, sign the [contributor license agreement](http://docs.grafana.org/project/cla/).
## Contribute
If you have any idea for an improvement or found a bug do not hesitate to open an issue.
And if you have time clone this repo and submit a pull request and help me make Grafana

View File

@@ -1,31 +1,29 @@
# Roadmap (2017-04-23)
# Roadmap (2017-08-29)
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)
- New Heatmap Panel (Implemented and available in master)
- Support for MySQL & Postgres as data sources (Work started and a alpha version for MySQL is available in master)
- User Groups & Dashboard folders with ACLs (work started, not yet completed, https://github.com/grafana/grafana/issues/1611#issuecomment-287742633)
- Improve new user UX
- Improve docs
- Support for alerting for Elasticsearch (can be tested in [branch](https://github.com/grafana/grafana/tree/alerting-elasticsearch) but needs more work)
- Graph annotations (create from grafana, region annotations, better annotation viz)
- Improve alerting (clustering, silence rules)
- Release Grafana v4.5 with fixes and minor enhancements
- Release Grafana v5
- User groups
- Dashboard folders
- Dashboard permissions (on folders as well), permissions on groups or users
- New Dashboard layout engine
- New sidemenu & nav UX
- Elasticsearch alerting
### Long term
- Improved dashboard panel layout engine (to make it easier and enable more flexible layouts)
- Backend plugins to support more Auth options, Alerting data sources & notifications
- Universial time series transformations for any data source (meta queries)
- Reporting
- Web socket & live data streams
- Migrate to Angular2
- Migrate to Angular2 or react
### Outside contributions
We know this is being worked on right now by contributors (and we hope to merge it when it's ready).
- Dashboard revisions (be able to revert dashboard changes)
- Clustering for alert engine (load distribution)

View File

@@ -76,8 +76,10 @@ password =
# Example: mysql://user:secret@host:port/database
url =
# Max idle conn setting default is 2
max_idle_conn = 2
# Max conn setting default is 0 (mean not set)
max_idle_conn =
max_open_conn =
# For "postgres", use either "disable", "require" or "verify-full"
@@ -184,10 +186,10 @@ snapshot_TTL_days = 90
#################################### Users ####################################
[users]
# disable user signup / registration
allow_sign_up = true
allow_sign_up = false
# Allow non admin users to create organizations
allow_org_create = true
allow_org_create = false
# Set to true to automatically assign new users to the default organization (id 1)
auto_assign_org = true
@@ -204,6 +206,11 @@ login_hint = email or username
# Default UI theme ("dark" or "light")
default_theme = dark
# External user management
external_manage_link_url =
external_manage_link_name =
external_manage_info =
[auth]
# Set to true to disable (hide) the login form, useful if you use OAuth
disable_login_form = false

View File

@@ -85,8 +85,10 @@
# For "sqlite3" only, path relative to data_path setting
;path = grafana.db
# Max idle conn setting default is 2
;max_idle_conn = 2
# Max conn setting default is 0 (mean not set)
;max_idle_conn =
;max_open_conn =
@@ -191,6 +193,11 @@
# Default UI theme ("dark" or "light")
;default_theme = dark
# External user management, these options affect the organization users view
;external_manage_link_url =
;external_manage_link_name =
;external_manage_info =
[auth]
# Set to true to disable (hide) the login form, useful if you use OAuth, defaults to false
;disable_login_form = false

View File

@@ -32,6 +32,7 @@ add ./files/my_htpasswd /etc/nginx/.htpasswd
# Add system service config
add ./files/nginx.conf /etc/nginx/nginx.conf
add ./files/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Nginx
#
# graphite
@@ -39,6 +40,7 @@ expose 80
# Carbon line receiver port
expose 2003
# Carbon cache query port
expose 7002

View File

@@ -0,0 +1,93 @@
FROM phusion/baseimage:0.9.22
MAINTAINER Denys Zhdanov <denis.zhdanov@gmail.com>
RUN apt-get -y update \
&& apt-get -y upgrade \
&& apt-get -y --force-yes install vim \
nginx \
python-dev \
python-flup \
python-pip \
python-ldap \
expect \
git \
memcached \
sqlite3 \
libffi-dev \
libcairo2 \
libcairo2-dev \
python-cairo \
python-rrdtool \
pkg-config \
nodejs \
&& rm -rf /var/lib/apt/lists/*
# fix python dependencies (LTS Django and newer memcached/txAMQP)
RUN pip install django==1.8.18 \
python-memcached==1.53 \
txAMQP==0.6.2 \
&& pip install --upgrade pip
# install whisper
RUN git clone -b 1.0.2 --depth 1 https://github.com/graphite-project/whisper.git /usr/local/src/whisper
WORKDIR /usr/local/src/whisper
RUN python ./setup.py install
# install carbon
RUN git clone -b 1.0.2 --depth 1 https://github.com/graphite-project/carbon.git /usr/local/src/carbon
WORKDIR /usr/local/src/carbon
RUN pip install -r requirements.txt \
&& python ./setup.py install
# install graphite
RUN git clone -b 1.0.2 --depth 1 https://github.com/graphite-project/graphite-web.git /usr/local/src/graphite-web
WORKDIR /usr/local/src/graphite-web
RUN pip install -r requirements.txt \
&& python ./setup.py install
ADD conf/opt/graphite/conf/*.conf /opt/graphite/conf/
ADD conf/opt/graphite/webapp/graphite/local_settings.py /opt/graphite/webapp/graphite/local_settings.py
ADD conf/opt/graphite/webapp/graphite/app_settings.py /opt/graphite/webapp/graphite/app_settings.py
WORKDIR /opt/graphite/webapp
RUN mkdir -p /var/log/graphite/ \
&& PYTHONPATH=/opt/graphite/webapp django-admin.py collectstatic --noinput --settings=graphite.settings
# install statsd
RUN git clone -b v0.7.2 https://github.com/etsy/statsd.git /opt/statsd
ADD conf/opt/statsd/config.js /opt/statsd/config.js
# config nginx
RUN rm /etc/nginx/sites-enabled/default
ADD conf/etc/nginx/nginx.conf /etc/nginx/nginx.conf
ADD conf/etc/nginx/sites-enabled/graphite-statsd.conf /etc/nginx/sites-enabled/graphite-statsd.conf
# init django admin
ADD conf/usr/local/bin/django_admin_init.exp /usr/local/bin/django_admin_init.exp
ADD conf/usr/local/bin/manage.sh /usr/local/bin/manage.sh
RUN chmod +x /usr/local/bin/manage.sh \
&& /usr/local/bin/django_admin_init.exp
# logging support
RUN mkdir -p /var/log/carbon /var/log/graphite /var/log/nginx
ADD conf/etc/logrotate.d/graphite-statsd /etc/logrotate.d/graphite-statsd
# daemons
ADD conf/etc/service/carbon/run /etc/service/carbon/run
ADD conf/etc/service/carbon-aggregator/run /etc/service/carbon-aggregator/run
ADD conf/etc/service/graphite/run /etc/service/graphite/run
ADD conf/etc/service/statsd/run /etc/service/statsd/run
ADD conf/etc/service/nginx/run /etc/service/nginx/run
# default conf setup
ADD conf /etc/graphite-statsd/conf
ADD conf/etc/my_init.d/01_conf_init.sh /etc/my_init.d/01_conf_init.sh
# cleanup
RUN apt-get clean\
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# defaults
EXPOSE 80 2003-2004 2023-2024 8125/udp 8126
VOLUME ["/opt/graphite/conf", "/opt/graphite/storage", "/etc/nginx", "/opt/statsd", "/etc/logrotate.d", "/var/log"]
WORKDIR /
ENV HOME /root
CMD ["/sbin/my_init"]

View File

@@ -0,0 +1,11 @@
/var/log/*.log /var/log/*/*.log {
weekly
size 50M
missingok
rotate 10
compress
delaycompress
notifempty
copytruncate
su root syslog
}

View File

@@ -0,0 +1,36 @@
#!/bin/bash
conf_dir=/etc/graphite-statsd/conf
# auto setup graphite with default configs if /opt/graphite is missing
# needed for the use case when a docker host volume is mounted at an of the following:
# - /opt/graphite
# - /opt/graphite/conf
# - /opt/graphite/webapp/graphite
graphite_dir_contents=$(find /opt/graphite -mindepth 1 -print -quit)
graphite_conf_dir_contents=$(find /opt/graphite/conf -mindepth 1 -print -quit)
graphite_webapp_dir_contents=$(find /opt/graphite/webapp/graphite -mindepth 1 -print -quit)
graphite_storage_dir_contents=$(find /opt/graphite/storage -mindepth 1 -print -quit)
if [[ -z $graphite_dir_contents ]]; then
git clone -b 1.0.2 --depth 1 https://github.com/graphite-project/graphite-web.git /usr/local/src/graphite-web
cd /usr/local/src/graphite-web && python ./setup.py install
fi
if [[ -z $graphite_storage_dir_contents ]]; then
/usr/local/bin/django_admin_init.exp
fi
if [[ -z $graphite_conf_dir_contents ]]; then
cp -R $conf_dir/opt/graphite/conf/*.conf /opt/graphite/conf/
fi
if [[ -z $graphite_webapp_dir_contents ]]; then
cp $conf_dir/opt/graphite/webapp/graphite/local_settings.py /opt/graphite/webapp/graphite/local_settings.py
fi
# auto setup statsd with default config if /opt/statsd is missing
# needed for the use case when a docker host volume is mounted at an of the following:
# - /opt/statsd
statsd_dir_contents=$(find /opt/statsd -mindepth 1 -print -quit)
if [[ -z $statsd_dir_contents ]]; then
git clone -b v0.7.2 https://github.com/etsy/statsd.git /opt/statsd
cp $conf_dir/opt/statsd/config.js /opt/statsd/config.js
fi

View File

@@ -0,0 +1,96 @@
user www-data;
worker_processes 4;
pid /run/nginx.pid;
daemon off;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
##
# nginx-naxsi config
##
# Uncomment it if you installed nginx-naxsi
##
#include /etc/nginx/naxsi_core.rules;
##
# nginx-passenger config
##
# Uncomment it if you installed nginx-passenger
##
#passenger_root /usr;
#passenger_ruby /usr/bin/ruby;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}

View File

@@ -0,0 +1,31 @@
server {
listen 80;
root /opt/graphite/static;
index index.html;
location /media {
# django admin static files
alias /usr/local/lib/python2.7/dist-packages/django/contrib/admin/media/;
}
location /admin/auth/admin {
alias /usr/local/lib/python2.7/dist-packages/django/contrib/admin/static/admin;
}
location /admin/auth/user/admin {
alias /usr/local/lib/python2.7/dist-packages/django/contrib/admin/static/admin;
}
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
add_header 'Access-Control-Allow-Credentials' 'true';
}
}

View File

@@ -0,0 +1,4 @@
#!/bin/bash
rm -f /opt/graphite/storage/carbon-aggregator-a.pid
exec /usr/bin/python /opt/graphite/bin/carbon-aggregator.py start --debug 2>&1 >> /var/log/carbon-aggregator.log

View File

@@ -0,0 +1,4 @@
#!/bin/bash
rm -f /opt/graphite/storage/carbon-cache-a.pid
exec /usr/bin/python /opt/graphite/bin/carbon-cache.py start --debug 2>&1 >> /var/log/carbon.log

View File

@@ -0,0 +1,3 @@
#!/bin/bash
export PYTHONPATH=/opt/graphite/webapp && exec /usr/local/bin/gunicorn wsgi --workers=4 --bind=127.0.0.1:8080 --log-file=/var/log/gunicorn.log --preload --pythonpath=/opt/graphite/webapp/graphite

View File

@@ -0,0 +1,4 @@
#!/bin/bash
mkdir -p /var/log/nginx
exec /usr/sbin/nginx -c /etc/nginx/nginx.conf

View File

@@ -0,0 +1,4 @@
#!/bin/bash
exec /usr/bin/nodejs /opt/statsd/stats.js /opt/statsd/config.js >> /var/log/statsd.log 2>&1

View File

@@ -0,0 +1,35 @@
# The form of each line in this file should be as follows:
#
# output_template (frequency) = method input_pattern
#
# This will capture any received metrics that match 'input_pattern'
# for calculating an aggregate metric. The calculation will occur
# every 'frequency' seconds and the 'method' can specify 'sum' or
# 'avg'. The name of the aggregate metric will be derived from
# 'output_template' filling in any captured fields from 'input_pattern'.
#
# For example, if you're metric naming scheme is:
#
# <env>.applications.<app>.<server>.<metric>
#
# You could configure some aggregations like so:
#
# <env>.applications.<app>.all.requests (60) = sum <env>.applications.<app>.*.requests
# <env>.applications.<app>.all.latency (60) = avg <env>.applications.<app>.*.latency
#
# As an example, if the following metrics are received:
#
# prod.applications.apache.www01.requests
# prod.applications.apache.www01.requests
#
# They would all go into the same aggregation buffer and after 60 seconds the
# aggregate metric 'prod.applications.apache.all.requests' would be calculated
# by summing their values.
#
# Template components such as <env> will match everything up to the next dot.
# To match metric multiple components including the dots, use <<metric>> in the
# input template:
#
# <env>.applications.<app>.all.<app_metric> (60) = sum <env>.applications.<app>.*.<<app_metric>>
#
# Note that any time this file is modified, it will be re-read automatically.

View File

@@ -0,0 +1,5 @@
# This file takes a single regular expression per line
# If USE_WHITELIST is set to True in carbon.conf, any metrics received which
# match one of these expressions will be dropped
# This file is reloaded automatically when changes are made
^some\.noisy\.metric\.prefix\..*

View File

@@ -0,0 +1,75 @@
# This is a configuration file with AMQP enabled
[cache]
LOCAL_DATA_DIR =
# Specify the user to drop privileges to
# If this is blank carbon runs as the user that invokes it
# This user must have write access to the local data directory
USER =
# Limit the size of the cache to avoid swapping or becoming CPU bound.
# Sorts and serving cache queries gets more expensive as the cache grows.
# Use the value "inf" (infinity) for an unlimited cache size.
MAX_CACHE_SIZE = inf
# Limits the number of whisper update_many() calls per second, which effectively
# means the number of write requests sent to the disk. This is intended to
# prevent over-utilizing the disk and thus starving the rest of the system.
# When the rate of required updates exceeds this, then carbon's caching will
# take effect and increase the overall throughput accordingly.
MAX_UPDATES_PER_SECOND = 1000
# Softly limits the number of whisper files that get created each minute.
# Setting this value low (like at 50) is a good way to ensure your graphite
# system will not be adversely impacted when a bunch of new metrics are
# sent to it. The trade off is that it will take much longer for those metrics'
# database files to all get created and thus longer until the data becomes usable.
# Setting this value high (like "inf" for infinity) will cause graphite to create
# the files quickly but at the risk of slowing I/O down considerably for a while.
MAX_CREATES_PER_MINUTE = inf
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2003
UDP_RECEIVER_INTERFACE = 0.0.0.0
UDP_RECEIVER_PORT = 2003
PICKLE_RECEIVER_INTERFACE = 0.0.0.0
PICKLE_RECEIVER_PORT = 2004
CACHE_QUERY_INTERFACE = 0.0.0.0
CACHE_QUERY_PORT = 7002
# Enable AMQP if you want to receve metrics using you amqp broker
ENABLE_AMQP = True
# Verbose means a line will be logged for every metric received
# useful for testing
AMQP_VERBOSE = True
# your credentials for the amqp server
# AMQP_USER = guest
# AMQP_PASSWORD = guest
# the network settings for the amqp server
# AMQP_HOST = localhost
# AMQP_PORT = 5672
# if you want to include the metric name as part of the message body
# instead of as the routing key, set this to True
# AMQP_METRIC_NAME_IN_BODY = False
# NOTE: you cannot run both a cache and a relay on the same server
# with the default configuration, you have to specify a distinict
# interfaces and ports for the listeners.
[relay]
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2003
PICKLE_RECEIVER_INTERFACE = 0.0.0.0
PICKLE_RECEIVER_PORT = 2004
CACHE_SERVERS = server1, server2, server3
MAX_QUEUE_SIZE = 10000

View File

@@ -0,0 +1,359 @@
[cache]
# Configure carbon directories.
#
# OS environment variables can be used to tell carbon where graphite is
# installed, where to read configuration from and where to write data.
#
# GRAPHITE_ROOT - Root directory of the graphite installation.
# Defaults to ../
# GRAPHITE_CONF_DIR - Configuration directory (where this file lives).
# Defaults to $GRAPHITE_ROOT/conf/
# GRAPHITE_STORAGE_DIR - Storage directory for whipser/rrd/log/pid files.
# Defaults to $GRAPHITE_ROOT/storage/
#
# To change other directory paths, add settings to this file. The following
# configuration variables are available with these default values:
#
# STORAGE_DIR = $GRAPHITE_STORAGE_DIR
# LOCAL_DATA_DIR = STORAGE_DIR/whisper/
# WHITELISTS_DIR = STORAGE_DIR/lists/
# CONF_DIR = STORAGE_DIR/conf/
# LOG_DIR = STORAGE_DIR/log/
# PID_DIR = STORAGE_DIR/
#
# For FHS style directory structures, use:
#
# STORAGE_DIR = /var/lib/carbon/
# CONF_DIR = /etc/carbon/
# LOG_DIR = /var/log/carbon/
# PID_DIR = /var/run/
#
#LOCAL_DATA_DIR = /opt/graphite/storage/whisper/
# Enable daily log rotation. If disabled, a kill -HUP can be used after a manual rotate
ENABLE_LOGROTATION = True
# Specify the user to drop privileges to
# If this is blank carbon runs as the user that invokes it
# This user must have write access to the local data directory
USER =
#
# NOTE: The above settings must be set under [relay] and [aggregator]
# to take effect for those daemons as well
# Limit the size of the cache to avoid swapping or becoming CPU bound.
# Sorts and serving cache queries gets more expensive as the cache grows.
# Use the value "inf" (infinity) for an unlimited cache size.
MAX_CACHE_SIZE = inf
# Limits the number of whisper update_many() calls per second, which effectively
# means the number of write requests sent to the disk. This is intended to
# prevent over-utilizing the disk and thus starving the rest of the system.
# When the rate of required updates exceeds this, then carbon's caching will
# take effect and increase the overall throughput accordingly.
MAX_UPDATES_PER_SECOND = 500
# If defined, this changes the MAX_UPDATES_PER_SECOND in Carbon when a
# stop/shutdown is initiated. This helps when MAX_UPDATES_PER_SECOND is
# relatively low and carbon has cached a lot of updates; it enables the carbon
# daemon to shutdown more quickly.
# MAX_UPDATES_PER_SECOND_ON_SHUTDOWN = 1000
# Softly limits the number of whisper files that get created each minute.
# Setting this value low (like at 50) is a good way to ensure your graphite
# system will not be adversely impacted when a bunch of new metrics are
# sent to it. The trade off is that it will take much longer for those metrics'
# database files to all get created and thus longer until the data becomes usable.
# Setting this value high (like "inf" for infinity) will cause graphite to create
# the files quickly but at the risk of slowing I/O down considerably for a while.
MAX_CREATES_PER_MINUTE = 50
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2003
# Set this to True to enable the UDP listener. By default this is off
# because it is very common to run multiple carbon daemons and managing
# another (rarely used) port for every carbon instance is not fun.
ENABLE_UDP_LISTENER = False
UDP_RECEIVER_INTERFACE = 0.0.0.0
UDP_RECEIVER_PORT = 2003
PICKLE_RECEIVER_INTERFACE = 0.0.0.0
PICKLE_RECEIVER_PORT = 2004
# Set to false to disable logging of successful connections
LOG_LISTENER_CONNECTIONS = True
# Per security concerns outlined in Bug #817247 the pickle receiver
# will use a more secure and slightly less efficient unpickler.
# Set this to True to revert to the old-fashioned insecure unpickler.
USE_INSECURE_UNPICKLER = False
CACHE_QUERY_INTERFACE = 0.0.0.0
CACHE_QUERY_PORT = 7002
# Set this to False to drop datapoints received after the cache
# reaches MAX_CACHE_SIZE. If this is True (the default) then sockets
# over which metrics are received will temporarily stop accepting
# data until the cache size falls below 95% MAX_CACHE_SIZE.
USE_FLOW_CONTROL = True
# By default, carbon-cache will log every whisper update and cache hit. This can be excessive and
# degrade performance if logging on the same volume as the whisper data is stored.
LOG_UPDATES = False
LOG_CACHE_HITS = False
LOG_CACHE_QUEUE_SORTS = True
# The thread that writes metrics to disk can use on of the following strategies
# determining the order in which metrics are removed from cache and flushed to
# disk. The default option preserves the same behavior as has been historically
# available in version 0.9.10.
#
# sorted - All metrics in the cache will be counted and an ordered list of
# them will be sorted according to the number of datapoints in the cache at the
# moment of the list's creation. Metrics will then be flushed from the cache to
# disk in that order.
#
# max - The writer thread will always pop and flush the metric from cache
# that has the most datapoints. This will give a strong flush preference to
# frequently updated metrics and will also reduce random file-io. Infrequently
# updated metrics may only ever be persisted to disk at daemon shutdown if
# there are a large number of metrics which receive very frequent updates OR if
# disk i/o is very slow.
#
# naive - Metrics will be flushed from the cache to disk in an unordered
# fashion. This strategy may be desirable in situations where the storage for
# whisper files is solid state, CPU resources are very limited or deference to
# the OS's i/o scheduler is expected to compensate for the random write
# pattern.
#
CACHE_WRITE_STRATEGY = sorted
# On some systems it is desirable for whisper to write synchronously.
# Set this option to True if you'd like to try this. Basically it will
# shift the onus of buffering writes from the kernel into carbon's cache.
WHISPER_AUTOFLUSH = False
# By default new Whisper files are created pre-allocated with the data region
# filled with zeros to prevent fragmentation and speed up contiguous reads and
# writes (which are common). Enabling this option will cause Whisper to create
# the file sparsely instead. Enabling this option may allow a large increase of
# MAX_CREATES_PER_MINUTE but may have longer term performance implications
# depending on the underlying storage configuration.
# WHISPER_SPARSE_CREATE = False
# Only beneficial on linux filesystems that support the fallocate system call.
# It maintains the benefits of contiguous reads/writes, but with a potentially
# much faster creation speed, by allowing the kernel to handle the block
# allocation and zero-ing. Enabling this option may allow a large increase of
# MAX_CREATES_PER_MINUTE. If enabled on an OS or filesystem that is unsupported
# this option will gracefully fallback to standard POSIX file access methods.
WHISPER_FALLOCATE_CREATE = True
# Enabling this option will cause Whisper to lock each Whisper file it writes
# to with an exclusive lock (LOCK_EX, see: man 2 flock). This is useful when
# multiple carbon-cache daemons are writing to the same files
# WHISPER_LOCK_WRITES = False
# Set this to True to enable whitelisting and blacklisting of metrics in
# CONF_DIR/whitelist and CONF_DIR/blacklist. If the whitelist is missing or
# empty, all metrics will pass through
# USE_WHITELIST = False
# By default, carbon itself will log statistics (such as a count,
# metricsReceived) with the top level prefix of 'carbon' at an interval of 60
# seconds. Set CARBON_METRIC_INTERVAL to 0 to disable instrumentation
# CARBON_METRIC_PREFIX = carbon
# CARBON_METRIC_INTERVAL = 60
# Enable AMQP if you want to receve metrics using an amqp broker
# ENABLE_AMQP = False
# Verbose means a line will be logged for every metric received
# useful for testing
# AMQP_VERBOSE = False
# AMQP_HOST = localhost
# AMQP_PORT = 5672
# AMQP_VHOST = /
# AMQP_USER = guest
# AMQP_PASSWORD = guest
# AMQP_EXCHANGE = graphite
# AMQP_METRIC_NAME_IN_BODY = False
# The manhole interface allows you to SSH into the carbon daemon
# and get a python interpreter. BE CAREFUL WITH THIS! If you do
# something like time.sleep() in the interpreter, the whole process
# will sleep! This is *extremely* helpful in debugging, assuming
# you are familiar with the code. If you are not, please don't
# mess with this, you are asking for trouble :)
#
# ENABLE_MANHOLE = False
# MANHOLE_INTERFACE = 127.0.0.1
# MANHOLE_PORT = 7222
# MANHOLE_USER = admin
# MANHOLE_PUBLIC_KEY = ssh-rsa AAAAB3NzaC1yc2EAAAABiwAaAIEAoxN0sv/e4eZCPpi3N3KYvyzRaBaMeS2RsOQ/cDuKv11dlNzVeiyc3RFmCv5Rjwn/lQ79y0zyHxw67qLyhQ/kDzINc4cY41ivuQXm2tPmgvexdrBv5nsfEpjs3gLZfJnyvlcVyWK/lId8WUvEWSWHTzsbtmXAF2raJMdgLTbQ8wE=
# Patterns for all of the metrics this machine will store. Read more at
# http://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol#Bindings
#
# Example: store all sales, linux servers, and utilization metrics
# BIND_PATTERNS = sales.#, servers.linux.#, #.utilization
#
# Example: store everything
# BIND_PATTERNS = #
# To configure special settings for the carbon-cache instance 'b', uncomment this:
#[cache:b]
#LINE_RECEIVER_PORT = 2103
#PICKLE_RECEIVER_PORT = 2104
#CACHE_QUERY_PORT = 7102
# and any other settings you want to customize, defaults are inherited
# from [carbon] section.
# You can then specify the --instance=b option to manage this instance
[relay]
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2013
PICKLE_RECEIVER_INTERFACE = 0.0.0.0
PICKLE_RECEIVER_PORT = 2014
# Set to false to disable logging of successful connections
LOG_LISTENER_CONNECTIONS = True
# Carbon-relay has several options for metric routing controlled by RELAY_METHOD
#
# Use relay-rules.conf to route metrics to destinations based on pattern rules
#RELAY_METHOD = rules
#
# Use consistent-hashing for even distribution of metrics between destinations
#RELAY_METHOD = consistent-hashing
#
# Use consistent-hashing but take into account an aggregation-rules.conf shared
# by downstream carbon-aggregator daemons. This will ensure that all metrics
# that map to a given aggregation rule are sent to the same carbon-aggregator
# instance.
# Enable this for carbon-relays that send to a group of carbon-aggregators
#RELAY_METHOD = aggregated-consistent-hashing
RELAY_METHOD = rules
# If you use consistent-hashing you can add redundancy by replicating every
# datapoint to more than one machine.
REPLICATION_FACTOR = 1
# This is a list of carbon daemons we will send any relayed or
# generated metrics to. The default provided would send to a single
# carbon-cache instance on the default port. However if you
# use multiple carbon-cache instances then it would look like this:
#
# DESTINATIONS = 127.0.0.1:2004:a, 127.0.0.1:2104:b
#
# The general form is IP:PORT:INSTANCE where the :INSTANCE part is
# optional and refers to the "None" instance if omitted.
#
# Note that if the destinations are all carbon-caches then this should
# exactly match the webapp's CARBONLINK_HOSTS setting in terms of
# instances listed (order matters!).
#
# If using RELAY_METHOD = rules, all destinations used in relay-rules.conf
# must be defined in this list
DESTINATIONS = 127.0.0.1:2004
# This defines the maximum "message size" between carbon daemons.
# You shouldn't need to tune this unless you really know what you're doing.
MAX_DATAPOINTS_PER_MESSAGE = 500
MAX_QUEUE_SIZE = 10000
# Set this to False to drop datapoints when any send queue (sending datapoints
# to a downstream carbon daemon) hits MAX_QUEUE_SIZE. If this is True (the
# default) then sockets over which metrics are received will temporarily stop accepting
# data until the send queues fall below 80% MAX_QUEUE_SIZE.
USE_FLOW_CONTROL = True
# Set this to True to enable whitelisting and blacklisting of metrics in
# CONF_DIR/whitelist and CONF_DIR/blacklist. If the whitelist is missing or
# empty, all metrics will pass through
# USE_WHITELIST = False
# By default, carbon itself will log statistics (such as a count,
# metricsReceived) with the top level prefix of 'carbon' at an interval of 60
# seconds. Set CARBON_METRIC_INTERVAL to 0 to disable instrumentation
# CARBON_METRIC_PREFIX = carbon
# CARBON_METRIC_INTERVAL = 60
[aggregator]
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2023
PICKLE_RECEIVER_INTERFACE = 0.0.0.0
PICKLE_RECEIVER_PORT = 2024
# Set to false to disable logging of successful connections
LOG_LISTENER_CONNECTIONS = True
# If set true, metric received will be forwarded to DESTINATIONS in addition to
# the output of the aggregation rules. If set false the carbon-aggregator will
# only ever send the output of aggregation.
FORWARD_ALL = True
# This is a list of carbon daemons we will send any relayed or
# generated metrics to. The default provided would send to a single
# carbon-cache instance on the default port. However if you
# use multiple carbon-cache instances then it would look like this:
#
# DESTINATIONS = 127.0.0.1:2004:a, 127.0.0.1:2104:b
#
# The format is comma-delimited IP:PORT:INSTANCE where the :INSTANCE part is
# optional and refers to the "None" instance if omitted.
#
# Note that if the destinations are all carbon-caches then this should
# exactly match the webapp's CARBONLINK_HOSTS setting in terms of
# instances listed (order matters!).
DESTINATIONS = 127.0.0.1:2004
# If you want to add redundancy to your data by replicating every
# datapoint to more than one machine, increase this.
REPLICATION_FACTOR = 1
# This is the maximum number of datapoints that can be queued up
# for a single destination. Once this limit is hit, we will
# stop accepting new data if USE_FLOW_CONTROL is True, otherwise
# we will drop any subsequently received datapoints.
MAX_QUEUE_SIZE = 10000
# Set this to False to drop datapoints when any send queue (sending datapoints
# to a downstream carbon daemon) hits MAX_QUEUE_SIZE. If this is True (the
# default) then sockets over which metrics are received will temporarily stop accepting
# data until the send queues fall below 80% MAX_QUEUE_SIZE.
USE_FLOW_CONTROL = True
# This defines the maximum "message size" between carbon daemons.
# You shouldn't need to tune this unless you really know what you're doing.
MAX_DATAPOINTS_PER_MESSAGE = 500
# This defines how many datapoints the aggregator remembers for
# each metric. Aggregation only happens for datapoints that fall in
# the past MAX_AGGREGATION_INTERVALS * intervalSize seconds.
MAX_AGGREGATION_INTERVALS = 5
# By default (WRITE_BACK_FREQUENCY = 0), carbon-aggregator will write back
# aggregated data points once every rule.frequency seconds, on a per-rule basis.
# Set this (WRITE_BACK_FREQUENCY = N) to write back all aggregated data points
# every N seconds, independent of rule frequency. This is useful, for example,
# to be able to query partially aggregated metrics from carbon-cache without
# having to first wait rule.frequency seconds.
# WRITE_BACK_FREQUENCY = 0
# Set this to True to enable whitelisting and blacklisting of metrics in
# CONF_DIR/whitelist and CONF_DIR/blacklist. If the whitelist is missing or
# empty, all metrics will pass through
# USE_WHITELIST = False
# By default, carbon itself will log statistics (such as a count,
# metricsReceived) with the top level prefix of 'carbon' at an interval of 60
# seconds. Set CARBON_METRIC_INTERVAL to 0 to disable instrumentation
# CARBON_METRIC_PREFIX = carbon
# CARBON_METRIC_INTERVAL = 60

View File

@@ -0,0 +1,57 @@
# This configuration file controls the behavior of the Dashboard UI, available
# at http://my-graphite-server/dashboard/.
#
# This file must contain a [ui] section that defines values for all of the
# following settings.
[ui]
default_graph_width = 400
default_graph_height = 250
automatic_variants = true
refresh_interval = 60
autocomplete_delay = 375
merge_hover_delay = 750
# You can set this 'default', 'white', or a custom theme name.
# To create a custom theme, copy the dashboard-default.css file
# to dashboard-myThemeName.css in the content/css directory and
# modify it to your liking.
theme = default
[keyboard-shortcuts]
toggle_toolbar = ctrl-z
toggle_metrics_panel = ctrl-space
erase_all_graphs = alt-x
save_dashboard = alt-s
completer_add_metrics = alt-enter
completer_del_metrics = alt-backspace
give_completer_focus = shift-space
# These settings apply to the UI as a whole, all other sections in this file
# pertain only to specific metric types.
#
# The dashboard presents only metrics that fall into specified naming schemes
# defined in this file. This creates a simpler, more targetted view of the
# data. The general form for defining a naming scheme is as follows:
#
#[Metric Type]
#scheme = basis.path.<field1>.<field2>.<fieldN>
#field1.label = Foo
#field2.label = Bar
#
#
# Where each <field> will be displayed as a dropdown box
# in the UI and the remaining portion of the namespace
# shown in the Metric Selector panel. The .label options set the labels
# displayed for each dropdown.
#
# For example:
#
#[Sales]
#scheme = sales.<channel>.<type>.<brand>
#channel.label = Channel
#type.label = Product Type
#brand.label = Brand
#
# This defines a 'Sales' metric type that uses 3 dropdowns in the Context Selector
# (the upper-left panel) while any deeper metrics (per-product counts or revenue, etc)
# will be available in the Metric Selector (upper-right panel).

View File

@@ -0,0 +1,38 @@
[default]
background = black
foreground = white
majorLine = white
minorLine = grey
lineColors = blue,green,red,purple,brown,yellow,aqua,grey,magenta,pink,gold,rose
fontName = Sans
fontSize = 10
fontBold = False
fontItalic = False
[noc]
background = black
foreground = white
majorLine = white
minorLine = grey
lineColors = blue,green,red,yellow,purple,brown,aqua,grey,magenta,pink,gold,rose
fontName = Sans
fontSize = 10
fontBold = False
fontItalic = False
[plain]
background = white
foreground = black
minorLine = grey
majorLine = rose
[summary]
background = black
lineColors = #6666ff, #66ff66, #ff6666
[alphas]
background = white
foreground = black
majorLine = grey
minorLine = rose
lineColors = 00ff00aa,ff000077,00337799

View File

@@ -0,0 +1,21 @@
# Relay destination rules for carbon-relay. Entries are scanned in order,
# and the first pattern a metric matches will cause processing to cease after sending
# unless `continue` is set to true
#
# [name]
# pattern = <regex>
# destinations = <list of destination addresses>
# continue = <boolean> # default: False
#
# name: Arbitrary unique name to identify the rule
# pattern: Regex pattern to match against the metric name
# destinations: Comma-separated list of destinations.
# ex: 127.0.0.1, 10.1.2.3:2004, 10.1.2.4:2004:a, myserver.mydomain.com
# continue: Continue processing rules if this rule matches (default: False)
# You must have exactly one section with 'default = true'
# Note that all destinations listed must also exist in carbon.conf
# in the DESTINATIONS setting in the [relay] section
[default]
default = true
destinations = 127.0.0.1:2004:a, 127.0.0.1:2104:b

View File

@@ -0,0 +1,18 @@
# This file defines regular expression patterns that can be used to
# rewrite metric names in a search & replace fashion. It consists of two
# sections, [pre] and [post]. The rules in the pre section are applied to
# metric names as soon as they are received. The post rules are applied
# after aggregation has taken place.
#
# The general form of each rule is as follows:
#
# regex-pattern = replacement-text
#
# For example:
#
# [post]
# _sum$ =
# _avg$ =
#
# These rules would strip off a suffix of _sum or _avg from any metric names
# after aggregation.

View File

@@ -0,0 +1,43 @@
# Aggregation methods for whisper files. Entries are scanned in order,
# and first match wins. This file is scanned for changes every 60 seconds
#
# [name]
# pattern = <regex>
# xFilesFactor = <float between 0 and 1>
# aggregationMethod = <average|sum|last|max|min>
#
# name: Arbitrary unique name for the rule
# pattern: Regex pattern to match against the metric name
# xFilesFactor: Ratio of valid data points required for aggregation to the next retention to occur
# aggregationMethod: function to apply to data points for aggregation
#
[min]
pattern = \.lower$
xFilesFactor = 0.1
aggregationMethod = min
[max]
pattern = \.upper(_\d+)?$
xFilesFactor = 0.1
aggregationMethod = max
[sum]
pattern = \.sum$
xFilesFactor = 0
aggregationMethod = sum
[count]
pattern = \.count$
xFilesFactor = 0
aggregationMethod = sum
[count_legacy]
pattern = ^stats_counts.*
xFilesFactor = 0
aggregationMethod = sum
[default_average]
pattern = .*
xFilesFactor = 0.3
aggregationMethod = average

View File

@@ -0,0 +1,17 @@
# Schema definitions for Whisper files. Entries are scanned in order,
[carbon]
pattern = ^carbon\..*
retentions = 1m:31d,10m:1y,1h:5y
[highres]
pattern = ^highres.*
retentions = 1s:1d,1m:7d
[statsd]
pattern = ^statsd.*
retentions = 1m:7d,10m:1y
[default]
pattern = .*
retentions = 10s:1d,1m:7d,10m:1y

View File

@@ -0,0 +1,6 @@
# This file takes a single regular expression per line
# If USE_WHITELIST is set to True in carbon.conf, only metrics received which
# match one of these expressions will be persisted. If this file is empty or
# missing, all metrics will pass through.
# This file is reloaded automatically when changes are made
.*

View File

@@ -0,0 +1,94 @@
"""Copyright 2008 Orbitz WorldWide
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License."""
# Django settings for graphite project.
# DO NOT MODIFY THIS FILE DIRECTLY - use local_settings.py instead
from os.path import dirname, join, abspath
#Django settings below, do not touch!
APPEND_SLASH = False
TEMPLATE_DEBUG = False
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
join(dirname( abspath(__file__) ), 'templates')
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
# Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this
# list if you haven't customized them:
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# Language code for this installation. All choices can be found here:
# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
# http://blogs.law.harvard.edu/tech/stories/storyReader$15
LANGUAGE_CODE = 'en-us'
# Absolute path to the directory that holds media.
MEDIA_ROOT = ''
# URL that handles the media served from MEDIA_ROOT.
# Example: "http://media.lawrence.com"
MEDIA_URL = ''
MIDDLEWARE_CLASSES = (
'graphite.middleware.LogExceptionsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.gzip.GZipMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
ROOT_URLCONF = 'graphite.urls'
INSTALLED_APPS = (
'graphite.metrics',
'graphite.render',
'graphite.browser',
'graphite.composer',
'graphite.account',
'graphite.dashboard',
'graphite.whitelist',
'graphite.events',
'graphite.url_shortener',
'django.contrib.auth',
'django.contrib.sessions',
'django.contrib.admin',
'django.contrib.contenttypes',
'django.contrib.staticfiles',
'tagging',
)
AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend']
GRAPHITE_WEB_APP_SETTINGS_LOADED = True
STATIC_URL = '/static/'
STATIC_ROOT = '/opt/graphite/static/'

View File

@@ -0,0 +1,215 @@
## Graphite local_settings.py
# Edit this file to customize the default Graphite webapp settings
#
# Additional customizations to Django settings can be added to this file as well
#####################################
# General Configuration #
#####################################
# Set this to a long, random unique string to use as a secret key for this
# install. This key is used for salting of hashes used in auth tokens,
# CRSF middleware, cookie storage, etc. This should be set identically among
# instances if used behind a load balancer.
#SECRET_KEY = 'UNSAFE_DEFAULT'
# In Django 1.5+ set this to the list of hosts your graphite instances is
# accessible as. See:
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-ALLOWED_HOSTS
#ALLOWED_HOSTS = [ '*' ]
# Set your local timezone (Django's default is America/Chicago)
# If your graphs appear to be offset by a couple hours then this probably
# needs to be explicitly set to your local timezone.
#TIME_ZONE = 'America/Los_Angeles'
# Override this to provide documentation specific to your Graphite deployment
#DOCUMENTATION_URL = "http://graphite.readthedocs.org/"
# Logging
#LOG_RENDERING_PERFORMANCE = True
#LOG_CACHE_PERFORMANCE = True
#LOG_METRIC_ACCESS = True
# Enable full debug page display on exceptions (Internal Server Error pages)
#DEBUG = True
# If using RRD files and rrdcached, set to the address or socket of the daemon
#FLUSHRRDCACHED = 'unix:/var/run/rrdcached.sock'
# This lists the memcached servers that will be used by this webapp.
# If you have a cluster of webapps you should ensure all of them
# have the *exact* same value for this setting. That will maximize cache
# efficiency. Setting MEMCACHE_HOSTS to be empty will turn off use of
# memcached entirely.
#
# You should not use the loopback address (127.0.0.1) here if using clustering
# as every webapp in the cluster should use the exact same values to prevent
# unneeded cache misses. Set to [] to disable caching of images and fetched data
#MEMCACHE_HOSTS = ['10.10.10.10:11211', '10.10.10.11:11211', '10.10.10.12:11211']
#DEFAULT_CACHE_DURATION = 60 # Cache images and data for 1 minute
#####################################
# Filesystem Paths #
#####################################
# Change only GRAPHITE_ROOT if your install is merely shifted from /opt/graphite
# to somewhere else
#GRAPHITE_ROOT = '/opt/graphite'
# Most installs done outside of a separate tree such as /opt/graphite will only
# need to change these three settings. Note that the default settings for each
# of these is relative to GRAPHITE_ROOT
#CONF_DIR = '/opt/graphite/conf'
#STORAGE_DIR = '/opt/graphite/storage'
#CONTENT_DIR = '/opt/graphite/webapp/content'
# To further or fully customize the paths, modify the following. Note that the
# default settings for each of these are relative to CONF_DIR and STORAGE_DIR
#
## Webapp config files
#DASHBOARD_CONF = '/opt/graphite/conf/dashboard.conf'
#GRAPHTEMPLATES_CONF = '/opt/graphite/conf/graphTemplates.conf'
## Data directories
# NOTE: If any directory is unreadable in DATA_DIRS it will break metric browsing
#WHISPER_DIR = '/opt/graphite/storage/whisper'
#RRD_DIR = '/opt/graphite/storage/rrd'
#DATA_DIRS = [WHISPER_DIR, RRD_DIR] # Default: set from the above variables
#LOG_DIR = '/opt/graphite/storage/log/webapp'
#INDEX_FILE = '/opt/graphite/storage/index' # Search index file
#####################################
# Email Configuration #
#####################################
# This is used for emailing rendered Graphs
# Default backend is SMTP
#EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
#EMAIL_HOST = 'localhost'
#EMAIL_PORT = 25
#EMAIL_HOST_USER = ''
#EMAIL_HOST_PASSWORD = ''
#EMAIL_USE_TLS = False
# To drop emails on the floor, enable the Dummy backend:
#EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'
#####################################
# Authentication Configuration #
#####################################
## LDAP / ActiveDirectory authentication setup
#USE_LDAP_AUTH = True
#LDAP_SERVER = "ldap.mycompany.com"
#LDAP_PORT = 389
# OR
#LDAP_URI = "ldaps://ldap.mycompany.com:636"
#LDAP_SEARCH_BASE = "OU=users,DC=mycompany,DC=com"
#LDAP_BASE_USER = "CN=some_readonly_account,DC=mycompany,DC=com"
#LDAP_BASE_PASS = "readonly_account_password"
#LDAP_USER_QUERY = "(username=%s)" #For Active Directory use "(sAMAccountName=%s)"
#
# If you want to further customize the ldap connection options you should
# directly use ldap.set_option to set the ldap module's global options.
# For example:
#
#import ldap
#ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW)
#ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, "/etc/ssl/ca")
#ldap.set_option(ldap.OPT_X_TLS_CERTFILE, "/etc/ssl/mycert.pem")
#ldap.set_option(ldap.OPT_X_TLS_KEYFILE, "/etc/ssl/mykey.pem")
# See http://www.python-ldap.org/ for further details on these options.
## REMOTE_USER authentication. See: https://docs.djangoproject.com/en/dev/howto/auth-remote-user/
#USE_REMOTE_USER_AUTHENTICATION = True
# Override the URL for the login link (e.g. for django_openid_auth)
#LOGIN_URL = '/account/login'
##########################
# Database Configuration #
##########################
# By default sqlite is used. If you cluster multiple webapps you will need
# to setup an external database (such as MySQL) and configure all of the webapp
# instances to use the same database. Note that this database is only used to store
# Django models such as saved graphs, dashboards, user preferences, etc.
# Metric data is not stored here.
#
# DO NOT FORGET TO RUN 'manage.py syncdb' AFTER SETTING UP A NEW DATABASE
#
# The following built-in database engines are available:
# django.db.backends.postgresql # Removed in Django 1.4
# django.db.backends.postgresql_psycopg2
# django.db.backends.mysql
# django.db.backends.sqlite3
# django.db.backends.oracle
#
# The default is 'django.db.backends.sqlite3' with file 'graphite.db'
# located in STORAGE_DIR
#
#DATABASES = {
# 'default': {
# 'NAME': '/opt/graphite/storage/graphite.db',
# 'ENGINE': 'django.db.backends.sqlite3',
# 'USER': '',
# 'PASSWORD': '',
# 'HOST': '',
# 'PORT': ''
# }
#}
#
#########################
# Cluster Configuration #
#########################
# (To avoid excessive DNS lookups you want to stick to using IP addresses only in this entire section)
#
# This should list the IP address (and optionally port) of the webapp on each
# remote server in the cluster. These servers must each have local access to
# metric data. Note that the first server to return a match for a query will be
# used.
#CLUSTER_SERVERS = ["10.0.2.2:80", "10.0.2.3:80"]
## These are timeout values (in seconds) for requests to remote webapps
#REMOTE_STORE_FETCH_TIMEOUT = 6 # Timeout to fetch series data
#REMOTE_STORE_FIND_TIMEOUT = 2.5 # Timeout for metric find requests
#REMOTE_STORE_RETRY_DELAY = 60 # Time before retrying a failed remote webapp
#REMOTE_FIND_CACHE_DURATION = 300 # Time to cache remote metric find results
## Remote rendering settings
# Set to True to enable rendering of Graphs on a remote webapp
#REMOTE_RENDERING = True
# List of IP (and optionally port) of the webapp on each remote server that
# will be used for rendering. Note that each rendering host should have local
# access to metric data or should have CLUSTER_SERVERS configured
#RENDERING_HOSTS = []
#REMOTE_RENDER_CONNECT_TIMEOUT = 1.0
# If you are running multiple carbon-caches on this machine (typically behind a relay using
# consistent hashing), you'll need to list the ip address, cache query port, and instance name of each carbon-cache
# instance on the local machine (NOT every carbon-cache in the entire cluster). The default cache query port is 7002
# and a common scheme is to use 7102 for instance b, 7202 for instance c, etc.
#
# You *should* use 127.0.0.1 here in most cases
#CARBONLINK_HOSTS = ["127.0.0.1:7002:a", "127.0.0.1:7102:b", "127.0.0.1:7202:c"]
#CARBONLINK_TIMEOUT = 1.0
#####################################
# Additional Django Settings #
#####################################
# Uncomment the following line for direct access to Django settings such as
# MIDDLEWARE_CLASSES or APPS
#from graphite.app_settings import *
import os
LOG_DIR = '/var/log/graphite'
SECRET_KEY = '$(date +%s | sha256sum | base64 | head -c 64)'
if (os.getenv("MEMCACHE_HOST") is not None):
MEMCACHE_HOSTS = os.getenv("MEMCACHE_HOST").split(",")
if (os.getenv("DEFAULT_CACHE_DURATION") is not None):
DEFAULT_CACHE_DURATION = int(os.getenv("CACHE_DURATION"))

View File

@@ -0,0 +1,6 @@
{
"graphiteHost": "127.0.0.1",
"graphitePort": 2003,
"port": 8125,
"flushInterval": 10000
}

View File

@@ -0,0 +1,26 @@
#!/usr/bin/env expect
set timeout -1
spawn /usr/local/bin/manage.sh
expect "Would you like to create one now" {
send "yes\r"
}
expect "Username" {
send "root\r"
}
expect "Email address:" {
send "root.graphite@mailinator.com\r"
}
expect "Password:" {
send "root\r"
}
expect "Password *:" {
send "root\r"
}
expect "Superuser created successfully"

View File

@@ -0,0 +1,3 @@
#!/bin/bash
PYTHONPATH=/opt/graphite/webapp django-admin.py syncdb --settings=graphite.settings
PYTHONPATH=/opt/graphite/webapp django-admin.py update_users --settings=graphite.settings

View File

@@ -0,0 +1,16 @@
graphite:
build: blocks/graphite1
ports:
- "8080:80"
- "2003:2003"
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
fake-graphite-data:
image: grafana/fake-data-gen
net: bridge
environment:
FD_DATASOURCE: graphite
FD_PORT: 2003

View File

@@ -0,0 +1,76 @@
[cache]
LOCAL_DATA_DIR = /opt/graphite/storage/whisper/
# Specify the user to drop privileges to
# If this is blank carbon runs as the user that invokes it
# This user must have write access to the local data directory
USER =
# Limit the size of the cache to avoid swapping or becoming CPU bound.
# Sorts and serving cache queries gets more expensive as the cache grows.
# Use the value "inf" (infinity) for an unlimited cache size.
MAX_CACHE_SIZE = inf
# Limits the number of whisper update_many() calls per second, which effectively
# means the number of write requests sent to the disk. This is intended to
# prevent over-utilizing the disk and thus starving the rest of the system.
# When the rate of required updates exceeds this, then carbon's caching will
# take effect and increase the overall throughput accordingly.
MAX_UPDATES_PER_SECOND = 1000
# Softly limits the number of whisper files that get created each minute.
# Setting this value low (like at 50) is a good way to ensure your graphite
# system will not be adversely impacted when a bunch of new metrics are
# sent to it. The trade off is that it will take much longer for those metrics'
# database files to all get created and thus longer until the data becomes usable.
# Setting this value high (like "inf" for infinity) will cause graphite to create
# the files quickly but at the risk of slowing I/O down considerably for a while.
MAX_CREATES_PER_MINUTE = inf
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2003
PICKLE_RECEIVER_INTERFACE = 0.0.0.0
PICKLE_RECEIVER_PORT = 2004
CACHE_QUERY_INTERFACE = 0.0.0.0
CACHE_QUERY_PORT = 7002
LOG_UPDATES = False
# Enable AMQP if you want to receve metrics using an amqp broker
# ENABLE_AMQP = False
# Verbose means a line will be logged for every metric received
# useful for testing
# AMQP_VERBOSE = False
# AMQP_HOST = localhost
# AMQP_PORT = 5672
# AMQP_VHOST = /
# AMQP_USER = guest
# AMQP_PASSWORD = guest
# AMQP_EXCHANGE = graphite
# Patterns for all of the metrics this machine will store. Read more at
# http://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol#Bindings
#
# Example: store all sales, linux servers, and utilization metrics
# BIND_PATTERNS = sales.#, servers.linux.#, #.utilization
#
# Example: store everything
# BIND_PATTERNS = #
# NOTE: you cannot run both a cache and a relay on the same server
# with the default configuration, you have to specify a distinict
# interfaces and ports for the listeners.
[relay]
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2003
PICKLE_RECEIVER_INTERFACE = 0.0.0.0
PICKLE_RECEIVER_PORT = 2004
CACHE_SERVERS = server1, server2, server3
MAX_QUEUE_SIZE = 10000

View File

@@ -0,0 +1,102 @@
import datetime
import time
from django.utils.timezone import get_current_timezone
from django.core.urlresolvers import get_script_prefix
from django.http import HttpResponse
from django.shortcuts import render_to_response, get_object_or_404
from pytz import timezone
from graphite.util import json
from graphite.events import models
from graphite.render.attime import parseATTime
def to_timestamp(dt):
return time.mktime(dt.timetuple())
class EventEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return to_timestamp(obj)
return json.JSONEncoder.default(self, obj)
def view_events(request):
if request.method == "GET":
context = { 'events' : fetch(request),
'slash' : get_script_prefix()
}
return render_to_response("events.html", context)
else:
return post_event(request)
def detail(request, event_id):
e = get_object_or_404(models.Event, pk=event_id)
context = { 'event' : e,
'slash' : get_script_prefix()
}
return render_to_response("event.html", context)
def post_event(request):
if request.method == 'POST':
event = json.loads(request.body)
assert isinstance(event, dict)
values = {}
values["what"] = event["what"]
values["tags"] = event.get("tags", None)
values["when"] = datetime.datetime.fromtimestamp(
event.get("when", time.time()))
if "data" in event:
values["data"] = event["data"]
e = models.Event(**values)
e.save()
return HttpResponse(status=200)
else:
return HttpResponse(status=405)
def get_data(request):
if 'jsonp' in request.REQUEST:
response = HttpResponse(
"%s(%s)" % (request.REQUEST.get('jsonp'),
json.dumps(fetch(request), cls=EventEncoder)),
mimetype='text/javascript')
else:
response = HttpResponse(
json.dumps(fetch(request), cls=EventEncoder),
mimetype="application/json")
return response
def fetch(request):
#XXX we need to move to USE_TZ=True to get rid of naive-time conversions
def make_naive(dt):
if 'tz' in request.GET:
tz = timezone(request.GET['tz'])
else:
tz = get_current_timezone()
local_dt = dt.astimezone(tz)
if hasattr(local_dt, 'normalize'):
local_dt = local_dt.normalize()
return local_dt.replace(tzinfo=None)
if request.GET.get("from", None) is not None:
time_from = make_naive(parseATTime(request.GET["from"]))
else:
time_from = datetime.datetime.fromtimestamp(0)
if request.GET.get("until", None) is not None:
time_until = make_naive(parseATTime(request.GET["until"]))
else:
time_until = datetime.datetime.now()
tags = request.GET.get("tags", None)
if tags is not None:
tags = request.GET.get("tags").split(" ")
return [x.as_dict() for x in
models.Event.find_events(time_from, time_until, tags=tags)]

View File

@@ -0,0 +1,20 @@
[
{
"pk": 1,
"model": "auth.user",
"fields": {
"username": "admin",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": true,
"is_staff": true,
"last_login": "2011-09-20 17:02:14",
"groups": [],
"user_permissions": [],
"password": "sha1$1b11b$edeb0a67a9622f1f2cfeabf9188a711f5ac7d236",
"email": "root@example.com",
"date_joined": "2011-09-20 17:02:14"
}
}
]

View File

@@ -0,0 +1,42 @@
# Edit this file to override the default graphite settings, do not edit settings.py
# Turn on debugging and restart apache if you ever see an "Internal Server Error" page
#DEBUG = True
# Set your local timezone (django will try to figure this out automatically)
TIME_ZONE = 'UTC'
# Setting MEMCACHE_HOSTS to be empty will turn off use of memcached entirely
#MEMCACHE_HOSTS = ['127.0.0.1:11211']
# Sometimes you need to do a lot of rendering work but cannot share your storage mount
#REMOTE_RENDERING = True
#RENDERING_HOSTS = ['fastserver01','fastserver02']
#LOG_RENDERING_PERFORMANCE = True
#LOG_CACHE_PERFORMANCE = True
# If you've got more than one backend server they should all be listed here
#CLUSTER_SERVERS = []
# Override this if you need to provide documentation specific to your graphite deployment
#DOCUMENTATION_URL = "http://wiki.mycompany.com/graphite"
# Enable email-related features
#SMTP_SERVER = "mail.mycompany.com"
# LDAP / ActiveDirectory authentication setup
#USE_LDAP_AUTH = True
#LDAP_SERVER = "ldap.mycompany.com"
#LDAP_PORT = 389
#LDAP_SEARCH_BASE = "OU=users,DC=mycompany,DC=com"
#LDAP_BASE_USER = "CN=some_readonly_account,DC=mycompany,DC=com"
#LDAP_BASE_PASS = "readonly_account_password"
#LDAP_USER_QUERY = "(username=%s)" #For Active Directory use "(sAMAccountName=%s)"
# If sqlite won't cut it, configure your real database here (don't forget to run manage.py syncdb!)
#DATABASE_ENGINE = 'mysql' # or 'postgres'
#DATABASE_NAME = 'graphite'
#DATABASE_USER = 'graphite'
#DATABASE_PASSWORD = 'graphite-is-awesome'
#DATABASE_HOST = 'mysql.mycompany.com'
#DATABASE_PORT = '3306'

View File

@@ -0,0 +1 @@
grafana:$apr1$4R/20xhC$8t37jPP5dbcLr48btdkU//

View File

@@ -0,0 +1,70 @@
daemon off;
user www-data;
worker_processes 1;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
server_names_hash_bucket_size 32;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
server {
listen 80 default_server;
server_name _;
open_log_file_cache max=1000 inactive=20s min_uses=2 valid=1m;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Host $host;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Access-Control-Allow-Headers "origin, authorization, accept";
location /content {
alias /opt/graphite/webapp/content;
}
location /media {
alias /usr/share/pyshared/django/contrib/admin/media;
}
}
}

View File

@@ -0,0 +1,8 @@
{
graphitePort: 2003,
graphiteHost: "127.0.0.1",
port: 8125,
mgmt_port: 8126,
backends: ['./backends/graphite'],
debug: true
}

View File

@@ -0,0 +1,19 @@
[min]
pattern = \.min$
xFilesFactor = 0.1
aggregationMethod = min
[max]
pattern = \.max$
xFilesFactor = 0.1
aggregationMethod = max
[sum]
pattern = \.count$
xFilesFactor = 0
aggregationMethod = sum
[default_average]
pattern = .*
xFilesFactor = 0.5
aggregationMethod = average

View File

@@ -0,0 +1,16 @@
[carbon]
pattern = ^carbon\..*
retentions = 1m:31d,10m:1y,1h:5y
[highres]
pattern = ^highres.*
retentions = 1s:1d,1m:7d
[statsd]
pattern = ^statsd.*
retentions = 1m:7d,10m:1y
[default]
pattern = .*
retentions = 10s:1d,1m:7d,10m:1y

View File

@@ -0,0 +1,26 @@
[supervisord]
nodaemon = true
environment = GRAPHITE_STORAGE_DIR='/opt/graphite/storage',GRAPHITE_CONF_DIR='/opt/graphite/conf'
[program:nginx]
command = /usr/sbin/nginx
stdout_logfile = /var/log/supervisor/%(program_name)s.log
stderr_logfile = /var/log/supervisor/%(program_name)s.log
autorestart = true
[program:carbon-cache]
;user = www-data
command = /opt/graphite/bin/carbon-cache.py --debug start
stdout_logfile = /var/log/supervisor/%(program_name)s.log
stderr_logfile = /var/log/supervisor/%(program_name)s.log
autorestart = true
[program:graphite-webapp]
;user = www-data
directory = /opt/graphite/webapp
environment = PYTHONPATH='/opt/graphite/webapp'
command = /usr/bin/gunicorn_django -b127.0.0.1:8000 -w2 graphite/settings.py
stdout_logfile = /var/log/supervisor/%(program_name)s.log
stderr_logfile = /var/log/supervisor/%(program_name)s.log
autorestart = true

View File

@@ -6,3 +6,4 @@ postgrestest:
POSTGRES_DATABASE: grafana
ports:
- "5432:5432"
command: postgres -c log_connections=on -c logging_collector=on -c log_destination=stderr -c log_directory=/var/log/postgresql

View File

@@ -1 +1 @@
v4.2
v4.3

View File

@@ -0,0 +1,15 @@
+++
title = "Internal metrics"
description = "Internal metrics exposed by Grafana"
keywords = ["grafana", "metrics", "internal metrics"]
type = "docs"
[menu.docs]
parent = "admin"
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.
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.

View File

@@ -22,7 +22,7 @@ to add and configure a `notification` channel (can be email, Pagerduty or other
{{< imgbox max-width="40%" img="/img/docs/v43/alert_notifications_menu.png" caption="Alerting Notification Channels" >}}
On the Notification Channels page hit the `New Channel` button to go the the page where you
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
@@ -92,6 +92,26 @@ Example json body:
- **state** - The possible values for alert state are: `ok`, `paused`, `alerting`, `pending`, `no_data`.
### DingDing/DingTalk
[Instructions in Chinese](https://open-doc.dingtalk.com/docs/doc.htm?spm=a219a.7629140.0.0.p2lr6t&treeId=257&articleId=105733&docType=1).
In DingTalk PC Client:
1. Click "more" icon on left bottom of the panel.
2. Click "Robot Manage" item in the pop menu, there will be a new panel call "Robot Manage".
3. In the "Robot Manage" panel, select "customised: customised robot with Webhook".
4. In the next new panel named "robot detail", click "Add" button.
5. In "Add Robot" panel, input a nickname for the robot and select a "message group" which the robot will join in. click "next".
6. There will be a Webhook URL in the panel, looks like this: https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxx. Copy this URL to the grafana Dingtalk setting page and then click "finish".
Dingtalk supports the following "message type": `text`, `link` and `markdown`. Only the `text` message type is supported.
### Other Supported Notification Channels
Grafana also supports the following Notification Channels:
@@ -112,11 +132,9 @@ Grafana also supports the following Notification Channels:
- LINE
- DingDing
# 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 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
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.
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.

View File

@@ -27,14 +27,12 @@ and the conditions that need to be met for the alert to change state and trigger
## Execution
The alert rules are evaluated in the Grafana backend in a scheduler and query execution engine that is part
of core Grafana. Only some data soures are supported right now. They include `Graphite`, `Prometheus`,
of core Grafana. Only some data sources are supported right now. They include `Graphite`, `Prometheus`,
`InfluxDB` and `OpenTSDB`.
### Clustering
We have not implemented clustering yet. So if you run multiple instances of grafana-server
you have to make sure [execute_alerts]({{< relref "installation/configuration.md#alerting" >}})
is true on only one instance or otherwise you will get duplicated notifications.
Currently alerting supports a limited form of high availability. Since v4.2.0 of Grafana, alert notifications are deduped when running multiple servers. This means all alerts are executed on every server but no duplicate alert notifications are sent due to the deduping logic. Proper load balancing of alerts will be introduced in the future.
<div class="clearfix"></div>
@@ -61,8 +59,8 @@ specify a query letter, time range and an aggregation function.
avg() OF query(A, 5m, now) IS BELOW 14
```
- `avg()` Controls how the values for **each** serie should be reduced to a value that can be compared against the threshold. Click on the function to change it to another aggregation function.
- `query(A, 5m, now)` The letter defines what query to execute from the **Metrics** tab. The second two parameters defines the time range, `5m, now` means 5 minutes from now to now. You can also do `10m, now-2m` to define a time range that will be 10 minutes from now to 2 minutes from now. This is useful if you want to ignore the last 2 minutes of data.
- `avg()` Controls how the values for **each** series should be reduced to a value that can be compared against the threshold. Click on the function to change it to another aggregation function.
- `query(A, 5m, now)` The letter defines what query to execute from the **Metrics** tab. The second two parameters define the time range, `5m, now` means 5 minutes from now to now. You can also do `10m, now-2m` to define a time range that will be 10 minutes from now to 2 minutes from now. This is useful if you want to ignore the last 2 minutes of data.
- `IS BELOW 14` Defines the type of threshold and the threshold value. You can click on `IS BELOW` to change the type of threshold.
The query used in an alert rule cannot contain any template variables. Currently we only support `AND` and `OR` operators between conditions and they are executed serially.
@@ -76,7 +74,7 @@ of another alert in your conditions, and `Time Of Day`.
#### Multiple Series
If a query returns multiple series then the aggregation function and threshold check will be evaluated for each series.
What Grafana does not do currently is track alert rule state **per series**. This has implications that is exemplified
What Grafana does not do currently is track alert rule state **per series**. This has implications that are detailed
in the scenario below.
- Alert condition with query that returns 2 series: **server1** and **server2**
@@ -91,8 +89,7 @@ we plan to track state **per series** in a future release.
### No Data / Null values
Below you condition you can configure how the rule evaluation engine should handle queries that return no data or only null valued
data.
Below your conditions you can configure how the rule evaluation engine should handle queries that return no data or only null values.
No Data Option | Description
------------ | -------------
@@ -102,23 +99,23 @@ Keep Last State | Keep the current alert rule state, what ever it is.
### Execution errors or timeouts
The last option is how to handle execution or timeout errors.
The last option tells how to handle execution or timeout errors.
Error or timeout option | Description
------------ | -------------
Alerting | Set alert rule state to `Alerting`
Keep Last State | Keep the current alert rule state, what ever it is.
If you an unreliable time series store that where queries sometime timeout or fail randomly you can set this option
t `Keep Last State` to basically ignore them.
If you have an unreliable time series store from which queries sometime timeout or fail randomly you can set this option
to `Keep Last State` in order to basically ignore them.
## Notifications
In alert tab you can also specify alert rule notifications along with a detailed messsage about the alert rule.
The message can contain anything, information about how you might solve the issue, link to runbook etc.
The message can contain anything, information about how you might solve the issue, link to runbook, etc.
The actual notifications are configured and shared between multiple alerts. Read the
[Notifications]({{< relref "notifications.md" >}}) guide for how to configure and setup notifications.
[notifications]({{< relref "notifications.md" >}}) guide for how to configure and setup notifications.
## Alert State History & Annotations
@@ -131,7 +128,7 @@ submenu in the alert tab to view & clear state history.
{{< imgbox max-width="40%" img="/img/docs/v4/alert_test_rule.png" caption="Test Rule" >}}
First level of troubleshooting you can do is hit the **Test Rule** button. You will get result back that you can expand
to the point where you can see the raw data that was returned form your query.
to the point where you can see the raw data that was returned from your query.
Further troubleshooting can also be done by inspecting the grafana-server log. If it's not an error or for some reason
the log does not say anything you can enable debug logging for some relevant components. This is done

View File

@@ -13,6 +13,10 @@ Here you can find links to older versions of the documentation that might be bet
of Grafana.
- [Latest](http://docs.grafana.org)
- [Version 4.4](http://docs.grafana.org/v4.4)
- [Version 4.3](http://docs.grafana.org/v4.3)
- [Version 4.2](http://docs.grafana.org/v4.2)
- [Version 4.1](http://docs.grafana.org/v4.1)
- [Version 4.0](http://docs.grafana.org/v4.0)
- [Version 3.1](http://docs.grafana.org/v3.1)
- [Version 3.0](http://docs.grafana.org/v3.0)

View File

@@ -84,8 +84,8 @@ Name | Description
*metrics(namespace, [region])* | Returns a list of metrics in the namespace. (specify region 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 id matching the specified `region`, `instance_id`.
*ec2_instance_attribute(region, attribute_name, filters)* | Returns a list of attribute matching the specified `region`, `attribute_name`, `filters`.
*ebs_volume_ids(region, instance_id)* | Returns a list of volume ids matching the specified `region`, `instance_id`.
*ec2_instance_attribute(region, attribute_name, filters)* | Returns a list of attributes matching the specified `region`, `attribute_name`, `filters`.
For details about the metrics CloudWatch provides, please refer to the [CloudWatch documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CW_Support_For_AWS.html).
@@ -101,10 +101,13 @@ Query | Service
*dimension_values(us-east-1,AWS/RDS,CPUUtilization,DBInstanceIdentifier)* | RDS
*dimension_values(us-east-1,AWS/S3,BucketSizeBytes,BucketName)* | S3
#### ec2_instance_attribute JSON filters
## ec2_instance_attribute examples
The `ec2_instance_attribute` query take `filters` in JSON format.
### JSON filters
The `ec2_instance_attribute` query takes `filters` in JSON format.
You can specify [pre-defined filters of ec2:DescribeInstances](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html).
Note that the actual filtering takes place on Amazon's servers, not in Grafana.
Filters syntax:
@@ -116,6 +119,45 @@ Example `ec2_instance_attribute()` query
ec2_instance_attribute(us-east-1, InstanceId, { "tag:Environment": [ "production" ] })
### Selecting Attributes
Only 1 attribute per instance can be returned. Any flat attribute can be selected (i.e. if the attribute has a single value and isn't an object or array). Below is a list of available flat attributes:
* `AmiLaunchIndex`
* `Architecture`
* `ClientToken`
* `EbsOptimized`
* `EnaSupport`
* `Hypervisor`
* `IamInstanceProfile`
* `ImageId`
* `InstanceId`
* `InstanceLifecycle`
* `InstanceType`
* `KernelId`
* `KeyName`
* `LaunchTime`
* `Platform`
* `PrivateDnsName`
* `PrivateIpAddress`
* `PublicDnsName`
* `PublicIpAddress`
* `RamdiskId`
* `RootDeviceName`
* `RootDeviceType`
* `SourceDestCheck`
* `SpotInstanceRequestId`
* `SriovNetSupport`
* `SubnetId`
* `VirtualizationType`
* `VpcId`
Tags can be selected by prepending the tag name with `Tags.`
Example `ec2_instance_attribute()` query
ec2_instance_attribute(us-east-1, Tags.Name, { "tag:Team": [ "sysops" ] })
## Cost
Amazon provides 1 million CloudWatch API requests each month at no additional charge. Past this,

View File

@@ -41,7 +41,9 @@ Proxy access means that the Grafana backend will proxy all requests from the bro
Click the ``Select metric`` link to start navigating the metric space. One you start you can continue using the mouse
or keyboard arrow keys. You can select a wildcard and still continue.
![](/img/docs/animated_gifs/graphite_query1.gif)
{{< docs-imagebox img="/img/docs/v45/graphite_query1_still.png"
animated-gif="/img/docs/v45/graphite_query1.gif" >}}
### Functions
@@ -50,18 +52,26 @@ a function is selected it will be added and your focus will be in the text box o
a parameter just click on it and it will turn into a text box. To delete a function click the function name followed
by the x icon.
![](/img/docs/animated_gifs/graphite_query2.gif)
{{< docs-imagebox img="/img/docs/v45/graphite_query2_still.png"
animated-gif="/img/docs/v45/graphite_query2.gif" >}}
### Optional parameters
Some functions like aliasByNode support an optional second argument. To add this parameter specify for example 3,-2 as the first parameter and the function editor will adapt and move the -2 to a second parameter. To remove the second optional parameter just click on it and leave it blank and the editor will remove it.
![](/img/docs/animated_gifs/func_editor_optional_params.gif)
{{< docs-imagebox img="/img/docs/v45/graphite_query3_still.png"
animated-gif="/img/docs/v45/graphite_query3.gif" >}}
### Nested Queries
You can reference queries by the row “letter” that theyre on (similar to Microsoft Excel). If you add a second query to a graph, you can reference the first query simply by typing in #A. This provides an easy and convenient way to build compounded queries.
{{< docs-imagebox img="/img/docs/v45/graphite_nested_queries_still.png"
animated-gif="/img/docs/v45/graphite_nested_queries.gif" >}}
## Point consolidation
All Graphite metrics are consolidated so that Graphite doesn't return more data points than there are pixels in the graph. By default,

View File

@@ -36,12 +36,12 @@ Name | Description
### Proxy vs Direct access
Proxy access means that the Grafana backend will proxy all requests from the browser. So requests to InfluxDB will be channeled through
`grafana-server`. This means that the URL you specify needs to be accessable from the server you are running Grafana on. Proxy access
`grafana-server`. This means that the URL you specify needs to be accessible from the server you are running Grafana on. Proxy access
mode is also more secure as the username & password will never reach the browser.
## Query Editor
![](/assets/img/blog/v2.6/influxdb_editor_v3.gif)
{{< docs-imagebox img="/img/docs/v45/influxdb_query_still.png" class="docs-image--no-shadow" animated-gif="/img/docs/v45/influxdb_query.gif" >}}
You find the InfluxDB editor in the metrics tab in Graph or Singlestat panel's edit mode. You enter edit mode by clicking the
panel title, then edit. The editor allows you to select metrics and tags.
@@ -57,10 +57,8 @@ will automatically adjust the filter tag condition to use the InfluxDB regex mat
### Field & Aggregation functions
In the `SELECT` row you can specify what fields and functions you want to use. If you have a
group by time you need an aggregation function. Some functions like derivative require an aggregation function.
The editor tries simplify and unify this part of the query. For example:
![](/img/docs/influxdb/select_editor.png)
group by time you need an aggregation function. Some functions like derivative require an aggregation function. The editor tries simplify and unify this part of the query. For example:<br>
![](/img/docs/influxdb/select_editor.png)<br>
The above will generate the following InfluxDB `SELECT` clause:
@@ -88,7 +86,7 @@ You can switch to raw query mode by clicking hamburger icon and then `Switch edi
- $m = replaced with measurement name
- $measurement = replaced with measurement name
- $col = replaced with column name
- $tag_exampletag = replaced with the value of the `exampletag` tag. To use your tag as an alias in the ALIAS BY field then the tag must be used to group by in the query.
- $tag_exampletag = replaced with the value of the `exampletag` tag. The syntax is `$tag_yourTagName` (must start with `$tag_`). To use your tag as an alias in the ALIAS BY field then the tag must be used to group by in the query.
- You can also use [[tag_hostname]] pattern replacement syntax. For example, in the ALIAS BY field using this text `Host: [[tag_hostname]]` would substitute in the `hostname` tag value for each legend value and an example legend value would be: `Host: server1`.
### Table query / raw data
@@ -132,7 +130,7 @@ You can fetch key names for a given measurement.
SHOW TAG KEYS [FROM <measurement_name>]
```
If you have a variable with key names you can use this variable in a group by clause. This will allow you to change group by using the variable dropdown a the top
If you have a variable with key names you can use this variable in a group by clause. This will allow you to change group by using the variable dropdown at the top
of the dashboard.
### Using variables in queries

View File

@@ -11,8 +11,7 @@ weight = 7
# Using MySQL in Grafana
> Only available in Grafana v4.3+. This data source is not ready for
> production use, currently in development (alpha state).
> Only available in Grafana v4.3+.
Grafana ships with a built-in MySQL data source plugin that allow you to query any visualize
data from a MySQL compatible database.
@@ -29,8 +28,7 @@ data from a MySQL compatible database.
The database user you specify when you add the data source should only be granted SELECT permissions on
the specified database & tables you want to query. Grafana does not validate that the query is safe. The query
could include any SQL statement. For example, statements like `USE otherdb;` and `DROP TABLE user;` would be
executed. To protect against this we **Highly** recommmend you create a specific mysql user with
restricted permissions.
executed. To protect against this we **Highly** recommmend you create a specific mysql user with restricted permissions.
Example:
@@ -49,11 +47,9 @@ Macro example | Description
------------ | -------------
*$__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)*
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.
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.
The query editor has a link named `Generated SQL` that show up after a query as been executed, while in panel edit mode. Click
on it and it will expand and show the raw interpolated SQL string that was executed.
The query editor has a link named `Generated SQL` that show up after a query as been executed, while in panel edit mode. Click on it and it will expand and show the raw interpolated SQL string that was executed.
## Table queries
@@ -61,8 +57,7 @@ If the `Format as` query option is set to `Table` then you can basically do any
Query editor with example query:
![](/img/docs/v43/mysql_table_query.png)
{{< docs-imagebox img="/img/docs/v45/mysql_table_query.png" >}}
The query:
@@ -109,8 +104,71 @@ This is something we plan to add.
## Templating
You can use variables in your queries but there are currently no support for defining `Query` variables
that target a MySQL data source.
This feature is currently available in the nightly builds and will be included in the 5.0.0 release.
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 makes it easy to change the data being displayed in your dashboard.
Checkout the [Templating]({{< relref "reference/templating.md" >}}) documentation for an introduction to the templating feature and the different types of template variables.
### Query Variable
If you add a template variable of the type `Query`, you can write a MySQL query that can
return things like measurement names, key names or key values that are shown as a dropdown select box.
For example, you can have a variable that contains all values for the `hostname` column in a table if you specify a query like this in the templating variable *Query* setting.
```sql
SELECT hostname FROM my_host
```
A query can returns multiple columns and Grafana will automatically create a list from them. For example, the query below will return a list with values from `hostname` and `hostname2`.
```sql
SELECT my_host.hostname, my_other_host.hostname2 FROM my_host JOIN my_other_host ON my_host.city = my_other_host.city
```
Another option is a query that can create a key/value variable. The query should return two columns that are named `__text` and `__value`. The `__text` column value should be unique (if it is not unique then the first value is used). The options in the dropdown will have a text and value that allows you to have a friendly name as text and an id as the value. An example query with `hostname` as the text and `id` as the value:
```sql
SELECT hostname AS __text, id AS __value FROM my_host
```
You can also create nested variables. For example if you had another variable named `region`. Then you could have
the hosts variable only show hosts from the current selected region with a query like this (if `region` is a multi-value variable then use the `IN` comparison operator rather than `=` to match against multiple values):
```sql
SELECT hostname FROM my_host WHERE region IN($region)
```
### Using Variables in Queries
Template variables are quoted automatically so if it is a string value do not wrap them in quotes in where clauses. If the variable is a multi-value variable then use the `IN` comparison operator rather than `=` to match against multiple values.
There are two syntaxes:
`$<varname>` Example with a template variable named `hostname`:
```sql
SELECT
UNIX_TIMESTAMP(atimestamp) as time_sec,
aint as value,
avarchar as metric
FROM my_table
WHERE $__timeFilter(atimestamp) and hostname in($hostname)
ORDER BY atimestamp ASC
```
`[[varname]]` Example with a template variable named `hostname`:
```sql
SELECT
UNIX_TIMESTAMP(atimestamp) as time_sec,
aint as value,
avarchar as metric
FROM my_table
WHERE $__timeFilter(atimestamp) and hostname in([[hostname]])
ORDER BY atimestamp ASC
```
## Alerting

View File

@@ -39,14 +39,16 @@ Name | Description
Open a graph in edit mode by click the title > Edit (or by pressing `e` key while hovering over panel).
![](/img/docs/v43/prometheus_query_editor.png)
{{< docs-imagebox img="/img/docs/v45/prometheus_query_editor_still.png"
animated-gif="/img/docs/v45/prometheus_query_editor.gif" >}}
Name | Description
------- | --------
*Query expression* | Prometheus query expression, check out the [Prometheus documentation](http://prometheus.io/docs/querying/basics/).
*Legend format* | Controls the name of the time series, using name or pattern. For example `{{hostname}}` will be replaced with label value for the label `hostname`.
*Min step* | Set a lower limit for the Prometheus step option. Step controls how big the jumps are when the Prometheus query engine performs range queries. Sadly there is no official prometheus documentation to link to for this very important option.
*Resolution* | Controls the step option. Small steps create high-resolution graphs but can be slow over larger time ranges, lowering the resolution can speed things up. `1/2` will try to set step option to generate 1 data point for every other pixel. A value of `1/10` will try to set step option so there is a data point every 10 pixels.*Metric lookup* | Search for metric names in this input field.
*Resolution* | Controls the step option. Small steps create high-resolution graphs but can be slow over larger time ranges, lowering the resolution can speed things up. `1/2` will try to set step option to generate 1 data point for every other pixel. A value of `1/10` will try to set step option so there is a data point every 10 pixels.
*Metric lookup* | Search for metric names in this input field.
*Format as* | **(New in v4.3)** Switch between Table & Time series. Table format will only work in the Table panel.
## Templating
@@ -77,7 +79,7 @@ For details of *metric names*, *label names* and *label values* are please refer
There are two syntaxes:
- `$<varname>` Example: rate(http_requests_total{job=~"$job"}[5m])
- `[[varname]]` Example: rate(http_requests_total{job="my[[job]]"}[5m])
- `[[varname]]` Example: rate(http_requests_total{job=~"[[job]]"}[5m])
Why two ways? The first syntax is easier to read and write but does not allow you to use a variable in the middle of a word. When the *Multi-value* or *Include all value*
options are enabled, Grafana converts the labels from plain text to a regex compatible string. Which means you have to use `=~` instead of `=`.

View File

@@ -13,7 +13,7 @@ weight = 20
The purpose of this data sources is to make it easier to create fake data for any panel.
Using `Grafana TestData` you can build your own time series and have any panel render it.
This make is much easier to verify functionally since the data can be shared very
This make is much easier to verify functionally since the data can be shared very easily.
## Enable

View File

@@ -50,15 +50,11 @@ populate the template variable to a desired value from the link.
The metrics tab defines what series data and sources to render. Each datasource provides different
options.
## Axes & Grid
## Axes
![](/img/docs/v43/graph_axes_grid_options.png)
The Axes & Grid tab controls the display of axes, grids and legend.
### Axes
The ``Left Y`` and ``Right Y`` can be customized using:
The Axes tab controls the display of axes, grids and legend. The ``Left Y`` and ``Right Y`` can be customized using:
- ``Unit`` - The display unit for the Y value
- ``Grid Max`` - The maximum Y value. (default auto)
@@ -67,6 +63,20 @@ The ``Left Y`` and ``Right Y`` can be customized using:
Axes can also be hidden by unchecking the appropriate box from `Show Axis`.
### X-Axis Mode
There are three options:
- The default option is `Time` and means the x-axis represents time and that the data is grouped by time (for example, by hour or by minute).
- The `Series` option means that the data is grouped by series and not by time. The y-axis still represents the value.
<img src="/img/docs/v4/x_axis_mode_series.png" class="no-shadow">
- The `Histogram` option converts the graph into a histogram. A Histogram is a kind of bar chart that groups numbers into ranges, often called buckets or bins. Taller bars show that more data falls in that range. Histograms and buckets are described in more detail [here](http://docs.grafana.org/features/panels/heatmap/#histograms-and-buckets).
<img src="/img/docs/v43/heatmap_histogram.png" class="no-shadow">
### Legend
The legend hand be hidden by checking the ``Show`` checkbox. If it's shown, it can be

View File

@@ -34,7 +34,7 @@ The singlestat panel has a normal query editor to allow you define your exact me
* `delta` - The total incremental increase (of a counter) in the series. An attempt is made to account for counter resets, but this will only be accurate for single instance metrics. Used to show total counter increase in time series.
* `diff` - The difference betwen 'current' (last value) and 'first'.
* `range` - The difference between 'min' and 'max'. Useful the show the range of change for a gauge.
4. `Postfixes`: The Postfix fields let you define a custom label and font-size (as a %) to appear *after* the value
4. `Prefix/Postfix`: The Prefix/Postfix fields let you define a custom label and font-size (as a %) to appear *before/after* the value. The `$__name` variable can be used here to use the series name or alias from the metric query.
5. `Units`: Units are appended to the the Singlestat within the panel, and will respect the color and threshold settings for the value.
6. `Decimals`: The Decimal field allows you to override the automatic decimal precision, and set it explicitly.

View File

@@ -12,7 +12,7 @@ weight = 2
# Table Panel
<img src="/assets/img/features/table-panel.png">
<img class="screenshot" src="/assets/img/features/table-panel.png">
The new table panel is very flexible, supporting both multiple modes for time series as well as for
table, annotation and raw JSON data. It also provides date formatting and value formatting and coloring options.
@@ -22,55 +22,63 @@ To view table panels in action and test different configurations with sample dat
## Options overview
The table panel has many ways to manipulate your data for optimal presentation.
{{< docs-imagebox img="/img/docs/v45/table_options.png" class="docs-image--no-shadow" max-width= "500px" >}}
<img class="no-shadow" src="/img/docs/v2/table-config2.png">
1. `Data`: Control how your query is transformed into a table.
2. `Table Display`: Table display options.
3. `Column Styles`: Column value formatting and display options.
2. `Paging`: Table display options.
## Data to Table
<img class="no-shadow" src="/img/docs/v2/table-data-options.png">
{{< docs-imagebox img="/img/docs/v45/table_data_options.png" max-width="500px" class="docs-image--right">}}
The data section contains the **To Table Transform (1)**. This is the primary option for how your data/metric
query should be transformed into a table format. The **Columns (2)** option allows you to select what columns
you want in the table. Only applicable for some transforms.
<div class="clearfix"></div>
### Time series to rows
<img src="/img/docs/v2/table_ts_to_rows2.png">
{{< docs-imagebox img="/img/docs/v45/table_ts_to_rows.png" >}}
In the most simple mode you can turn time series to rows. This means you get a `Time`, `Metric` and a `Value` column. Where `Metric` is the name of the time series.
### Time series to columns
![](/img/docs/v2/table_ts_to_columns2.png)
{{< docs-imagebox img="/img/docs/v45/table_ts_to_columns.png" >}}
This transform allows you to take multiple time series and group them by time. Which will result in the primary column being `Time` and a column for each time series.
### Time series aggregations
![](/img/docs/v2/table_ts_to_aggregations2.png)
{{< docs-imagebox img="/img/docs/v45/table_ts_to_aggregations.png" >}}
This table transformation will lay out your table into rows by metric, allowing columns of `Avg`, `Min`, `Max`, `Total`, `Current` and `Count`. More than one column can be added.
### Annotations
![](/img/docs/v2/table_annotations.png)
{{< docs-imagebox img="/img/docs/v45/table_annotations.png" >}}
If you have annotations enabled in the dashboard you can have the table show them. If you configure this
mode then any queries you have in the metrics tab will be ignored.
### JSON Data
![](/img/docs/v2/table_json_data.png)
{{< docs-imagebox img="/img/docs/v45/table_json_data.png" max-width="500px" >}}
If you have an Elasticsearch **Raw Document** query or an Elasticsearch query without a `date histogram` use this
transform mode and pick the columns using the **Columns** section.
![](/img/docs/v2/elastic_raw_doc.png)
{{< docs-imagebox img="/img/docs/v45/elastic_raw_doc.png" >}}
## Table Display
<img class="no-shadow" src="/img/docs/v2/table-display.png">
{{< docs-imagebox img="/img/docs/v45/table_paging.png" class="docs-image--no-shadow docs-image--right" max-width="350px" >}}
1. `Pagination (Page Size)`: The table display fields allow you to control The `Pagination` (page size) is the threshold at which the table rows will be broken into pages. For example, if your table had 95 records with a pagination value of 10, your table would be split across 9 pages.
2. `Scroll`: The `scroll bar` checkbox toggles the ability to scroll within the panel, when unchecked, the panel height will grow to display all rows.
@@ -81,13 +89,11 @@ transform mode and pick the columns using the **Columns** section.
The column styles allow you control how dates and numbers are formatted.
<img class="no-shadow" src="/img/docs/v2/Column-Options.png">
{{< docs-imagebox img="/img/docs/v45/table_column_styles.png" class="docs-image--no-shadow" >}}
1. `Name or regex`: The Name or Regex field controls what columns the rule should be applied to. The regex or name filter will be matched against the column name not against column values.
2. `Type`: The three supported types of types are `Number`, `String` and `Date`.
3. `Title`: Title for the column, when using a Regex the title can include replacement strings like `$1`.
4. `Format`: Specify date format. Only available when `Type` is set to `Date`.
5. `Coloring` and `Thresholds`: Specify color mode and thresholds limits.
6. `Unit` and `Decimals`: Specify unit and decimal precision for numbers.
7. `Add column style rule`: Add new column rule.
2. `Column Header`: Title for the column, when using a Regex the title can include replacement strings like `$1`.
3. `Add column style rule`: Add new column rule.
4. `Thresholds` and `Coloring`: Specify color mode and thresholds limits.
5. `Type`: The three supported types of types are `Number`, `String` and `Date`. `Unit` and `Decimals`: Specify unit and decimal precision for numbers.`Format`: Specify date format for dates.

View File

@@ -8,7 +8,7 @@ weight = 7
# Keyboard shortcuts
{{< docs-imagebox img="/img/docs/v4/shortcuts.png" max-width="20rem" >}}
{{< docs-imagebox img="/img/docs/v4/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

View File

@@ -24,9 +24,9 @@ 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 at the bottom 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/v2/v2_top_nav_annotated.png">
<img class="no-shadow" src="/img/docs/v45/top_nav_annotated.png">
The image above shows you the top header for a Dashboard.
@@ -41,19 +41,7 @@ The image above shows you the top header for a Dashboard.
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.
## Adding & Editing Graphs and Panels
![](/img/docs/v2/graph_metrics_tab_graphite.png)
1. You add panels via row menu. The row menu is the green icon to the left of each row.
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.
When you click the `Metrics` tab, you are presented with a Query Editor that is specific to the Panel Data Source. Use the Query Editor to build your queries and Grafana will visualize them in real time.
<img src="/img/docs/v2/dashboard_annotated.png" class="no-shadow">
<img src="/img/docs/v45/dashboard_annotated.png" class="no-shadow">
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.
@@ -62,6 +50,17 @@ When you click the `Metrics` tab, you are presented with a Query Editor that is
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.
## Adding & Editing Graphs and Panels
![](/img/docs/v45/metrics_tab.png)
1. You add panels via row menu. The row menu is the icon to the left of each row.
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.
When you click the `Metrics` tab, you are presented with a Query Editor that is specific to the Panel Data Source. Use the Query Editor to build your queries and Grafana will visualize them in real time.
## 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.

View File

@@ -0,0 +1,50 @@
+++
title = "What's New in Grafana v4.4"
description = "Feature & improvement highlights for Grafana v4.4"
keywords = ["grafana", "new", "documentation", "4.4.0"]
type = "docs"
[menu.docs]
name = "Version 4.4"
identifier = "v4.4"
parent = "whatsnew"
weight = -3
+++
## What's New in Grafana v4.4
Grafana v4.4 is now [available for download](https://grafana.com/grafana/download/4.4.0).
**Highlights**:
- Dashboard History - version control for dashboards.
## New Features
**Dashboard History**: View dashboard version history, compare any two versions (summary & json diffs), restore to old version. This big feature
was contributed by **Walmart Labs**. Big thanks to them for this massive contribution!
Initial feature request: [#4638](https://github.com/grafana/grafana/issues/4638)
Pull Request: [#8472](https://github.com/grafana/grafana/pull/8472)
## Enhancements
* **Elasticsearch**: Added filter aggregation label [#8420](https://github.com/grafana/grafana/pull/8420), thx [@tianzk](github.com/tianzk)
* **Sensu**: Added option for source and handler [#8405](https://github.com/grafana/grafana/pull/8405), thx [@joemiller](github.com/joemiller)
* **CSV**: Configurable csv export datetime format [#8058](https://github.com/grafana/grafana/issues/8058), thx [@cederigo](github.com/cederigo)
* **Table Panel**: Column style that preserves formatting/indentation (like pre tag) [#6617](https://github.com/grafana/grafana/issues/6617)
* **DingDing**: Add DingDing Alert Notifier [#8473](https://github.com/grafana/grafana/pull/8473) thx [@jiamliang](https://github.com/jiamliang)
## Minor Enhancements
* **Elasticsearch**: Add option for result set size in raw_document [#3426](https://github.com/grafana/grafana/issues/3426) [#8527](https://github.com/grafana/grafana/pull/8527), thx [@mk-dhia](github.com/mk-dhia)
## Bug Fixes
* **Graph**: Bug fix for negative values in histogram mode [#8628](https://github.com/grafana/grafana/issues/8628)
## Download
Head to the [v4.4 download page](https://grafana.com/grafana/download) for download links & instructions.
## Thanks
A big thanks to all the Grafana users who contribute by submitting PRs, bug reports, helping out on our [community site](https://community.grafana.com/) and providing feedback!

View File

@@ -0,0 +1,71 @@
+++
title = "What's New in Grafana v4.5"
description = "Feature & improvement highlights for Grafana v4.5"
keywords = ["grafana", "new", "documentation", "4.5"]
type = "docs"
[menu.docs]
name = "Version 4.5"
identifier = "v4.5"
parent = "whatsnew"
weight = -4
+++
# What's New in Grafana v4.5
## Hightlights
### New prometheus query editor
The new query editor has full syntax highlighting. As well as auto complete for metrics, functions, and range vectors. There is also integrated function docs right from the query editor!
{{< docs-imagebox img="/img/docs/v45/prometheus_query_editor_still.png" class="docs-image--block" animated-gif="/img/docs/v45/prometheus_query_editor.gif" >}}
### Elasticsearch: Add ad-hoc filters from the table panel
{{< docs-imagebox img="/img/docs/v45/elastic_ad_hoc_filters.png" class="docs-image--block" >}}
### Table cell links!
Create column styles that turn cells into links that use the value in the cell (or other other row values) to generate a url to another dashboard or system:
![](/img/docs/v45/table_links.jpg)
### Query Inspector
Query Inspector is a new feature that shows query requests and responses. This can be helpful if a graph is not shown or shows something very different than what you expected.
More information [here](https://community.grafana.com/t/using-grafanas-query-inspector-to-troubleshoot-issues/2630).
![](/img/docs/v45/query_inspector.png)
## Changelog
### New Features
* **Table panel**: Render cell values as links that can have an url template that uses variables from current table row. [#3754](https://github.com/grafana/grafana/issues/3754)
* **Elasticsearch**: Add ad hoc filters directly by clicking values in table panel [#8052](https://github.com/grafana/grafana/issues/8052).
* **MySQL**: New rich query editor with syntax highlighting
* **Prometheus**: New rich query editor with syntax highlighting, metric & range auto complete and integrated function docs. [#5117](https://github.com/grafana/grafana/issues/5117)
### Enhancements
* **GitHub OAuth**: Support for GitHub organizations with 100+ teams. [#8846](https://github.com/grafana/grafana/issues/8846), thx [@skwashd](https://github.com/skwashd)
* **Graphite**: Calls to Graphite api /metrics/find now include panel or dashboad time range (from & until) in most cases, [#8055](https://github.com/grafana/grafana/issues/8055)
* **Graphite**: Added new graphite 1.0 functions, available if you set version to 1.0.x in data source settings. New Functions: mapSeries, reduceSeries, isNonNull, groupByNodes, offsetToZero, grep, weightedAverage, removeEmptySeries, aggregateLine, averageOutsidePercentile, delay, exponentialMovingAverage, fallbackSeries, integralByInterval, interpolate, invert, linearRegression, movingMin, movingMax, movingSum, multiplySeriesWithWildcards, pow, powSeries, removeBetweenPercentile, squareRoot, timeSlice, closes [#8261](https://github.com/grafana/grafana/issues/8261)
- **Elasticsearch**: Ad-hoc filters now use query phrase match filters instead of term filters, works on non keyword/raw fields [#9095](https://github.com/grafana/grafana/issues/9095).
### Breaking change
* **InfluxDB/Elasticsearch**: The panel & data source option named "Group by time interval" is now named "Min time interval" and does now always define a lower limit for the auto group by time. Without having to use `>` prefix (that prefix still works). This should in theory have close to zero actual impact on existing dashboards. It does mean that if you used this setting to define a hard group by time interval of, say "1d", if you zoomed to a time range wide enough the time range could increase above the "1d" range as the setting is now always considered a lower limit.
This option is now rennamed (and moved to Options sub section above your queries):
![image|519x120](upload://ySjHOVpavV6yk9LHQxL9nq2HIsT.png)
Datas source selection & options & help are now above your metric queries.
![image|690x179](upload://5kNDxKgMz1BycOKgG3iWYLsEVXv.png)
### Minor Changes
* **InfluxDB**: Change time range filter for absolute time ranges to be inclusive instead of exclusive [#8319](https://github.com/grafana/grafana/issues/8319), thx [@Oxydros](https://github.com/Oxydros)
* **InfluxDB**: Added paranthesis around tag filters in queries [#9131](https://github.com/grafana/grafana/pull/9131)
## Bug Fixes
* **Modals**: Maintain scroll position after opening/leaving modal [#8800](https://github.com/grafana/grafana/issues/8800)
* **Templating**: You cannot select data source variables as data source for other template variables [#7510](https://github.com/grafana/grafana/issues/7510)

View File

@@ -11,14 +11,16 @@ parent = "http_api"
# Admin API
The admin http API does not currently work with an api token. Api Token's are currently only linked to an organization and organization role. They cannot given
the permission of server admin, only user's can be given that permission. So in order to use these API calls you will have to use basic auth and Grafana user
with Grafana admin permission.
The Admin HTTP API does not currently work with an API Token. API Tokens are currently only linked to an organization and an organization role. They cannot be given
the permission of server admin, only users can be given that permission. So in order to use these API calls you will have to use Basic Auth and the Grafana user
must have the Grafana Admin permission. (The default admin user is called `admin` and has permission to use this API.)
## Settings
`GET /api/admin/settings`
Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
**Example Request**:
GET /api/admin/settings
@@ -176,6 +178,8 @@ with Grafana admin permission.
`GET /api/admin/stats`
Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
**Example Request**:
GET /api/admin/stats
@@ -203,7 +207,7 @@ with Grafana admin permission.
`POST /api/admin/users`
Create new user
Create new user. Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
**Example Request**:
@@ -229,7 +233,8 @@ Create new user
`PUT /api/admin/users/:id/password`
Change password for specific user
Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
Change password for a specific user.
**Example Request**:
@@ -250,6 +255,8 @@ Change password for specific user
`PUT /api/admin/users/:id/permissions`
Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
**Example Request**:
PUT /api/admin/users/2/permissions HTTP/1.1
@@ -269,6 +276,8 @@ Change password for specific user
`DELETE /api/admin/users/:id`
Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
**Example Request**:
DELETE /api/admin/users/2 HTTP/1.1
@@ -286,6 +295,8 @@ Change password for specific user
`POST /api/admin/pause-all-alerts`
Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
**Example Request**:
POST /api/admin/pause-all-alerts HTTP/1.1

View File

@@ -46,6 +46,7 @@ JSON Body schema:
- **200** Created
- **400** Errors (invalid json, missing or invalid fields, etc)
- **401** Unauthorized
- **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
@@ -239,7 +240,7 @@ Get all tags of dashboards
`GET /api/search/`
Status Codes:
Query parameters:
- **query** Search Query
- **tag** Tag to use
@@ -268,9 +269,3 @@ Status Codes:
"isStarred":false
}
]
"email":"admin@mygraf.com",
"login":"admin",
"role":"Admin"
}
]

View File

@@ -137,7 +137,7 @@ parent = "http_api"
`POST /api/datasources`
**Example Request**:
**Example Graphite Request**:
POST /api/datasources HTTP/1.1
Accept: application/json
@@ -152,6 +152,28 @@ parent = "http_api"
"basicAuth":false
}
**Example CloudWatch Request**:
```
POST /api/datasources HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
{
"name": "test_datasource",
"type": "cloudwatch",
"url": "http://monitoring.us-west-1.amazonaws.com",
"access": "proxy",
"jsonData": {
"authType": "keys",
"defaultRegion": "us-west-1"
},
"secureJsonData": {
"accessKey": "Ol4pIDpeKSA6XikgOl4p",
"secretKey": "dGVzdCBrZXkgYmxlYXNlIGRvbid0IHN0ZWFs"
}
}
```
**Example Response**:

View File

@@ -20,9 +20,9 @@ parent = "http_api"
GET /api/users HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
Authorization: Basic YWRtaW46YWRtaW4=
Default value for the `perpage` parameter is `1000` and for the `page` parameter is `1`.
Default value for the `perpage` parameter is `1000` and for the `page` parameter is `1`. Requires basic authentication and that the authenticated user is a Grafana Admin.
**Example Response**:
@@ -55,10 +55,12 @@ Default value for the `perpage` parameter is `1000` and for the `page` parameter
GET /api/users/search?perpage=10&page=1&query=mygraf HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
Authorization: Basic YWRtaW46YWRtaW4=
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 user list E.g. if `totalCount` is equal to 100 users and the `perpage` parameter is set to 10 then there are 10 pages of users. The `query` parameter is optional and it will return results where the query value is contained in one of the `name`, `login` or `email` fields. Query values with spaces need to be url encoded e.g. `query=Jane%20Doe`.
Requires basic authentication and that the authenticated user is a Grafana Admin.
**Example Response**:
HTTP/1.1 200
@@ -94,7 +96,9 @@ Default value for the `perpage` parameter is `1000` and for the `page` parameter
GET /api/users/1 HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
Authorization: Basic YWRtaW46YWRtaW4=
Requires basic authentication and that the authenticated user is a Grafana Admin.
**Example Response**:
@@ -126,7 +130,9 @@ Default value for the `perpage` parameter is `1000` and for the `page` parameter
GET /api/users/lookup?loginOrEmail=admin HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
Authorization: Basic YWRtaW46YWRtaW4=
Requires basic authentication and that the authenticated user is a Grafana Admin.
**Example Response**:
@@ -152,7 +158,7 @@ Default value for the `perpage` parameter is `1000` and for the `page` parameter
PUT /api/users/2 HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
Authorization: Basic YWRtaW46YWRtaW4=
{
"email":"user@mygraf.com",
@@ -161,6 +167,8 @@ Default value for the `perpage` parameter is `1000` and for the `page` parameter
"theme":"light"
}
Requires basic authentication and that the authenticated user is a Grafana Admin.
**Example Response**:
HTTP/1.1 200
@@ -178,7 +186,9 @@ Default value for the `perpage` parameter is `1000` and for the `page` parameter
GET /api/users/1/orgs HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
Authorization: Basic YWRtaW46YWRtaW4=
Requires basic authentication and that the authenticated user is a Grafana Admin.
**Example Response**:
@@ -246,11 +256,29 @@ Changes the password for the user
{"message":"User password changed"}
## Switch user context
## Switch user context for a specified user
`POST /api/user/using/:organisationId`
`POST /api/users/:userId/using/:organizationId`
Switch user context to the given organisation.
Switch user context to the given organization. Requires basic authentication and that the authenticated user is a Grafana Admin.
**Example Request**:
POST /api/users/7/using/2 HTTP/1.1
Authorization: Basic YWRtaW46YWRtaW4=
**Example Response**:
HTTP/1.1 200
Content-Type: application/json
{"message":"Active organization changed"}
## Switch user context for signed in user
`POST /api/user/using/:organizationId`
Switch user context to the given organization.
**Example Request**:

View File

@@ -15,6 +15,12 @@ weight = 1
The Grafana back-end has a number of configuration options that can be
specified in a `.ini` configuration file or specified using environment variables.
## Comments In .ini Files
Semicolons (the `;` char) are the standard way to comment out lines in a `.ini` file.
A common problem is forgetting to uncomment a line in the `custom.ini` (or `grafana.ini`) file which causes the configuration option to be ignored.
## Config file locations
- Default configuration from `$WORKING_DIR/conf/defaults.ini`
@@ -206,7 +212,7 @@ For MySQL, use either `true`, `false`, or `skip-verify`.
### max_idle_conn
The maximum number of connections in the idle connection pool.
### max_open_conn
### max_open_conn
The maximum number of open connections to the database.
<hr />
@@ -246,13 +252,13 @@ Define a white list of allowed ips/domains to use in data sources. Format: `ip_o
### allow_sign_up
Set to `false` to prohibit users from being able to sign up / create
user accounts. Defaults to `true`. The admin user can still create
user accounts. Defaults to `false`. The admin user can still create
users from the [Grafana Admin Pages](../../reference/admin)
### allow_org_create
Set to `false` to prohibit users from creating new organizations.
Defaults to `true`.
Defaults to `false`.
### auto_assign_org

View File

@@ -15,7 +15,8 @@ weight = 1
Description | Download
------------ | -------------
Stable for Debian-based Linux | [grafana_4.3.1_amd64.deb](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.3.1_amd64.deb)
Stable for Debian-based Linux | [grafana_4.4.3_amd64.deb](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.4.3_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)
Read [Upgrading Grafana]({{< relref "installation/upgrading.md" >}}) for tips and guidance on updating an existing
installation.
@@ -23,20 +24,18 @@ installation.
## Install Stable
```bash
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.3.1_amd64.deb
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.4.3_amd64.deb
sudo apt-get install -y adduser libfontconfig
sudo dpkg -i grafana_4.3.1_amd64.deb
sudo dpkg -i grafana_4.4.3_amd64.deb
```
<!--
## Install Beta
## Install Latest Beta
```bash
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.3.0-beta1_amd64.deb
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.5.0-beta1_amd64.deb
sudo apt-get install -y adduser libfontconfig
sudo dpkg -i grafana_4.3.0-beta1_amd64.deb
sudo dpkg -i grafana_4.5.0-beta1_amd64.deb
```
-->
## APT Repository

View File

@@ -14,7 +14,7 @@ weight = 4
Grafana is very easy to install and run using the offical docker container.
$ docker run -i -p 3000:3000 grafana/grafana
$ docker run -d -p 3000:3000 grafana/grafana
All Grafana configuration settings can be defined using environment
variables, this is especially useful when using the above container.

View File

@@ -15,7 +15,8 @@ weight = 2
Description | Download
------------ | -------------
Stable for CentOS / Fedora / OpenSuse / Redhat Linux | [4.3.1 (x86-64 rpm)](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.3.1-1.x86_64.rpm)
Stable for CentOS / Fedora / OpenSuse / Redhat Linux | [4.4.3 (x86-64 rpm)](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.4.3-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.
@@ -24,19 +25,19 @@ installation.
You can install Grafana using Yum directly.
$ sudo yum install https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.3.1-1.x86_64.rpm
$ sudo yum install https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.4.3-1.x86_64.rpm
Or install manually using `rpm`.
#### On CentOS / Fedora / Redhat:
$ wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.3.1-1.x86_64.rpm
$ wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.4.3-1.x86_64.rpm
$ sudo yum install initscripts fontconfig
$ sudo rpm -Uvh grafana-4.3.1-1.x86_64.rpm
$ sudo rpm -Uvh grafana-4.4.3-1.x86_64.rpm
#### On OpenSuse:
$ sudo rpm -i --nodeps grafana-4.3.1-1.x86_64.rpm
$ sudo rpm -i --nodeps grafana-4.4.3-1.x86_64.rpm
## Install via YUM Repository

View File

@@ -11,13 +11,18 @@ weight = 8
# Troubleshooting
## visualization & query issues
## Visualization & Query issues
{{< imgbox max-width="40%" img="/img/docs/v45/query_inspector.png" caption="Query Inspector" >}}
The most common problems are related to the query & response from you data source. Even if it looks
like a bug or visualization issue in Grafana it is 99% of time a problem with the data source query or
the data source response.
So make sure to check the query sent and the raw response, learn how in this guide: [How to troubleshoot metric query issues](https://community.grafana.com/t/how-to-troubleshoot-metric-query-issues/50)
To check this you should use Query Inspector (new in Grafana v4.5). The query Inspector shows query requests and responses.
For more on the query insector read [this guide here](https://community.grafana.com/t/using-grafanas-query-inspector-to-troubleshoot-issues/2630). For
older versions of Grafana read the [how troubleshoot metric query issue](https://community.grafana.com/t/how-to-troubleshoot-metric-query-issues/50/2) article.
## Logging

View File

@@ -13,7 +13,7 @@ weight = 3
Description | Download
------------ | -------------
Latest stable package for Windows | [grafana.4.3.1.windows-x64.zip](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.3.1.windows-x64.zip)
Latest stable package for Windows | [grafana.4.4.3.windows-x64.zip](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.4.3.windows-x64.zip)
Read [Upgrading Grafana]({{< relref "installation/upgrading.md" >}}) for tips and guidance on updating an existing
installation.
@@ -27,7 +27,7 @@ this folder to anywhere you want Grafana to run from. Go into the
The default Grafana port is `3000`, this port requires extra permissions
on windows. Edit `custom.ini` and uncomment the `http_port`
configuration option and change it to something like `8080` or similar.
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

View File

@@ -17,7 +17,7 @@ you can get title, tags, and text information for the event.
## Queries
Annotatation events are fetched via annotation queries. To add a new annotation query to a dashboard
Annotation events are fetched via annotation queries. To add a new annotation query to a dashboard
open the dashboard settings menu, then select `Annotations`. This will open the dashboard annotations
settings view. To create a new annotation query hit the `New` button.

View File

@@ -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" >}}
{{< docs-imagebox img="/img/docs/v3/playlist.png" max-width="25rem" class="docs-image--right">}}
The Playlist feature can be accessed from Grafana's sidemenu, in the Dashboard submenu.
@@ -43,3 +43,25 @@ Playlists can also be manually controlled utilizing the Playlist controls at the
Click the stop button to stop the Playlist, and exit to the current Dashboard.
Click the next button to advance to the next Dashboard in the Playlist.
Click the back button to rewind to the previous Dashboard in the Playlist.
## TV or Kiosk Mode
In TV mode the top navbar, row & panel controls will all fade to transparent.
This happens automatically after one minute of user inactivity but can also be toggled manually
with the `d v` sequence shortcut. Any mouse movement or keyboard action will
restore navbar & controls.
Another feature is the kiosk mode - in kiosk mode the navbar is completely hidden/removed from view. This can be enabled with the `d k`
shortcut.
To put a playlist into kiosk mode, use the `d k` shortcut after the playlist has started. The same shortcut will toggle the playlist out of kiosk mode.
### Linking to the Playlist in Kiosk Mode
If you want to create a link to the playlist with kiosk mode enabled:
1. Copy the Start Url (by right clicking on the Play button and choosing Copy link address).
2. Add the `?kiosk` parameter to the url.
For example, to open the first playlist on the Grafana Play site in kiosk mode: [http://play.grafana.org/playlists/play/1?kiosk](http://play.grafana.org/playlists/play/1?kiosk)

View File

@@ -8,10 +8,12 @@ weight = 6
+++
# Sharing features
Grafana provides a number of ways to share a dashboard or a specific panel to other users within your
organization. It also provides ways to publish interactive snapshots that can be accessed by external partners.
## Share dashboard
Share a dashboard via the share icon in the top nav. This opens the share dialog where you
can get a link to the current dashboard with the current selected time range and template variables. If you have
made changes to the dashboard, make sure those are saved before sending the link.
@@ -25,18 +27,35 @@ snapshots can be accessed by anyone who has the link and can reach the URL.
![](/img/docs/v4/share_panel_modal.png)
### Publish snapshots
You can publish snapshots to you local instance or to [snapshot.raintank.io](http://snapshot.raintank.io). The later is a free service
that is provided by [Raintank](http://raintank.io) that allows you to publish dashboard snapshots to an external grafana instance.
The same rules still apply, anyone with the link can view it. You can set an expiration time if you want the snapshot to be removed
after a certain time period.
## Share Panel
Click a panel title to open the panel menu, then click share in the panel menu to open the Share Panel dialog. Here you
have access to a link that will take you to exactly this panel with the current time range and selected template variables.
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.
Click a panel title to open the panel menu, then click share in the panel menu to open the Share Panel dialog. Here you have access to a link that will take you to exactly this panel with the current time range and selected template variables.
### 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.
Example of a link to a server-side rendered PNG:
```
http://play.grafana.org/render/dashboard-solo/db/grafana-play-home?orgId=1&panelId=4&from=1499272191563&to=1499279391563&width=1000&height=500&tz=UTC%2B02%3A00&timeout=5000
```
#### Query String Parameters For Server-Side Rendered Images
- **width**: width in pixels. Default is 800.
- **height**: height in pixels. Default is 400.
- **tz**: timezone in the format `UTC%2BHH%3AMM` where HH and MM are offset in hours and minutes after UTC
- **timeout**: number of seconds. The timeout can be increased if the query for the panel needs more than the default 30 seconds.
### Embed Panel
You can embed a panel using an iframe on another web site. This tab will show you the html that you need to use.
Example:
@@ -46,4 +65,16 @@ Example:
```
Below there should be an interactive Grafana graph embedded in an iframe:
<iframe src="https://snapshot.raintank.io/dashboard-solo/snapshot/y7zwi2bZ7FcoTlB93WN7yWO4aMiz3pZb?from=1493369923321&to=1493377123321&panelId=4" width="650" height="300" frameborder="0"></iframe>
### Export Panel Data
![](/img/docs/v4/export_panel_data.png)
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.
This menu contains two options for exporting data:
- The panel JSON (the specification and not the data) can be exported or updated via the panel context menu.
- Panel data can be exported in the CSV format for Table and Graph Panels.

View File

@@ -88,7 +88,7 @@ The query expressions are different for each data source.
- [Elasticsearch templating queries]({{< relref "features/datasources/elasticsearch.md#templating" >}})
- [InfluxDB templating queries]({{< relref "features/datasources/influxdb.md#templating" >}})
- [Prometheus templating queries]({{< relref "features/datasources/prometheus.md#templating" >}})
- [OpenTSDB templating queries]({{< relref "features/datasources/prometheus.md#templating" >}})
- [OpenTSDB templating queries]({{< relref "features/datasources/opentsdb.md#templating" >}})
One thing to note is that query expressions can contain references to other variables and in effect create linked variables.
Grafana will detect this and automatically refresh a variable when one of it's containing variables change.
@@ -97,7 +97,7 @@ Grafana will detect this and automatically refresh a variable when one of it's c
Option | Description
------- | --------
*Mulit-value* | If enabled, the variable will support the selection of multiple options at the same time.
*Multi-value* | If enabled, the variable will support the selection of multiple options at the same time.
*Include All option* | Add a special `All` option whose value includes all options.
*Custom all value* | By default the `All` value will include all options in combined expression. This can become very long and can have performance problems. Many times it can be better to specify a custom all value, like a wildcard regex. To make it possible to have custom regex, globs or lucene syntax in the **Custom all value** option it is never escaped so you will have to think avbout what is a valid value for your data source.
@@ -177,6 +177,10 @@ This is used in the WHERE clause for the InfluxDB data source. Grafana adds it a
The `$__timeFilter` is used in the MySQL data source.
### The $__name Variable
This variable is only available in the Singlestat panel and can be used in the prefix or suffix fields on the Options tab. The variable will be replaced with the series name or alias.
## Repeating Panels
Template variables can be very useful to dynamically change your queries across a whole dashboard. If you want

View File

@@ -74,7 +74,9 @@ If you do not get an image when opening this link verify that the required font
### Grafana API Key
<img src="/img/docs/v2/orgdropdown_api_keys.png" style="width: 150px" class="right"></img>
<!--<img src="/img/docs/v2/orgdropdown_api_keys.png" style="width: 150px" class="right"></img>-->
{{< docs-imagebox img="/img/docs/v2/orgdropdown_api_keys.png" max-width="150px" class="docs-image--right">}}
You need to set the environment variable `HUBOT_GRAFANA_API_KEY` to a Grafana API Key.
You can add these from the API Keys page which you find in the Organization dropdown.

View File

@@ -1,4 +1,4 @@
{
"stable": "4.2.0",
"testing": "4.2.0"
"stable": "4.4.1",
"testing": "4.4.1"
}

View File

@@ -1,10 +1,10 @@
{
"author": {
"name": "Torkel Ödegaard",
"company": "Coding Instinct AB"
"company": "Grafana Labs"
},
"name": "grafana",
"version": "4.4.0",
"version": "4.5.1",
"repository": {
"type": "git",
"url": "http://github.com/grafana/grafana.git"
@@ -33,7 +33,7 @@
"grunt-ng-annotate": "^3.0.0",
"grunt-notify": "^0.4.5",
"grunt-postcss": "^0.8.0",
"grunt-sass": "^1.2.1",
"grunt-sass": "^2.0.0",
"grunt-string-replace": "~1.3.1",
"grunt-systemjs-builder": "^0.2.7",
"grunt-usemin": "3.1.1",
@@ -53,16 +53,14 @@
"systemjs": "0.19.41",
"zone.js": "^0.7.2"
},
"engines": {
"node": "4.x",
"npm": "2.14.x"
},
"scripts": {
"build": "./node_modules/grunt-cli/bin/grunt",
"test": "./node_modules/grunt-cli/bin/grunt test"
"test": "./node_modules/grunt-cli/bin/grunt test",
"dev": "./node_modules/grunt-cli/bin/grunt && ./node_modules/grunt-cli/bin/grunt watch"
},
"license": "Apache-2.0",
"dependencies": {
"ace-builds": "^1.2.8",
"eventemitter3": "^2.0.2",
"gaze": "^1.1.2",
"grunt-jscs": "3.0.1",

View File

@@ -6,6 +6,7 @@ set -e
IS_UPGRADE=false
case "$1" in
configure)
[ -z "$GRAFANA_USER" ] && GRAFANA_USER="grafana"

View File

@@ -17,3 +17,6 @@ CONF_FILE=/etc/grafana/grafana.ini
RESTART_ON_UPGRADE=true
PLUGINS_DIR=/var/lib/grafana/plugins
# Only used on systemd systems
PID_FILE_DIR=/var/run/grafana

View File

@@ -12,11 +12,13 @@ Group=grafana
Type=simple
Restart=on-failure
WorkingDirectory=/usr/share/grafana
ExecStart=/usr/sbin/grafana-server \
--config=${CONF_FILE} \
--pidfile=${PID_FILE} \
cfg:default.paths.logs=${LOG_DIR} \
cfg:default.paths.data=${DATA_DIR} \
RuntimeDirectory=grafana
RuntimeDirectoryMode=0750
ExecStart=/usr/sbin/grafana-server \
--config=${CONF_FILE} \
--pidfile=${PID_FILE_DIR}/grafana-server.pid \
cfg:default.paths.logs=${LOG_DIR} \
cfg:default.paths.data=${DATA_DIR} \
cfg:default.paths.plugins=${PLUGINS_DIR}
LimitNOFILE=10000
TimeoutStopSec=20

View File

@@ -1,13 +1,15 @@
#! /usr/bin/env bash
version=4.3.1
version=4.4.2
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_${version}_amd64.deb
package_cloud push grafana/stable/debian/jessie grafana_${version}_amd64.deb
package_cloud push grafana/stable/debian/wheezy grafana_${version}_amd64.deb
package_cloud push grafana/stable/debian/stretch grafana_${version}_amd64.deb
package_cloud push grafana/testing/debian/jessie grafana_${version}_amd64.deb
package_cloud push grafana/testing/debian/wheezy grafana_${version}_amd64.deb
package_cloud push grafana/testing/debian/stretch grafana_${version}_amd64.deb
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-${version}-1.x86_64.rpm
@@ -16,3 +18,5 @@ package_cloud push grafana/testing/el/7 grafana-${version}-1.x86_64.rpm
package_cloud push grafana/stable/el/7 grafana-${version}-1.x86_64.rpm
package_cloud push grafana/stable/el/6 grafana-${version}-1.x86_64.rpm
rm grafana*.{deb,rpm}

View File

@@ -1,14 +1,16 @@
#! /usr/bin/env bash
deb_ver=4.3.0-beta1
rpm_ver=4.3.0-beta1
deb_ver=4.5.0-beta1
rpm_ver=4.5.0-beta1
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_${deb_ver}_amd64.deb
# wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_${deb_ver}_amd64.deb
package_cloud push grafana/testing/debian/jessie grafana_${deb_ver}_amd64.deb
# package_cloud push grafana/testing/debian/jessie grafana_${deb_ver}_amd64.deb
package_cloud push grafana/testing/debian/wheezy grafana_${deb_ver}_amd64.deb
package_cloud push grafana/testing/debian/stretch grafana_${deb_ver}_amd64.deb
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-${rpm_ver}.x86_64.rpm
package_cloud push grafana/testing/el/6 grafana-${rpm_ver}.x86_64.rpm
package_cloud push grafana/testing/el/7 grafana-${rpm_ver}.x86_64.rpm
rm grafana*.{deb,rpm}

View File

@@ -25,6 +25,7 @@ stopGrafana() {
fi
}
# Initial installation: $1 == 1
# Upgrade: $1 == 2, and configured to restart on upgrade
if [ $1 -eq 1 ] ; then

View File

@@ -17,3 +17,6 @@ CONF_FILE=/etc/grafana/grafana.ini
RESTART_ON_UPGRADE=true
PLUGINS_DIR=/var/lib/grafana/plugins
# Only used on systemd systems
PID_FILE_DIR=/var/run/grafana

View File

@@ -12,11 +12,13 @@ Group=grafana
Type=simple
Restart=on-failure
WorkingDirectory=/usr/share/grafana
ExecStart=/usr/sbin/grafana-server \
--config=${CONF_FILE} \
--pidfile=${PID_FILE} \
cfg:default.paths.logs=${LOG_DIR} \
cfg:default.paths.data=${DATA_DIR} \
RuntimeDirectory=grafana
RuntimeDirectoryMode=0750
ExecStart=/usr/sbin/grafana-server \
--config=${CONF_FILE} \
--pidfile=${PID_FILE_DIR}/grafana-server.pid \
cfg:default.paths.logs=${LOG_DIR} \
cfg:default.paths.data=${DATA_DIR} \
cfg:default.paths.plugins=${PLUGINS_DIR}
LimitNOFILE=10000
TimeoutStopSec=20

View File

@@ -35,7 +35,7 @@ func AdminCreateUser(c *middleware.Context, form dtos.AdminCreateUserForm) {
return
}
metrics.M_Api_Admin_User_Create.Inc(1)
metrics.M_Api_Admin_User_Create.Inc()
user := cmd.Result

View File

@@ -10,7 +10,7 @@ import (
// Register adds http routes
func (hs *HttpServer) registerRoutes() {
r := hs.macaron
macaronR := hs.macaron
reqSignedIn := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true})
reqGrafanaAdmin := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true, ReqGrafanaAdmin: true})
reqEditorRole := middleware.RoleAuth(m.ROLE_EDITOR, m.ROLE_ADMIN)
@@ -19,7 +19,9 @@ func (hs *HttpServer) registerRoutes() {
bind := binding.Bind
// automatically set HEAD for every GET
r.SetAutoHead(true)
macaronR.SetAutoHead(true)
r := newRouteRegister(middleware.RequestMetrics)
// not logged in views
r.Get("/", reqSignedIn, Index)
@@ -98,197 +100,195 @@ func (hs *HttpServer) registerRoutes() {
r.Get("/api/login/ping", quota("session"), LoginApiPing)
// authed api
r.Group("/api", func() {
r.Group("/api", func(apiRoute RouteRegister) {
// user (signed in)
r.Group("/user", func() {
r.Get("/", wrap(GetSignedInUser))
r.Put("/", bind(m.UpdateUserCommand{}), wrap(UpdateSignedInUser))
r.Post("/using/:id", wrap(UserSetUsingOrg))
r.Get("/orgs", wrap(GetSignedInUserOrgList))
apiRoute.Group("/user", func(userRoute RouteRegister) {
userRoute.Get("/", wrap(GetSignedInUser))
userRoute.Put("/", bind(m.UpdateUserCommand{}), wrap(UpdateSignedInUser))
userRoute.Post("/using/:id", wrap(UserSetUsingOrg))
userRoute.Get("/orgs", wrap(GetSignedInUserOrgList))
r.Post("/stars/dashboard/:id", wrap(StarDashboard))
r.Delete("/stars/dashboard/:id", wrap(UnstarDashboard))
userRoute.Post("/stars/dashboard/:id", wrap(StarDashboard))
userRoute.Delete("/stars/dashboard/:id", wrap(UnstarDashboard))
r.Put("/password", bind(m.ChangeUserPasswordCommand{}), wrap(ChangeUserPassword))
r.Get("/quotas", wrap(GetUserQuotas))
r.Put("/helpflags/:id", wrap(SetHelpFlag))
userRoute.Put("/password", bind(m.ChangeUserPasswordCommand{}), wrap(ChangeUserPassword))
userRoute.Get("/quotas", wrap(GetUserQuotas))
userRoute.Put("/helpflags/:id", wrap(SetHelpFlag))
// For dev purpose
r.Get("/helpflags/clear", wrap(ClearHelpFlags))
userRoute.Get("/helpflags/clear", wrap(ClearHelpFlags))
r.Get("/preferences", wrap(GetUserPreferences))
r.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), wrap(UpdateUserPreferences))
userRoute.Get("/preferences", wrap(GetUserPreferences))
userRoute.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), wrap(UpdateUserPreferences))
})
// users (admin permission required)
r.Group("/users", func() {
r.Get("/", wrap(SearchUsers))
r.Get("/search", wrap(SearchUsersWithPaging))
r.Get("/:id", wrap(GetUserById))
r.Get("/:id/orgs", wrap(GetUserOrgList))
apiRoute.Group("/users", func(usersRoute RouteRegister) {
usersRoute.Get("/", wrap(SearchUsers))
usersRoute.Get("/search", wrap(SearchUsersWithPaging))
usersRoute.Get("/:id", wrap(GetUserById))
usersRoute.Get("/:id/orgs", wrap(GetUserOrgList))
// query parameters /users/lookup?loginOrEmail=admin@example.com
r.Get("/lookup", wrap(GetUserByLoginOrEmail))
r.Put("/:id", bind(m.UpdateUserCommand{}), wrap(UpdateUser))
r.Post("/:id/using/:orgId", wrap(UpdateUserActiveOrg))
usersRoute.Get("/lookup", wrap(GetUserByLoginOrEmail))
usersRoute.Put("/:id", bind(m.UpdateUserCommand{}), wrap(UpdateUser))
usersRoute.Post("/:id/using/:orgId", wrap(UpdateUserActiveOrg))
}, reqGrafanaAdmin)
// org information available to all users.
r.Group("/org", func() {
r.Get("/", wrap(GetOrgCurrent))
r.Get("/quotas", wrap(GetOrgQuotas))
apiRoute.Group("/org", func(orgRoute RouteRegister) {
orgRoute.Get("/", wrap(GetOrgCurrent))
orgRoute.Get("/quotas", wrap(GetOrgQuotas))
})
// current org
r.Group("/org", func() {
r.Put("/", bind(dtos.UpdateOrgForm{}), wrap(UpdateOrgCurrent))
r.Put("/address", bind(dtos.UpdateOrgAddressForm{}), wrap(UpdateOrgAddressCurrent))
r.Post("/users", quota("user"), bind(m.AddOrgUserCommand{}), wrap(AddOrgUserToCurrentOrg))
r.Get("/users", wrap(GetOrgUsersForCurrentOrg))
r.Patch("/users/:userId", bind(m.UpdateOrgUserCommand{}), wrap(UpdateOrgUserForCurrentOrg))
r.Delete("/users/:userId", wrap(RemoveOrgUserForCurrentOrg))
apiRoute.Group("/org", func(orgRoute RouteRegister) {
orgRoute.Put("/", bind(dtos.UpdateOrgForm{}), wrap(UpdateOrgCurrent))
orgRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), wrap(UpdateOrgAddressCurrent))
orgRoute.Post("/users", quota("user"), bind(m.AddOrgUserCommand{}), wrap(AddOrgUserToCurrentOrg))
orgRoute.Get("/users", wrap(GetOrgUsersForCurrentOrg))
orgRoute.Patch("/users/:userId", bind(m.UpdateOrgUserCommand{}), wrap(UpdateOrgUserForCurrentOrg))
orgRoute.Delete("/users/:userId", wrap(RemoveOrgUserForCurrentOrg))
// invites
r.Get("/invites", wrap(GetPendingOrgInvites))
r.Post("/invites", quota("user"), bind(dtos.AddInviteForm{}), wrap(AddOrgInvite))
r.Patch("/invites/:code/revoke", wrap(RevokeInvite))
orgRoute.Get("/invites", wrap(GetPendingOrgInvites))
orgRoute.Post("/invites", quota("user"), bind(dtos.AddInviteForm{}), wrap(AddOrgInvite))
orgRoute.Patch("/invites/:code/revoke", wrap(RevokeInvite))
// prefs
r.Get("/preferences", wrap(GetOrgPreferences))
r.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), wrap(UpdateOrgPreferences))
orgRoute.Get("/preferences", wrap(GetOrgPreferences))
orgRoute.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), wrap(UpdateOrgPreferences))
}, reqOrgAdmin)
// create new org
r.Post("/orgs", quota("org"), bind(m.CreateOrgCommand{}), wrap(CreateOrg))
apiRoute.Post("/orgs", quota("org"), bind(m.CreateOrgCommand{}), wrap(CreateOrg))
// search all orgs
r.Get("/orgs", reqGrafanaAdmin, wrap(SearchOrgs))
apiRoute.Get("/orgs", reqGrafanaAdmin, wrap(SearchOrgs))
// orgs (admin routes)
r.Group("/orgs/:orgId", func() {
r.Get("/", wrap(GetOrgById))
r.Put("/", bind(dtos.UpdateOrgForm{}), wrap(UpdateOrg))
r.Put("/address", bind(dtos.UpdateOrgAddressForm{}), wrap(UpdateOrgAddress))
r.Delete("/", wrap(DeleteOrgById))
r.Get("/users", wrap(GetOrgUsers))
r.Post("/users", bind(m.AddOrgUserCommand{}), wrap(AddOrgUser))
r.Patch("/users/:userId", bind(m.UpdateOrgUserCommand{}), wrap(UpdateOrgUser))
r.Delete("/users/:userId", wrap(RemoveOrgUser))
r.Get("/quotas", wrap(GetOrgQuotas))
r.Put("/quotas/:target", bind(m.UpdateOrgQuotaCmd{}), wrap(UpdateOrgQuota))
apiRoute.Group("/orgs/:orgId", func(orgsRoute RouteRegister) {
orgsRoute.Get("/", wrap(GetOrgById))
orgsRoute.Put("/", bind(dtos.UpdateOrgForm{}), wrap(UpdateOrg))
orgsRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), wrap(UpdateOrgAddress))
orgsRoute.Delete("/", wrap(DeleteOrgById))
orgsRoute.Get("/users", wrap(GetOrgUsers))
orgsRoute.Post("/users", bind(m.AddOrgUserCommand{}), wrap(AddOrgUser))
orgsRoute.Patch("/users/:userId", bind(m.UpdateOrgUserCommand{}), wrap(UpdateOrgUser))
orgsRoute.Delete("/users/:userId", wrap(RemoveOrgUser))
orgsRoute.Get("/quotas", wrap(GetOrgQuotas))
orgsRoute.Put("/quotas/:target", bind(m.UpdateOrgQuotaCmd{}), wrap(UpdateOrgQuota))
}, reqGrafanaAdmin)
// orgs (admin routes)
r.Group("/orgs/name/:name", func() {
r.Get("/", wrap(GetOrgByName))
apiRoute.Group("/orgs/name/:name", func(orgsRoute RouteRegister) {
orgsRoute.Get("/", wrap(GetOrgByName))
}, reqGrafanaAdmin)
// auth api keys
r.Group("/auth/keys", func() {
r.Get("/", wrap(GetApiKeys))
r.Post("/", quota("api_key"), bind(m.AddApiKeyCommand{}), wrap(AddApiKey))
r.Delete("/:id", wrap(DeleteApiKey))
apiRoute.Group("/auth/keys", func(keysRoute RouteRegister) {
keysRoute.Get("/", wrap(GetApiKeys))
keysRoute.Post("/", quota("api_key"), bind(m.AddApiKeyCommand{}), wrap(AddApiKey))
keysRoute.Delete("/:id", wrap(DeleteApiKey))
}, reqOrgAdmin)
// Preferences
r.Group("/preferences", func() {
r.Post("/set-home-dash", bind(m.SavePreferencesCommand{}), wrap(SetHomeDashboard))
apiRoute.Group("/preferences", func(prefRoute RouteRegister) {
prefRoute.Post("/set-home-dash", bind(m.SavePreferencesCommand{}), wrap(SetHomeDashboard))
})
// Data sources
r.Group("/datasources", func() {
r.Get("/", wrap(GetDataSources))
r.Post("/", quota("data_source"), bind(m.AddDataSourceCommand{}), AddDataSource)
r.Put("/:id", bind(m.UpdateDataSourceCommand{}), wrap(UpdateDataSource))
r.Delete("/:id", DeleteDataSourceById)
r.Delete("/name/:name", DeleteDataSourceByName)
r.Get("/:id", wrap(GetDataSourceById))
r.Get("/name/:name", wrap(GetDataSourceByName))
apiRoute.Group("/datasources", func(datasourceRoute RouteRegister) {
datasourceRoute.Get("/", wrap(GetDataSources))
datasourceRoute.Post("/", quota("data_source"), bind(m.AddDataSourceCommand{}), AddDataSource)
datasourceRoute.Put("/:id", bind(m.UpdateDataSourceCommand{}), wrap(UpdateDataSource))
datasourceRoute.Delete("/:id", DeleteDataSourceById)
datasourceRoute.Delete("/name/:name", DeleteDataSourceByName)
datasourceRoute.Get("/:id", wrap(GetDataSourceById))
datasourceRoute.Get("/name/:name", wrap(GetDataSourceByName))
}, reqOrgAdmin)
r.Get("/datasources/id/:name", wrap(GetDataSourceIdByName), reqSignedIn)
apiRoute.Get("/datasources/id/:name", wrap(GetDataSourceIdByName), reqSignedIn)
r.Get("/plugins", wrap(GetPluginList))
r.Get("/plugins/:pluginId/settings", wrap(GetPluginSettingById))
r.Get("/plugins/:pluginId/readme", wrap(GetPluginReadme))
apiRoute.Get("/plugins", wrap(GetPluginList))
apiRoute.Get("/plugins/:pluginId/settings", wrap(GetPluginSettingById))
apiRoute.Get("/plugins/:pluginId/markdown/:name", wrap(GetPluginMarkdown))
r.Group("/plugins", func() {
r.Get("/:pluginId/dashboards/", wrap(GetPluginDashboards))
r.Post("/:pluginId/settings", bind(m.UpdatePluginSettingCmd{}), wrap(UpdatePluginSetting))
apiRoute.Group("/plugins", func(pluginRoute RouteRegister) {
pluginRoute.Get("/:pluginId/dashboards/", wrap(GetPluginDashboards))
pluginRoute.Post("/:pluginId/settings", bind(m.UpdatePluginSettingCmd{}), wrap(UpdatePluginSetting))
}, reqOrgAdmin)
r.Get("/frontend/settings/", GetFrontendSettings)
r.Any("/datasources/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest)
r.Any("/datasources/proxy/:id", reqSignedIn, ProxyDataSourceRequest)
apiRoute.Get("/frontend/settings/", GetFrontendSettings)
apiRoute.Any("/datasources/proxy/:id/*", reqSignedIn, hs.ProxyDataSourceRequest)
apiRoute.Any("/datasources/proxy/:id", reqSignedIn, hs.ProxyDataSourceRequest)
// Dashboard
r.Group("/dashboards", func() {
r.Combo("/db/:slug").Get(GetDashboard).Delete(DeleteDashboard)
apiRoute.Group("/dashboards", func(dashboardRoute RouteRegister) {
dashboardRoute.Get("/db/:slug", GetDashboard)
dashboardRoute.Delete("/db/:slug", reqEditorRole, DeleteDashboard)
r.Get("/id/:dashboardId/versions", wrap(GetDashboardVersions))
r.Get("/id/:dashboardId/versions/:id", wrap(GetDashboardVersion))
r.Post("/id/:dashboardId/restore", reqEditorRole, bind(dtos.RestoreDashboardVersionCommand{}), wrap(RestoreDashboardVersion))
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))
r.Post("/calculate-diff", bind(dtos.CalculateDiffOptions{}), wrap(CalculateDashboardDiff))
dashboardRoute.Post("/calculate-diff", bind(dtos.CalculateDiffOptions{}), wrap(CalculateDashboardDiff))
r.Post("/db", reqEditorRole, bind(m.SaveDashboardCommand{}), wrap(PostDashboard))
r.Get("/file/:file", GetDashboardFromJsonFile)
r.Get("/home", wrap(GetHomeDashboard))
r.Get("/tags", GetDashboardTags)
r.Post("/import", bind(dtos.ImportDashboardCommand{}), wrap(ImportDashboard))
dashboardRoute.Post("/db", reqEditorRole, bind(m.SaveDashboardCommand{}), wrap(PostDashboard))
dashboardRoute.Get("/file/:file", GetDashboardFromJsonFile)
dashboardRoute.Get("/home", wrap(GetHomeDashboard))
dashboardRoute.Get("/tags", GetDashboardTags)
dashboardRoute.Post("/import", bind(dtos.ImportDashboardCommand{}), wrap(ImportDashboard))
})
// Dashboard snapshots
r.Group("/dashboard/snapshots", func() {
r.Get("/", wrap(SearchDashboardSnapshots))
apiRoute.Group("/dashboard/snapshots", func(dashboardRoute RouteRegister) {
dashboardRoute.Get("/", wrap(SearchDashboardSnapshots))
})
// Playlist
r.Group("/playlists", func() {
r.Get("/", wrap(SearchPlaylists))
r.Get("/:id", ValidateOrgPlaylist, wrap(GetPlaylist))
r.Get("/:id/items", ValidateOrgPlaylist, wrap(GetPlaylistItems))
r.Get("/:id/dashboards", ValidateOrgPlaylist, wrap(GetPlaylistDashboards))
r.Delete("/:id", reqEditorRole, ValidateOrgPlaylist, wrap(DeletePlaylist))
r.Put("/:id", reqEditorRole, bind(m.UpdatePlaylistCommand{}), ValidateOrgPlaylist, wrap(UpdatePlaylist))
r.Post("/", reqEditorRole, bind(m.CreatePlaylistCommand{}), wrap(CreatePlaylist))
apiRoute.Group("/playlists", func(playlistRoute RouteRegister) {
playlistRoute.Get("/", wrap(SearchPlaylists))
playlistRoute.Get("/:id", ValidateOrgPlaylist, wrap(GetPlaylist))
playlistRoute.Get("/:id/items", ValidateOrgPlaylist, wrap(GetPlaylistItems))
playlistRoute.Get("/:id/dashboards", ValidateOrgPlaylist, wrap(GetPlaylistDashboards))
playlistRoute.Delete("/:id", reqEditorRole, ValidateOrgPlaylist, wrap(DeletePlaylist))
playlistRoute.Put("/:id", reqEditorRole, bind(m.UpdatePlaylistCommand{}), ValidateOrgPlaylist, wrap(UpdatePlaylist))
playlistRoute.Post("/", reqEditorRole, bind(m.CreatePlaylistCommand{}), wrap(CreatePlaylist))
})
// Search
r.Get("/search/", Search)
apiRoute.Get("/search/", Search)
// metrics
r.Post("/tsdb/query", bind(dtos.MetricRequest{}), wrap(QueryMetrics))
r.Get("/tsdb/testdata/scenarios", wrap(GetTestDataScenarios))
r.Get("/tsdb/testdata/gensql", reqGrafanaAdmin, wrap(GenerateSqlTestData))
r.Get("/tsdb/testdata/random-walk", wrap(GetTestDataRandomWalk))
apiRoute.Post("/tsdb/query", bind(dtos.MetricRequest{}), wrap(QueryMetrics))
apiRoute.Get("/tsdb/testdata/scenarios", wrap(GetTestDataScenarios))
apiRoute.Get("/tsdb/testdata/gensql", reqGrafanaAdmin, wrap(GenerateSqlTestData))
apiRoute.Get("/tsdb/testdata/random-walk", wrap(GetTestDataRandomWalk))
// metrics
r.Get("/metrics", wrap(GetInternalMetrics))
r.Group("/alerts", func() {
r.Post("/test", bind(dtos.AlertTestCommand{}), wrap(AlertTest))
r.Post("/:alertId/pause", bind(dtos.PauseAlertCommand{}), wrap(PauseAlert), reqEditorRole)
r.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert))
r.Get("/", wrap(GetAlerts))
r.Get("/states-for-dashboard", wrap(GetAlertStatesForDashboard))
apiRoute.Group("/alerts", func(alertsRoute RouteRegister) {
alertsRoute.Post("/test", bind(dtos.AlertTestCommand{}), wrap(AlertTest))
alertsRoute.Post("/:alertId/pause", bind(dtos.PauseAlertCommand{}), wrap(PauseAlert), reqEditorRole)
alertsRoute.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert))
alertsRoute.Get("/", wrap(GetAlerts))
alertsRoute.Get("/states-for-dashboard", wrap(GetAlertStatesForDashboard))
})
r.Get("/alert-notifications", wrap(GetAlertNotifications))
r.Get("/alert-notifiers", wrap(GetAlertNotifiers))
apiRoute.Get("/alert-notifications", wrap(GetAlertNotifications))
apiRoute.Get("/alert-notifiers", wrap(GetAlertNotifiers))
r.Group("/alert-notifications", func() {
r.Post("/test", bind(dtos.NotificationTestCommand{}), wrap(NotificationTest))
r.Post("/", bind(m.CreateAlertNotificationCommand{}), wrap(CreateAlertNotification))
r.Put("/:notificationId", bind(m.UpdateAlertNotificationCommand{}), wrap(UpdateAlertNotification))
r.Get("/:notificationId", wrap(GetAlertNotificationById))
r.Delete("/:notificationId", wrap(DeleteAlertNotification))
apiRoute.Group("/alert-notifications", func(alertNotifications RouteRegister) {
alertNotifications.Post("/test", bind(dtos.NotificationTestCommand{}), wrap(NotificationTest))
alertNotifications.Post("/", bind(m.CreateAlertNotificationCommand{}), wrap(CreateAlertNotification))
alertNotifications.Put("/:notificationId", bind(m.UpdateAlertNotificationCommand{}), wrap(UpdateAlertNotification))
alertNotifications.Get("/:notificationId", wrap(GetAlertNotificationById))
alertNotifications.Delete("/:notificationId", wrap(DeleteAlertNotification))
}, reqEditorRole)
r.Get("/annotations", wrap(GetAnnotations))
r.Post("/annotations/mass-delete", reqOrgAdmin, bind(dtos.DeleteAnnotationsCmd{}), wrap(DeleteAnnotations))
apiRoute.Get("/annotations", wrap(GetAnnotations))
apiRoute.Post("/annotations/mass-delete", reqOrgAdmin, bind(dtos.DeleteAnnotationsCmd{}), wrap(DeleteAnnotations))
r.Group("/annotations", func() {
r.Post("/", bind(dtos.PostAnnotationsCmd{}), wrap(PostAnnotation))
apiRoute.Group("/annotations", func(annotationsRoute RouteRegister) {
annotationsRoute.Post("/", bind(dtos.PostAnnotationsCmd{}), wrap(PostAnnotation))
}, reqEditorRole)
// error test
@@ -297,16 +297,16 @@ func (hs *HttpServer) registerRoutes() {
}, reqSignedIn)
// admin api
r.Group("/api/admin", func() {
r.Get("/settings", AdminGetSettings)
r.Post("/users", bind(dtos.AdminCreateUserForm{}), AdminCreateUser)
r.Put("/users/:id/password", bind(dtos.AdminUpdateUserPasswordForm{}), AdminUpdateUserPassword)
r.Put("/users/:id/permissions", bind(dtos.AdminUpdateUserPermissionsForm{}), AdminUpdateUserPermissions)
r.Delete("/users/:id", AdminDeleteUser)
r.Get("/users/:id/quotas", wrap(GetUserQuotas))
r.Put("/users/:id/quotas/:target", bind(m.UpdateUserQuotaCmd{}), wrap(UpdateUserQuota))
r.Get("/stats", AdminGetStats)
r.Post("/pause-all-alerts", bind(dtos.PauseAllAlertsCommand{}), wrap(PauseAllAlerts))
r.Group("/api/admin", func(adminRoute RouteRegister) {
adminRoute.Get("/settings", AdminGetSettings)
adminRoute.Post("/users", bind(dtos.AdminCreateUserForm{}), AdminCreateUser)
adminRoute.Put("/users/:id/password", bind(dtos.AdminUpdateUserPasswordForm{}), AdminUpdateUserPassword)
adminRoute.Put("/users/:id/permissions", bind(dtos.AdminUpdateUserPermissionsForm{}), AdminUpdateUserPermissions)
adminRoute.Delete("/users/:id", AdminDeleteUser)
adminRoute.Get("/users/:id/quotas", wrap(GetUserQuotas))
adminRoute.Put("/users/:id/quotas/:target", bind(m.UpdateUserQuotaCmd{}), wrap(UpdateUserQuota))
adminRoute.Get("/stats", AdminGetStats)
adminRoute.Post("/pause-all-alerts", bind(dtos.PauseAllAlertsCommand{}), wrap(PauseAllAlerts))
}, reqGrafanaAdmin)
// rendering
@@ -325,7 +325,9 @@ func (hs *HttpServer) registerRoutes() {
// streams
//r.Post("/api/streams/push", reqSignedIn, bind(dtos.StreamMessage{}), liveConn.PushToStream)
InitAppPluginRoutes(r)
r.Register(macaronR)
r.NotFound(NotFoundHandler)
InitAppPluginRoutes(macaronR)
macaronR.NotFound(NotFoundHandler)
}

View File

@@ -32,8 +32,7 @@ func InitAppPluginRoutes(r *macaron.Macaron) {
url := util.JoinUrlFragments("/api/plugin-proxy/"+plugin.Id, route.Path)
handlers := make([]macaron.Handler, 0)
handlers = append(handlers, middleware.Auth(&middleware.AuthOptions{
ReqSignedIn: true,
ReqGrafanaAdmin: route.ReqGrafanaAdmin,
ReqSignedIn: true,
}))
if route.ReqRole != "" {

View File

@@ -217,7 +217,10 @@ func (this *thunderTask) Fetch() {
this.Done()
}
var client = &http.Client{}
var client *http.Client = &http.Client{
Timeout: time.Second * 2,
Transport: &http.Transport{Proxy: http.ProxyFromEnvironment},
}
func (this *thunderTask) fetch() error {
this.Avatar.timestamp = time.Now()

View File

@@ -39,6 +39,7 @@ type cwRequest struct {
type datasourceInfo struct {
Profile string
Region string
AuthType string
AssumeRoleArn string
Namespace string
@@ -47,6 +48,7 @@ type datasourceInfo struct {
}
func (req *cwRequest) GetDatasourceInfo() *datasourceInfo {
authType := req.DataSource.JsonData.Get("authType").MustString()
assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString()
accessKey := ""
secretKey := ""
@@ -61,6 +63,7 @@ func (req *cwRequest) GetDatasourceInfo() *datasourceInfo {
}
return &datasourceInfo{
AuthType: authType,
AssumeRoleArn: assumeRoleArn,
Region: req.Region,
Profile: req.DataSource.Database,
@@ -110,7 +113,7 @@ func getCredentials(dsInfo *datasourceInfo) (*credentials.Credentials, error) {
sessionToken := ""
var expiration *time.Time
expiration = nil
if strings.Index(dsInfo.AssumeRoleArn, "arn:aws:iam:") == 0 {
if dsInfo.AuthType == "arn" && strings.Index(dsInfo.AssumeRoleArn, "arn:aws:iam:") == 0 {
params := &sts.AssumeRoleInput{
RoleArn: aws.String(dsInfo.AssumeRoleArn),
RoleSessionName: aws.String("GrafanaSession"),
@@ -166,7 +169,7 @@ func getCredentials(dsInfo *datasourceInfo) (*credentials.Credentials, error) {
SecretAccessKey: dsInfo.SecretKey,
}},
&credentials.SharedCredentialsProvider{Filename: "", Profile: dsInfo.Profile},
&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute},
remoteCredProvider(sess),
})
credentialCacheLock.Lock()
@@ -263,7 +266,7 @@ func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
c.JsonApiErr(500, "Unable to call AWS API", err)
return
}
metrics.M_Aws_CloudWatch_GetMetricStatistics.Inc(1)
metrics.M_Aws_CloudWatch_GetMetricStatistics.Inc()
c.JSON(200, resp)
}
@@ -299,7 +302,7 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) {
var resp cloudwatch.ListMetricsOutput
err = svc.ListMetricsPages(params,
func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool {
metrics.M_Aws_CloudWatch_ListMetrics.Inc(1)
metrics.M_Aws_CloudWatch_ListMetrics.Inc()
metrics, _ := awsutil.ValuesAtPath(page, "Metrics")
for _, metric := range metrics {
resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric))

View File

@@ -42,7 +42,7 @@ func init() {
"AWS/EC2Spot": {"AvailableInstancePoolsCount", "BidsSubmittedForCapacity", "EligibleInstancePoolCount", "FulfilledCapacity", "MaxPercentCapacityAllocation", "PendingCapacity", "PercentCapacityAllocation", "TargetCapacity", "TerminatingCapacity"},
"AWS/ECS": {"CPUReservation", "MemoryReservation", "CPUUtilization", "MemoryUtilization"},
"AWS/EFS": {"BurstCreditBalance", "ClientConnections", "DataReadIOBytes", "DataWriteIOBytes", "MetadataIOBytes", "TotalIOBytes", "PermittedThroughput", "PercentIOLimit"},
"AWS/ELB": {"HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount"},
"AWS/ELB": {"HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount", "EstimatedALBActiveConnectionCount", "EstimatedALBConsumedLCUs", "EstimatedALBNewConnectionCount", "EstimatedProcessedBytes"},
"AWS/ElastiCache": {
"CPUUtilization", "FreeableMemory", "NetworkBytesIn", "NetworkBytesOut", "SwapUsage",
"BytesUsedForCacheItems", "BytesReadIntoMemcached", "BytesWrittenOutFromMemcached", "CasBadval", "CasHits", "CasMisses", "CmdFlush", "CmdGet", "CmdSet", "CurrConnections", "CurrItems", "DecrHits", "DecrMisses", "DeleteHits", "DeleteMisses", "Evictions", "GetHits", "GetMisses", "IncrHits", "IncrMisses", "Reclaimed",
@@ -78,6 +78,7 @@ func init() {
"AWS/Lambda": {"Invocations", "Errors", "Duration", "Throttles", "IteratorAge"},
"AWS/Logs": {"IncomingBytes", "IncomingLogEvents", "ForwardedBytes", "ForwardedLogEvents", "DeliveryErrors", "DeliveryThrottling"},
"AWS/ML": {"PredictCount", "PredictFailureCount"},
"AWS/NATGateway": {"PacketsOutToDestination", "PacketsOutToSource", "PacketsInFromSource", "PacketsInFromDestination", "BytesOutToDestination", "BytesOutToSource", "BytesInFromSource", "BytesInFromDestination", "ErrorPortAllocation", "ActiveConnectionCount", "ConnectionAttemptCount", "ConnectionEstablishedCount", "IdleTimeoutCount", "PacketsDropCount"},
"AWS/OpsWorks": {"cpu_idle", "cpu_nice", "cpu_system", "cpu_user", "cpu_waitio", "load_1", "load_5", "load_15", "memory_buffers", "memory_cached", "memory_free", "memory_swap", "memory_total", "memory_used", "procs"},
"AWS/Redshift": {"CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"},
"AWS/RDS": {"ActiveTransactions", "AuroraBinlogReplicaLag", "AuroraReplicaLag", "AuroraReplicaLagMaximum", "AuroraReplicaLagMinimum", "BinLogDiskUsage", "BlockedTransactions", "BufferCacheHitRatio", "CommitLatency", "CommitThroughput", "BinLogDiskUsage", "CPUCreditBalance", "CPUCreditUsage", "CPUUtilization", "DatabaseConnections", "DDLLatency", "DDLThroughput", "Deadlocks", "DeleteLatency", "DeleteThroughput", "DiskQueueDepth", "DMLLatency", "DMLThroughput", "EngineUptime", "FailedSqlStatements", "FreeableMemory", "FreeLocalStorage", "FreeStorageSpace", "InsertLatency", "InsertThroughput", "LoginFailures", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "NetworkThroughput", "Queries", "ReadIOPS", "ReadLatency", "ReadThroughput", "ReplicaLag", "ResultSetCacheHitRatio", "SelectLatency", "SelectThroughput", "SwapUsage", "TotalConnections", "UpdateLatency", "UpdateThroughput", "VolumeBytesUsed", "VolumeReadIOPS", "VolumeWriteIOPS", "WriteIOPS", "WriteLatency", "WriteThroughput"},
@@ -91,7 +92,7 @@ func init() {
"AWS/SWF": {"DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut",
"ActivityTaskScheduleToCloseTime", "ActivityTaskScheduleToStartTime", "ActivityTaskStartToCloseTime", "ActivityTasksCanceled", "ActivityTasksCompleted", "ActivityTasksFailed", "ScheduledActivityTasksTimedOutOnClose", "ScheduledActivityTasksTimedOutOnStart", "StartedActivityTasksTimedOutOnClose", "StartedActivityTasksTimedOutOnHeartbeat"},
"AWS/VPN": {"TunnelState", "TunnelDataIn", "TunnelDataOut"},
"AWS/WAF": {"AllowedRequests", "BlockedRequests", "CountedRequests"},
"WAF": {"AllowedRequests", "BlockedRequests", "CountedRequests"},
"AWS/WorkSpaces": {"Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"},
"KMS": {"SecondsUntilKeyMaterialExpiration"},
}
@@ -122,6 +123,7 @@ func init() {
"AWS/Lambda": {"FunctionName", "Resource", "Version", "Alias"},
"AWS/Logs": {"LogGroupName", "DestinationType", "FilterName"},
"AWS/ML": {"MLModelId", "RequestMode"},
"AWS/NATGateway": {"NatGatewayId"},
"AWS/OpsWorks": {"StackId", "LayerId", "InstanceId"},
"AWS/Redshift": {"NodeID", "ClusterIdentifier"},
"AWS/RDS": {"DBInstanceIdentifier", "DBClusterIdentifier", "DatabaseClass", "EngineName", "Role"},
@@ -133,7 +135,7 @@ func init() {
"AWS/StorageGateway": {"GatewayId", "GatewayName", "VolumeId"},
"AWS/SWF": {"Domain", "WorkflowTypeName", "WorkflowTypeVersion", "ActivityTypeName", "ActivityTypeVersion"},
"AWS/VPN": {"VpnId", "TunnelIpAddress"},
"AWS/WAF": {"Rule", "WebACL"},
"WAF": {"Rule", "WebACL"},
"AWS/WorkSpaces": {"DirectoryId", "WorkspaceId"},
"KMS": {"KeyId"},
}
@@ -166,9 +168,7 @@ func handleGetNamespaces(req *cwRequest, c *middleware.Context) {
customNamespaces := req.DataSource.JsonData.Get("customMetricsNamespaces").MustString()
if customNamespaces != "" {
for _, key := range strings.Split(customNamespaces, ",") {
keys = append(keys, key)
}
keys = append(keys, strings.Split(customNamespaces, ",")...)
}
sort.Sort(sort.StringSlice(keys))
@@ -275,7 +275,7 @@ func getAllMetrics(cwData *datasourceInfo) (cloudwatch.ListMetricsOutput, error)
var resp cloudwatch.ListMetricsOutput
err = svc.ListMetricsPages(params,
func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool {
metrics.M_Aws_CloudWatch_ListMetrics.Inc(1)
metrics.M_Aws_CloudWatch_ListMetrics.Inc()
metrics, _ := awsutil.ValuesAtPath(page, "Metrics")
for _, metric := range metrics {
resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric))
@@ -292,11 +292,6 @@ func getAllMetrics(cwData *datasourceInfo) (cloudwatch.ListMetricsOutput, error)
var metricsCacheLock sync.Mutex
func getMetricsForCustomMetrics(dsInfo *datasourceInfo, getAllMetrics func(*datasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) {
result, err := getAllMetrics(dsInfo)
if err != nil {
return []string{}, err
}
metricsCacheLock.Lock()
defer metricsCacheLock.Unlock()
@@ -314,6 +309,10 @@ func getMetricsForCustomMetrics(dsInfo *datasourceInfo, getAllMetrics func(*data
if customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) {
return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil
}
result, err := getAllMetrics(dsInfo)
if err != nil {
return []string{}, err
}
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0)
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire = time.Now().Add(5 * time.Minute)
@@ -330,11 +329,6 @@ func getMetricsForCustomMetrics(dsInfo *datasourceInfo, getAllMetrics func(*data
var dimensionsCacheLock sync.Mutex
func getDimensionsForCustomMetrics(dsInfo *datasourceInfo, getAllMetrics func(*datasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) {
result, err := getAllMetrics(dsInfo)
if err != nil {
return []string{}, err
}
dimensionsCacheLock.Lock()
defer dimensionsCacheLock.Unlock()
@@ -352,6 +346,10 @@ func getDimensionsForCustomMetrics(dsInfo *datasourceInfo, getAllMetrics func(*d
if customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) {
return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil
}
result, err := getAllMetrics(dsInfo)
if err != nil {
return []string{}, err
}
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0)
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire = time.Now().Add(5 * time.Minute)

View File

@@ -34,13 +34,13 @@ func CreateDashboardSnapshot(c *middleware.Context, cmd m.CreateDashboardSnapsho
cmd.OrgId = -1
cmd.UserId = -1
metrics.M_Api_Dashboard_Snapshot_External.Inc(1)
metrics.M_Api_Dashboard_Snapshot_External.Inc()
} else {
cmd.Key = util.GetRandomString(32)
cmd.DeleteKey = util.GetRandomString(32)
cmd.OrgId = c.OrgId
cmd.UserId = c.UserId
metrics.M_Api_Dashboard_Snapshot_Create.Inc(1)
metrics.M_Api_Dashboard_Snapshot_Create.Inc()
}
if err := bus.Dispatch(&cmd); err != nil {
@@ -84,7 +84,7 @@ func GetDashboardSnapshot(c *middleware.Context) {
},
}
metrics.M_Api_Dashboard_Snapshot_Get.Inc(1)
metrics.M_Api_Dashboard_Snapshot_Get.Inc()
c.Resp.Header().Set("Cache-Control", "public, max-age=3600")
c.JSON(200, dto)

View File

@@ -1,197 +1,60 @@
package api
import (
"bytes"
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"fmt"
"time"
"github.com/grafana/grafana/pkg/api/cloudwatch"
"github.com/grafana/grafana/pkg/api/pluginproxy"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/metrics"
"github.com/grafana/grafana/pkg/middleware"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/plugins"
)
var (
dataproxyLogger log.Logger = log.New("data-proxy-log")
)
const HeaderNameNoBackendCache = "X-Grafana-NoCache"
func NewReverseProxy(ds *m.DataSource, proxyPath string, targetUrl *url.URL) *httputil.ReverseProxy {
director := func(req *http.Request) {
req.URL.Scheme = targetUrl.Scheme
req.URL.Host = targetUrl.Host
req.Host = targetUrl.Host
func (hs *HttpServer) getDatasourceById(id int64, orgId int64, nocache bool) (*m.DataSource, error) {
cacheKey := fmt.Sprintf("ds-%d", id)
reqQueryVals := req.URL.Query()
if ds.Type == m.DS_INFLUXDB_08 {
req.URL.Path = util.JoinUrlFragments(targetUrl.Path, "db/"+ds.Database+"/"+proxyPath)
reqQueryVals.Add("u", ds.User)
reqQueryVals.Add("p", ds.Password)
req.URL.RawQuery = reqQueryVals.Encode()
} else if ds.Type == m.DS_INFLUXDB {
req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath)
req.URL.RawQuery = reqQueryVals.Encode()
if !ds.BasicAuth {
req.Header.Del("Authorization")
req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.User, ds.Password))
}
} else {
req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath)
}
if ds.BasicAuth {
req.Header.Del("Authorization")
req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword))
}
dsAuth := req.Header.Get("X-DS-Authorization")
if len(dsAuth) > 0 {
req.Header.Del("X-DS-Authorization")
req.Header.Del("Authorization")
req.Header.Add("Authorization", dsAuth)
}
// clear cookie headers
req.Header.Del("Cookie")
req.Header.Del("Set-Cookie")
// clear X-Forwarded Host/Port/Proto headers
req.Header.Del("X-Forwarded-Host")
req.Header.Del("X-Forwarded-Port")
req.Header.Del("X-Forwarded-Proto")
// set X-Forwarded-For header
if req.RemoteAddr != "" {
remoteAddr, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
remoteAddr = req.RemoteAddr
}
if req.Header.Get("X-Forwarded-For") != "" {
req.Header.Set("X-Forwarded-For", req.Header.Get("X-Forwarded-For")+", "+remoteAddr)
} else {
req.Header.Set("X-Forwarded-For", remoteAddr)
if !nocache {
if cached, found := hs.cache.Get(cacheKey); found {
ds := cached.(*m.DataSource)
if ds.OrgId == orgId {
return ds, nil
}
}
// reqBytes, _ := httputil.DumpRequestOut(req, true);
// log.Trace("Proxying datasource request: %s", string(reqBytes))
}
return &httputil.ReverseProxy{Director: director, FlushInterval: time.Millisecond * 200}
}
func getDatasource(id int64, orgId int64) (*m.DataSource, error) {
query := m.GetDataSourceByIdQuery{Id: id, OrgId: orgId}
if err := bus.Dispatch(&query); err != nil {
return nil, err
}
hs.cache.Set(cacheKey, query.Result, time.Second*5)
return query.Result, nil
}
func ProxyDataSourceRequest(c *middleware.Context) {
func (hs *HttpServer) ProxyDataSourceRequest(c *middleware.Context) {
c.TimeRequest(metrics.M_DataSource_ProxyReq_Timer)
ds, err := getDatasource(c.ParamsInt64(":id"), c.OrgId)
nocache := c.Req.Header.Get(HeaderNameNoBackendCache) == "true"
ds, err := hs.getDatasourceById(c.ParamsInt64(":id"), c.OrgId, nocache)
if err != nil {
c.JsonApiErr(500, "Unable to load datasource meta data", err)
return
}
if ds.Type == m.DS_INFLUXDB {
if c.Query("db") != ds.Database {
c.JsonApiErr(403, "Datasource is not configured to allow this database", nil)
return
}
}
if ds.Type == m.DS_CLOUDWATCH {
cloudwatch.HandleRequest(c, ds)
return
}
targetUrl, _ := url.Parse(ds.Url)
if !checkWhiteList(c, targetUrl.Host) {
// find plugin
plugin, ok := plugins.DataSources[ds.Type]
if !ok {
c.JsonApiErr(500, "Unable to find datasource plugin", err)
return
}
proxyPath := c.Params("*")
if ds.Type == m.DS_PROMETHEUS {
if c.Req.Request.Method != http.MethodGet || !strings.HasPrefix(proxyPath, "api/") {
c.JsonApiErr(403, "GET is only allowed on proxied Prometheus datasource", nil)
return
}
}
if ds.Type == m.DS_ES {
if c.Req.Request.Method == "DELETE" {
c.JsonApiErr(403, "Deletes not allowed on proxied Elasticsearch datasource", nil)
return
}
if c.Req.Request.Method == "PUT" {
c.JsonApiErr(403, "Puts not allowed on proxied Elasticsearch datasource", nil)
return
}
if c.Req.Request.Method == "POST" && proxyPath != "_msearch" {
c.JsonApiErr(403, "Posts not allowed on proxied Elasticsearch datasource except on /_msearch", nil)
return
}
}
proxy := NewReverseProxy(ds, proxyPath, targetUrl)
proxy.Transport, err = ds.GetHttpTransport()
if err != nil {
c.JsonApiErr(400, "Unable to load TLS certificate", err)
return
}
logProxyRequest(ds.Type, c)
proxy.ServeHTTP(c.Resp, c.Req.Request)
c.Resp.Header().Del("Set-Cookie")
}
func logProxyRequest(dataSourceType string, c *middleware.Context) {
if !setting.DataProxyLogging {
return
}
var body string
if c.Req.Request.Body != nil {
buffer, err := ioutil.ReadAll(c.Req.Request.Body)
if err == nil {
c.Req.Request.Body = ioutil.NopCloser(bytes.NewBuffer(buffer))
body = string(buffer)
}
}
dataproxyLogger.Info("Proxying incoming request",
"userid", c.UserId,
"orgid", c.OrgId,
"username", c.Login,
"datasource", dataSourceType,
"uri", c.Req.RequestURI,
"method", c.Req.Request.Method,
"body", body)
}
func checkWhiteList(c *middleware.Context, host string) bool {
if host != "" && len(setting.DataProxyWhiteList) > 0 {
if _, exists := setting.DataProxyWhiteList[host]; !exists {
c.JsonApiErr(403, "Data proxy hostname and ip are not included in whitelist", nil)
return false
}
}
return true
proxy := pluginproxy.NewDataSourceProxy(ds, plugin, c, proxyPath)
proxy.HandleRequest()
}

View File

@@ -1,63 +0,0 @@
package api
import (
"net/http"
"net/url"
"testing"
. "github.com/smartystreets/goconvey/convey"
m "github.com/grafana/grafana/pkg/models"
)
func TestDataSourceProxy(t *testing.T) {
Convey("When getting graphite datasource proxy", t, func() {
ds := m.DataSource{Url: "htttp://graphite:8080", Type: m.DS_GRAPHITE}
targetUrl, err := url.Parse(ds.Url)
proxy := NewReverseProxy(&ds, "/render", targetUrl)
proxy.Transport, err = ds.GetHttpTransport()
So(err, ShouldBeNil)
transport, ok := proxy.Transport.(*http.Transport)
So(ok, ShouldBeTrue)
So(transport.TLSClientConfig.InsecureSkipVerify, ShouldBeTrue)
requestUrl, _ := url.Parse("http://grafana.com/sub")
req := http.Request{URL: requestUrl}
proxy.Director(&req)
Convey("Can translate request url and path", func() {
So(req.URL.Host, ShouldEqual, "graphite:8080")
So(req.URL.Path, ShouldEqual, "/render")
})
})
Convey("When getting influxdb datasource proxy", t, func() {
ds := m.DataSource{
Type: m.DS_INFLUXDB_08,
Url: "http://influxdb:8083",
Database: "site",
User: "user",
Password: "password",
}
targetUrl, _ := url.Parse(ds.Url)
proxy := NewReverseProxy(&ds, "", targetUrl)
requestUrl, _ := url.Parse("http://grafana.com/sub")
req := http.Request{URL: requestUrl}
proxy.Director(&req)
Convey("Should add db to url", func() {
So(req.URL.Path, ShouldEqual, "/db/site/")
})
Convey("Should add username and password", func() {
queryVals := req.URL.Query()
So(queryVals["u"][0], ShouldEqual, "user")
So(queryVals["p"][0], ShouldEqual, "password")
})
})
}

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