Merge branch 'master' into table-col-alias

This commit is contained in:
Dan Cech 2017-05-05 12:41:35 -04:00
commit 0f24b45c1a
57 changed files with 1370 additions and 873 deletions

View File

@ -8,6 +8,8 @@
* **Graph**: Support auto grid min/max when using log scale [#3090](https://github.com/grafana/grafana/issues/3090), thx [@bigbenhur](https://github.com/bigbenhur)
* **Graph**: Support for histograms [#600](https://github.com/grafana/grafana/issues/600)
* **Prometheus**: Support table response formats (column per label) [#6140](https://github.com/grafana/grafana/issues/6140), thx [@mtanda](https://github.com/mtanda)
* **Single Stat Panel**: support for non time series data [#6564](https://github.com/grafana/grafana/issues/6564)
## Minor Enchancements

3
docs/publish.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
make publish ENV=prod VERSION=root

View File

@ -12,18 +12,18 @@ weight = 2
# Alert Notifications
{{< imgbox max-width="40%" img="/img/docs/v4/alert_notifications_menu.png" caption="Alerting notifications" >}}
> Alerting is only available in Grafana v4.0 and above.
When an alert changes state it sends out notifications. Each alert rule can have
multiple notifications. But in order to add a notification to an alert rule you first need
to add and configure a `notification` object. This is done from the Alerting/Notifications page.
to add and configure a `notification` channel (can be email, Pagerduty or other integration). This is done from the Notification Channels page.
## Notification Setup
## Notification Channel Setup
On the notifications list page hit the `New Notification` button to go the the page where you
can configure and setup a new notification.
{{< 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
can configure and setup a new Notification Channel.
You specify name and type, and type specific options. You can also test the notification to make
sure it's working and setup correctly.
@ -32,15 +32,15 @@ sure it's working and setup correctly.
When checked this option will make this notification used for all alert rules, existing and new.
## Supported notification types
## Supported Notification Types
Grafana ships with a set of notification types. More will be added in future releases.
Grafana ships with the following set of notification types:
### Email
To enable email notification you have to setup [SMTP settings](/installation/configuration/#smtp)
in the Grafana config. Email notification will upload an image of the alert graph to an
external image destination if available or fallback on attaching the image in the email.
external image destination if available or fallback to attaching the image in the email.
### Slack
@ -55,19 +55,29 @@ Setting | Description
Recipient | allows you to override the slack recipient.
Mention | make it possible to include a mention in the slack notification sent by Grafana. Ex @here or @channel
### PagerDuty
To set up PagerDuty, all you have to do is to provide an api key.
Setting | Description
---------- | -----------
Integration Key | Integration key for pagerduty.
Auto resolve incidents | Resolve incidents in pagerduty once the alert goes back to ok
### Webhook
The webhook notification is a simple way to send information about an state change over HTTP to a custom endpoint.
Using this notification you could integrated Grafana into any system you choose, by yourself.
Using this notification you could integrate Grafana into any system you choose, by yourself.
Example json body:
```json
{
"title": "My alert",
"ruleId": 1,
"ruleName": "Load peaking!",
"ruleUrl": "http://url.to.grafana/db/dashboard/my_dashboard?panelId=2",
"state": "Alerting",
"state": "alerting",
"imageUrl": "http://s3.image.url",
"message": "Load is peaking. Make sure the traffic is real and spin up more webfronts",
"evalMatches": [
@ -80,30 +90,38 @@ Example json body:
}
```
### PagerDuty
- **state** - The possible values for alert state are: `ok`, `paused`, `alerting`, `pending`, `no_data`.
To set up PagerDuty, all you have to do is to provide an api key.
### Other Supported Notification Channels
Setting | Description
---------- | -----------
Integration Key | Integration key for pagerduty.
Auto resolve incidents | Resolve incidents in pagerduty once the alert goes back to ok
Grafana also supports the following Notification Channels:
- HipChat
- VictorOps
- Sensu
- OpsGenie
- Threema
- Pushover
- Telegram
- LINE
# Enable images in notifications {#external-image-store}
Grafana can render the panel associated with the alert rule and include that in the notification. Some types
of notifications require that this image be publicly accessable (Slack for example). In order to support
images in notifications like Slack Grafana can upload the image to an image store. It currently supports
Amazon S3 for this and Webdav. So to set that up you need to configure the
[external image uploader](/installation/configuration/#external-image-storage) in your grafana-server ini
config file.
Grafana can render the panel associated with the alert rule and include that in the notification. Most Notification Channels require that this image be publicly accessable (Slack and PagerDuty for example). In order to include images in alert notifications, Grafana can upload the image to an image store. It currently supports
Amazon S3 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.
This is an optional requirement, you can get slack and email notifications without setting this up.
Currently only the Email Channels attaches images if no external image store is specified. To include images in alert notifications for other channels then you need to set up an external image store.
This is an optional requirement, you can get Slack and email notifications without setting this up.
# Configure the link back to Grafana from alert notifications
All alert notifications contains a link back to the triggered alert in the Grafana instance.
This url is based on the [domain](/installation/configuration/#domain) setting in Grafana.

View File

@ -12,34 +12,29 @@ weight = 3
# Using Elasticsearch in Grafana
Grafana ships with advanced support for Elasticsearch. You can do many types of
simple or complex elasticsearch queries to visualize logs or metrics stored in elasticsearch. You can
also annotate your graphs with log events stored in elasticsearch.
Grafana ships with advanced support for Elasticsearch. You can do many types of simple or complex Elasticsearch queries to
visualize logs or metrics stored in Elasticsearch. You can also annotate your graphs with log events stored in Elasticsearch.
## Adding the data source
![](/img/docs/v2/add_Graphite.jpg)
1. Open the side menu by clicking the the Grafana icon in the top header.
1. Open the side menu by clicking the Grafana icon in the top header.
2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`.
3. Click the `+ Add data source` button in the top header.
4. Select *Elasticsearch* from the *Type* dropdown.
> NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization.
3. Click the `Add new` link in the top header.
4. Select `Elasticsearch` from the dropdown.
> NOTE: If you're not seeing the `Data Sources` link in your side menu it means that your current user does not have the `Admin` role for the current organization.
Name | Description
------------ | -------------
Name | The data source name, important that this is the same as in Grafana v1.x if you plan to import old dashboards.
Default | Default data source means that it will be pre-selected for new panels.
Url | The http protocol, ip and port of you elasticsearch server.
Access | Proxy = access via Grafana backend, Direct = access directly from browser.
*Name* | The data source name. This is how you refer to the data source in panels & queries.
*Default* | Default data source means that it will be pre-selected for new panels.
*Url* | The HTTP protocol, IP, and port of your Elasticsearch server.
*Access* | Proxy = access via Grafana backend, Direct = access directly from browser.
Proxy access means that the Grafana backend will proxy all requests from the browser, and send them on to the Data Source. This is useful because it can eliminate CORS (Cross Origin Site Resource) issues, as well as eliminate the need to disseminate authentication details to the Data Source to the browser.
Direct access is still supported because in some cases it may be useful to access a Data Source directly depending on the use case and topology of Grafana, the user, and the Data Source.
Proxy access means that the Grafana backend will proxy all requests from the browser, and send them on to the Data Source. This is useful because it can eliminate CORS (Cross Origin Site Resource) issues, as well as eliminate the need to disseminate authentication to the browser.
### Direct access
If you select direct access you must update your Elasticsearch configuration to allow other domains to access
Elasticsearch from the browser. You do this by specifying these to options in your **elasticsearch.yml** config file.
@ -50,46 +45,93 @@ Elasticsearch from the browser. You do this by specifying these to options in yo
![](/img/docs/elasticsearch/elasticsearch_ds_details.png)
Here you can specify a default for the `time field` and specify the name of your elasticsearch index. You can use
Here you can specify a default for the `time field` and specify the name of your Elasticsearch index. You can use
a time pattern for the index name or a wildcard.
### Elasticsearch version
Be sure to specify your Elasticsearch version in the version selection dropdown. This is very important as there are differences how queries are composed. Currently only 2.x and 5.x
are supported.
## Metric Query editor
![](/img/docs/elasticsearch/query_editor.png)
The Elasticsearch query editor allows you to select multiple metrics and group by multiple terms or filters. Use the plus and minus icons to the right to add / remove
metrics or group bys. Some metrics and group by have options, click the option text to expand the the row to view and edit metric or group by options.
The Elasticsearch query editor allows you to select multiple metrics and group by multiple terms or filters. Use the plus and minus icons to the right to add/remove
metrics or group by clauses. Some metrics and group by clauses haves options, click the option text to expand the row to view and edit metric or group by options.
## Series naming & alias patterns
You can control the name for time series via the `Alias` input field.
Pattern | Description
------------ | -------------
*{{term fieldname}}* | replaced with value of a term group by
*{{metric}}* | replaced with metric name (ex. Average, Min, Max)
*{{field}}* | replaced with the metric field name
## Pipeline metrics
If you have Elasticsearch 2.x and Grafana 2.6 or above then you can use pipeline metric aggregations like
**Moving Average** and **Derivative**. Elasticsearch pipeline metrics require another metric to be based on. Use the eye icon next to the metric
to hide metrics from appearing in the graph. This is useful for metrics you only have in the query to be used
in a pipeline metric.
Some metric aggregations are called Pipeline aggregations, for example, *Moving Average* and *Derivative*. Elasticsearch pipeline metrics require another metric to be based on. Use the eye icon next to the metric to hide metrics from appearing in the graph. This is useful for metrics you only have in the query for use in a pipeline metric.
![](/img/docs/elasticsearch/pipeline_metrics_editor.png)
## Templating
The Elasticsearch datasource supports two types of queries you can use to fill template variables with values.
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.
### Possible values for a field
Checkout the [Templating]({{< relref "reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
types of template variables.
```json
{"find": "terms", "field": "@hostname"}
### Query variable
The Elasticsearch data source supports two types of queries you can use in the *Query* field of *Query* variables. The query is written using a custom JSON string.
Query | Description
------------ | -------------
*{"find": "fields", "type": "keyword"} | Returns a list of field names with the index type `keyword`.
*{"find": "terms", "field": "@hostname"}* | Returns a list of values for a field using term aggregation. Query will user current dashboard time range as time range for query.
*{"find": "terms", "field": "@hostname", "query": '<lucene query>'}* | Returns a list of values for a field using term aggregation & and a specified lucene query filter. Query will use current dashboard time range as time range for query.
You can use other variables inside the query. Example query definition for a variable named `$host`.
```
{"find": "terms", "field": "@hostname", "query": "@source:$source"}
```
### Fields filtered by type
```json
{"find": "fields", "type": "string"}
```
In the above example, we use another variable named `$source` inside the query definition. Whenever you change, via the dropdown, the current value of the ` $source` variable, it will trigger an update of the `$host` variable so it now only contains hostnames filtered by in this case the
`@source` document property.
### Fields filtered by type, with filter
```json
{"find": "fields", "type": "string", "query": <lucene query>}
```
### Using variables in queries
### Multi format / All format
Use lucene format.
There are two syntaxes:
- `$<varname>` Example: @hostname:$hostname
- `[[varname]]` Example: @hostname:[[hostname]]
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 lucene compatible condition.
![](/img/docs/v43/elastic_templating_query.png)
In the above example, we have a lucene query that filters documents based on the `@hostname` property using a variable named `$hostname`. It is also using
a variable in the *Terms* group by field input box. This allows you to use a variable to quickly change how the data is grouped.
Example dashboard:
[Elasticsearch Templated Dashboard](http://play.grafana.org/dashboard/db/elasticsearch-templated)
## Annotations
[Annotations]({{< relref "reference/annotations.md" >}}) allows you to overlay rich event information on top of graphs. You add annotation
queries via the Dashboard menu / Annotations view. Grafana can query any Elasticsearch index
for annotation events.
Name | Description
------------ | -------------
Query | You can leave the search query blank or specify a lucene query
Time | The name of the time field, needs to be date field.
Title | The name of the field to use for the event title.
Tags | Optional field name to use for event tags (can be an array or a CSV string).
Text | Optional field name to use event text body.

View File

@ -18,28 +18,22 @@ change function parameters and much more. The editor can handle all types of gra
queries through the use of query references.
## Adding the data source
![](/img/docs/v2/add_Graphite.jpg)
1. Open the side menu by clicking the the Grafana icon in the top header.
1. Open the side menu by clicking the Grafana icon in the top header.
2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`.
3. Click the `+ Add data source` button in the top header.
4. Select `Graphite` from the *Type* dropdown.
> NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization.
3. Click the `Add new` link in the top header.
4. Select `Graphite` from the dropdown.
> NOTE: If you're not seeing the `Data Sources` link in your side menu it means that your current user does not have the `Admin` role for the current organization.
Name | Description
------------ | -------------
Name | The data source name, important that this is the same as in Grafana v1.x if you plan to import old dashboards.
Default | Default data source means that it will be pre-selected for new panels.
Url | The http protocol, ip and port of your graphite-web or graphite-api install.
Access | Proxy = access via Grafana backend, Direct = access directly from browser.
Proxy access means that the Grafana backend will proxy all requests from the browser, and send them on to the Data Source. This is useful because it can eliminate CORS (Cross Origin Site Resource) issues, as well as eliminate the need to disseminate authentication details to the Data Source to the browser.
Direct access is still supported because in some cases it may be useful to access a Data Source directly depending on the use case and topology of Grafana, the user, and the Data Source.
*Name* | The data source name. This is how you refer to the data source in panels & queries.
*Default* | Default data source means that it will be pre-selected for new panels.
*Url* | The HTTP protocol, IP, and port of your graphite-web or graphite-api install.
*Access* | Proxy = access via Grafana backend, Direct = access directly from browser.
Proxy access means that the Grafana backend will proxy all requests from the browser, and send them on to the Data Source. This is useful because it can eliminate CORS (Cross Origin Site Resource) issues, as well as eliminate the need to disseminate authentication details to the browser.
## Metric editor
@ -50,6 +44,7 @@ or keyboard arrow keys. You can select a wildcard and still continue.
![](/img/docs/animated_gifs/graphite_query1.gif)
### Functions
Click the plus icon to the right to add a function. You can search for the function or select it from the menu. Once
a function is selected it will be added and your focus will be in the text box of the first parameter. To later change
a parameter just click on it and it will turn into a text box. To delete a function click the function name followed
@ -57,32 +52,61 @@ by the x icon.
![](/img/docs/animated_gifs/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)
### 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.
## 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
All Graphite metrics are consolidated so that Graphite doesn't return more data points than there are pixels in the graph. By default,
this consolidation is done using `avg` function. You can how Graphite consolidates metrics by adding the Graphite consolidateBy function.
> *Notice* This means that legend summary values (max, min, total) cannot be all correct at the same time. They are calculated
> client side by Grafana. And depending on your consolidation function only one or two can be correct at the same time.
## Templating
You can create a template variable in Grafana and have that variable filled with values from any Graphite metric exploration query.
You can then use this variable in your Graphite queries, either as part of a metric path or as arguments to functions.
For example a query like `prod.servers.*` will fill the variable with all possible
values that exists in the wildcard position.
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
The query you specify in the query field should be a metric find type of query. For example, a query like `prod.servers.*` will fill the
variable with all possible values that exist in the wildcard position.
You can also create nested variables that use other variables in their definition. For example
`apps.$app.servers.*` uses the variable `$app` in its query definition.
### Variable usage
You can use a variable in a metric node path or as a parameter to a function.
![](/img/docs/v2/templated_variable_parameter.png)
There are two syntaxes:
## Query Reference
You can reference queries by the row “letter” that theyre on (similar to Microsoft Excel). If you add a second query to graph, you can reference the first query simply by typing in #A. This provides an easy and convenient way to build compounded queries.
- `$<varname>` Example: apps.frontend.$server.requests.count
- `[[varname]]` Example: apps.frontend.[[server]].requests.count
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. Use
the second syntax in expressions like `my.server[[serverNumber]].count`.
Example:
[Graphite Templated Dashboard](http://play.grafana.org/dashboard/db/graphite-templated-nested)
## Annotations
[Annotations]({{< relref "reference/annotations.md" >}}) allows you to overlay rich event information on top of graphs. You add annotation
queries via the Dashboard menu / Annotations view.
Graphite supports two ways to query annotations. A regular metric query, for this you use the `Graphite query` textbox. A Graphite events query, use the `Graphite event tags` textbox,
specify a tag or wildcard (leave empty should also work)

View File

@ -15,29 +15,29 @@ weight = 3
Grafana ships with very feature rich data source plugin for InfluxDB. Supporting a feature rich query editor, annotation and templating queries.
## Adding the data source
![](/img/docs/v2/add_Influx.jpg)
1. Open the side menu by clicking the the Grafana icon in the top header.
1. Open the side menu by clicking the Grafana icon in the top header.
2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`.
3. Click the `+ Add data source` button in the top header.
4. Select *InfluxDB* from the *Type* dropdown.
> NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization.
3. Click the `Add new` link in the top header.
> NOTE: If you're not seeing the `Data Sources` link in your side menu it means that your current user does not have the `Admin` role for the current organization.
Name | Description
------------ | -------------
Name | The data source name, important that this is the same as in Grafana v1.x if you plan to import old dashboards.
Default | Default data source means that it will be pre-selected for new panels.
Url | The http protocol, ip and port of you influxdb api (influxdb api port is by default 8086)
Access | Proxy = access via Grafana backend, Direct = access directly from browser.
Database | Name of your influxdb database
User | Name of your database user
Password | Database user's password
*Name* | The data source name. This is how you refer to the data source in panels & queries.
*Default* | Default data source means that it will be pre-selected for new panels.
*Url* | The http protocol, ip and port of you influxdb api (influxdb api port is by default 8086)
*Access* | Proxy = access via Grafana backend, Direct = access directly from browser.
*Database* | Name of your influxdb database
*User* | Name of your database user
*Password* | Database user's password
> Proxy access means that the Grafana backend will proxy all requests from the browser, and send them on to the Data Source. This is useful because it can eliminate CORS (Cross Origin Site Resource) issues, as well as eliminate the need to disseminate authentication details to the Data Source to the browser.
> Direct access is still supported because in some cases it may be useful to access a Data Source directly depending on the use case and topology of Grafana, the user, and the Data Source.
### 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
mode is also more secure as the username & password will never reach the browser.
## Query Editor
@ -100,11 +100,21 @@ change the option `Format As` to `Table` if you want to show raw data in the `Ta
## Templating
You can create a template variable in Grafana and have that variable filled with values from any InfluxDB metric exploration query.
You can then use this variable in your InfluxDB metric queries.
For example you can have a variable that contains all values for tag `hostname` if you specify a query like this
in the templating edit view.
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 InfluxDB exploration (meta data) query. These queries can
return things like measurement names, key names or key values.
For example you can have a variable that contains all values for tag `hostname` if you specify a query like this in the templating variable *Query* setting.
```sql
SHOW TAG VALUES WITH KEY = "hostname"
```
@ -116,12 +126,46 @@ the hosts variable only show hosts from the current selected region with a query
SHOW TAG VALUES WITH KEY = "hostname" WHERE region =~ /$region/
```
> Always use `regex values` or `regex wildcard` for All format or multi select format.
You can fetch key names for a given measurement.
![](/img/docs/influxdb/templating_simple_ex1.png)
```sql
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
of the dashboard.
### Using variables in queries
There are two syntaxes:
`$<varname>` Example:
```sql
SELECT mean("value") FROM "logins" WHERE "hostname" =~ /^$host$/ AND $timeFilter GROUP BY time($__interval), "hostname"
```
`[[varname]]` Example:
```sql
SELECT mean("value") FROM "logins" WHERE "hostname" =~ /^[[host]]$/ AND $timeFilter GROUP BY time($__interval), "hostname"
```
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 `=`.
Example Dashboard:
[InfluxDB Templated Dashboard](http://play.grafana.org/dashboard/db/influxdb-templated-queries)
### Ad hoc filters variable
InfluxDB supports the special `Ad hoc filters` variable type. This variable allows you to specify any number of key/value filters on the fly. These filters will automatically
be applied to all your InfluxDB queries.
## Annotations
Annotations allows you to overlay rich event information on top of graphs.
[Annotations]({{< relref "reference/annotations.md" >}}) allows you to overlay rich event information on top of graphs. You add annotation
queries via the Dashboard menu / Annotations view.
An example query:
@ -129,4 +173,8 @@ An example query:
SELECT title, description from events WHERE $timeFilter order asc
```
For InfluxDB you need to enter a query like in the above example. You need to have the ```where $timeFilter```
part. If you only select one column you will not need to enter anything in the column mapping fields. The
Tags field can be a comma seperated string.

View File

@ -12,59 +12,79 @@ weight = 5
# Using OpenTSDB in Grafana
{{< docs-imagebox img="/img/docs/v2/add_OpenTSDB.png" max-width="14rem" >}}
Grafana ships with advanced support for OpenTSDB.
The newest release of Grafana adds additional functionality when using an OpenTSDB Data source.
## Adding the data source
1. Open the side menu by clicking the the Grafana icon in the top header.
1. Open the side menu by clicking the Grafana icon in the top header.
2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`.
3. Click the `+ Add data source` button in the top header.
4. Select *OpenTSDB* from the *Type* dropdown.
> NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization.
3. Click the `Add new` link in the top header.
4. Select `OpenTSDB` from the dropdown.
> NOTE: If you're not seeing the `Data Sources` link in your side menu it means that your current user does not have the `Admin` role for the current organization.
Name | Description
------------ | -------------
Name | The data source name, important that this is the same as in Grafana v1.x if you plan to import old dashboards.
Default | Default data source means that it will be pre-selected for new panels.
Url | The http protocol, ip and port of you opentsdb server (default port is usually 4242)
Access | Proxy = access via Grafana backend, Direct = access directly from browser.
Version | Version = opentsdb version, either <=2.1 or 2.2
Resolution | Metrics from opentsdb may have datapoints with either second or millisecond resolution.
*Name* | The data source name. This is how you refer to the data source in panels & queries.
*Default* | Default data source means that it will be pre-selected for new panels.
*Url* | The http protocol, ip and port of you opentsdb server (default port is usually 4242)
*Access* | Proxy = access via Grafana backend, Direct = access directly from browser.
*Version* | Version = opentsdb version, either <=2.1 or 2.2
*Resolution* | Metrics from opentsdb may have datapoints with either second or millisecond resolution.
## Query editor
Open a graph in edit mode by click the title. Query editor will differ if the datasource has version <=2.1 or = 2.2. In the former version, only tags can be used to query opentsdb. But in the latter version, filters as well as tags can be used to query opentsdb. Fill Policy is also introduced in opentsdb 2.2.
> Note: While using Opentsdb 2.2 datasource, make sure you use either Filters or Tags as they are mutually exclusive. If used together, might give you weird results.
Open a graph in edit mode by click the title. Query editor will differ if the datasource has version <=2.1 or = 2.2.
In the former version, only tags can be used to query OpenTSDB. But in the latter version, filters as well as tags
can be used to query opentsdb. Fill Policy is also introduced in OpenTSDB 2.2.
![](/img/docs/v2/opentsdb_query_editor.png)
![](/img/docs/v43/opentsdb_query_editor.png)
> Note: While using OpenTSDB 2.2 datasource, make sure you use either Filters or Tags as they are mutually exclusive. If used together, might give you weird results.
### Auto complete suggestions
As soon as you start typing metric names, tag names and tag values , you should see highlighted auto complete suggestions for them.
> Note: This is required for the OpenTSDB `suggest` api to work.
As soon as you start typing metric names, tag names and tag values , you should see highlighted auto complete suggestions for them.
The autocomplete only works if the OpenTSDB suggest api is enabled.
## Templating queries
Grafana's OpenTSDB data source now supports template variable values queries. This means you can create template variables that fetch the values from OpenTSDB (for example metric names, tag names, or tag values). The query editor is also enhanced to limiting tags by metric.
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
Grafana's OpenTSDB data source supports template variable queries. This means you can create template variables
that fetch the values from OpenTSDB. For example, metric names, tag names, or tag values.
When using OpenTSDB with a template variable of `query` type you can use following syntax for lookup.
metrics(prefix) // returns metric names with specific prefix (can be empty)
tag_names(cpu) // return tag names (i.e. keys) for a specific cpu metric
tag_values(cpu, hostname) // return tag values for metric cpu and tag key hostname
suggest_tagk(prefix) // return tag names (i.e. keys) for all metrics with specific prefix (can be empty)
suggest_tagv(prefix) // return tag values for all metrics with specific prefix (can be empty)
Query | Description
------------ | -------------
*metrics(prefix)* | Returns metric names with specific prefix (can be empty)
*tag_names(cpu)* | Return tag names (i.e. keys) for a specific cpu metric
*tag_values(cpu, hostname)* | Return tag values for metric cpu and tag key hostname
*suggest_tagk(prefix)* | Return tag names (i.e. keys) for all metrics with specific prefix (can be empty)
*suggest_tagv(prefix)* | Return tag values for all metrics with specific prefix (can be empty)
If you do not see template variables being populated in `Preview of values` section, you need to enable `tsd.core.meta.enable_realtime_ts` in the OpenTSDB server settings. Also, to populate metadata of the existing time series data in OpenTSDB, you need to run `tsdb uid metasync` on the OpenTSDB server.
If you do not see template variables being populated in `Preview of values` section, you need to enable
`tsd.core.meta.enable_realtime_ts` in the OpenTSDB server settings. Also, to populate metadata of
the existing time series data in OpenTSDB, you need to run `tsdb uid metasync` on the OpenTSDB server.
### Nested Templating
One template variable can be used to filter tag values for another template varible. Very importantly, the order of the parameters matter in tag_values function. First parameter is the metric name, second parameter is the tag key for which you need to find tag values, and after that all other dependent template variables. Some examples are mentioned below to make nested template queries work successfully.
One template variable can be used to filter tag values for another template varible. First parameter is the metric name,
second parameter is the tag key for which you need to find tag values, and after that all other dependent template variables.
Some examples are mentioned below to make nested template queries work successfully.
tag_values(cpu, hostname, env=$env) // return tag values for cpu metric, selected env tag value and tag key hostname
tag_values(cpu, hostanme, env=$env, region=$region) // return tag values for cpu metric, selected env tag value, selected region tag value and tag key hostname
Query | Description
------------ | -------------
*tag_values(cpu, hostname, env=$env)* | Return tag values for cpu metric, selected env tag value and tag key hostname
*tag_values(cpu, hostanme, env=$env, region=$region)* | Return tag values for cpu metric, selected env tag value, selected region tag value and tag key hostname
> Note: This is required for the OpenTSDB `lookup` api to work.
For details on opentsdb metric queries checkout the official [OpenTSDB documentation](http://opentsdb.net/docs/build/html/index.html)
For details on OpenTSDB metric queries checkout the official [OpenTSDB documentation](http://opentsdb.net/docs/build/html/index.html)

View File

@ -10,74 +10,86 @@ parent = "datasources"
weight = 2
+++
# Using Prometheus in Grafana
Grafana includes support for Prometheus Datasources. While the process of adding the datasource is similar to adding a Graphite or OpenTSDB datasource type, Prometheus does have a few different options for building queries.
Grafana includes built-in support for Prometheus.
## Adding the data source to Grafana
![](/img/docs/v2/add_Prometheus.png)
1. Open the side menu by clicking the the Grafana icon in the top header.
1. Open the side menu by clicking the Grafana icon in the top header.
2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`.
3. Click the `+ Add data source` button in the top header.
4. Select `Prometheus` from the *Type* dropdown.
> NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization.
> NOTE: If you're not seeing the `Data Sources` link in your side menu it means that your current user does not have the `Admin` role for the current organization.
3. Click the `Add new` link in the top header.
4. Select `Prometheus` from the dropdown.
## Data source options
Name | Description
------------ | -------------
Name | The data source name, important that this is the same as in Grafana v1.x if you plan to import old dashboards.
Default | Default data source means that it will be pre-selected for new panels.
Url | The http protocol, ip and port of you Prometheus server (default port is usually 9090)
Access | Proxy = access via Grafana backend, Direct = access directly from browser.
Basic Auth | Enable basic authentication to the Prometheus datasource.
User | Name of your Prometheus user
Password | Database user's password
> Proxy access means that the Grafana backend will proxy all requests from the browser, and send them on to the Data Source. This is useful because it can eliminate CORS (Cross Origin Site Resource) issues, as well as eliminate the need to disseminate authentication details to the Data Source to the browser.
> Direct access is still supported because in some cases it may be useful to access a Data Source directly depending on the use case and topology of Grafana, the user, and the Data Source.
*Name* | The data source name. This is how you refer to the data source in panels & queries.
*Default* | Default data source means that it will be pre-selected for new panels.
*Url* | The http protocol, ip and port of you Prometheus server (default port is usually 9090)
*Access* | Proxy = access via Grafana backend, Direct = access directly from browser.
*Basic Auth* | Enable basic authentication to the Prometheus data source.
*User* | Name of your Prometheus user
*Password* | Database user's password
## Query editor
Open a graph in edit mode by click the title.
![](/img/v2/prometheus_editor.png)
Open a graph in edit mode by click the title > Edit (or by pressing `e` key while hovering over panel).
For details on Prometheus metric queries check out the Prometheus documentation
- [Query Metrics - Prometheus documentation](http://prometheus.io/docs/querying/basics/).
## Templated queries
Prometheus Datasource Plugin provides the following functions in `Variables values query` field in Templating Editor to query `metric names` and `labels names` on the Prometheus server.
![](/img/docs/v43/prometheus_query_editor.png)
Name | Description
------- | --------
`label_values(label)` | Returns a list of label values for the `label` in every metric.
`label_values(metric, label)` | Returns a list of label values for the `label` in the specified metric.
`metrics(metric)` | Returns a list of metrics matching the specified `metric` regex.
`query_result(query)` | Returns a list of Prometheus query result for the `query`.
*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.
*Format as* | **(New in v4.3)** Switch between Table & Time series. Table format will only work in the Table panel.
For details of `metric names` & `label names`, and `label values`, please refer to the [Prometheus documentation](http://prometheus.io/docs/concepts/data_model/#metric-names-and-labels).
## Templating
> Note: The part of queries is incompatible with the version before 2.6, if you specify like `foo.*`, please change like `metrics(foo.*)`.
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.
You can create a template variable in Grafana and have that variable filled with values from any Prometheus metric exploration query.
You can then use this variable in your Prometheus metric queries.
Checkout the [Templating]({{< relref "reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
types of template variables.
For example you can have a variable that contains all values for label `hostname` if you specify a query like this in the templating edit view.
### Query variable
```sql
label_values(hostname)
```
Variable of the type *Query* allows you to query Prometheus for a list of metrics, labels or label values. The Prometheus data source plugin
provides the following functions you can use in the `Query` input field.
You can also use raw queries & regular expressions to extract anything you might need.
Name | Description
---- | --------
*label_values(label)* | Returns a list of label values for the `label` in every metric.
*label_values(metric, label)* | Returns a list of label values for the `label` in the specified metric.
*metrics(metric)* | Returns a list of metrics matching the specified `metric` regex.
*query_result(query)* | Returns a list of Prometheus query result for the `query`.
### Using templated variables in queries
For details of *metric names*, *label names* and *label values* are please refer to the [Prometheus documentation](http://prometheus.io/docs/concepts/data_model/#metric-names-and-labels).
When the `Include All` option or `Multi-Value` option is enabled, Grafana converts the labels from plain text to a regex compatible string.
Which means you have to use `=~` instead of `=` in your Prometheus queries. For example `ALERTS{instance=~$instance}` instead of `ALERTS{instance=$instance}`.
### Using variables in queries
![](/img/docs/v2/prometheus_templating.png)
There are two syntaxes:
- `$<varname>` Example: rate(http_requests_total{job=~"$job"}[5m])
- `[[varname]]` Example: rate(http_requests_total{job="my[[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 `=`.
## Annotations
[Annotations]({{< relref "reference/annotations.md" >}}) allows you to overlay rich event information on top of graphs. You add annotation
queries via the Dashboard menu / Annotations view.
Prometheus supports two ways to query annotations.
- A regular metric query
- A Prometheus query for pending and firing alerts (for details see [Inspecting alerts during runtime](https://prometheus.io/docs/alerting/rules/#inspecting-alerts-during-runtime))
The step option is useful to limit the number of events returned from your query.

View File

@ -280,14 +280,22 @@ Change password for specific user
## Pause all alerts
`DELETE /api/admin/pause-all-alerts`
`POST /api/admin/pause-all-alerts`
**Example Request**:
DELETE /api/admin/pause-all-alerts HTTP/1.1
POST /api/admin/pause-all-alerts HTTP/1.1
Accept: application/json
Content-Type: application/json
{
"paused": true
}
JSON Body schema:
- **paused** If true then all alerts are to be paused, false unpauses all alerts.
**Example Response**:
HTTP/1.1 200

View File

@ -28,6 +28,17 @@ This API can also be used to create, update and delete alert notifications.
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
Querystring Parameters:
These parameters are used as querystring parameters. For example:
`/api/alerts?dashboardId=1`
- **dashboardId** Return alerts for a specified dashboard.
- **panelId** Return alerts for a specified panel on a dashboard.
- **limit** - Limit response to x number of alerts.
- **state** - Return alerts with one or more of the following alert states: `ALL`,`no_data`, `paused`, `alerting`, `ok`, `pending`. To specify multiple states use the following format: `?state=paused&state=alerting`
**Example Response**:
HTTP/1.1 200
@ -40,6 +51,13 @@ This API can also be used to create, update and delete alert notifications.
"name": "fire place sensor",
"message": "Someone is trying to break in through the fire place",
"state": "alerting",
"evalDate": "0001-01-01T00:00:00Z",
"evalData": [
{
"metric": "fire",
"tags": null,
"value": 5.349999999999999
}
"newStateDate": "2016-12-25",
"executionError": "",
"dashboardUri": "http://grafana.com/dashboard/db/sensors"
@ -73,7 +91,6 @@ This API can also be used to create, update and delete alert notifications.
"dashboardUri": "http://grafana.com/dashboard/db/sensors"
}
## Pause alert
`POST /api/alerts/:id/pause`
@ -86,10 +103,15 @@ This API can also be used to create, update and delete alert notifications.
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
{
"alertId": 1,
"paused": true
}
The :id query parameter is the id of the alert to be paused or unpaused.
JSON Body Schema:
- **paused** Can be `true` or `false`. True to pause an alert. False to unpause an alert.
**Example Response**:
HTTP/1.1 200
@ -111,6 +133,8 @@ This API can also be used to create, update and delete alert notifications.
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
**Example Response**:
HTTP/1.1 200

View File

@ -229,6 +229,10 @@ Used for signing keep me logged in / remember me cookies.
Set to `true` to disable the use of Gravatar for user profile images.
Default is `false`.
### data_source_proxy_whitelist
Define a white list of allowed ips/domains to use in data sources. Format: `ip_or_domain:port` separated by spaces
<hr />
## [users]

View File

@ -17,6 +17,9 @@ Description | Download
------------ | -------------
Stable for Debian-based Linux | [4.2.0 (x86-64 deb)](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.2.0_amd64.deb)
Read [Upgrading Grafana]({{< relref "installation/upgrading.md" >}}) for tips and guidance on updating an existing
installation.
## Install Stable
```

View File

@ -73,7 +73,7 @@ email = "email"
[[servers.group_mappings]]
group_dn = "cn=admins,dc=grafana,dc=org"
org_role = "Admin"
# The Grafana organization database id, optional, if left out the default org (id 1) will be used
# The Grafana organization database id, optional, if left out the default org (id 1) will be used. Setting this allows for multiple group_dn's to be assigned to the same org_role provided the org_id differs
# org_id = 1
[[servers.group_mappings]]

View File

@ -3,9 +3,6 @@ title = "Migrating from older versions"
description = "Upgrading & Migrating Grafana from older versions"
keywords = ["grafana", "configuration", "documentation", "migration"]
type = "docs"
[menu.docs]
parent = "installation"
weight = 10
+++
# Migrating from older versions

View File

@ -1,34 +0,0 @@
+++
title = "Installing via provisioning tools"
description = "Guide to install Grafana via provisioning tools like puppet & chef"
keywords = ["grafana", "provisioning", "documentation", "puppet", "chef", "ansible"]
type = "docs"
aliases = ["docs/provisioning"]
[menu.docs]
parent = "installation"
weight = 8
+++
# Installing via provisioning tools
Here are links for how to install Grafana (and some include Graphite or
InfluxDB as well) via a provisioning system. These are not maintained by
any core Grafana team member and might be out of date.
### Puppet
* [forge.puppetlabs.com/bfraser/grafana](https://forge.puppetlabs.com/bfraser/grafana)
### Ansible
* [github.com/picotrading/ansible-grafana](https://github.com/picotrading/ansible-grafana)
### Docker
* [github.com/grafana/grafana-docker](https://github.com/grafana/grafana-docker)
### Chef
* [github.com/JonathanTron/chef-grafana](https://github.com/JonathanTron/chef-grafana)
* [github.com/Nordstrom/grafana2-cookbook](https://github.com/Nordstrom/grafana2-cookbook)

View File

@ -17,6 +17,9 @@ Description | Download
------------ | -------------
Stable for CentOS / Fedora / OpenSuse / Redhat Linux | [4.2.0 (x86-64 rpm)](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.2.0-1.x86_64.rpm)
Read [Upgrading Grafana]({{< relref "installation/upgrading.md" >}}) for tips and guidance on updating an existing
installation.
## Install Stable
You can install Grafana using Yum directly.

View File

@ -11,48 +11,24 @@ weight = 8
# Troubleshooting
This page is dedicated to helping you solve any problem you have getting
Grafana to work. Please review it before opening a new [GitHub
issue](https://github.com/grafana/grafana/issues/new) or asking a
question in the `#grafana` IRC channel on freenode.
## visualization & query issues
## General connection issues
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.
When setting up Grafana for the first time you might experience issues
with Grafana being unable to query Graphite, OpenTSDB or InfluxDB. You
might not be able to get metric name completion or the graph might show
an error like this:
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)
![](/img/docs/v1/graph_timestore_error.png)
## Logging
For some types of errors, the `View details` link will show you error
details. For many types of HTTP connection errors, however, there is very
little information. The best way to troubleshoot these issues is use
the [Chrome developer tools](https://developer.chrome.com/devtools/index).
By pressing `F12` you can bring up the chrome dev tools.
If you encounter an error or problem it is a good idea to check the grafana server log. Usually
located at `/var/log/grafana/grafana.log` on unix systems or in `<grafana_install_dir>/data/log` on
other platforms & manual installs.
![](/img/docs/v1/toubleshooting_chrome_dev_tools.png)
You can enable more logging by changing log level in you grafana configuration file.
There are two important tabs in the Chrome developer tools: `Network`
and `Console`. The `Console` tab will show you Javascript errors and
HTTP request errors. In the Network tab you will be able to identify the
request that failed and review request and response parameters. This
information will be of great help in finding the cause of the error.
## FAQ
If you are unable to solve the issue, even after reading the remainder
of this troubleshooting guide, you should open a [GitHub support
issue](https://github.com/grafana/grafana/issues). Before you do that
please search the existing closed or open issues. Also if you need to
create a support issue, screen shots and or text information about the
chrome console error, request and response information from the
`Network` tab in Chrome developer tools are of great help.
### Inspecting Grafana metric requests
![](/img/docs/v1/toubleshooting_chrome_dev_tools_network.png)
After opening the Chrome developer tools for the first time the
`Network` tab is empty. You will need to refresh the page to get
requests to show. For some type of errors, especially CORS-related,
there might not be a response at all.
Checkout the [FAQ](https://community.grafana.com/c/howto/faq) section on our community page for frequently
asked questions.

View File

@ -0,0 +1,103 @@
+++
title = "Upgrading"
description = "Upgrading Grafana guide"
keywords = ["grafana", "configuration", "documentation", "upgrade"]
type = "docs"
[menu.docs]
name = "Upgrading"
identifier = "upgrading"
parent = "installation"
weight = 10
+++
# Upgrading Grafana
We recommend everyone to upgrade Grafana often to stay up to date with the latest fixes and enhancements.
In order make this a reality Grafana upgrades are backward compatible and the upgrade process is simple & quick.
Upgrading is generally always safe (between many minor and one major version) and dashboards and graphs will look the same. There can be minor breaking changes in some edge cases which are usually outlined in the [Release Notes](https://community.grafana.com/c/releases) and [Changelog](https://github.com/grafana/grafana/blob/master/CHANGELOG.md)
## Database Backup
Before upgrading it can be a good idea to backup your Grafana database. This will ensure that you can always rollback to your previous version. During startup, Grafana will automatically migrate the database schema (if there are changes or new tables). Sometimes this can cause issues if you later want to downgrade.
#### sqlite
If you use sqlite you only need to make a backup of you `grafana.db` file. This is usually located at `/var/lib/grafana/grafana.db` on unix system.
If you are unsure what database you use and where it is stored check you grafana configuration file. If you
installed grafana to custom location using a binary tar/zip it is usally in `<grafana_install_dir>/data`.
#### mysql
```
backup:
> mysqldump -u root -p[root_password] [grafana] > grafana_backup.sql
restore:
> mysql -u root -p grafana < grafana_backup.sql
```
#### postgres
```
backup:
> pg_dump grafana > grafana_backup
restore:
> psql grafana < grafana_backup
```
### Ubuntu / Debian
If you installed grafana by downloading a debian package (`.deb`) you can just follow the same installation guide
and execute the same `dpkg -i` command but with the new package. It will upgrade your Grafana install.
If you used our APT repository:
```
sudo apt-get update
sudo apt-get install grafana
```
#### Upgrading from binary tar file
If you downloaded the binary tar package you can just download and extract a new package
and overwrite all your existing files. But this might overwrite your config changes. We
recommend you place your config changes in a file named `<grafana_install_dir>/conf/custom.ini`
as this will make upgrades easier without risking losing your config changes.
### Centos / RHEL
If you installed grafana by downloading a rpm package you can just follow the same installation guide
and execute the same `yum install` or `rpm -i` command but with the new package. It will upgrade your Grafana install.
If you used our YUM repository:
```
sudo yum update grafana
```
### Docker
This just an example, details depend on how you configured your grafana container.
```
docker pull grafana
docker stop my-grafana-container
docker rm my-grafana-container
docker run --name=my-grafana-container --restart=always -v /var/lib/grafana:/var/lib/grafana
```
### Windows
If you downloaded the windows binary package you can just download a newer package and extract
to the same location (and overwrite the existing files). This might overwrite your config changes. We
recommend you place your config changes in a file named `<grafana_install_dir>/conf/custom.ini`
as this will make upgrades easier without risking losing your config changes.
## Upgrading form 1.x
[Migrating from 1.x to 2.x]({{< relref "installation/migrating_to2.md" >}})
## Upgrading form 2.x
We are not aware of any issues upgrading directly from 2.x to 4.x but to on the safe side go via 3.x.

View File

@ -15,6 +15,9 @@ Description | Download
------------ | -------------
Latest stable package for Windows | [grafana.4.2.0.windows-x64.zip](https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.2.0.windows-x64.zip)
Read [Upgrading Grafana]({{< relref "installation/upgrading.md" >}}) for tips and guidance on updating an existing
installation.
## Configure
The zip file contains a folder with the current Grafana version. Extract

View File

@ -13,42 +13,28 @@ weight = 2
Annotations provide a way to mark points on the graph with rich events. When you hover over an annotation
you can get title, tags, and text information for the event.
![](/img/docs/v1/annotated_graph1.png)
![](/img/docs/annotations/toggles.png)
To add an annotation query click dashboard settings icon in top menu and select `Annotations` from the
dropdown. This will open the `Annotations` edit view. Click the `Add` tab to add a new annotation query.
## Queries
> Note: Annotations apply to all graphs in a given dashboard, not on a per-panel basis.
Annotatation 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.
## Graphite annotations
![](/img/docs/annotations/new_query.png)
Graphite supports two ways to query annotations.
Specify a name for the annotation query. This name is given to the toggle (checkbox) that will allow
you to enable/disable showing annotation events from this query. For example you might have two
annotation queries named `Deploys` and `Outages`. The toggles will allow you to decide what annotations
to show.
- A regular metric query, use the `Graphite target expression` text input for this
- Graphite events query, use the `Graphite event tags` text input, specify an tag or wildcard (leave empty should also work)
### Annotation query details
## Elasticsearch annotations
![](/img/docs/v2/annotations_es.png)
The annotation query options are different for each data source.
Grafana can query any Elasticsearch index for annotation events. The index name can be the name of an alias or an index wildcard pattern.
You can leave the search query blank or specify a lucene query.
- [Graphite annotation queries]({{< relref "features/datasources/graphite.md#annotations" >}})
- [Elasticsearch annotation queries]({{< relref "features/datasources/elasticsearch.md#annotations" >}})
- [InfluxDB annotation queries]({{< relref "features/datasources/influxdb.md#annotations" >}})
- [Prometheus annotation queries]({{< relref "features/datasources/prometheus.md#annotations" >}})
If your elasticsearch document has a timestamp field other than `@timestamp` you will need to specify that. As well
as the name for the fields that should be used for the annotation title, tags and text. Tags and text are optional.
> **Note** The annotation timestamp field in elasticsearch need to be in UTC format.
## InfluxDB Annotations
![](/img/docs/v2/annotations_influxdb.png)
For InfluxDB you need to enter a query like in the above screenshot. You need to have the ```where $timeFilter``` part.
If you only select one column you will not need to enter anything in the column mapping fields.
## Prometheus Annotations
![](/img/docs/v3/annotations_prom.png)
Prometheus supports two ways to query annotations.
- A regular metric query
- A Prometheus query for pending and firing alerts (for details see [Inspecting alerts during runtime](https://prometheus.io/docs/alerting/rules/#inspecting-alerts-during-runtime))

View File

@ -22,7 +22,7 @@ A dashboard snapshot is an instant way to share an interactive dashboard publicl
(metric, template and annotation) and panel links, leaving only the visible metric data and series names embedded into your dashboard. Dashboard
snapshots can be accessed by anyone who has the link and can reach the URL.
![](/img/docs/v2/dashboard_snapshot_dialog.png)
![](/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
@ -42,8 +42,8 @@ You can embed a panel using an iframe on another web site. This tab will show yo
Example:
```html
<iframe src="http://snapshot.raintank.io/dashboard/solo/snapshot/UtvRYDv650fHOV2jV5QlAQhLnNOhB5ZN?panelId=4&fullscreen&from=1427385145990&to=1427388745990" width="650" height="300" frameborder="0"></iframe>
<iframe src="https://snapshot.raintank.io/dashboard-solo/snapshot/y7zwi2bZ7FcoTlB93WN7yWO4aMiz3pZb?from=1493369923321&to=1493377123321&panelId=4" width="650" height="300" frameborder="0"></iframe>
```
Below there should be an interactive Grafana graph embedded in an iframe:
<iframe src="https://snapshot.raintank.io/dashboard-solo/snapshot/4IKyWYNEQll1B9FXcN3RIgx4M2VGgU8d?panelId=4&fullscreen" width="650" height="300" frameborder="0"></iframe>
<iframe src="https://snapshot.raintank.io/dashboard-solo/snapshot/y7zwi2bZ7FcoTlB93WN7yWO4aMiz3pZb?from=1493369923321&to=1493377123321&panelId=4" width="650" height="300" frameborder="0"></iframe>

View File

@ -10,76 +10,162 @@ weight = 1
# Templating
<img class="no-shadow" src="/img/docs/v2/templating_var_list.png">
Templating allows for more interactive and dynamic dashboards. Instead of hard-coding things like server, application
and sensor name in you metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of
the dashboard. These dropdowns make it easy to change the data being displayed in your dashboard.
Dashboard Templating allows you to make your Dashboards more interactive and dynamic.
<img class="no-shadow" src="/img/docs/v4/templated_dash.png">
Theyre one of the most powerful and most used features of Grafana, and theyve recently gotten even more attention in Grafana 2.0 and Grafana 2.1.
## What is a variable?
You can create Dashboard Template variables that can be used practically anywhere in a Dashboard: data queries on individual Panels (within the Query Editor), the names in your legends, or titles in Panels and Rows.
A variable is a placeholder for a value. You can use variables in metric queries and in panel titles. So when you change
the value, using the dropdown at the top of the dashboard, your panel's metric queries will change to reflect the new value.
You can configure Dashboard Templating by clicking the dropdown cog on the top of the Dashboard while viewing it.
### Interpolation
Panel titles and metric queries can refer to variables using two different syntaxes:
- `$<varname>` Example: apps.frontend.$server.requests.count
- `[[varname]]` Example: apps.frontend.[[server]].requests.count
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 word. Use
the second syntax in expressions like `my.server[[serverNumber]].count`.
Before queries are sent to your data source the query is **interpolated**, meaning the variable is replaced with its current value. During
interpolation the variable value might be **escaped** in order to conform to the syntax of the query language and where it is used.
For example, a variable used in a regex expression in an InfluxDB or Prometheus query will be regex escaped. Read the data source specific
documentation article for details on value escaping during interpolation.
### Variable options
A variable is presented as a dropdown select box at the top of the dashboard. It has a current value and a set of **options**. The **options**
is the set of values you can choose from.
## Adding a variable
<img class="no-shadow" src="/img/docs/v4/templating_var_list.png">
You add variables via Dashboard cogs menu > Templating. This opens up a list of variables and a `New` button to create a new variable.
### Basic variable options
Option | Description
------- | --------
*Name* | The name of the variable, this is the name you use when you refer to your variable in your metric queries. Must be unique and contain no white-spaces.
*Label* | The name of the dropdown for this variable.
*Hide* | Options to hide the dropdown select box.
*Type* | Defines the variable type.
## Variable types
### Variable types
There are three different types of Template variables: query, custom, and interval.
Type | Description
------- | --------
*Query* | This variable type allows you to write a data source query that usually returns a list of metric names, tag values or keys. For example, a query that returns a list of server names, sensor ids or data centers.
*Interval* | This variable can represent time spans. Instead of hard-coding a group by time or date histogram interval, use a variable of this type.
*Datasource* | This type allows you to quickly change the data source for an entire Dashboard. Useful if you have multiple instances of a data source in for example different environments.
*Custom* | Define the variable options manually using a comma separated list.
*Constant* | Define a hidden constant. Useful for metric path prefixes for dashboards you want to share. During dashboard export, constant variables will be made into an import option.
*Ad hoc filters* | Very special kind of variable that only works with some data sources, InfluxDB & Elasticsearch currently. It allows you to add key/value filters that will automatically be added to all metric queries that use the specified data source.
They can all be used to create dynamic variables that you can use throughout the Dashboard, but they differ in how they get the data for their values.
### Query options
This variable type is the most powerful and complex as it can dynamically fetch its options using a data source query.
### Query
Option | Description
------- | --------
*Data source* | The data source target for the query.
*Refresh* | Controls when to update the variable option list (values in the dropdown). **On Dashboard Load** will slow down dashboard load as the variable query needs to be completed before dashboard can be initialized. Set this only to **On Time Range Change** if your variable options query contains a time range filter or is dependent on dashboard time range.
*Query* | The data source specific query expression.
*Regex* | Regex to filter or capture specific parts of the names return by your data source query. Optional.
*Sort* | Define sort order for options in dropdown. **Disabled** means that the order of options returned by your data source query will be used.
> Note: The Query type is Data Source specific. Please consult the appropriate documentation for your particular Data Source.
### Query expressions
Query is the most common type of Template variable. Use the `Query` template type to generate a dynamic list of variables, simply by allowing Grafana to explore your Data Source metric namespace when the Dashboard loads.
The query expressions are different for each data source.
For example a query like `prod.servers.*` will fill the variable with all possible values that exists in that wildcard position (in the case of the Graphite Data Source).
- [Graphite templating queries]({{< relref "features/datasources/graphite.md#templating" >}})
- [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" >}})
You can even create nested variables that use other variables in their definition. For example `apps.$app.servers.*` uses the variable $app in its own query definition.
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.
You can utilize the special ** All ** value to allow the Dashboard user to query for every single Query variable returned. Grafana will automatically translate ** All ** into the appropriate format for your Data Source.
## Selection Options
#### Multi-select
As of Grafana 2.1, it is now possible to select a subset of Query Template variables (previously it was possible to select an individual value or 'All', not multiple values that were less than All). This is accomplished via the Multi-Select option. If enabled, the Dashboard user will be able to enable and disable individual variables.
Option | Description
------- | --------
*Mulit-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.
The Multi-Select functionality is taken a step further with the introduction of Multi-Select Tagging. This functionality allows you to group individual Template variables together under a Tag or Group name.
### Formating multiple values
For example, if you were using Templating to list all 20 of your applications, you could use Multi-Select Tagging to group your applications by function or region or criticality, etc.
Interpolating a variable with multiple values selected is tricky as it is not straight forward how to format the multiple values to into a string that
is valid in the given context where the variable is used. Grafana tries to solve this by allowing each data source plugin to
inform the templating interpolation engine what format to use for multiple values.
> Note: Multi-Select Tagging functionality is currently experimental but is part of Grafana 2.1. To enable this feature click the enable icon when editing Template options for a particular variable.
**Graphite**, for example, uses glob expressions. A variable with multiple values would, in this case, be interpolated as `{host1,host2,host3}` if
the current variable value was *host1*, *host2* and *host3*.
<img class="no-shadow" src="/img/docs/v2/template-tags-config.png">
**InfluxDB and Prometheus** uses regex expressions, so the same variable
would be interpolated as `(host1|host2|host3)`. Every value would also be regex escaped if not, a value with a regex control character would
break the regex expression.
Grafana gets the list of tags and the list of values in each tag by performing two queries on your metric namespace.
**Elasticsearch** uses lucene query syntax, so the same variable would, in this case, be formatted as `("host1" OR "host2" OR "host3")`. In this case every value
needs to be escaped so that the value can contain lucene control words and quotation marks.
The Tags query returns a list of Tags.
#### Formating troubles
The Tag values query returns the values for a given Tag.
Automatic escaping & formatting can cause problems and it can be tricky to grasp the logic is behind it.
Especially for InfluxDB and Prometheus where the use of regex syntax requires that the variable is used in regex operator context.
If you do not want Grafana to do this automatic regex escaping and formatting your only option is to disable the *Multi-value* or *Include All option*
options.
Note: a proof of concept shim that translates the metric query into a SQL call is provided. This allows you to maintain your tag:value mapping independently of your Data Source.
### Value groups/tags
Once configured, Multi-Select Tagging provides a convenient way to group and your template variables, and slice your data in the exact way you want. The Tags can be seen on the right side of the template pull-down.
If you have a lot of options in the dropdown for a multi-value variable. You can use this feature to group the values into selectable tags.
![](/img/docs/v2/multi-select.gif)
Option | Description
------- | --------
*Tags query* | Data source query that should return a list of tags
*Tag values query* | Data source query that should return a list of values for a specified tag key. Use `$tag` in the query to refer the currently selected tag.
### Interval
![](/img/docs/v4/variable_dropdown_tags.png)
Use the `Interval` type to create Template variables around time ranges (eg. `1m`,`1h`, `1d`). There is also a special `auto` option that will change depending on the current time range, you can specify how many times the current time range should be divided to calculate the current `auto` range.
### Interval variables
![](/img/docs/v2/templated_variable_parameter.png)
Use the `Interval` type to create a variable that represents a time span (eg. `1m`,`1h`, `1d`). There is also a special `auto` option that will change depending on the current time range. You can specify how many times the current time range should be divided to calculate the current `auto` timespan.
### Custom
This variable type is useful as a parameter to group by time (for InfluxDB), Date histogram interval (for Elasticsearch) or as a *summarize* function parameter (for Graphite).
Use the `Custom` type to manually create Template variables around explicit values that are hard-coded into the Dashboard, and not dependent on any Data Source. You can specify multiple Custom Template values by separating them with a comma.
## Repeating Panels
## Repeating Panels and Repeating Rows
Template variables can be very useful to dynamically change your queries across a whole dashboard. If you want
Grafana to dynamically create new panels or rows based on what values you have selected you can use the *Repeat* feature.
Template Variables can be very useful to dynamically change what you're visualizing on a given panel. Sometimes, you might want to create entire new Panels (or Rows) based on what Template Variables have been selected. This is now possible in Grafana 2.1.
If you have a variable with `Multi-value` or `Include all value` options enabled you can choose one panel or one row and have Grafana repeat that row
for every selected value. You find this option under the General tab in panel edit mode. Select the variable to repeat by, and a `min span`.
The `min span` controls how small Grafana will make the panels (if you have many values selected). Grafana will automatically adjust the width of
each repeated panel so that the whole row is filled. Currently, you cannot mix other panels on a row with a repeated panel.
Once you've got your Template variables (of any type) configured the way you'd like, check out the Repeating Panels and Repeating Row documentation
Only make changes to the first panel (the original template). To have the changes take effect on all panels you need to trigger a dynamic dashboard re-build.
You can do this by either changing the variable value (that is the basis for the repeat) or reload the dashboard.
## Screencast - Templated Graphite Queries
## Repeating Rows
<iframe width="561" height="315" src="//www.youtube.com/embed/FhNUrueWwOk?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" frameborder="0" allowfullscreen></iframe>
This option requires you to open the row options view. Hover over the row left side to trigger the row menu, in this menu click `Row Options`. This
opens the row options view. Here you find a *Repeat* dropdown where you can select the variable to repeat by.
### URL state
Variable values are always synced to the URL using the syntax `var-<varname>=value`.
### Examples
- [Graphite Templated Dashboard](http://play.grafana.org/dashboard/db/graphite-templated-nested)
- [Elasticsearch Templated Dashboard](http://play.grafana.org/dashboard/db/elasticsearch-templated)
- [InfluxDB Templated Dashboard](http://play.grafana.org/dashboard/db/influxdb-templated-queries)

View File

@ -9,58 +9,116 @@ weight = 10
# Screencasts
{{< screencast src="https://www.youtube.com/embed/sKNZMtoSHN4?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}}
### Episode 7 - Beginners guide to building dashboards
For newer users of Grafana, this screencast will familiarize you with the general UI and teach you how to build your first Dashboard.
<div class="clearfix"></div>
{{< screencast src="https://www.youtube.com/embed/9ZCMVNxUf6s?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}}
### Episode 6 - Adding data sources, users & organizations
Now that Grafana has been installed, learn about adding data sources and get a closer look at adding and managing Users and Organizations.
<div class="clearfix"></div>
{{< screencast src="https://www.youtube.com/embed/E-gMFv85FE8?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}}
### Episode 5 - Installation & Configuration on Red Hat / CentOS
This screencasts shows how to get Grafana 2.0 installed and configured quickly on RPM-based Linux operating systems.
<div class="clearfix"></div>
{{< screencast src="https://www.youtube.com/embed/JY22EBOR9hQ?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}}
### Episode 4 - Installation & Configuration on Ubuntu / Debian
Learn how to easily install the dependencies and packages to get Grafana 2.0 up and running on Ubuntu or Debian in just a few minutes.
<div class="clearfix"></div>
{{< screencast src="https://www.youtube.com/embed/FC13uhFRsVw?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}}
### Episode 3 - Whats New In Grafana 2.0
This screencast highlights many of the great new features that were included in the Grafana 2.0 release.
<div class="clearfix"></div>
{{< screencast src="//www.youtube.com/embed/FhNUrueWwOk?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}}
### Episode 2 - Templated Graphite Queries
The screencast focuses on Templating with the Graphite Data Source. Learn how to make dynamic and adaptable Dashboards for your Graphite metrics.
<div class="clearfix"></div>
{{< screencast src="//www.youtube.com/embed/mgcJPREl3CU?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}}
### Episode 1 - Building Graphite Queries
Learn how the Graphite Query Editor works, and how to use different graphing functions. There's also an introduction to graph display settings.
<div class="clearfix"></div>
<div class="video-card-container">
<figure class="video-card">
<a href="https://youtu.be/iUj6DwfBh88?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
<img src="/img/docs/v4/screencast_generic.png">
<i class="fa fa-play"></i>
</a>
<figcaption>
<a href="https://youtu.be/iUj6DwfBh88?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
#10 Dashboard Discovery & Sharing
</a>
</figcaption>
</figure>
<figure class="video-card">
<a href="https://youtu.be/d6KicssNzxM?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
<img src="/img/docs/v4/screencast_generic.png">
<i class="fa fa-play"></i>
</a>
<figcaption>
<a href="https://youtu.be/d6KicssNzxM?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
#9 Using Elasticsearch in Grafana
</a>
</figcaption>
</figure>
<figure class="video-card">
<a href="https://youtu.be/1kJyQKgk_oY?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
<img src="/img/docs/v4/screencast_generic.png">
<i class="fa fa-play"></i>
</a>
<figcaption>
<a href="https://youtu.be/1kJyQKgk_oY?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
#8 What's new in Grafana 3.0
</a>
</figcaption>
</figure>
<figure class="video-card">
<a href="https://youtu.be/sKNZMtoSHN4?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
<img src="/img/docs/v4/screencast_generic.png">
<i class="fa fa-play"></i>
</a>
<figcaption>
<a href="https://youtu.be/sKNZMtoSHN4?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
#7 Beginners guide to building dashboards
</a>
</figcaption>
</figure>
<figure class="video-card">
<a href="https://youtu.be/9ZCMVNxUf6s?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
<img src="/img/docs/v4/screencast_generic.png">
<i class="fa fa-play"></i>
</a>
<figcaption>
<a href="https://youtu.be/9ZCMVNxUf6s?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
#6 Adding data sources, users & orgs.
</a>
</figcaption>
</figure>
<figure class="video-card">
<a href="https://youtu.be/E-gMFv84FE8?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
<img src="/img/docs/v4/screencast_generic.png">
<i class="fa fa-play"></i>
</a>
<figcaption>
<a href="https://youtu.be/E-gMFv84FE8?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
#5 Install & Setup on Redhat / Centos
</a>
</figcaption>
</figure>
<figure class="video-card">
<a href="https://youtu.be/JY22EBOR9hQ?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
<img src="/img/docs/v4/screencast_generic.png">
<i class="fa fa-play"></i>
</a>
<figcaption>
<a href="https://youtu.be/JY22EBOR9hQ?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
#4 Install & Setup on Ubuntu / Debian
</a>
</figcaption>
</figure>
<figure class="video-card">
<a href="https://youtu.be/FC13uhFRsVw?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
<img src="/img/docs/v4/screencast_generic.png">
<i class="fa fa-play"></i>
</a>
<figcaption>
<a href="https://youtu.be/FC13uhFRsVw?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
#3 Whats New In Grafana 2.0
</a>
</figcaption>
</figure>
<figure class="video-card">
<a href="https://youtu.be/FhNUrueWwOk?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
<img src="/img/docs/v4/screencast_generic.png">
<i class="fa fa-play"></i>
</a>
<figcaption>
<a href="https://youtu.be/FhNUrueWwOk?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
#2 Templated Graphite Queries
</a>
</figcaption>
</figure>
<figure class="video-card">
<a href="https://youtu.be/mgcJPREl3CU?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
<img src="/img/docs/v4/screencast_generic.png">
<i class="fa fa-play"></i>
</a>
<figcaption>
<a href="https://youtu.be/mgcJPREl3CU?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" target="_blank" rel="noopener noreferrer">
#1 Building Graphite Queries
</a>
</figcaption>
</figure>
</div>

View File

@ -166,10 +166,12 @@ func getPanelSort(id string) int {
sort = 3
case "text":
sort = 4
case "alertlist":
case "heatmap":
sort = 5
case "dashlist":
case "alertlist":
sort = 6
case "dashlist":
sort = 7
}
return sort
}

View File

@ -78,5 +78,5 @@ func (u *S3Uploader) Upload(imageDiskPath string) (string, error) {
return "", err
}
return "https://" + u.bucket + ".s3.amazonaws.com/" + key, nil
return "https://" + u.bucket + ".s3-" + u.region + ".amazonaws.com/" + key, nil
}

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"github.com/grafana/grafana/pkg/models"
@ -76,9 +77,11 @@ func (s *GenericOAuth) IsOrganizationMember(client *http.Client) bool {
func (s *GenericOAuth) FetchPrivateEmail(client *http.Client) (string, error) {
type Record struct {
Email string `json:"email"`
Primary bool `json:"primary"`
Verified bool `json:"verified"`
Email string `json:"email"`
Primary bool `json:"primary"`
IsPrimary bool `json:"is_primary"`
Verified bool `json:"verified"`
IsConfirmed bool `json:"is_confirmed"`
}
emailsUrl := fmt.Sprintf(s.apiUrl + "/emails")
@ -91,14 +94,30 @@ func (s *GenericOAuth) FetchPrivateEmail(client *http.Client) (string, error) {
var records []Record
if err = json.NewDecoder(r.Body).Decode(&records); err != nil {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return "", err
}
err = json.Unmarshal(body, records)
if err != nil {
var data struct {
Values []Record `json:"values"`
}
err = json.Unmarshal(body, &data)
if err != nil {
return "", err
}
records = data.Values
}
var email = ""
for _, record := range records {
if record.Primary {
if record.Primary || record.IsPrimary {
email = record.Email
break
}
}
@ -161,11 +180,12 @@ func (s *GenericOAuth) FetchOrganizations(client *http.Client) ([]string, error)
func (s *GenericOAuth) UserInfo(client *http.Client) (*BasicUserInfo, error) {
var data struct {
Name string `json:"name"`
Login string `json:"login"`
Username string `json:"username"`
Email string `json:"email"`
Attributes map[string][]string `json:"attributes"`
Name string `json:"name"`
DisplayName string `json:"display_name"`
Login string `json:"login"`
Username string `json:"username"`
Email string `json:"email"`
Attributes map[string][]string `json:"attributes"`
}
var err error
@ -197,6 +217,10 @@ func (s *GenericOAuth) UserInfo(client *http.Client) (*BasicUserInfo, error) {
}
}
if userInfo.Name == "" && data.DisplayName != "" {
userInfo.Name = data.DisplayName
}
if userInfo.Login == "" && data.Username != "" {
userInfo.Login = data.Username
}

View File

@ -13,6 +13,7 @@ function (angular, _, coreModule) {
if (options === '*' || options.value === '*') {
this.value = '*';
this.html = $sce.trustAsHtml('<i class="fa fa-asterisk"><i>');
this.type = options.type;
this.expandable = true;
return;
}

View File

@ -18,6 +18,12 @@
<li class="gf-tabs-item" ng-show="ctrl.mode === 'new'">
<span class="active gf-tabs-link">New Query</span>
</li>
<li class="gf-tabs-item" >
<a class="gf-tabs-link" ng-click="ctrl.mode = 'help';" ng-class="{active: ctrl.mode === 'help'}">
Help
</a>
</li>
</ul>
<button class="tabbed-view-close-btn" ng-click="dismiss();">
@ -26,9 +32,24 @@
</div>
<div class="tabbed-view-body">
<div ng-show="ctrl.mode === 'help'">
<div class="grafana-info-box col-lg-8">
<h5>What are Annotations?</h5>
<p>
Annotations provide a way to integrate event data into your graphs. They are visualized as vertical lines and icons
on all graph panels. When you hover over an annotation icon you can get title, tags, and text information for the event.
In the <i>Queries</i> tab you can add queries that return annotation events.
<br>
<br>
Checkout the <a class="external-link" target="_blank" href="http://docs.grafana.org/reference/annotations/">Annotations documentation</a> for more information.
</p>
</div>
</div>
<div class="editor-row row" ng-if="ctrl.mode === 'list'">
<div ng-if="ctrl.annotations.length === 0">
<em>No annotations defined</em>
<em>No annotation queries defined</em>
</div>
<table class="grafana-options-table">
<tr ng-repeat="annotation in ctrl.annotations">

View File

@ -9,10 +9,6 @@
<i class="fa fa-random"></i>
Switch theme
</a>
<a class="btn btn-inverse" ng-click="ctrl.switchTheme()">
<i class="fa fa-refresh"></i>
Reload
</a>
<div class="page-header-tabs">
<ul class="gf-tabs">
@ -43,6 +39,19 @@
</div>
</div>
<div class="tab-pane style-guide-icon-list" ng-if="ctrl.page.icons">
<div class="row">
<div ng-repeat="icon in ctrl.icons" class="col-md-2 col-sm-3 col-xs-4">
<i class="icon-gf icon-gf-{{icon}}" bs-tooltip="'icon-gf icon-gf-{{icon}}'"></i>
</div>
</div>
</div>
<div class="tab-pane style-guide-plugin-authoring" ng-if="ctrl.page.plugins">
<p>From grafana 3.0 it's very easy to develop your own plugins and share them with other grafana users.</p>
<p>More information about plugin development can be found at <a href="http://docs.grafana.org/plugins/developing/development/" target="_blank">docs.grafana.org</a></p>
</div>
<div class="tab-pane" ng-if="ctrl.page.forms">
forms
</div>

View File

@ -9,11 +9,12 @@ class StyleGuideCtrl {
buttonNames = ['primary', 'secondary', 'inverse', 'success', 'warning', 'danger'];
buttonSizes = ['btn-small', '', 'btn-large'];
buttonVariants = ['-', '-outline-'];
icons: any = [];
page: any;
pages = ['colors', 'buttons'];
pages = ['colors', 'buttons', 'icons', 'plugins'];
/** @ngInject **/
constructor(private $http, private $routeParams, private $location) {
constructor(private $http, private $routeParams, private $location, private backendSrv) {
this.theme = config.bootData.user.lightTheme ? 'light': 'dark';
this.page = {};
@ -26,6 +27,10 @@ class StyleGuideCtrl {
if (this.page.colors) {
this.loadColors();
}
if (this.page.icons) {
this.loadIcons();
}
}
loadColors() {
@ -36,10 +41,20 @@ class StyleGuideCtrl {
});
}
loadIcons() {
this.$http.get('public/sass/icons.json').then(res => {
this.icons = res.data;
});
}
switchTheme() {
this.$routeParams.theme = this.theme === 'dark' ? 'light' : 'dark';
this.$location.search(this.$routeParams);
setTimeout(() => {
var cmd = {
theme: this.$routeParams.theme
};
this.backendSrv.put('/api/user/preferences', cmd).then(() => {
window.location.href = window.location.href;
});
}

View File

@ -17,6 +17,11 @@
</li>
<li class="gf-tabs-item" ng-show="mode === 'new'">
<span class="active gf-tabs-link">New</span>
</li>
<li class="gf-tabs-item" >
<a class="gf-tabs-link" ng-click="mode = 'help';" ng-class="{active: mode === 'help'}">
Help
</a>
</li>
</ul>
@ -30,7 +35,8 @@
<div ng-if="mode === 'list'">
<div ng-if="variables.length === 0">
<em>No template variables defined</em>
</div>
<br /> <br />
</div>
<table class="grafana-options-table">
<tr ng-repeat="variable in variables">
<td style="width: 1%">
@ -64,6 +70,20 @@
</table>
</div>
<div ng-show="mode === 'help'">
<div class="grafana-info-box col-lg-8">
<h5>What does templating do?</h5>
<p>Templating allows for more interactive and dynamic dashboards. Instead of hard-coding things like server, application
and sensor name in you metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of
the dashboard. These dropdowns make it easy to change the data being displayed in your dashboard.
<br>
<br>
Checkout the <a class="external-link" target="_blank" href="http://docs.grafana.org/reference/templating/">Templating documentation</a> for more information.
</p>
</div>
</div>
<div class="gf-form" ng-show="mode === 'list'">
<div class="gf-form-button-row">
<a type="button" class="btn gf-form-button btn-success" ng-click="mode = 'new';"><i class="fa fa-plus" ></i>&nbsp;&nbsp;New</a>

View File

@ -17,3 +17,4 @@
</rebuild-on-change>
</div>
<div class="clearfix"></div>

View File

@ -15,14 +15,14 @@
</div>
<div class="gf-form" ng-show='ctrl.current.jsonData.authType == "keys"'>
<label class="gf-form-label width-13">Access key </label>
<label class="gf-form-label width-13">Access key ID </label>
<label class="gf-form-label width-13" ng-show="ctrl.accessKeyExist">Configured</label>
<a class="btn btn-secondary gf-form-btn" type="submit" ng-click="ctrl.resetAccessKey()" ng-show="ctrl.accessKeyExist">Reset</a>
<input type="text" class="gf-form-input max-width-18" ng-hide="ctrl.accessKeyExist" ng-model='ctrl.current.secureJsonData.accessKey'></input>
</div>
<div class="gf-form" ng-show='ctrl.current.jsonData.authType == "keys"'>
<label class="gf-form-label width-13">Secret key</label>
<label class="gf-form-label width-13">Secret access key</label>
<label class="gf-form-label width-13" ng-show="ctrl.secretKeyExist">Configured</label>
<a class="btn btn-secondary gf-form-btn" type="submit" ng-click="ctrl.resetSecretKey()" ng-show="ctrl.secretKeyExist">Reset</a>
<input type="text" class="gf-form-input max-width-18" ng-hide="ctrl.secretKeyExist" ng-model='ctrl.current.secureJsonData.secretKey'></input>

View File

@ -13,9 +13,10 @@
ng-model-onblur ng-change="ctrl.refreshMetricData()">
</input>
</div>
<div class="gf-form">
<label class="gf-form-label">Min step</label>
<input type="text" class="gf-form-input max-width-5" ng-model="ctrl.target.interval"
<label class="gf-form-label width-6">Min step</label>
<input type="text" class="gf-form-input width-8" ng-model="ctrl.target.interval"
data-placement="right"
spellcheck='false'
placeholder="{{ctrl.panelCtrl.interval}}"
@ -26,6 +27,7 @@
Leave blank for auto handling based on time range and panel width
</info-popover>
</div>
<div class="gf-form">
<label class="gf-form-label">Resolution</label>
<div class="gf-form-select-wrapper max-width-15">
@ -36,14 +38,20 @@
</div>
</div>
<div class="gf-form max-width-22">
<label class="gf-form-label">Metric lookup</label>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<div class="gf-form-inline">
<div class="gf-form max-width-26">
<label class="gf-form-label width-8">Metric lookup</label>
<input type="text" class="gf-form-input" ng-model="ctrl.target.metric" spellcheck='false' bs-typeahead="ctrl.suggestMetrics" placeholder="metric name" data-min-length=0 data-items=100>
</div>
<div class="gf-form">
<label class="gf-form-label">Format as</label>
<div class="gf-form-select-wrapper">
<label class="gf-form-label width-6">Format as</label>
<div class="gf-form-select-wrapper width-8">
<select class="gf-form-input gf-size-auto" ng-model="ctrl.target.format" ng-options="f.value as f.text for f in ctrl.formats" ng-change="ctrl.refresh()"></select>
</div>
<label class="gf-form-label">

View File

@ -1,33 +1,75 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="100px" height="100px" viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="32.3342" y1="95.7019" x2="32.3342" y2="5.2695">
<stop offset="0" style="stop-color:#FFDE17"/>
<stop offset="0.0803" style="stop-color:#FFD210"/>
<stop offset="0.1774" style="stop-color:#FEC90D"/>
<stop offset="0.2809" style="stop-color:#FDC70C"/>
<stop offset="0.6685" style="stop-color:#F3903F"/>
<stop offset="0.8876" style="stop-color:#ED683C"/>
<stop offset="1" style="stop-color:#E93E3A"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M48.173,57.757V39.825c0-1.302,1.055-2.357,2.357-2.357h9.691
c0.897,0,1.346-1.084,0.712-1.718L34.112,0.737c-0.982-0.982-2.574-0.982-3.556,0L3.735,35.75
c-0.634,0.634-0.185,1.718,0.712,1.718h9.691c1.302,0,2.357,1.055,2.357,2.357v17.932c0,0.958,0.776,1.734,1.734,1.734h28.21
C47.397,59.491,48.173,58.715,48.173,57.757z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="67.6658" y1="94.1706" x2="67.6658" y2="3.7383">
<stop offset="0" style="stop-color:#FFDE17"/>
<stop offset="0.0803" style="stop-color:#FFD210"/>
<stop offset="0.1774" style="stop-color:#FEC90D"/>
<stop offset="0.2809" style="stop-color:#FDC70C"/>
<stop offset="0.6685" style="stop-color:#F3903F"/>
<stop offset="0.8876" style="stop-color:#ED683C"/>
<stop offset="1" style="stop-color:#E93E3A"/>
</linearGradient>
<path style="fill:url(#SVGID_2_);" d="M95.553,62.532h-9.691c-1.302,0-2.357-1.055-2.357-2.357V42.243
c0-0.958-0.776-1.734-1.734-1.734h-28.21c-0.958,0-1.734,0.776-1.734,1.734v17.932c0,1.302-1.055,2.357-2.357,2.357h-9.691
c-0.897,0-1.346,1.084-0.712,1.718l26.821,35.013c0.982,0.982,2.574,0.982,3.556,0L96.265,64.25
C96.898,63.616,96.45,62.532,95.553,62.532z"/>
<path fill="#1F1F1F" d="M18.2,4.2c-1.5,0-2.9,0.6-3.9,1.6l-0.5,0.5l-0.5-0.5c-1-1.1-2.4-1.6-3.9-1.6S6.6,4.8,5.5,5.8
c-1,1-1.6,2.4-1.6,3.9s0.6,2.9,1.6,3.9l8.3,8.3l8.3-8.3c1-1,1.6-2.4,1.6-3.9s-0.6-2.9-1.6-3.9C21.1,4.8,19.7,4.2,18.2,4.2z
M21,12.5l-7.2,7.2l-7.1-7.1c-0.7-0.7-1.1-1.7-1.1-2.8c0-1,0.4-2,1.1-2.8c0.7-0.7,1.7-1.1,2.8-1.1c1,0,2,0.4,2.8,1.1l0.5,0.5
l0.6,0.6l0.6,0.6l0.6-0.6L15,7.5L15.5,7c0.7-0.7,1.7-1.1,2.8-1.1c1,0,2,0.4,2.8,1.1c0.7,0.7,1.1,1.7,1.1,2.8
C22.1,10.8,21.7,11.8,21,12.5z"/>
<path fill="#1F1F1F" d="M18.2,77.3c-1.5,0-2.9,0.6-3.9,1.6l-0.5,0.5L13.4,79c-1-1.1-2.4-1.6-3.9-1.6S6.6,77.9,5.5,79
c-1,1-1.6,2.4-1.6,3.9s0.6,2.9,1.6,3.9l8.3,8.3l8.3-8.3c1-1,1.6-2.4,1.6-3.9S23.2,80,22.1,79C21.1,77.9,19.7,77.3,18.2,77.3z
M21,85.6l-7.2,7.2l-7.1-7.1c-0.7-0.7-1.1-1.7-1.1-2.8c0-1,0.4-2,1.1-2.8C7.4,79.4,8.4,79,9.4,79c1,0,2,0.4,2.8,1.1l0.5,0.5
l0.6,0.6l0.6,0.6l0.6-0.6l0.6-0.6l0.5-0.5c0.7-0.7,1.7-1.1,2.8-1.1c1,0,2,0.4,2.8,1.1c0.7,0.7,1.1,1.7,1.1,2.8
C22.1,83.9,21.7,84.9,21,85.6z"/>
<path fill="#1F1F1F" d="M0,0v100h100V0H0z M22.7,87.4l-8.9,8.9l-8.9-8.9C3.7,86.2,3,84.6,3,82.9s0.7-3.3,1.9-4.5
c1.2-1.2,2.8-1.9,4.5-1.9c1.6,0,3.2,0.6,4.4,1.7c1.2-1.1,2.7-1.7,4.4-1.7c1.7,0,3.3,0.7,4.5,1.9c1.2,1.2,1.9,2.8,1.9,4.5
S23.9,86.2,22.7,87.4z M22.7,63l-8.9,8.9L4.9,63C3.7,61.8,3,60.2,3,58.5c0-1.7,0.7-3.3,1.9-4.5c1.2-1.2,2.8-1.9,4.5-1.9
c1.1,0,2.1,0.3,3,0.7l0,0.1l0,0l-1.3,6.6l0,0l0,0.1l2.3-0.1l-0.6,6.1l0-0.1l0,0l3.4-8.3l-2,0.3l1.2-3.7l0-0.1l0,0l0.3-1.1
c0.8-0.3,1.6-0.5,2.4-0.5c1.7,0,3.3,0.7,4.5,1.9c1.2,1.2,1.9,2.8,1.9,4.5C24.6,60.2,23.9,61.8,22.7,63z M22.7,38.7l-8.9,8.9
l-8.9-8.9C3.7,37.5,3,35.9,3,34.1s0.7-3.3,1.9-4.5c1.2-1.2,2.8-1.9,4.5-1.9c1.1,0,2.1,0.3,3,0.7l0,0.1l0,0l-1.3,6.6l0,0l0,0.1
l2.3-0.1l-0.6,6.1l0-0.1l0,0l3.4-8.3l-2,0.3l1.2-3.7l0-0.1l0,0l0.3-1.1c0.8-0.3,1.6-0.5,2.4-0.5c1.7,0,3.3,0.7,4.5,1.9
c1.2,1.2,1.9,2.8,1.9,4.5S23.9,37.5,22.7,38.7z M22.7,14.3l-8.9,8.9l-8.9-8.9C3.7,13.1,3,11.5,3,9.8s0.7-3.3,1.9-4.5
c1.2-1.2,2.8-1.9,4.5-1.9c1.6,0,3.2,0.6,4.4,1.7C15,4,16.6,3.4,18.2,3.4c1.7,0,3.3,0.7,4.5,1.9c1.2,1.2,1.9,2.8,1.9,4.5
S23.9,13.1,22.7,14.3z M96.6,94.4c0,1-0.8,1.8-1.8,1.8H33.4c-1,0-1.8-0.8-1.8-1.8V78.6c0-1,0.8-1.8,1.8-1.8h61.4
c1,0,1.8,0.8,1.8,1.8V94.4z M96.6,69.9c0,1-0.8,1.8-1.8,1.8H33.4c-1,0-1.8-0.8-1.8-1.8V54.1c0-1,0.8-1.8,1.8-1.8h61.4
c1,0,1.8,0.8,1.8,1.8V69.9z M96.6,45.4c0,1-0.8,1.8-1.8,1.8H33.4c-1,0-1.8-0.8-1.8-1.8V29.6c0-1,0.8-1.8,1.8-1.8h61.4
c1,0,1.8,0.8,1.8,1.8V45.4z M96.6,20.9c0,1-0.8,1.8-1.8,1.8H33.4c-1,0-1.8-0.8-1.8-1.8V5.1c0-1,0.8-1.8,1.8-1.8h61.4
c1,0,1.8,0.8,1.8,1.8V20.9z"/>
<path fill="#1F1F1F" d="M18.2,53c-0.5,0-1,0.1-1.4,0.2l-0.7,2.1c0.6-0.4,1.3-0.6,2.1-0.6c1,0,2,0.4,2.8,1.1
c0.7,0.7,1.1,1.7,1.1,2.8c0,1-0.4,2-1.1,2.8l-7.2,7.2l-7.1-7.1c-0.7-0.7-1.1-1.7-1.1-2.8c0-1,0.4-2,1.1-2.8
c0.7-0.7,1.7-1.1,2.8-1.1c0.5,0,1,0.1,1.5,0.3l0.3-1.6c-0.6-0.2-1.2-0.3-1.8-0.3c-1.5,0-2.9,0.6-3.9,1.6c-1,1-1.6,2.4-1.6,3.9
c0,1.5,0.6,2.9,1.6,3.9l8.3,8.3l8.3-8.3c1-1,1.6-2.4,1.6-3.9c0-1.5-0.6-2.9-1.6-3.9C21.1,53.5,19.7,53,18.2,53z"/>
<path fill="#1F1F1F" d="M18.2,28.6c-0.5,0-1,0.1-1.4,0.2l-0.7,2.1c0.6-0.4,1.3-0.6,2.1-0.6c1,0,2,0.4,2.8,1.1
c0.7,0.7,1.1,1.7,1.1,2.8c0,1-0.4,2-1.1,2.8l-7.2,7.2l-7.1-7.1c-0.7-0.7-1.1-1.7-1.1-2.8c0-1,0.4-2,1.1-2.8
c0.7-0.7,1.7-1.1,2.8-1.1c0.5,0,1,0.1,1.5,0.3l0.3-1.6c-0.6-0.2-1.2-0.3-1.8-0.3c-1.5,0-2.9,0.6-3.9,1.6c-1,1-1.6,2.4-1.6,3.9
s0.6,2.9,1.6,3.9l8.3,8.3l8.3-8.3c1-1,1.6-2.4,1.6-3.9s-0.6-2.9-1.6-3.9C21.1,29.2,19.7,28.6,18.2,28.6z"/>
<path fill="#898989" d="M94.7,3.3H33.4c-1,0-1.8,0.8-1.8,1.8v15.8c0,1,0.8,1.8,1.8,1.8h61.4c1,0,1.8-0.8,1.8-1.8V5.1
C96.6,4.1,95.7,3.3,94.7,3.3z"/>
<path fill="#898989" d="M94.7,27.8H33.4c-1,0-1.8,0.8-1.8,1.8v15.8c0,1,0.8,1.8,1.8,1.8h61.4c1,0,1.8-0.8,1.8-1.8V29.6
C96.6,28.6,95.7,27.8,94.7,27.8z"/>
<path fill="#898989" d="M94.7,52.3H33.4c-1,0-1.8,0.8-1.8,1.8v15.8c0,1,0.8,1.8,1.8,1.8h61.4c1,0,1.8-0.8,1.8-1.8V54.1
C96.6,53.1,95.7,52.3,94.7,52.3z"/>
<path fill="#898989" d="M94.7,76.8H33.4c-1,0-1.8,0.8-1.8,1.8v15.8c0,1,0.8,1.8,1.8,1.8h61.4c1,0,1.8-0.8,1.8-1.8V78.6
C96.6,77.6,95.7,76.8,94.7,76.8z"/>
<path fill="#04A64D" d="M18.2,3.4c-1.6,0-3.2,0.6-4.4,1.7C12.6,4,11.1,3.4,9.4,3.4c-1.7,0-3.3,0.7-4.5,1.9C3.7,6.5,3,8.1,3,9.8
s0.7,3.3,1.9,4.5l8.9,8.9l8.9-8.9c1.2-1.2,1.9-2.8,1.9-4.5s-0.7-3.3-1.9-4.5C21.5,4.1,19.9,3.4,18.2,3.4z M22.1,13.7L13.8,22
l-8.3-8.3c-1-1-1.6-2.4-1.6-3.9s0.6-2.9,1.6-3.9c1-1,2.4-1.6,3.9-1.6s2.9,0.6,3.9,1.6l0.5,0.5l0.5-0.5c1-1,2.4-1.6,3.9-1.6
c1.5,0,2.9,0.6,3.9,1.6c1,1,1.6,2.4,1.6,3.9S23.2,12.7,22.1,13.7z"/>
<path fill="#04A64D" d="M18.2,5.9c-1,0-2,0.4-2.8,1.1L15,7.5l-0.6,0.6l-0.6,0.6l-0.6-0.6l-0.6-0.6L12.2,7c-0.7-0.7-1.7-1.1-2.8-1.1
c-1,0-2,0.4-2.8,1.1C5.9,7.8,5.5,8.7,5.5,9.8c0,1,0.4,2,1.1,2.8l7.1,7.1l7.2-7.2c0.7-0.7,1.1-1.7,1.1-2.8c0-1-0.4-2-1.1-2.8
C20.2,6.3,19.3,5.9,18.2,5.9z"/>
<path fill="#04A64D" d="M18.2,76.5c-1.6,0-3.2,0.6-4.4,1.7c-1.2-1.1-2.7-1.7-4.4-1.7c-1.7,0-3.3,0.7-4.5,1.9
C3.7,79.6,3,81.2,3,82.9s0.7,3.3,1.9,4.5l8.9,8.9l8.9-8.9c1.2-1.2,1.9-2.8,1.9-4.5s-0.7-3.3-1.9-4.5C21.5,77.2,19.9,76.5,18.2,76.5
z M22.1,86.8l-8.3,8.3l-8.3-8.3c-1-1-1.6-2.4-1.6-3.9S4.5,80,5.5,79c1-1,2.4-1.6,3.9-1.6s2.9,0.6,3.9,1.6l0.5,0.5l0.5-0.5
c1-1,2.4-1.6,3.9-1.6c1.5,0,2.9,0.6,3.9,1.6c1,1,1.6,2.4,1.6,3.9S23.2,85.8,22.1,86.8z"/>
<path fill="#04A64D" d="M18.2,79c-1,0-2,0.4-2.8,1.1L15,80.6l-0.6,0.6l-0.6,0.6l-0.6-0.6l-0.6-0.6l-0.5-0.5
c-0.7-0.7-1.7-1.1-2.8-1.1c-1,0-2,0.4-2.8,1.1c-0.7,0.7-1.1,1.7-1.1,2.8c0,1,0.4,2,1.1,2.8l7.1,7.1l7.2-7.2
c0.7-0.7,1.1-1.7,1.1-2.8c0-1-0.4-2-1.1-2.8C20.2,79.4,19.3,79,18.2,79z"/>
<path fill="#EB242A" d="M18.2,27.8c-0.8,0-1.7,0.2-2.4,0.5l-0.3,1.1l0,0l0,0.1l-1.2,3.7l2-0.3l-3.4,8.3l0,0l0,0.1l0.6-6.1l-2.3,0.1
l0-0.1l0,0l1.3-6.6l0,0l0-0.1c-0.9-0.5-1.9-0.7-3-0.7c-1.7,0-3.3,0.7-4.5,1.9C3.7,30.8,3,32.4,3,34.1s0.7,3.3,1.9,4.5l8.9,8.9
l8.9-8.9c1.2-1.2,1.9-2.8,1.9-4.5s-0.7-3.3-1.9-4.5C21.5,28.4,19.9,27.8,18.2,27.8z M22.1,38.1l-8.3,8.3l-8.3-8.3
c-1-1-1.6-2.4-1.6-3.9s0.6-2.9,1.6-3.9c1-1,2.4-1.6,3.9-1.6c0.6,0,1.2,0.1,1.8,0.3l-0.3,1.6c-0.5-0.2-1-0.3-1.5-0.3
c-1,0-2,0.4-2.8,1.1c-0.7,0.7-1.1,1.7-1.1,2.8c0,1,0.4,2,1.1,2.8l7.1,7.1l7.2-7.2c0.7-0.7,1.1-1.7,1.1-2.8c0-1-0.4-2-1.1-2.8
c-0.7-0.7-1.7-1.1-2.8-1.1c-0.8,0-1.5,0.2-2.1,0.6l0.7-2.1c0.5-0.1,0.9-0.2,1.4-0.2c1.5,0,2.9,0.6,3.9,1.6c1,1,1.6,2.4,1.6,3.9
S23.2,37,22.1,38.1z"/>
<path fill="#EB242A" d="M18.2,52.1c-0.8,0-1.7,0.2-2.4,0.5l-0.3,1.1l0,0l0,0.1l-1.2,3.7l2-0.3l-3.4,8.3l0,0l0,0.1l0.6-6.1l-2.3,0.1
l0-0.1l0,0l1.3-6.6l0,0l0-0.1c-0.9-0.5-1.9-0.7-3-0.7c-1.7,0-3.3,0.7-4.5,1.9C3.7,55.2,3,56.8,3,58.5c0,1.7,0.7,3.3,1.9,4.5
l8.9,8.9l8.9-8.9c1.2-1.2,1.9-2.8,1.9-4.5c0-1.7-0.7-3.3-1.9-4.5C21.5,52.8,19.9,52.1,18.2,52.1z M22.1,62.4l-8.3,8.3l-8.3-8.3
c-1-1-1.6-2.4-1.6-3.9c0-1.5,0.6-2.9,1.6-3.9c1-1,2.4-1.6,3.9-1.6c0.6,0,1.2,0.1,1.8,0.3l-0.3,1.6c-0.5-0.2-1-0.3-1.5-0.3
c-1,0-2,0.4-2.8,1.1c-0.7,0.7-1.1,1.7-1.1,2.8c0,1,0.4,2,1.1,2.8l7.1,7.1l7.2-7.2c0.7-0.7,1.1-1.7,1.1-2.8c0-1-0.4-2-1.1-2.8
c-0.7-0.7-1.7-1.1-2.8-1.1c-0.8,0-1.5,0.2-2.1,0.6l0.7-2.1c0.5-0.1,0.9-0.2,1.4-0.2c1.5,0,2.9,0.6,3.9,1.6c1,1,1.6,2.4,1.6,3.9
C23.8,60,23.2,61.4,22.1,62.4z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -10,11 +10,10 @@ export class AxesEditorCtrl {
dataFormats: any;
/** @ngInject */
constructor($scope) {
constructor($scope, uiSegmentSrv) {
$scope.editor = this;
this.panelCtrl = $scope.ctrl;
this.panel = this.panelCtrl.panel;
this.unitFormats = kbn.getUnitFormats();
this.logScales = {
@ -27,7 +26,7 @@ export class AxesEditorCtrl {
this.dataFormats = {
'Time series': 'timeseries',
'Time series Pre-bucketed': 'tsbuckets'
'Time series buckets': 'tsbuckets'
};
}

View File

@ -25,15 +25,10 @@ let panelDefaults = {
colorScale: 'sqrt',
exponent: 0.5,
colorScheme: 'interpolateOranges',
fillBackground: false
},
dataFormat: 'timeseries',
xBucketSize: null,
xBucketNumber: null,
yBucketSize: null,
yBucketNumber: null,
xAxis: {
show: true
show: true,
},
yAxis: {
show: true,
@ -45,6 +40,10 @@ let panelDefaults = {
max: null,
removeZeroValues: false
},
xBucketSize: null,
xBucketNumber: null,
yBucketSize: null,
yBucketNumber: null,
tooltip: {
show: true,
seriesStat: false,

View File

@ -87,7 +87,7 @@ export class HeatmapTooltip {
let tooltipHtml = `<div class="graph-tooltip-time">${time}</div>
<div class="heatmap-histogram"></div>`;
if (yData) {
if (yData && yData.bounds) {
boundBottom = valueFormatter(yData.bounds.bottom);
boundTop = valueFormatter(yData.bounds.top);
valuesNumber = yData.values.length;

View File

@ -1,195 +1,88 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
width="100px"
height="100px"
viewBox="0 0 100 100"
style="enable-background:new 0 0 100 100;"
xml:space="preserve"
sodipodi:docname="icn-heatmap-panel.svg"
inkscape:version="0.92.1 unknown"><metadata
id="metadata108"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs106" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2491"
inkscape:window-height="1410"
id="namedview104"
showgrid="false"
inkscape:zoom="9.44"
inkscape:cx="37.431994"
inkscape:cy="46.396264"
inkscape:window-x="69"
inkscape:window-y="30"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><rect
x="-0.017525015"
y="33.438038"
style="opacity:0.35714285;fill:#decd87;fill-opacity:1;stroke-width:0.70710677"
width="15.8115"
height="15.049"
id="rect69" /><path
style="opacity:0.42857145;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 16.874036,24.263391 v -7.46822 h 7.891949 7.891949 v 7.46822 7.46822 h -7.891949 -7.891949 z"
id="path4883"
inkscape:connector-curvature="0" /><path
style="opacity:0.79365079;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 33.69883,24.337252 v -7.46822 h 7.891949 7.891949 v 7.46822 7.46822 H 41.590779 33.69883 Z"
id="path4885"
inkscape:connector-curvature="0" /><path
style="opacity:0.80952382;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 50.523624,24.337251 v -7.46822 h 7.891949 7.89195 v 7.46822 7.46822 h -7.89195 -7.891949 z"
id="path4887"
inkscape:connector-curvature="0" /><path
style="opacity:0.43650794;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 67.348418,24.167764 v -7.46822 h 7.891949 7.891949 v 7.46822 7.46822 h -7.891949 -7.891949 z"
id="path4889"
inkscape:connector-curvature="0" /><path
style="opacity:0.24603176;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 84.173218,24.279957 v -7.46822 h 7.891947 7.891956 v 7.46822 7.46822 h -7.891956 -7.891947 z"
id="path4891"
inkscape:connector-curvature="0" /><path
style="opacity:0.38158725;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 84.226177,40.968612 v -7.46822 h 7.891949 7.891954 v 7.46822 7.468221 h -7.891954 -7.891949 z"
id="path4893"
inkscape:connector-curvature="0" /><path
style="opacity:0.75396824;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 67.377433,40.884464 v -7.46822 h 7.891949 7.891949 v 7.46822 7.468221 h -7.891949 -7.891949 z"
id="path4895"
inkscape:connector-curvature="0" /><path
style="opacity:0.94444442;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 50.528693,41.011582 v -7.46822 h 7.891949 7.89195 v 7.46822 7.468221 h -7.89195 -7.891949 z"
id="path4897"
inkscape:connector-curvature="0" /><path
style="opacity:0.53174606;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 33.679956,41.011587 v -7.46822 h 7.891949 7.891949 v 7.46822 7.468221 h -7.891949 -7.891949 z"
id="path4899"
inkscape:connector-curvature="0" /><path
style="opacity:0.64285715;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 16.831216,40.956187 v -7.46822 h 7.891949 7.891949 v 7.46822 7.468221 h -7.891949 -7.891949 z"
id="path4901"
inkscape:connector-curvature="0" /><path
style="opacity:0.58730158;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 0.04924114,57.615687 v -7.46822 H 7.8882241 15.727207 v 7.46822 7.468221 H 7.8882241 0.04924114 Z"
id="path4905"
inkscape:connector-curvature="0" /><path
style="opacity:0.43650794;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 16.884627,57.648974 v -7.46822 h 7.838984 7.838983 v 7.46822 7.468221 h -7.838983 -7.838984 z"
id="path4907"
inkscape:connector-curvature="0" /><path
style="opacity:1;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 67.390785,57.601163 v -7.46822 h 7.891949 7.891949 v 7.46822 7.468221 h -7.891949 -7.891949 z"
id="path4913"
inkscape:connector-curvature="0" /><path
style="opacity:0.29365079;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 84.226177,57.657262 v -7.46822 h 7.891947 7.891946 v 7.46822 7.468221 h -7.891946 -7.891947 z"
id="path4915"
inkscape:connector-curvature="0" /><path
style="opacity:0.73015873;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 84.226177,74.345913 v -7.46822 h 7.891948 7.891955 v 7.46822 7.468221 h -7.891955 -7.891948 z"
id="path4917"
inkscape:connector-curvature="0" /><path
style="opacity:0.58730158;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 67.380199,74.317863 v -7.46822 h 7.891949 7.891949 v 7.46822 7.468221 h -7.891949 -7.891949 z"
id="path4919"
inkscape:connector-curvature="0" /><path
style="opacity:0.66666667;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 50.534214,74.360232 v -7.46822 h 7.891949 7.89195 v 7.46822 7.468221 h -7.89195 -7.891949 z"
id="path4921"
inkscape:connector-curvature="0" /><path
style="opacity:0.84920636;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 33.688232,74.360242 v -7.46822 h 7.891949 7.891949 v 7.46822 7.468221 h -7.891949 -7.891949 z"
id="path4923"
inkscape:connector-curvature="0" /><path
style="opacity:0.70634921;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 16.842256,74.341769 v -7.46822 h 7.891949 7.891949 v 7.46822 7.468221 h -7.891949 -7.891949 z"
id="path4925"
inkscape:connector-curvature="0" /><path
style="opacity:0.43650794;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="M -0.00372516,74.325127 V 66.856906 H 7.8882239 15.780174 v 7.468221 7.46822 H 7.8882239 -0.00372516 Z"
id="path4927"
inkscape:connector-curvature="0" /><path
style="opacity:0.13492061;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="M 0.04924124,91.034564 V 83.566343 H 7.8882241 15.727207 v 7.468221 7.468221 H 7.8882241 0.04924114 Z"
id="path4929"
inkscape:connector-curvature="0" /><path
style="opacity:0.26190479;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="M 16.88187,91.034561 V 83.56634 h 7.838983 7.838984 v 7.468221 7.468224 h -7.838983 -7.838983 z"
id="path4931"
inkscape:connector-curvature="0" /><path
style="opacity:0.58730158;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 33.714496,91.034569 v -7.468221 h 7.891949 7.891949 v 7.468221 7.468216 h -7.891949 -7.891949 z"
id="path4933"
inkscape:connector-curvature="0" /><path
style="opacity:0.30158727;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="M 50.547126,91.034561 V 83.56634 h 7.891949 7.89195 v 7.468221 7.468224 h -7.89195 -7.891949 z"
id="path4935"
inkscape:connector-curvature="0" /><path
style="opacity:0.15873018;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 67.379756,91.034564 v -7.468221 h 7.891949 7.891949 v 7.468221 7.468221 h -7.891949 -7.891949 z"
id="path4937"
inkscape:connector-curvature="0" /><path
style="opacity:0.11904764;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 84.212376,91.034568 v -7.468221 h 7.891952 7.89195 v 7.468221 7.468217 h -7.89195 -7.891952 z"
id="path4939"
inkscape:connector-curvature="0" /><path
style="opacity:0.89682539;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 50.555398,57.68591 v -7.46822 h 7.838983 7.838983 v 7.46822 7.468221 h -7.838983 -7.838983 z"
id="path4941"
inkscape:connector-curvature="0" /><path
style="opacity:1;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 33.720011,57.685908 v -7.46822 h 7.838983 7.838983 v 7.46822 7.468221 h -7.838983 -7.838983 z"
id="path4943"
inkscape:connector-curvature="0" /><path
style="opacity:0.16666667;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="M 0.04924152,24.249783 V 16.728597 H 7.8882245 15.727207 v 7.521186 7.521186 H 7.8882245 0.04924152 Z"
id="path4976"
inkscape:connector-curvature="0" /><rect
x="16.900255"
y="0.10238234"
style="opacity:0.43650794;fill:#decd87;fill-opacity:1;stroke-width:0.70710677"
width="15.8115"
height="15.049"
id="rect69-5-7-3" /><rect
x="84.304306"
y="0.12308588"
style="opacity:0.11904764;fill:#decd87;fill-opacity:1;stroke-width:0.70710677"
width="15.8115"
height="15.049"
id="rect69-5-2-2-6" /><path
style="opacity:0.3174603;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="M 33.751268,7.6629239 V 0.19470386 h 7.891949 7.891949 V 7.6629239 15.131142 h -7.891949 -7.891949 z"
id="path4885-1"
inkscape:connector-curvature="0" /><path
style="opacity:0.43650794;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="M 50.602281,7.6629315 V 0.19471149 h 7.891949 7.891951 V 7.6629315 15.13115 H 58.49423 50.602281 Z"
id="path4887-2"
inkscape:connector-curvature="0" /><path
style="opacity:0.73015873;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="m 67.453295,7.4510673 v -7.4682202 h 7.89195 7.89195 v 7.4682202 7.4682177 h -7.89195 -7.89195 z"
id="path4889-9"
inkscape:connector-curvature="0" /><path
style="opacity:0.15873018;fill:#decd87;fill-opacity:1;stroke-width:0.10593221"
d="M -0.02566414,7.5403525 V 0.0191665 H 7.8133188 15.652302 v 7.521186 7.5211835 H 7.8133188 -0.02566414 Z"
id="path4976-3"
inkscape:connector-curvature="0" /></svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<g>
<path d="M-0.2-0.2v100.4h100.4V-0.2H-0.2z M13.7,1.4H24v10H13.7V1.4z M13.7,13.9H24v10H13.7V13.9z M13.7,26.3H24v10H13.7V26.3z
M13.7,38.8H24v10H13.7V38.8z M11.7,98.5H1.3v-10h10.4V98.5z M11.7,86.1H1.3v-10h10.4V86.1z M11.7,73.6H1.3v-10h10.4V73.6z
M11.7,61.2H1.3v-10h10.4V61.2z M11.7,48.8H1.3v-10h10.4V48.8z M11.7,36.3H1.3v-10h10.4V36.3z M11.7,23.9H1.3v-10h10.4V23.9z
M11.7,11.4H1.3v-10h10.4V11.4z M24,98.5H13.7v-10H24V98.5z M24,86.1H13.7v-10H24V86.1z M24,73.6H13.7v-10H24V73.6z M24.1,61.2
H13.8v-10h10.4V61.2z M36.5,98.5H26.1v-10h10.4V98.5z M36.5,86.1H26.1v-10h10.4V86.1z M36.5,73.6H26.1v-10h10.4V73.6z M36.5,61.2
H26.1v-10h10.4V61.2z M36.5,48.8H26.1v-10h10.4V48.8z M36.5,36.3H26.1v-10h10.4V36.3z M36.5,23.9H26.1v-10h10.4V23.9z M36.5,11.4
H26.1v-10h10.4V11.4z M48.9,98.5H38.5v-10h10.4V98.5z M48.9,86.1H38.5v-10h10.4V86.1z M48.9,73.6H38.5v-10h10.4V73.6z M48.9,61.2
H38.5v-10h10.4V61.2z M48.9,48.8H38.5v-10h10.4V48.8z M48.9,36.3H38.5v-10h10.4V36.3z M48.9,23.9H38.5v-10h10.4V23.9z M48.9,11.4
H38.5v-10h10.4V11.4z M50.9,26.3h10.4v10H50.9V26.3z M51,63.6h10.4v10H51V63.6z M61.3,98.5H51v-10h10.4V98.5z M61.3,86.1H51v-10
h10.4V86.1z M61.3,61.2H51v-10h10.4V61.2z M61.3,48.8H51v-10h10.4V48.8z M61.3,23.9H51v-10h10.4V23.9z M61.3,11.4H51v-10h10.4V11.4
z M73.8,98.5H63.4v-10h10.4V98.5z M73.8,86.1H63.4v-10h10.4V86.1z M73.8,73.6H63.4v-10h10.4V73.6z M73.8,61.2H63.4v-10h10.4V61.2z
M73.8,48.8H63.4v-10h10.4V48.8z M73.8,36.3H63.4v-10h10.4V36.3z M73.8,23.9H63.4v-10h10.4V23.9z M73.8,11.4H63.4v-10h10.4V11.4z
M86.2,98.5H75.8v-10h10.4V98.5z M86.2,86.1H75.8v-10h10.4V86.1z M86.2,73.6H75.8v-10h10.4V73.6z M86.2,61.2H75.8v-10h10.4V61.2z
M86.2,48.8H75.8v-10h10.4V48.8z M86.2,36.3H75.8v-10h10.4V36.3z M86.2,23.9H75.8v-10h10.4V23.9z M86.2,11.4H75.8v-10h10.4V11.4z
M98.6,98.5H88.3v-10h10.4V98.5z M98.6,86.1H88.3v-10h10.4V86.1z M98.6,73.6H88.3v-10h10.4V73.6z M98.6,61.2H88.3v-10h10.4V61.2z
M98.6,48.8H88.3v-10h10.4V48.8z M98.6,36.3H88.3v-10h10.4V36.3z M98.6,23.9H88.3v-10h10.4V23.9z M98.6,11.4H88.3v-10h10.4V11.4z"
/>
<rect x="26.1" y="1.4" fill="#0062A7" width="10.4" height="10"/>
<rect x="26.1" y="13.9" fill="#1A83BD" width="10.4" height="10"/>
<rect x="26.1" y="26.3" fill="#B2DBB9" width="10.4" height="10"/>
<rect x="26.1" y="38.8" fill="#B2DBB9" width="10.4" height="10"/>
<rect x="26.1" y="88.5" fill="#0062A7" width="10.4" height="10"/>
<rect x="26.1" y="51.2" fill="#E3F1DC" width="10.4" height="10"/>
<rect x="13.8" y="51.2" fill="#E3F1DC" width="10.4" height="10"/>
<rect x="26.1" y="63.6" fill="#60C0CB" width="10.4" height="10"/>
<rect x="26.1" y="76.1" fill="#1A83BD" width="10.4" height="10"/>
<rect x="1.3" y="1.4" fill="#1A83BD" width="10.4" height="10"/>
<rect x="1.3" y="13.9" fill="#39A4CB" width="10.4" height="10"/>
<rect x="1.3" y="26.3" fill="#39A4CB" width="10.4" height="10"/>
<rect x="1.3" y="38.8" fill="#60C0CB" width="10.4" height="10"/>
<rect x="1.3" y="88.5" fill="#0062A7" width="10.4" height="10"/>
<rect x="1.3" y="51.2" fill="#8CD0BC" width="10.4" height="10"/>
<rect x="1.3" y="63.6" fill="#0062A7" width="10.4" height="10"/>
<rect x="1.3" y="76.1" fill="#1A83BD" width="10.4" height="10"/>
<rect x="13.7" y="1.4" fill="#1A83BD" width="10.4" height="10"/>
<rect x="13.7" y="13.9" fill="#1A83BD" width="10.4" height="10"/>
<rect x="13.7" y="26.3" fill="#39A4CB" width="10.4" height="10"/>
<rect x="13.7" y="38.8" fill="#60C0CB" width="10.4" height="10"/>
<rect x="13.7" y="88.5" fill="#1A83BD" width="10.4" height="10"/>
<rect x="13.7" y="63.6" fill="#60C0CB" width="10.4" height="10"/>
<rect x="13.7" y="76.1" fill="#60C0CB" width="10.4" height="10"/>
<rect x="38.5" y="1.4" fill="#1A83BD" width="10.4" height="10"/>
<rect x="38.5" y="13.9" fill="#60C0CB" width="10.4" height="10"/>
<rect x="38.5" y="26.3" fill="#8CD0BC" width="10.4" height="10"/>
<rect x="38.5" y="38.8" fill="#8CD0BC" width="10.4" height="10"/>
<rect x="38.5" y="88.5" fill="#0062A7" width="10.4" height="10"/>
<rect x="38.5" y="51.2" fill="#B2DBB9" width="10.4" height="10"/>
<rect x="38.5" y="63.6" fill="#8CD0BC" width="10.4" height="10"/>
<rect x="38.5" y="76.1" fill="#0062A7" width="10.4" height="10"/>
<rect x="51" y="1.4" fill="#0062A7" width="10.4" height="10"/>
<rect x="51" y="13.9" fill="#39A4CB" width="10.4" height="10"/>
<rect x="51" y="38.8" fill="#8CD0BC" width="10.4" height="10"/>
<rect x="51" y="88.5" fill="#1A83BD" width="10.4" height="10"/>
<rect x="51" y="51.2" fill="#E3F1DC" width="10.4" height="10"/>
<rect x="51" y="76.1" fill="#8CD0BC" width="10.4" height="10"/>
<rect x="63.4" y="1.4" fill="#0062A7" width="10.4" height="10"/>
<rect x="63.4" y="13.9" fill="#39A4CB" width="10.4" height="10"/>
<rect x="63.4" y="26.3" fill="#60C0CB" width="10.4" height="10"/>
<rect x="50.9" y="26.3" fill="#60C0CB" width="10.4" height="10"/>
<rect x="63.4" y="38.8" fill="#B2DBB9" width="10.4" height="10"/>
<rect x="63.4" y="88.5" fill="#0062A7" width="10.4" height="10"/>
<rect x="63.4" y="51.2" fill="#E3F1DC" width="10.4" height="10"/>
<rect x="63.4" y="63.6" fill="#39A4CB" width="10.4" height="10"/>
<rect x="63.4" y="76.1" fill="#39A4CB" width="10.4" height="10"/>
<rect x="75.8" y="1.4" fill="#1A83BD" width="10.4" height="10"/>
<rect x="75.8" y="13.9" fill="#39A4CB" width="10.4" height="10"/>
<rect x="75.8" y="26.3" fill="#60C0CB" width="10.4" height="10"/>
<rect x="75.8" y="38.8" fill="#8CD0BC" width="10.4" height="10"/>
<rect x="75.8" y="88.5" fill="#0062A7" width="10.4" height="10"/>
<rect x="75.8" y="51.2" fill="#E3F1DC" width="10.4" height="10"/>
<rect x="51" y="63.6" fill="#8CD0BC" width="10.4" height="10"/>
<rect x="75.8" y="63.6" fill="#60C0CB" width="10.4" height="10"/>
<rect x="75.8" y="76.1" fill="#1A83BD" width="10.4" height="10"/>
<rect x="88.3" y="13.9" fill="#39A4CB" width="10.4" height="10"/>
<rect x="88.3" y="26.3" fill="#39A4CB" width="10.4" height="10"/>
<rect x="88.3" y="38.8" fill="#1A83BD" width="10.4" height="10"/>
<rect x="88.3" y="88.5" fill="#1A83BD" width="10.4" height="10"/>
<rect x="88.3" y="51.2" fill="#8CD0BC" width="10.4" height="10"/>
<rect x="88.3" y="63.6" fill="#1A83BD" width="10.4" height="10"/>
<rect x="88.3" y="76.1" fill="#0062A7" width="10.4" height="10"/>
<rect x="88.3" y="1.4" fill="#0062A7" width="10.4" height="10"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -7,6 +7,5 @@
<div class="heatmap-panel" ng-dblclick="ctrl.zoomOut()"></div>
</div>
<!-- <div class="graph-legend-wrapper" ng-if="ctrl.panel.legend.show" heatmap-legend></div> -->
</div>
<div class="clearfix"></div>

View File

@ -1,95 +1,91 @@
<div class="editor-row">
<div class="section gf-form-group">
<h5 class="section-heading">Y Axis</h5>
<gf-form-switch class="gf-form" label-class="width-5"
label="Show"
checked="ctrl.panel.yAxis.show" on-change="ctrl.render()">
</gf-form-switch>
<div class="gf-form">
<label class="gf-form-label width-5">Unit</label>
<div class="gf-form-dropdown-typeahead max-width-15"
ng-model="ctrl.panel.yAxis.format"
dropdown-typeahead2="editor.unitFormats"
dropdown-typeahead-on-select="editor.setUnitFormat($subItem)">
<label class="gf-form-label width-6">Unit</label>
<div class="gf-form-dropdown-typeahead max-width-10"
ng-model="ctrl.panel.yAxis.format"
dropdown-typeahead2="editor.unitFormats"
dropdown-typeahead-on-select="editor.setUnitFormat($subItem)">
</div>
</div>
<div class="gf-form">
<label class="gf-form-label width-5">Scale</label>
<div class="gf-form-select-wrapper max-width-15">
<label class="gf-form-label width-6">Scale</label>
<div class="gf-form-select-wrapper max-width-10">
<select class="gf-form-input" ng-model="ctrl.panel.yAxis.logBase" ng-options="v as k for (k, v) in editor.logScales" ng-change="ctrl.refresh()"></select>
</div>
</div>
<div class="gf-form-inline">
<div class="gf-form max-width-10">
<label class="gf-form-label width-5">Y-Min</label>
<input type="text" class="gf-form-input" placeholder="auto" empty-to-null ng-model="ctrl.panel.yAxis.min" ng-change="ctrl.render()" ng-model-onblur>
</div>
<div class="gf-form max-width-10">
<label class="gf-form-label width-5">Y-Max</label>
<input type="text" class="gf-form-input" placeholder="auto" empty-to-null ng-model="ctrl.panel.yAxis.max" ng-change="ctrl.render()" ng-model-onblur>
</div>
<div class="gf-form">
<label class="gf-form-label width-6">Y-Min</label>
<input type="text" class="gf-form-input width-10" placeholder="auto" empty-to-null ng-model="ctrl.panel.yAxis.min" ng-change="ctrl.render()" ng-model-onblur>
</div>
<div class="gf-form">
<label class="gf-form-label width-10">Decimals</label>
<input type="number" class="gf-form-input width-10" placeholder="auto" data-placement="right"
bs-tooltip="'Override automatic decimal precision for axis.'"
ng-model="ctrl.panel.yAxis.decimals" ng-change="ctrl.render()" ng-model-onblur>
<label class="gf-form-label width-6">Y-Max</label>
<input type="text" class="gf-form-input width-10" placeholder="auto" empty-to-null ng-model="ctrl.panel.yAxis.max" ng-change="ctrl.render()" ng-model-onblur>
</div>
<div class="gf-form">
<label class="gf-form-label width-6">Decimals</label>
<input type="number" class="gf-form-input width-10" placeholder="auto" data-placement="right"
bs-tooltip="'Override automatic decimal precision for axis.'"
ng-model="ctrl.panel.yAxis.decimals" ng-change="ctrl.render()" ng-model-onblur>
</div>
</div>
<div class="section gf-form-group" ng-if="ctrl.panel.dataFormat == 'timeseries'">
<h5 class="section-heading">Buckets</h5>
<div ng-show="ctrl.panel.yAxis.logBase === 1">
<div class="gf-form">
<label class="gf-form-label width-10">Buckets</label>
<input type="number" class="gf-form-input width-10" placeholder="auto" data-placement="right"
bs-tooltip="'Number of buckets for Y axis.'"
ng-model="ctrl.panel.yBucketNumber" ng-change="ctrl.refresh()" ng-model-onblur>
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label">Y Axis</label>
<label class="gf-form-label">Buckets</label>
<input type="number" class="gf-form-input width-5" placeholder="auto" data-placement="right"
bs-tooltip="'Number of buckets for Y axis.'"
ng-model="ctrl.panel.yBucketNumber" ng-change="ctrl.refresh()" ng-model-onblur>
</div>
<div class="gf-form">
<label class="gf-form-label">Size</label>
<input type="number" class="gf-form-input width-5" placeholder="auto" data-placement="right"
bs-tooltip="'Size of bucket. Has priority over Buckets option.'"
ng-model="ctrl.panel.yBucketSize" ng-change="ctrl.refresh()" ng-model-onblur>
</div>
</div>
<div class="gf-form">
<label class="gf-form-label width-10">Bucket Size</label>
<input type="number" class="gf-form-input width-10" placeholder="auto" data-placement="right"
bs-tooltip="'Size of bucket. Has priority over Buckets option.'"
ng-model="ctrl.panel.yBucketSize" ng-change="ctrl.refresh()" ng-model-onblur>
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label">X Axis</label>
<label class="gf-form-label">Buckets</label>
<input type="number" class="gf-form-input width-5" placeholder="auto" data-placement="right"
bs-tooltip="'Number of buckets for Y axis.'"
ng-model="ctrl.panel.yBucketNumber" ng-change="ctrl.refresh()" ng-model-onblur>
</div>
<div class="gf-form">
<label class="gf-form-label">Size</label>
<input type="text" class="gf-form-input width-5" placeholder="auto" data-placement="right"
bs-tooltip="'Size of bucket. Number or interval (10s, 5m, 1h, etc). Supported intervals: ms, s, m, h, d, w, M, y. Has priority over Buckets option.'"
ng-model="ctrl.panel.xBucketSize" ng-change="ctrl.refresh()" ng-model-onblur>
</div>
</div>
</div>
<div ng-show="ctrl.panel.yAxis.logBase !== 1">
<div class="gf-form">
<label class="gf-form-label width-10">Split Buckets</label>
<input type="number" class="gf-form-input width-10" placeholder="1" data-placement="right"
bs-tooltip="'For log scales only. By default Y values is splitted by integer powers of log base (1, 2, 4, 8, 16, ... for log2). This option allows to split each default bucket into specified number of buckets.'"
ng-model="ctrl.panel.yAxis.splitFactor" ng-change="ctrl.refresh()" ng-model-onblur>
<label class="gf-form-label width-7">Split Factor</label>
<input type="number"
class="gf-form-input width-3"
placeholder="1"
data-placement="right"
bs-tooltip="'For log scales only. By default Y values is splitted by integer powers of log base (1, 2, 4, 8, 16, ... for log2). This option allows to split each default bucket into specified number of buckets.'"
ng-model="ctrl.panel.yAxis.splitFactor" ng-change="ctrl.refresh()" ng-model-onblur>
</input>
</div>
<gf-form-switch class="gf-form" label-class="width-10"
label="Remove zero values"
checked="ctrl.panel.yAxis.removeZeroValues" on-change="ctrl.render()">
</gf-form-switch>
</div>
</div>
<div class="section gf-form-group">
<h5 class="section-heading">X Axis</h5>
<gf-form-switch class="gf-form" label-class="width-8"
label="Show"
checked="ctrl.panel.xAxis.show" on-change="ctrl.render()">
</gf-form-switch>
<h5 class="section-heading">Data format</h5>
<div class="gf-form">
<label class="gf-form-label width-8">Buckets</label>
<input type="number" class="gf-form-input width-8" placeholder="auto" data-placement="right"
bs-tooltip="'Number of buckets for X axis.'"
ng-model="ctrl.panel.xBucketNumber" ng-change="ctrl.refresh()" ng-model-onblur>
</div>
<div class="gf-form">
<label class="gf-form-label width-8">Bucket Size</label>
<input type="text" class="gf-form-input width-8" placeholder="auto" data-placement="right"
bs-tooltip="'Size of bucket. Number or interval (10s, 5m, 1h, etc). Supported intervals: ms, s, m, h, d, w, M, y. Has priority over Buckets option.'"
ng-model="ctrl.panel.xBucketSize" ng-change="ctrl.refresh()" ng-model-onblur>
</div>
</div>
<div class="section gf-form-group">
<h5 class="section-heading">Data format</h5>
<div class="gf-form">
<label class="gf-form-label width-5">Format</label>
<div class="gf-form-select-wrapper max-width-15">
<select class="gf-form-input" ng-model="ctrl.panel.dataFormat" ng-options="v as k for (k, v) in editor.dataFormats" ng-change="ctrl.render()"></select>
<label class="gf-form-label width-5">Format</label>
<div class="gf-form-select-wrapper max-width-15">
<select class="gf-form-input" ng-model="ctrl.panel.dataFormat" ng-options="v as k for (k, v) in editor.dataFormats" ng-change="ctrl.render()"></select>
</div>
</div>
</div>
</div>
</div>

View File

@ -2,51 +2,49 @@
<div class="section gf-form-group">
<h5 class="section-heading">Colors</h5>
<div class="gf-form">
<label class="gf-form-label width-7">Mode</label>
<div class="gf-form-select-wrapper width-12">
<label class="gf-form-label width-9">Mode</label>
<div class="gf-form-select-wrapper width-8">
<select class="input-small gf-form-input" ng-model="ctrl.panel.color.mode" ng-options="s for s in ctrl.colorModes" ng-change="ctrl.render()"></select>
</div>
</div>
<div ng-show="ctrl.panel.color.mode === 'opacity'">
<div class="gf-form">
<label class="gf-form-label width-7">Color</label>
<label class="gf-form-label width-9">Color</label>
<span class="gf-form-label">
<spectrum-picker ng-model="ctrl.panel.color.cardColor" ng-change="ctrl.render()" ></spectrum-picker>
</span>
</div>
<div class="gf-form">
<label class="gf-form-label width-7">Scale</label>
<label class="gf-form-label width-9">Scale</label>
<div class="gf-form-select-wrapper width-8">
<select class="input-small gf-form-input" ng-model="ctrl.panel.color.colorScale" ng-options="s for s in ctrl.opacityScales" ng-change="ctrl.render()"></select>
</div>
</div>
<div class="gf-form" ng-if="ctrl.panel.color.colorScale === 'sqrt'">
<label class="gf-form-label width-7">Exponent</label>
<label class="gf-form-label width-9">Exponent</label>
<input type="number" class="gf-form-input width-8" placeholder="auto" data-placement="right" bs-tooltip="''" ng-model="ctrl.panel.color.exponent" ng-change="ctrl.refresh()" ng-model-onblur>
</div>
<div class="gf-form">
<svg id="heatmap-opacity-legend" width="22.7em" height="2em"></svg>
<svg id="heatmap-opacity-legend" width="19em" height="2em"></svg>
</div>
</div>
<div ng-show="ctrl.panel.color.mode === 'spectrum'">
<div class="gf-form">
<label class="gf-form-label width-7">Scheme</label>
<div class="gf-form-select-wrapper width-12">
<label class="gf-form-label width-9">Scheme</label>
<div class="gf-form-select-wrapper width-8">
<select class="input-small gf-form-input" ng-model="ctrl.panel.color.colorScheme" ng-options="s.value as s.name for s in ctrl.colorSchemes" ng-change="ctrl.render()"></select>
</div>
</div>
<div class="gf-form">
<svg id="heatmap-color-legend" width="22.7em" height="2em"></svg>
<svg id="heatmap-color-legend" width="19em" height="2em"></svg>
</div>
<gf-form-switch class="gf-form" label-class="width-9" label="Fill background" checked="ctrl.panel.color.fillBackground" on-change="ctrl.render()">
</gf-form-switch>
</div>
</div>
<div class="section gf-form-group">
<h5 class="section-heading">Cards</h5>
<h5 class="section-heading">Buckets</h5>
<div class="gf-form">
<label class="gf-form-label width-8">Space</label>
<input type="number" class="gf-form-input width-5" placeholder="auto" data-placement="right" bs-tooltip="''" ng-model="ctrl.panel.cards.cardPadding" ng-change="ctrl.refresh()" ng-model-onblur>
@ -64,10 +62,6 @@
checked="ctrl.panel.tooltip.show" on-change="ctrl.render()">
</gf-form-switch>
<div ng-if="ctrl.panel.tooltip.show">
<gf-form-switch class="gf-form" label-class="width-8"
label="Highlight cards"
checked="ctrl.panel.highlightCards" on-change="ctrl.render()">
</gf-form-switch>
<gf-form-switch class="gf-form" label-class="width-8"
label="Series stats"
checked="ctrl.panel.tooltip.seriesStat" on-change="ctrl.render()">

View File

@ -376,10 +376,6 @@ export default function link(scope, elem, attrs, ctrl) {
setOpacityScale(max_value);
setCardSize();
if (panel.color.fillBackground && panel.color.mode === 'spectrum') {
fillBackground(heatmap, colorScale(0));
}
let cards = heatmap.selectAll(".heatmap-card").data(cardsData);
cards.append("title");
cards = cards.enter().append("rect")
@ -407,24 +403,20 @@ export default function link(scope, elem, attrs, ctrl) {
}
function highlightCard(event) {
if (panel.highlightCards) {
let color = d3.select(event.target).style("fill");
let highlightColor = d3.color(color).darker(2);
let strokeColor = d3.color(color).brighter(4);
let current_card = d3.select(event.target);
tooltip.originalFillColor = color;
current_card.style("fill", highlightColor)
.style("stroke", strokeColor)
.style("stroke-width", 1);
}
let color = d3.select(event.target).style("fill");
let highlightColor = d3.color(color).darker(2);
let strokeColor = d3.color(color).brighter(4);
let current_card = d3.select(event.target);
tooltip.originalFillColor = color;
current_card.style("fill", highlightColor)
.style("stroke", strokeColor)
.style("stroke-width", 1);
}
function resetCardHighLight(event) {
if (panel.highlightCards) {
d3.select(event.target).style("fill", tooltip.originalFillColor)
.style("stroke", tooltip.originalFillColor)
.style("stroke-width", 0);
}
d3.select(event.target).style("fill", tooltip.originalFillColor)
.style("stroke", tooltip.originalFillColor)
.style("stroke-width", 0);
}
function getColorScale(maxValue) {
@ -442,12 +434,12 @@ export default function link(scope, elem, attrs, ctrl) {
function setOpacityScale(max_value) {
if (panel.color.colorScale === 'linear') {
opacityScale = d3.scaleLinear()
.domain([0, max_value])
.range([0, 1]);
.domain([0, max_value])
.range([0, 1]);
} else if (panel.color.colorScale === 'sqrt') {
opacityScale = d3.scalePow().exponent(panel.color.exponent)
.domain([0, max_value])
.range([0, 1]);
.domain([0, max_value])
.range([0, 1]);
}
}
@ -549,15 +541,6 @@ export default function link(scope, elem, attrs, ctrl) {
}
}
function fillBackground(heatmap, color) {
heatmap.insert("rect", "g")
.attr("x", yAxisWidth)
.attr("y", margin.top)
.attr("width", chartWidth)
.attr("height", chartHeight)
.attr("fill", color);
}
/////////////////////////////
// Selection and crosshair //
/////////////////////////////
@ -570,12 +553,12 @@ export default function link(scope, elem, attrs, ctrl) {
if (ctrl.dashboard.graphTooltip === 2) {
tooltip.show(event.pos, data);
}
});
}, scope);
appEvents.on('graph-hover-clear', () => {
clearCrosshair();
tooltip.destroy();
});
}, scope);
function onMouseDown(event) {
selection.active = true;
@ -584,6 +567,7 @@ export default function link(scope, elem, attrs, ctrl) {
mouseUpHandler = function() {
onMouseUp();
};
$(document).one("mouseup", mouseUpHandler);
}
@ -660,11 +644,11 @@ export default function link(scope, elem, attrs, ctrl) {
if (selectionWidth > MIN_SELECTION_WIDTH) {
heatmap.append("rect")
.attr("class", "heatmap-selection")
.attr("x", selectionX)
.attr("width", selectionWidth)
.attr("y", chartTop)
.attr("height", chartHeight);
.attr("class", "heatmap-selection")
.attr("x", selectionX)
.attr("width", selectionWidth)
.attr("y", chartTop)
.attr("height", chartHeight);
}
}
}
@ -687,14 +671,14 @@ export default function link(scope, elem, attrs, ctrl) {
posX = Math.min(posX, chartWidth + yAxisWidth);
heatmap.append("g")
.attr("class", "heatmap-crosshair")
.attr("transform", "translate(" + posX + ",0)")
.append("line")
.attr("x1", 1)
.attr("y1", chartTop)
.attr("x2", 1)
.attr("y2", chartBottom)
.attr("stroke-width", 1);
.attr("class", "heatmap-crosshair")
.attr("transform", "translate(" + posX + ",0)")
.append("line")
.attr("x1", 1)
.attr("y1", chartTop)
.attr("x2", 1)
.attr("y2", chartBottom)
.attr("stroke-width", 1);
}
}
@ -725,14 +709,14 @@ export default function link(scope, elem, attrs, ctrl) {
var legendRects = legend.selectAll(".heatmap-color-legend-rect").data(valuesRange);
legendRects.enter().append("rect")
.attr("x", d => d)
.attr("y", 0)
.attr("width", rangeStep + 1) // Overlap rectangles to prevent gaps
.attr("height", legendHeight)
.attr("stroke-width", 0)
.attr("fill", d => {
return legendColorScale(d);
});
.attr("x", d => d)
.attr("y", 0)
.attr("width", rangeStep + 1) // Overlap rectangles to prevent gaps
.attr("height", legendHeight)
.attr("stroke-width", 0)
.attr("fill", d => {
return legendColorScale(d);
});
}
function drawOpacityLegend() {
@ -745,12 +729,12 @@ export default function link(scope, elem, attrs, ctrl) {
let legendOpacityScale;
if (panel.color.colorScale === 'linear') {
legendOpacityScale = d3.scaleLinear()
.domain([0, legendWidth])
.range([0, 1]);
.domain([0, legendWidth])
.range([0, 1]);
} else if (panel.color.colorScale === 'sqrt') {
legendOpacityScale = d3.scalePow().exponent(panel.color.exponent)
.domain([0, legendWidth])
.range([0, 1]);
.domain([0, legendWidth])
.range([0, 1]);
}
let rangeStep = 1;
@ -758,15 +742,15 @@ export default function link(scope, elem, attrs, ctrl) {
var legendRects = legend.selectAll(".heatmap-opacity-legend-rect").data(valuesRange);
legendRects.enter().append("rect")
.attr("x", d => d)
.attr("y", 0)
.attr("width", rangeStep)
.attr("height", legendHeight)
.attr("stroke-width", 0)
.attr("fill", panel.color.cardColor)
.style("opacity", d => {
return legendOpacityScale(d);
});
.attr("x", d => d)
.attr("y", 0)
.attr("width", rangeStep)
.attr("height", legendHeight)
.attr("stroke-width", 0)
.attr("fill", panel.color.cardColor)
.style("opacity", d => {
return legendOpacityScale(d);
});
}
function render() {
@ -774,34 +758,26 @@ export default function link(scope, elem, attrs, ctrl) {
panel = ctrl.panel;
timeRange = ctrl.range;
if (setElementHeight()) {
if (data) {
// Draw default axes and return if no data
if (_.isEmpty(data.buckets)) {
addHeatmapCanvas();
addAxes();
return;
}
addHeatmap();
scope.yScale = yScale;
scope.xScale = xScale;
scope.yAxisWidth = yAxisWidth;
scope.xAxisHeight = xAxisHeight;
scope.chartHeight = chartHeight;
scope.chartWidth = chartWidth;
scope.chartTop = chartTop;
// Register selection listeners
$heatmap.on("mousedown", onMouseDown);
$heatmap.on("mousemove", onMouseMove);
$heatmap.on("mouseleave", onMouseLeave);
} else {
return;
}
if (!setElementHeight() || !data) {
return;
}
// Draw default axes and return if no data
if (_.isEmpty(data.buckets)) {
addHeatmapCanvas();
addAxes();
return;
}
addHeatmap();
scope.yScale = yScale;
scope.xScale = xScale;
scope.yAxisWidth = yAxisWidth;
scope.xAxisHeight = xAxisHeight;
scope.chartHeight = chartHeight;
scope.chartWidth = chartWidth;
scope.chartTop = chartTop;
// Draw only if color editor is opened
if (!d3.select("#heatmap-color-legend").empty()) {
drawColorLegend();
@ -810,6 +786,11 @@ export default function link(scope, elem, attrs, ctrl) {
drawOpacityLegend();
}
}
// Register selection listeners
$heatmap.on("mousedown", onMouseDown);
$heatmap.on("mousemove", onMouseMove);
$heatmap.on("mouseleave", onMouseLeave);
}
function grafanaTimeFormat(ticks, min, max) {

View File

@ -10,11 +10,13 @@
.grafana-info-box {
position: relative;
padding: 5px 20px;
background-color: $tight-form-bg;
border: 1px solid $tight-form-border;
background: $card-background;
box-shadow: $card-shadow;
padding: 1rem;
border-radius: 4px;
h5 {
margin-top: 5px;
margin-bottom: $spacer;
}
ul {
padding-left: $spacer;

52
public/sass/icons.json Normal file
View File

@ -0,0 +1,52 @@
[
"grafana_wordmark",
"worldping",
"raintank_wordmark",
"raintank_r-icn",
"check-alt",
"check",
"collector",
"dashboard",
"panel",
"datasources",
"endpoint-tiny",
"endpoint",
"page",
"filter",
"status",
"monitoring",
"monitoring-tiny",
"jump-to-dashboard",
"warning",
"nodata",
"critical",
"crit",
"online",
"event-error",
"event",
"sadface",
"private-collector",
"alert-disabled",
"refresh",
"save",
"share",
"star",
"search",
"remove",
"video",
"bulk_action",
"grabber",
"users",
"globe",
"snapshot",
"play-grafana-icon",
"grafana-icon",
"email",
"stopwatch",
"skull",
"probe",
"apps",
"scale",
"pending",
"verified"
]

View File

@ -21,6 +21,11 @@
}
}
.style-guide-icon-list {
font-size: 1.8em;
text-align: center;
}
// define("areas/styleguide/static/script/app/colors", [], function() {
// "use strict";
// var a = function(a) {

View File

@ -1,10 +0,0 @@
language: go
go:
- 1.1
- 1.2
- 1.3
- 1.4
- 1.5
- 1.6
- tip

View File

@ -45,7 +45,14 @@ srvlog.SetHandler(log.MultiHandler(
log.StreamHandler(os.Stderr, log.LogfmtFormat()),
log.LvlFilterHandler(
log.LvlError,
log.Must.FileHandler("errors.json", log.JsonFormat())))
log.Must.FileHandler("errors.json", log.JsonFormat()))))
```
Will result in output that looks like this:
```
WARN[06-17|21:58:10] abnormal conn rate module=app/server rate=0.500 low=0.100 high=0.800
INFO[06-17|21:58:10] connection open module=app/server raddr=10.0.0.1
```
## Breaking API Changes

View File

@ -97,7 +97,7 @@ context, CallerFileHandler, CallerFuncHandler and CallerStackHandler. Here's
an example that adds the source file and line number of each logging call to
the context.
h := log.CallerFileHandler(log.StdoutHandler())
h := log.CallerFileHandler(log.StdoutHandler)
log.Root().SetHandler(h)
...
log.Error("open file", "err", err)
@ -108,7 +108,7 @@ This will output a line that looks like:
Here's an example that logs the call stack rather than just the call site.
h := log.CallerStackHandler("%+v", log.StdoutHandler())
h := log.CallerStackHandler("%+v", log.StdoutHandler)
log.Root().SetHandler(h)
...
log.Error("open file", "err", err)

View File

@ -7,6 +7,7 @@ import (
"reflect"
"strconv"
"strings"
"sync"
"time"
)
@ -108,7 +109,9 @@ func logfmt(buf *bytes.Buffer, ctx []interface{}, color int) {
if color > 0 {
fmt.Fprintf(buf, "\x1b[%dm%s\x1b[0m=%s", color, k, v)
} else {
fmt.Fprintf(buf, "%s=%s", k, v)
buf.WriteString(k)
buf.WriteByte('=')
buf.WriteString(v)
}
}
@ -205,6 +208,12 @@ func formatLogfmtValue(value interface{}) string {
return "nil"
}
if t, ok := value.(time.Time); ok {
// Performance optimization: No need for escaping since the provided
// timeFormat doesn't have any escape characters, and escaping is
// expensive.
return t.Format(timeFormat)
}
value = formatShared(value)
switch v := value.(type) {
case bool:
@ -222,36 +231,49 @@ func formatLogfmtValue(value interface{}) string {
}
}
var stringBufPool = sync.Pool{
New: func() interface{} { return new(bytes.Buffer) },
}
func escapeString(s string) string {
needQuotes := false
e := bytes.Buffer{}
e.WriteByte('"')
needsQuotes := false
needsEscape := false
for _, r := range s {
if r <= ' ' || r == '=' || r == '"' {
needQuotes = true
needsQuotes = true
}
if r == '\\' || r == '"' || r == '\n' || r == '\r' || r == '\t' {
needsEscape = true
}
}
if needsEscape == false && needsQuotes == false {
return s
}
e := stringBufPool.Get().(*bytes.Buffer)
e.WriteByte('"')
for _, r := range s {
switch r {
case '\\', '"':
e.WriteByte('\\')
e.WriteByte(byte(r))
case '\n':
e.WriteByte('\\')
e.WriteByte('n')
e.WriteString("\\n")
case '\r':
e.WriteByte('\\')
e.WriteByte('r')
e.WriteString("\\r")
case '\t':
e.WriteByte('\\')
e.WriteByte('t')
e.WriteString("\\t")
default:
e.WriteRune(r)
}
}
e.WriteByte('"')
start, stop := 0, e.Len()
if !needQuotes {
start, stop = 1, stop-1
var ret string
if needsQuotes {
ret = e.String()
} else {
ret = string(e.Bytes()[1 : e.Len()-1])
}
return string(e.Bytes()[start:stop])
e.Reset()
stringBufPool.Put(e)
return ret
}

View File

@ -180,7 +180,7 @@ func MatchFilterHandler(key string, value interface{}, h Handler) Handler {
// level to the wrapped Handler. For example, to only
// log Error/Crit records:
//
// log.LvlFilterHandler(log.Error, log.StdoutHandler)
// log.LvlFilterHandler(log.LvlError, log.StdoutHandler)
//
func LvlFilterHandler(maxLvl Lvl, h Handler) Handler {
return FilterHandler(func(r *Record) (pass bool) {

View File

@ -14,7 +14,7 @@ func SyslogHandler(priority syslog.Priority, tag string, fmtr Format) (Handler,
return sharedSyslog(fmtr, wr, err)
}
// SyslogHandler opens a connection to a log daemon over the network and writes
// SyslogNetHandler opens a connection to a log daemon over the network and writes
// all log records to it.
func SyslogNetHandler(net, addr string, priority syslog.Priority, tag string, fmtr Format) (Handler, error) {
wr, err := syslog.Dial(net, addr, priority, tag)

View File

@ -2,6 +2,7 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !appengine
package term

View File

@ -0,0 +1,7 @@
package term
import "syscall"
const ioctlReadTermios = syscall.TIOCGETA
type Termios syscall.Termios

View File

@ -3,7 +3,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux,!appengine darwin freebsd openbsd
// +build linux,!appengine darwin freebsd openbsd netbsd
package term

View File

@ -0,0 +1,9 @@
package term
import "golang.org/x/sys/unix"
// IsTty returns true if the given file descriptor is a terminal.
func IsTty(fd uintptr) bool {
_, err := unix.IoctlGetTermios(int(fd), unix.TCGETA)
return err == nil
}

12
vendor/vendor.json vendored
View File

@ -416,6 +416,18 @@
"revision": "3ab3a8b8831546bd18fd182c20687ca853b2bb13",
"revisionTime": "2016-12-15T22:53:35Z"
},
{
"checksumSHA1": "mrmfY0cVu7jvgoIuTRaR8yVVh/M=",
"path": "github.com/inconshreveable/log15",
"revision": "39bacc234bf1afd0b68573e95b45871f67ba2cd4",
"revisionTime": "2017-02-16T22:56:31Z"
},
{
"checksumSHA1": "oVIIInZXKkcRozJfuH2vWJsAS7s=",
"path": "github.com/inconshreveable/log15/term",
"revision": "39bacc234bf1afd0b68573e95b45871f67ba2cd4",
"revisionTime": "2017-02-16T22:56:31Z"
},
{
"checksumSHA1": "BM6ZlNJmtKy3GBoWwg2X55gnZ4A=",
"path": "github.com/klauspost/crc32",