Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into graph-legend-to-r…
Browse files Browse the repository at this point in the history
…eact
  • Loading branch information
alexanderzobnin committed Oct 25, 2018
2 parents e4b3f31 + df7915f commit 533f358
Show file tree
Hide file tree
Showing 44 changed files with 2,180 additions and 1,571 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,23 @@

* Postgres/MySQL/MSSQL datasources now per default uses `max open connections` = `unlimited` (earlier 10), `max idle connections` = `2` (earlier 10) and `connection max lifetime` = `4` hours (earlier unlimited)

# 5.3.2 (unreleased)
# 5.3.2 (2018-10-24)

* **InfluxDB/Graphite/Postgres**: Prevent cross site scripting (XSS) in query editor [#13667](https://github.com/grafana/grafana/issues/13667), thx [@svenklemm](https://github.com/svenklemm)
* **Postgres**: Fix template variables error [#13692](https://github.com/grafana/grafana/issues/13692), thx [@svenklemm](https://github.com/svenklemm)
* **Cloudwatch**: Fix service panic because of race conditions [#13674](https://github.com/grafana/grafana/issues/13674), thx [@mtanda](https://github.com/mtanda)
* **Cloudwatch**: Fix check for invalid percentile statistics [#13633](https://github.com/grafana/grafana/issues/13633), thx [@apalaniuk](https://github.com/apalaniuk)
* **Stackdriver/Cloudwatch**: Allow user to change unit in graph panel if cloudwatch/stackdriver datasource response doesn't include unit [#13718](https://github.com/grafana/grafana/issues/13718), thx [@mtanda](https://github.com/mtanda)
* **Stackdriver**: stackdriver user-metrics duplicated response when multiple resource types [#13691](https://github.com/grafana/grafana/issues/13691)
* **Variables**: Fix text box template variable doesn't work properly without a default value [#13666](https://github.com/grafana/grafana/issues/13666)
* **Variables**: Fix variable dependency check when using `${var}` format [#13600](https://github.com/grafana/grafana/issues/13600)
* **Dashboard**: Fix kiosk=1 url parameter should put dashboard in kiosk mode [#13764](https://github.com/grafana/grafana/pull/13764)
* **LDAP**: Fix super admins can also be admins of orgs [#13710](https://github.com/grafana/grafana/issues/13710), thx [@adrien-f](https://github.com/adrien-f)
* **Provisioning**: Fix deleting provisioned dashboard folder should cleanup provisioning meta data [#13280](https://github.com/grafana/grafana/issues/13280)

### Minor

* **Docker**: adds curl back into the docker image for utility. [#13794](https://github.com/grafana/grafana/pull/13794)

# 5.3.1 (2018-10-16)

Expand Down
2 changes: 1 addition & 1 deletion docs/sources/alerting/notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ In DingTalk PC Client:

6. There will be a Webhook URL in the panel, looks like this: https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxx. Copy this URL to the grafana Dingtalk setting page and then click "finish".

Dingtalk supports the following "message type": `text`, `link` and `markdown`. Only the `text` message type is supported.
Dingtalk supports the following "message type": `text`, `link` and `markdown`. Only the `link` message type is supported.

### Kafka

Expand Down
10 changes: 10 additions & 0 deletions docs/sources/features/datasources/stackdriver.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ Example Alias By: `{{metric.type}} - {{metric.labels.instance_name}}`

Example Result: `compute.googleapis.com/instance/cpu/usage_time - server1-prod`

It is also possible to resolve the name of the Monitored Resource Type.

| Alias Pattern Format | Description | Example Result |
| ------------------------ | ------------------------------------------------| ---------------- |
| `{{resource.type}}` | returns the name of the monitored resource type | `gce_instance` |

Example Alias By: `{{resource.type}} - {{metric.type}}`

Example Result: `gce_instance - compute.googleapis.com/instance/cpu/usage_time`

## Templating

Instead of hard-coding things like server, application and sensor name in you metric queries you can use variables in their place.
Expand Down
7 changes: 6 additions & 1 deletion docs/sources/tutorials/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
+++
title = "Tutorials"
type = "docs"
[menu.docs]
identifier = "tutorials"
weight = 6
Expand All @@ -11,7 +12,11 @@ This section of the docs contains a series for tutorials and stack setup guides.

## Articles

- [How to integrate Hubot with Grafana](hubot_howto.md)
- [Running Grafana behind a reverse proxy]({{< relref "behind_proxy.md" >}})
- [API Tutorial: How To Create API Tokens And Dashboards For A Specific Organization]({{< relref "api_org_token_howto.md" >}})
- [How to Use IIS with URL Rewrite as a Reverse Proxy for Grafana on Windows]({{< relref "iis.md" >}})
- [How to integrate Hubot with Grafana]({{< relref "hubot_howto.md" >}})
- [How to setup Grafana for high availability]({{< relref "ha_setup.md" >}})

## External links

Expand Down
4 changes: 2 additions & 2 deletions latest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"stable": "5.3.1",
"testing": "5.3.1"
"stable": "5.3.2",
"testing": "5.3.2"
}
2 changes: 1 addition & 1 deletion packaging/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ ENV PATH=/usr/share/grafana/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bi

WORKDIR $GF_PATHS_HOME

RUN apt-get update && apt-get install -qq -y libfontconfig ca-certificates && \
RUN apt-get update && apt-get install -qq -y libfontconfig ca-certificates curl && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*

Expand Down
3 changes: 3 additions & 0 deletions pkg/services/alerting/notifiers/dingding.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error {
message := evalContext.Rule.Message
picUrl := evalContext.ImagePublicUrl
title := evalContext.GetNotificationTitle()
if message == "" {
message = title
}

bodyJSON, err := simplejson.NewJson([]byte(`{
"msgtype": "link",
Expand Down
7 changes: 6 additions & 1 deletion pkg/services/sqlstore/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,18 @@ func DeleteDashboard(cmd *m.DeleteDashboardCommand) error {
"DELETE FROM dashboard WHERE id = ?",
"DELETE FROM playlist_item WHERE type = 'dashboard_by_id' AND value = ?",
"DELETE FROM dashboard_version WHERE dashboard_id = ?",
"DELETE FROM dashboard WHERE folder_id = ?",
"DELETE FROM annotation WHERE dashboard_id = ?",
"DELETE FROM dashboard_provisioning WHERE dashboard_id = ?",
}

if dashboard.IsFolder {
deletes = append(deletes, "DELETE FROM dashboard_provisioning WHERE dashboard_id in (select id from dashboard where folder_id = ?)")
deletes = append(deletes, "DELETE FROM dashboard WHERE folder_id = ?")
}

for _, sql := range deletes {
_, err := sess.Exec(sql, dashboard.Id)

if err != nil {
return err
}
Expand Down
32 changes: 30 additions & 2 deletions pkg/services/sqlstore/dashboard_provisioning_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,30 @@ func TestDashboardProvisioningTest(t *testing.T) {
Convey("Testing Dashboard provisioning", t, func() {
InitTestDB(t)

saveDashboardCmd := &models.SaveDashboardCommand{
folderCmd := &models.SaveDashboardCommand{
OrgId: 1,
FolderId: 0,
IsFolder: true,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dashboard",
}),
}

err := SaveDashboard(folderCmd)
So(err, ShouldBeNil)

saveDashboardCmd := &models.SaveDashboardCommand{
OrgId: 1,
IsFolder: false,
FolderId: folderCmd.Result.Id,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dashboard",
}),
}

Convey("Saving dashboards with extras", func() {
Convey("Saving dashboards with provisioning meta data", func() {
now := time.Now()

cmd := &models.SaveProvisionedDashboardCommand{
Expand Down Expand Up @@ -67,6 +80,21 @@ func TestDashboardProvisioningTest(t *testing.T) {
So(err, ShouldBeNil)
So(query.Result, ShouldBeFalse)
})

Convey("Deleteing folder should delete provision meta data", func() {
deleteCmd := &models.DeleteDashboardCommand{
Id: folderCmd.Result.Id,
OrgId: 1,
}

So(DeleteDashboard(deleteCmd), ShouldBeNil)

query := &models.IsDashboardProvisionedQuery{DashboardId: cmd.Result.Id}

err = GetProvisionedDataByDashboardId(query)
So(err, ShouldBeNil)
So(query.Result, ShouldBeFalse)
})
})
})
}
23 changes: 19 additions & 4 deletions pkg/tsdb/stackdriver/stackdriver.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,11 +355,21 @@ func (e *StackdriverExecutor) unmarshalResponse(res *http.Response) (Stackdriver
func (e *StackdriverExecutor) parseResponse(queryRes *tsdb.QueryResult, data StackdriverResponse, query *StackdriverQuery) error {
metricLabels := make(map[string][]string)
resourceLabels := make(map[string][]string)
var resourceTypes []string

for _, series := range data.TimeSeries {
if !containsLabel(resourceTypes, series.Resource.Type) {
resourceTypes = append(resourceTypes, series.Resource.Type)
}
}

for _, series := range data.TimeSeries {
points := make([]tsdb.TimePoint, 0)

defaultMetricName := series.Metric.Type
if len(resourceTypes) > 1 {
defaultMetricName += " " + series.Resource.Type
}

for key, value := range series.Metric.Labels {
if !containsLabel(metricLabels[key], value) {
Expand Down Expand Up @@ -403,7 +413,7 @@ func (e *StackdriverExecutor) parseResponse(queryRes *tsdb.QueryResult, data Sta
points = append(points, tsdb.NewTimePoint(null.FloatFrom(value), float64((point.Interval.EndTime).Unix())*1000))
}

metricName := formatLegendKeys(series.Metric.Type, defaultMetricName, series.Metric.Labels, series.Resource.Labels, make(map[string]string), query)
metricName := formatLegendKeys(series.Metric.Type, defaultMetricName, series.Resource.Type, series.Metric.Labels, series.Resource.Labels, make(map[string]string), query)

queryRes.Series = append(queryRes.Series, &tsdb.TimeSeries{
Name: metricName,
Expand All @@ -429,7 +439,7 @@ func (e *StackdriverExecutor) parseResponse(queryRes *tsdb.QueryResult, data Sta
bucketBound := calcBucketBound(point.Value.DistributionValue.BucketOptions, i)
additionalLabels := map[string]string{"bucket": bucketBound}
buckets[i] = &tsdb.TimeSeries{
Name: formatLegendKeys(series.Metric.Type, defaultMetricName, series.Metric.Labels, series.Resource.Labels, additionalLabels, query),
Name: formatLegendKeys(series.Metric.Type, defaultMetricName, series.Resource.Type, series.Metric.Labels, series.Resource.Labels, additionalLabels, query),
Points: make([]tsdb.TimePoint, 0),
}
if maxKey < i {
Expand All @@ -445,7 +455,7 @@ func (e *StackdriverExecutor) parseResponse(queryRes *tsdb.QueryResult, data Sta
bucketBound := calcBucketBound(point.Value.DistributionValue.BucketOptions, i)
additionalLabels := map[string]string{"bucket": bucketBound}
buckets[i] = &tsdb.TimeSeries{
Name: formatLegendKeys(series.Metric.Type, defaultMetricName, series.Metric.Labels, series.Resource.Labels, additionalLabels, query),
Name: formatLegendKeys(series.Metric.Type, defaultMetricName, series.Resource.Type, series.Metric.Labels, series.Resource.Labels, additionalLabels, query),
Points: make([]tsdb.TimePoint, 0),
}
}
Expand All @@ -460,6 +470,7 @@ func (e *StackdriverExecutor) parseResponse(queryRes *tsdb.QueryResult, data Sta
queryRes.Meta.Set("resourceLabels", resourceLabels)
queryRes.Meta.Set("metricLabels", metricLabels)
queryRes.Meta.Set("groupBys", query.GroupBys)
queryRes.Meta.Set("resourceTypes", resourceTypes)

return nil
}
Expand All @@ -473,7 +484,7 @@ func containsLabel(labels []string, newLabel string) bool {
return false
}

func formatLegendKeys(metricType string, defaultMetricName string, metricLabels map[string]string, resourceLabels map[string]string, additionalLabels map[string]string, query *StackdriverQuery) string {
func formatLegendKeys(metricType string, defaultMetricName string, resourceType string, metricLabels map[string]string, resourceLabels map[string]string, additionalLabels map[string]string, query *StackdriverQuery) string {
if query.AliasBy == "" {
return defaultMetricName
}
Expand All @@ -487,6 +498,10 @@ func formatLegendKeys(metricType string, defaultMetricName string, metricLabels
return []byte(metricType)
}

if metaPartName == "resource.type" && resourceType != "" {
return []byte(resourceType)
}

metricPart := replaceWithMetricPart(metaPartName, metricType)

if metricPart != nil {
Expand Down
1 change: 1 addition & 0 deletions public/app/core/components/help/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export class HelpCtrl {
{ keys: ['p', 's'], description: 'Open Panel Share Modal' },
{ keys: ['p', 'd'], description: 'Duplicate Panel' },
{ keys: ['p', 'r'], description: 'Remove Panel' },
{ keys: ['p', 'l'], description: 'Toggle panel legend' },
],
'Time Range': [
{ keys: ['t', 'z'], description: 'Zoom out time range' },
Expand Down
12 changes: 12 additions & 0 deletions public/app/core/services/keybindingSrv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,18 @@ export class KeybindingSrv {
}
});

// toggle panel legend
this.bind('p l', () => {
if (dashboard.meta.focusPanelId) {
const panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId);
if (panelInfo.panel.legend) {
const panelRef = dashboard.getPanelById(dashboard.meta.focusPanelId);
panelRef.legend.show = !panelRef.legend.show;
panelRef.refresh();
}
}
});

// collapse all rows
this.bind('d shift+c', () => {
dashboard.collapseRows();
Expand Down
Loading

0 comments on commit 533f358

Please sign in to comment.