From e944803f10e6bf2ad0bf9f572bc6cd4ed659bff0 Mon Sep 17 00:00:00 2001 From: nikoalch <33036213+nikoalch@users.noreply.github.com> Date: Wed, 11 Jul 2018 08:13:15 -0700 Subject: [PATCH 001/155] Update debian.md added local login info --- docs/sources/installation/debian.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sources/installation/debian.md b/docs/sources/installation/debian.md index 4bb245a586e..d3d1e3db4b2 100644 --- a/docs/sources/installation/debian.md +++ b/docs/sources/installation/debian.md @@ -100,6 +100,8 @@ This will start the `grafana-server` process as the `grafana` user, which was created during the package installation. The default HTTP port is `3000` and default user and group is `admin`. +Default login and password `admin`/ `admin` + To configure the Grafana server to start at boot time: ```bash From bcb11d6747fd8ec960608c052760d1efa386f1c0 Mon Sep 17 00:00:00 2001 From: nikoalch <33036213+nikoalch@users.noreply.github.com> Date: Wed, 11 Jul 2018 08:13:48 -0700 Subject: [PATCH 002/155] Update rpm.md added local login info --- docs/sources/installation/rpm.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sources/installation/rpm.md b/docs/sources/installation/rpm.md index 13597b9d921..0a3aaf9995f 100644 --- a/docs/sources/installation/rpm.md +++ b/docs/sources/installation/rpm.md @@ -115,6 +115,8 @@ This will start the `grafana-server` process as the `grafana` user, which is created during package installation. The default HTTP port is `3000`, and default user and group is `admin`. +Default login and password `admin`/ `admin` + To configure the Grafana server to start at boot time: ```bash From a0e1f58815a1bed873fe645816be58a5fc8dd5f4 Mon Sep 17 00:00:00 2001 From: nikoalch <33036213+nikoalch@users.noreply.github.com> Date: Wed, 11 Jul 2018 08:14:25 -0700 Subject: [PATCH 003/155] Update windows.md --- docs/sources/installation/windows.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/sources/installation/windows.md b/docs/sources/installation/windows.md index 5dc87984512..dd8a2a6c3ee 100644 --- a/docs/sources/installation/windows.md +++ b/docs/sources/installation/windows.md @@ -31,6 +31,9 @@ on windows. Edit `custom.ini` and uncomment the `http_port` configuration option (`;` is the comment character in ini files) and change it to something like `8080` or similar. That port should not require extra Windows privileges. +Default login and password `admin`/ `admin` + + Start Grafana by executing `grafana-server.exe`, located in the `bin` directory, preferably from the command line. If you want to run Grafana as windows service, download [NSSM](https://nssm.cc/). It is very easy to add Grafana as a Windows From f34f5008baae06a4f260e27454157921872f1cc1 Mon Sep 17 00:00:00 2001 From: nikoalch <33036213+nikoalch@users.noreply.github.com> Date: Wed, 11 Jul 2018 08:15:23 -0700 Subject: [PATCH 004/155] Update mac.md added local login info --- docs/sources/installation/mac.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sources/installation/mac.md b/docs/sources/installation/mac.md index 12ff4adaab9..b09958a58ae 100644 --- a/docs/sources/installation/mac.md +++ b/docs/sources/installation/mac.md @@ -60,6 +60,8 @@ Then start Grafana using: brew services start grafana ``` +Default login and password `admin`/ `admin` + ### Configuration From e35f06b938b90750f162849f3831a905831d6168 Mon Sep 17 00:00:00 2001 From: Axel Pirek Date: Mon, 24 Sep 2018 14:33:45 +0200 Subject: [PATCH 005/155] Run all sql data source queries for one panel concurrently --- pkg/tsdb/sql_engine.go | 50 ++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/pkg/tsdb/sql_engine.go b/pkg/tsdb/sql_engine.go index 18e02e328d1..8dcf35a70bc 100644 --- a/pkg/tsdb/sql_engine.go +++ b/pkg/tsdb/sql_engine.go @@ -116,9 +116,7 @@ func (e *sqlQueryEndpoint) Query(ctx context.Context, dsInfo *models.DataSource, Results: make(map[string]*QueryResult), } - session := e.engine.NewSession() - defer session.Close() - db := session.DB() + var wg sync.WaitGroup for _, query := range tsdbQuery.Queries { rawSQL := query.Model.Get("rawSql").MustString() @@ -145,31 +143,41 @@ func (e *sqlQueryEndpoint) Query(ctx context.Context, dsInfo *models.DataSource, queryResult.Meta.Set("sql", rawSQL) - rows, err := db.Query(rawSQL) - if err != nil { - queryResult.Error = err - continue - } + wg.Add(1) - defer rows.Close() + go func(rawSQL string, query *Query, queryResult *QueryResult) { + defer wg.Done() + session := e.engine.NewSession() + defer session.Close() + db := session.DB() - format := query.Model.Get("format").MustString("time_series") - - switch format { - case "time_series": - err := e.transformToTimeSeries(query, rows, queryResult, tsdbQuery) + rows, err := db.Query(rawSQL) if err != nil { queryResult.Error = err - continue + return } - case "table": - err := e.transformToTable(query, rows, queryResult, tsdbQuery) - if err != nil { - queryResult.Error = err - continue + + defer rows.Close() + + format := query.Model.Get("format").MustString("time_series") + + switch format { + case "time_series": + err := e.transformToTimeSeries(query, rows, queryResult, tsdbQuery) + if err != nil { + queryResult.Error = err + return + } + case "table": + err := e.transformToTable(query, rows, queryResult, tsdbQuery) + if err != nil { + queryResult.Error = err + return + } } - } + }(rawSQL, query, queryResult) } + wg.Wait() return result, nil } From ac5d5859026cd4de6795d35053c63d1f98017e50 Mon Sep 17 00:00:00 2001 From: Leonard Gram Date: Mon, 24 Sep 2018 16:31:59 +0200 Subject: [PATCH 006/155] docs: whats new for 5.3 --- docs/sources/guides/whats-new-in-v5-3.md | 32 ++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/sources/guides/whats-new-in-v5-3.md b/docs/sources/guides/whats-new-in-v5-3.md index 4a2674c9b39..ed5238d1b94 100644 --- a/docs/sources/guides/whats-new-in-v5-3.md +++ b/docs/sources/guides/whats-new-in-v5-3.md @@ -12,6 +12,38 @@ weight = -9 # What's New in Grafana v5.3 +Grafana v5.3 brings new features, many enhancements and bug fixes. This article will detail the major new features and enhancements. + +- [TV mode]({{< relref "#tv-and-kiosk-mode" >}}) is improved +- [Alerting]({{< relref "#notification-reminders" >}}) with notification reminders +- [Postgres query builder]({{< relref "#postgres-query-builder" >}}) it's finally here! +- [OAuth]({{< relref "#improved-oauth-support-for-gitlab" >}}) support for Gitlab is improved + +## TV and kiosk mode + +We've improved the TV & kiosk mode to make it easier to use. There's now an icon in the top bar that will let you cycle through the different display modes. + +Clicks: + +1. (TV mode) Removes the sidebar and most of the buttons in the top bar +2. (Kiosk mode) Removes the top bar completely so that only the dashboard itself is showing + +Hit the escape key to go back to the default mode. + +**gif here** + +## Notification reminders + +Do you use Grafana alerting and have some notifications that are more important than others? Then it's possible to set reminders so that you get alerted until the problem is fixed. This is done on the notification channel itself and will affect all alerts that use that channel. Read more about reminders [here](http://docs.grafana.org/alerting/notifications/#send-reminders) + +## Postgres query builder + +Grafana 5.3 comes with a new graphical query builder for Postgres. Bringing Postgres integration more in line with some the other datasources and making it easier for both advanced and beginners to work with timeseries in Postgres. + +## Improved OAuth support for Gitlab + +Grafana 5.3 now supports filtering to specific groups when using Gitlab OAuth. This is makes it possible to use Gitlab OAuth with Grafana in a shared environment without giving access to Grafana to everyone. + ## Changelog Checkout the [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md) file for a complete list From 06d24df7b49ecaec30a1c07c21ed8d54f3a76bb9 Mon Sep 17 00:00:00 2001 From: Leonard Gram Date: Mon, 24 Sep 2018 16:58:39 +0200 Subject: [PATCH 007/155] docs: postgres gif. --- docs/sources/guides/whats-new-in-v5-3.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sources/guides/whats-new-in-v5-3.md b/docs/sources/guides/whats-new-in-v5-3.md index ed5238d1b94..d8e60517ecb 100644 --- a/docs/sources/guides/whats-new-in-v5-3.md +++ b/docs/sources/guides/whats-new-in-v5-3.md @@ -40,6 +40,8 @@ Do you use Grafana alerting and have some notifications that are more important Grafana 5.3 comes with a new graphical query builder for Postgres. Bringing Postgres integration more in line with some the other datasources and making it easier for both advanced and beginners to work with timeseries in Postgres. +{{< docs-imagebox img="/img/docs/v53/postgres_query_still.png" class="docs-image--no-shadow" animated-gif="/img/docs/v53/postgres_query.gif" >}} + ## Improved OAuth support for Gitlab Grafana 5.3 now supports filtering to specific groups when using Gitlab OAuth. This is makes it possible to use Gitlab OAuth with Grafana in a shared environment without giving access to Grafana to everyone. From dd09ece8c9d6afe063149e2b5358e7ef538b6d67 Mon Sep 17 00:00:00 2001 From: Axel Pirek Date: Mon, 24 Sep 2018 14:35:13 +0200 Subject: [PATCH 008/155] Make max open, max idle connections and connection max life time configurable --- pkg/tsdb/sql_engine.go | 8 ++++++-- .../datasource/mssql/partials/config.html | 18 ++++++++++++++++++ .../datasource/mysql/partials/config.html | 18 ++++++++++++++++++ .../datasource/postgres/partials/config.html | 18 ++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/pkg/tsdb/sql_engine.go b/pkg/tsdb/sql_engine.go index 8dcf35a70bc..60b1e68ebd8 100644 --- a/pkg/tsdb/sql_engine.go +++ b/pkg/tsdb/sql_engine.go @@ -98,8 +98,12 @@ var NewSqlQueryEndpoint = func(config *SqlQueryEndpointConfiguration, rowTransfo return nil, err } - engine.SetMaxOpenConns(10) - engine.SetMaxIdleConns(10) + maxOpenConns := config.Datasource.JsonData.Get("maxOpenConns").MustInt(0) + engine.SetMaxOpenConns(maxOpenConns) + maxIdleConns := config.Datasource.JsonData.Get("maxIdleConns").MustInt(2) + engine.SetMaxIdleConns(maxIdleConns) + connMaxLifetime := config.Datasource.JsonData.Get("connMaxLifetime").MustInt(14400) + engine.SetConnMaxLifetime(time.Duration(connMaxLifetime) * time.Second) engineCache.versions[config.Datasource.Id] = config.Datasource.Version engineCache.cache[config.Datasource.Id] = engine diff --git a/public/app/plugins/datasource/mssql/partials/config.html b/public/app/plugins/datasource/mssql/partials/config.html index f8a36502009..f59bf6ae267 100644 --- a/public/app/plugins/datasource/mssql/partials/config.html +++ b/public/app/plugins/datasource/mssql/partials/config.html @@ -29,6 +29,24 @@ +
+
+ Max open connections + +
+
+ Max idle connections + +
+
+ Connection lifetime + + + The connection lifetime in seconds. + +
+
+

MSSQL details

diff --git a/public/app/plugins/datasource/mysql/partials/config.html b/public/app/plugins/datasource/mysql/partials/config.html index 6bc9cceb8f1..8ddad1f47cc 100644 --- a/public/app/plugins/datasource/mysql/partials/config.html +++ b/public/app/plugins/datasource/mysql/partials/config.html @@ -24,6 +24,24 @@
+
+
+ Max open connections + +
+
+ Max idle connections + +
+
+ Connection lifetime + + + The connection lifetime in seconds. + +
+
+

MySQL details

diff --git a/public/app/plugins/datasource/postgres/partials/config.html b/public/app/plugins/datasource/postgres/partials/config.html index c8b551c2aa8..b0012faacbd 100644 --- a/public/app/plugins/datasource/postgres/partials/config.html +++ b/public/app/plugins/datasource/postgres/partials/config.html @@ -38,6 +38,24 @@
+
+
+ Max open connections + +
+
+ Max idle connections + +
+
+ Connection lifetime + + + The connection lifetime in seconds. + +
+
+

PostgreSQL details

From 12230dfa71892da2fcaf8426195edf611ba72e91 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 2 Oct 2018 17:43:15 +0200 Subject: [PATCH 009/155] ux: put connection limits under own section --- .../datasource/mssql/partials/config.html | 43 ++++++++++++------- .../datasource/mysql/partials/config.html | 43 ++++++++++++------- .../datasource/postgres/partials/config.html | 43 ++++++++++++------- 3 files changed, 84 insertions(+), 45 deletions(-) diff --git a/public/app/plugins/datasource/mssql/partials/config.html b/public/app/plugins/datasource/mssql/partials/config.html index f59bf6ae267..4cb42e90f7c 100644 --- a/public/app/plugins/datasource/mssql/partials/config.html +++ b/public/app/plugins/datasource/mssql/partials/config.html @@ -29,22 +29,35 @@
+Connection limits +
-
- Max open connections - -
-
- Max idle connections - -
-
- Connection lifetime - - - The connection lifetime in seconds. - -
+
+ Max open + + + The maximum number of open connections to the database. If Max idle connections is greater than 0 and the + Max open connections is less than Max idle connections, then Max idle connections will be + reduced to match the Max open connections limit. If set to 0, there is no limit on the number of open + connections. + +
+
+ Max idle + + + The maximum number of connections in the idle connection pool. If Max open connections is greater than 0 but + less than the Max idle connections, then the Max idle connections will be reduced to match the + Max open connections limit. If set to 0, no idle connections are retained. + +
+
+ Max lifetime + + + The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused forever. + +

MSSQL details

diff --git a/public/app/plugins/datasource/mysql/partials/config.html b/public/app/plugins/datasource/mysql/partials/config.html index 8ddad1f47cc..3d27dd38bf5 100644 --- a/public/app/plugins/datasource/mysql/partials/config.html +++ b/public/app/plugins/datasource/mysql/partials/config.html @@ -24,22 +24,35 @@ +Connection limits +
-
- Max open connections - -
-
- Max idle connections - -
-
- Connection lifetime - - - The connection lifetime in seconds. - -
+
+ Max open + + + The maximum number of open connections to the database. If Max idle connections is greater than 0 and the + Max open connections is less than Max idle connections, then Max idle connections will be + reduced to match the Max open connections limit. If set to 0, there is no limit on the number of open + connections. + +
+
+ Max idle + + + The maximum number of connections in the idle connection pool. If Max open connections is greater than 0 but + less than the Max idle connections, then the Max idle connections will be reduced to match the + Max open connections limit. If set to 0, no idle connections are retained. + +
+
+ Max lifetime + + + The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused forever. + +

MySQL details

diff --git a/public/app/plugins/datasource/postgres/partials/config.html b/public/app/plugins/datasource/postgres/partials/config.html index b0012faacbd..13b74d6b20e 100644 --- a/public/app/plugins/datasource/postgres/partials/config.html +++ b/public/app/plugins/datasource/postgres/partials/config.html @@ -38,22 +38,35 @@ +Connection limits +
-
- Max open connections - -
-
- Max idle connections - -
-
- Connection lifetime - - - The connection lifetime in seconds. - -
+
+ Max open + + + The maximum number of open connections to the database. If Max idle connections is greater than 0 and the + Max open connections is less than Max idle connections, then Max idle connections will be + reduced to match the Max open connections limit. If set to 0, there is no limit on the number of open + connections. + +
+
+ Max idle + + + The maximum number of connections in the idle connection pool. If Max open connections is greater than 0 but + less than the Max idle connections, then the Max idle connections will be reduced to match the + Max open connections limit. If set to 0, no idle connections are retained. + +
+
+ Max lifetime + + + The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused forever. + +

PostgreSQL details

From e5c376aeadd230f70d9b1f7f38ad023c31fea7bb Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 2 Oct 2018 17:43:54 +0200 Subject: [PATCH 010/155] docs: connection limits for sql datasources --- docs/sources/administration/provisioning.md | 3 +++ docs/sources/features/datasources/mssql.md | 7 +++++++ docs/sources/features/datasources/mysql.md | 7 +++++++ docs/sources/features/datasources/postgres.md | 6 ++++++ 4 files changed, 23 insertions(+) diff --git a/docs/sources/administration/provisioning.md b/docs/sources/administration/provisioning.md index a026d1ec0cd..587e1411c26 100644 --- a/docs/sources/administration/provisioning.md +++ b/docs/sources/administration/provisioning.md @@ -168,6 +168,9 @@ Since not all datasources have the same configuration settings we only have the | sslmode | string | PostgreSQL | SSLmode. 'disable', 'require', 'verify-ca' or 'verify-full' | | postgresVersion | number | PostgreSQL | Postgres version as a number (903/904/905/906/1000) meaning v9.3, v9.4, ..., v10 | | timescaledb | boolean | PostgreSQL | Enable usage of TimescaleDB extension | +| maxOpenConns | number | MySQL, PostgreSQL & MSSQL | Maximum number of open connections to the database | +| maxIdleConns | number | MySQL, PostgreSQL & MSSQL | Maximum number of connections in the idle connection pool | +| connMaxLifetime | number | MySQL, PostgreSQL & MSSQL | Maximum amount of time in seconds a connection may be reused | #### Secure Json Data diff --git a/docs/sources/features/datasources/mssql.md b/docs/sources/features/datasources/mssql.md index debf771ffb0..a3e350ab47b 100644 --- a/docs/sources/features/datasources/mssql.md +++ b/docs/sources/features/datasources/mssql.md @@ -32,6 +32,9 @@ Name | Description *Database* | Name of your MSSQL database. *User* | Database user's login/username *Password* | Database user's password +*Max open* | The maximum number of open connections to the database, default `unlimited`. +*Max idle* | The maximum number of connections in the idle connection pool, default `2`. +*Max lifetime* | The maximum amount of time in seconds a connection may be reused, default `14400` (4 hours). ### Min time interval @@ -585,6 +588,10 @@ datasources: url: localhost:1433 database: grafana user: grafana + jsonData: + maxOpenConns: 0 + maxIdleConns: 2 + connMaxLifetime: 14400 secureJsonData: password: "Password!" diff --git a/docs/sources/features/datasources/mysql.md b/docs/sources/features/datasources/mysql.md index d713a4b42b7..8cb6dea785d 100644 --- a/docs/sources/features/datasources/mysql.md +++ b/docs/sources/features/datasources/mysql.md @@ -35,6 +35,9 @@ Name | Description *Database* | Name of your MySQL database. *User* | Database user's login/username *Password* | Database user's password +*Max open* | The maximum number of open connections to the database, default `unlimited`. +*Max idle* | The maximum number of connections in the idle connection pool, default `2`. +*Max lifetime* | The maximum amount of time in seconds a connection may be reused, default `14400` (4 hours). ### Min time interval @@ -316,4 +319,8 @@ datasources: database: grafana user: grafana password: password + jsonData: + maxOpenConns: 0 + maxIdleConns: 2 + connMaxLifetime: 14400 ``` diff --git a/docs/sources/features/datasources/postgres.md b/docs/sources/features/datasources/postgres.md index 7076ff033b3..07413ad6510 100644 --- a/docs/sources/features/datasources/postgres.md +++ b/docs/sources/features/datasources/postgres.md @@ -31,6 +31,9 @@ Name | Description *User* | Database user's login/username *Password* | Database user's password *SSL Mode* | This option determines whether or with what priority a secure SSL TCP/IP connection will be negotiated with the server. +*Max open* | The maximum number of open connections to the database, default `unlimited`. +*Max idle* | The maximum number of connections in the idle connection pool, default `2`. +*Max lifetime* | The maximum amount of time in seconds a connection may be reused, default `14400` (4 hours). *Version* | This option determines which functions are available in the query builder (only available in Grafana 5.3+). *TimescaleDB* | TimescaleDB is a time-series database built as a PostgreSQL extension. If enabled, Grafana will use `time_bucket` in the `$__timeGroup` macro and display TimescaleDB specific aggregate functions in the query builder (only available in Grafana 5.3+). @@ -374,6 +377,9 @@ datasources: password: "Password!" jsonData: sslmode: "disable" # disable/require/verify-ca/verify-full + maxOpenConns: 0 + maxIdleConns: 2 + connMaxLifetime: 14400 postgresVersion: 903 # 903=9.3, 904=9.4, 905=9.5, 906=9.6, 1000=10 timescaledb: false ``` From 6770f2e9401547863048f58d88a52e3e9dbcb975 Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Tue, 2 Oct 2018 19:42:30 +0900 Subject: [PATCH 011/155] stackdriver heatmap support --- pkg/tsdb/stackdriver/stackdriver.go | 126 +++++++++++++----- pkg/tsdb/stackdriver/types.go | 40 +++++- .../datasource/stackdriver/constants.ts | 2 +- 3 files changed, 133 insertions(+), 35 deletions(-) diff --git a/pkg/tsdb/stackdriver/stackdriver.go b/pkg/tsdb/stackdriver/stackdriver.go index 586e154cd5d..ebf468be877 100644 --- a/pkg/tsdb/stackdriver/stackdriver.go +++ b/pkg/tsdb/stackdriver/stackdriver.go @@ -300,29 +300,6 @@ func (e *StackdriverExecutor) parseResponse(queryRes *tsdb.QueryResult, data Sta for _, series := range data.TimeSeries { points := make([]tsdb.TimePoint, 0) - // reverse the order to be ascending - for i := len(series.Points) - 1; i >= 0; i-- { - point := series.Points[i] - value := point.Value.DoubleValue - - if series.ValueType == "INT64" { - parsedValue, err := strconv.ParseFloat(point.Value.IntValue, 64) - if err == nil { - value = parsedValue - } - } - - if series.ValueType == "BOOL" { - if point.Value.BoolValue { - value = 1 - } else { - value = 0 - } - } - - points = append(points, tsdb.NewTimePoint(null.FloatFrom(value), float64((point.Interval.EndTime).Unix())*1000)) - } - defaultMetricName := series.Metric.Type for key, value := range series.Metric.Labels { @@ -338,18 +315,87 @@ func (e *StackdriverExecutor) parseResponse(queryRes *tsdb.QueryResult, data Sta if !containsLabel(resourceLabels[key], value) { resourceLabels[key] = append(resourceLabels[key], value) } - if containsLabel(query.GroupBys, "resource.label."+key) { defaultMetricName += " " + value } } - metricName := formatLegendKeys(series.Metric.Type, defaultMetricName, series.Metric.Labels, series.Resource.Labels, query) + // reverse the order to be ascending + if series.ValueType != "DISTRIBUTION" { + for i := len(series.Points) - 1; i >= 0; i-- { + point := series.Points[i] + value := point.Value.DoubleValue - queryRes.Series = append(queryRes.Series, &tsdb.TimeSeries{ - Name: metricName, - Points: points, - }) + if series.ValueType == "INT64" { + parsedValue, err := strconv.ParseFloat(point.Value.IntValue, 64) + if err == nil { + value = parsedValue + } + } + + if series.ValueType == "BOOL" { + if point.Value.BoolValue { + value = 1 + } else { + value = 0 + } + } + + 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) + + queryRes.Series = append(queryRes.Series, &tsdb.TimeSeries{ + Name: metricName, + Points: points, + }) + } else { + buckets := make(map[int]*tsdb.TimeSeries) + + for i := len(series.Points) - 1; i >= 0; i-- { + point := series.Points[i] + if len(point.Value.DistributionValue.BucketCounts) == 0 { + continue + } + maxKey := 0 + for i := 0; i < len(point.Value.DistributionValue.BucketCounts); i++ { + value, err := strconv.ParseFloat(point.Value.DistributionValue.BucketCounts[i], 64) + if err != nil { + continue + } + if _, ok := buckets[i]; !ok { + // set lower bounds + // https://cloud.google.com/monitoring/api/ref_v3/rest/v3/TimeSeries#Distribution + 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), + Points: make([]tsdb.TimePoint, 0), + } + if maxKey < i { + maxKey = i + } + } + buckets[i].Points = append(buckets[i].Points, tsdb.NewTimePoint(null.FloatFrom(value), float64((point.Interval.EndTime).Unix())*1000)) + } + + // fill empty bucket + for i := 0; i < maxKey; i++ { + if _, ok := buckets[i]; !ok { + 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), + Points: make([]tsdb.TimePoint, 0), + } + } + } + } + for i := 0; i < len(buckets); i++ { + queryRes.Series = append(queryRes.Series, buckets[i]) + } + } } queryRes.Meta.Set("resourceLabels", resourceLabels) @@ -368,7 +414,7 @@ func containsLabel(labels []string, newLabel string) bool { return false } -func formatLegendKeys(metricType string, defaultMetricName string, metricLabels map[string]string, resourceLabels map[string]string, query *StackdriverQuery) string { +func formatLegendKeys(metricType string, defaultMetricName string, metricLabels map[string]string, resourceLabels map[string]string, additionalLabels map[string]string, query *StackdriverQuery) string { if query.AliasBy == "" { return defaultMetricName } @@ -400,6 +446,10 @@ func formatLegendKeys(metricType string, defaultMetricName string, metricLabels return []byte(val) } + if val, exists := additionalLabels[metaPartName]; exists { + return []byte(val) + } + return in }) @@ -425,6 +475,22 @@ func replaceWithMetricPart(metaPartName string, metricType string) []byte { return nil } +func calcBucketBound(bucketOptions StackdriverBucketOptions, n int) string { + bucketBound := "0" + if n == 0 { + return bucketBound + } + + if bucketOptions.LinearBuckets != nil { + bucketBound = strconv.FormatInt(bucketOptions.LinearBuckets.Offset+(bucketOptions.LinearBuckets.Width*int64(n-1)), 10) + } else if bucketOptions.ExponentialBuckets != nil { + bucketBound = strconv.FormatInt(int64(bucketOptions.ExponentialBuckets.Scale*math.Pow(bucketOptions.ExponentialBuckets.GrowthFactor, float64(n-1))), 10) + } else if bucketOptions.ExplicitBuckets != nil { + bucketBound = strconv.FormatInt(bucketOptions.ExplicitBuckets.Bounds[(n-1)], 10) + } + return bucketBound +} + func (e *StackdriverExecutor) createRequest(ctx context.Context, dsInfo *models.DataSource) (*http.Request, error) { u, _ := url.Parse(dsInfo.Url) u.Path = path.Join(u.Path, "render") diff --git a/pkg/tsdb/stackdriver/types.go b/pkg/tsdb/stackdriver/types.go index c58ac2968f2..3821ce7ceda 100644 --- a/pkg/tsdb/stackdriver/types.go +++ b/pkg/tsdb/stackdriver/types.go @@ -14,6 +14,22 @@ type StackdriverQuery struct { AliasBy string } +type StackdriverBucketOptions struct { + LinearBuckets *struct { + NumFiniteBuckets int64 `json:"numFiniteBuckets"` + Width int64 `json:"width"` + Offset int64 `json:"offset"` + } `json:"linearBuckets"` + ExponentialBuckets *struct { + NumFiniteBuckets int64 `json:"numFiniteBuckets"` + GrowthFactor float64 `json:"growthFactor"` + Scale float64 `json:"scale"` + } `json:"exponentialBuckets"` + ExplicitBuckets *struct { + Bounds []int64 `json:"bounds"` + } `json:"explicitBuckets"` +} + // StackdriverResponse is the data returned from the external Google Stackdriver API type StackdriverResponse struct { TimeSeries []struct { @@ -33,10 +49,26 @@ type StackdriverResponse struct { EndTime time.Time `json:"endTime"` } `json:"interval"` Value struct { - DoubleValue float64 `json:"doubleValue"` - StringValue string `json:"stringValue"` - BoolValue bool `json:"boolValue"` - IntValue string `json:"int64Value"` + DoubleValue float64 `json:"doubleValue"` + StringValue string `json:"stringValue"` + BoolValue bool `json:"boolValue"` + IntValue string `json:"int64Value"` + DistributionValue struct { + Count string `json:"count"` + Mean float64 `json:"mean"` + SumOfSquaredDeviation float64 `json:"sumOfSquaredDeviation"` + Range struct { + Min int `json:"min"` + Max int `json:"max"` + } `json:"range"` + BucketOptions StackdriverBucketOptions `json:"bucketOptions"` + BucketCounts []string `json:"bucketCounts"` + Examplars []struct { + Value float64 `json:"value"` + Timestamp string `json:"timestamp"` + // attachments + } `json:"examplars"` + } `json:"distributionValue"` } `json:"value"` } `json:"points"` } `json:"timeSeries"` diff --git a/public/app/plugins/datasource/stackdriver/constants.ts b/public/app/plugins/datasource/stackdriver/constants.ts index 628e480c3db..b11f4a1bcb1 100644 --- a/public/app/plugins/datasource/stackdriver/constants.ts +++ b/public/app/plugins/datasource/stackdriver/constants.ts @@ -19,7 +19,7 @@ export const alignOptions = [ { text: 'delta', value: 'ALIGN_DELTA', - valueTypes: [ValueTypes.INT64, ValueTypes.DOUBLE, ValueTypes.MONEY], + valueTypes: [ValueTypes.INT64, ValueTypes.DOUBLE, ValueTypes.MONEY, ValueTypes.DISTRIBUTION], metricKinds: [MetricKind.CUMULATIVE, MetricKind.DELTA], }, { From c2c0cdb49c92126c39150b5aaaef766eb404511f Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Tue, 2 Oct 2018 22:45:54 +0900 Subject: [PATCH 012/155] add test --- pkg/tsdb/stackdriver/stackdriver_test.go | 42 +++++++ .../3-series-response-distribution.json | 112 ++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 pkg/tsdb/stackdriver/test-data/3-series-response-distribution.json diff --git a/pkg/tsdb/stackdriver/stackdriver_test.go b/pkg/tsdb/stackdriver/stackdriver_test.go index da4d6890207..1e8e9cea025 100644 --- a/pkg/tsdb/stackdriver/stackdriver_test.go +++ b/pkg/tsdb/stackdriver/stackdriver_test.go @@ -4,6 +4,8 @@ import ( "encoding/json" "fmt" "io/ioutil" + "math" + "strconv" "testing" "time" @@ -341,6 +343,46 @@ func TestStackdriver(t *testing.T) { }) }) }) + + Convey("when data from query is distribution", func() { + data, err := loadTestFile("./test-data/3-series-response-distribution.json") + So(err, ShouldBeNil) + So(len(data.TimeSeries), ShouldEqual, 1) + + res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"} + query := &StackdriverQuery{AliasBy: "{{bucket}}"} + err = executor.parseResponse(res, data, query) + So(err, ShouldBeNil) + + So(len(res.Series), ShouldEqual, 11) + for i := 0; i < 11; i++ { + if i == 0 { + So(res.Series[i].Name, ShouldEqual, "0") + } else { + So(res.Series[i].Name, ShouldEqual, strconv.FormatInt(int64(math.Pow(float64(2), float64(i-1))), 10)) + } + So(len(res.Series[i].Points), ShouldEqual, 3) + } + + Convey("timestamps should be in ascending order", func() { + So(res.Series[0].Points[0][1].Float64, ShouldEqual, 1536668940000) + So(res.Series[0].Points[1][1].Float64, ShouldEqual, 1536669000000) + So(res.Series[0].Points[2][1].Float64, ShouldEqual, 1536669060000) + }) + + Convey("value should be correct", func() { + So(res.Series[8].Points[0][0].Float64, ShouldEqual, 1) + So(res.Series[9].Points[0][0].Float64, ShouldEqual, 1) + So(res.Series[10].Points[0][0].Float64, ShouldEqual, 1) + So(res.Series[8].Points[1][0].Float64, ShouldEqual, 0) + So(res.Series[9].Points[1][0].Float64, ShouldEqual, 0) + So(res.Series[10].Points[1][0].Float64, ShouldEqual, 1) + So(res.Series[8].Points[2][0].Float64, ShouldEqual, 0) + So(res.Series[9].Points[2][0].Float64, ShouldEqual, 1) + So(res.Series[10].Points[2][0].Float64, ShouldEqual, 0) + }) + }) + }) }) } diff --git a/pkg/tsdb/stackdriver/test-data/3-series-response-distribution.json b/pkg/tsdb/stackdriver/test-data/3-series-response-distribution.json new file mode 100644 index 00000000000..8603f78eab4 --- /dev/null +++ b/pkg/tsdb/stackdriver/test-data/3-series-response-distribution.json @@ -0,0 +1,112 @@ +{ + "timeSeries": [ + { + "metric": { + "type": "loadbalancing.googleapis.com\/https\/backend_latencies" + }, + "resource": { + "type": "https_lb_rule", + "labels": { + "project_id": "grafana-prod" + } + }, + "metricKind": "DELTA", + "valueType": "DISTRIBUTION", + "points": [ + { + "interval": { + "startTime": "2018-09-11T12:30:00Z", + "endTime": "2018-09-11T12:31:00Z" + }, + "value": { + "distributionValue": { + "count": "1", + "bucketOptions": { + "exponentialBuckets": { + "numFiniteBuckets": 10, + "growthFactor": 2, + "scale": 1 + } + }, + "bucketCounts": [ + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "0" + ] + } + } + }, + { + "interval": { + "startTime": "2018-09-11T12:29:00Z", + "endTime": "2018-09-11T12:30:00Z" + }, + "value": { + "distributionValue": { + "count": "1", + "bucketOptions": { + "exponentialBuckets": { + "numFiniteBuckets": 10, + "growthFactor": 2, + "scale": 1 + } + }, + "bucketCounts": [ + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1" + ] + } + } + }, + { + "interval": { + "startTime": "2018-09-11T12:28:00Z", + "endTime": "2018-09-11T12:29:00Z" + }, + "value": { + "distributionValue": { + "count": "3", + "bucketOptions": { + "exponentialBuckets": { + "numFiniteBuckets": 10, + "growthFactor": 2, + "scale": 1 + } + }, + "bucketCounts": [ + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "1", + "1", + "1" + ] + } + } + } + ] + } + ] +} From 00843037d4aeb2120009a6eb761768f8cd21d73d Mon Sep 17 00:00:00 2001 From: Leonard Gram Date: Wed, 3 Oct 2018 13:56:43 +0200 Subject: [PATCH 013/155] docs: better wording and docs links. --- docs/sources/guides/whats-new-in-v5-3.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sources/guides/whats-new-in-v5-3.md b/docs/sources/guides/whats-new-in-v5-3.md index d8e60517ecb..5c5ff366fda 100644 --- a/docs/sources/guides/whats-new-in-v5-3.md +++ b/docs/sources/guides/whats-new-in-v5-3.md @@ -16,7 +16,7 @@ Grafana v5.3 brings new features, many enhancements and bug fixes. This article - [TV mode]({{< relref "#tv-and-kiosk-mode" >}}) is improved - [Alerting]({{< relref "#notification-reminders" >}}) with notification reminders -- [Postgres query builder]({{< relref "#postgres-query-builder" >}}) it's finally here! +- [Postgres]({{< relref "#postgres-query-builder" >}}) gets a new query builder! - [OAuth]({{< relref "#improved-oauth-support-for-gitlab" >}}) support for Gitlab is improved ## TV and kiosk mode @@ -38,13 +38,13 @@ Do you use Grafana alerting and have some notifications that are more important ## Postgres query builder -Grafana 5.3 comes with a new graphical query builder for Postgres. Bringing Postgres integration more in line with some the other datasources and making it easier for both advanced and beginners to work with timeseries in Postgres. +Grafana 5.3 comes with a new graphical query builder for Postgres. Bringing Postgres integration more in line with some of the other datasources and making it easier for both advanced and beginners to work with timeseries in Postgres. Learn more about it in the [documentation](http://docs.grafana.org/features/datasources/postgres/#query-editor). {{< docs-imagebox img="/img/docs/v53/postgres_query_still.png" class="docs-image--no-shadow" animated-gif="/img/docs/v53/postgres_query.gif" >}} ## Improved OAuth support for Gitlab -Grafana 5.3 now supports filtering to specific groups when using Gitlab OAuth. This is makes it possible to use Gitlab OAuth with Grafana in a shared environment without giving access to Grafana to everyone. +Grafana 5.3 gets native support for Gitlab OAuth with filtering to specific groups. This is makes it possible to use Gitlab OAuth with Grafana in a shared environment without giving everyone access to Grafana. More on usage in the [documentation](http://docs.grafana.org/auth/gitlab/). ## Changelog From d2dc770c793f07b12c50e3a58878155d0466fcf4 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Wed, 3 Oct 2018 17:10:41 +0200 Subject: [PATCH 014/155] various fixes and improvements --- docs/sources/guides/whats-new-in-v5-3.md | 36 +++++++++++++++++------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/docs/sources/guides/whats-new-in-v5-3.md b/docs/sources/guides/whats-new-in-v5-3.md index 5c5ff366fda..e52ad4aa7c3 100644 --- a/docs/sources/guides/whats-new-in-v5-3.md +++ b/docs/sources/guides/whats-new-in-v5-3.md @@ -14,37 +14,53 @@ weight = -9 Grafana v5.3 brings new features, many enhancements and bug fixes. This article will detail the major new features and enhancements. -- [TV mode]({{< relref "#tv-and-kiosk-mode" >}}) is improved +- [Google Stackdriver]({{< relref "#google-stackdriver" >}}) as a core datasource! +- [TV mode]({{< relref "#tv-and-kiosk-mode" >}}) is improved and more accessible - [Alerting]({{< relref "#notification-reminders" >}}) with notification reminders - [Postgres]({{< relref "#postgres-query-builder" >}}) gets a new query builder! - [OAuth]({{< relref "#improved-oauth-support-for-gitlab" >}}) support for Gitlab is improved +## Google Stackdriver + +Grafana v5.3 ships with built-in support for [Google Stackdriver](https://cloud.google.com/stackdriver/) and enables you to visualize your Stackdriver metrics in Grafana. + +The datasource is still in a `beta` phase meaning it's currently in active development and could be missing important features. +Please try it out, but be aware of that it might be subject to changes and possible bugs. We would love to hear your feedback. + +Please read [Using Google Stackdriver in Grafana](/features/datasources/stackdriver/) for more detailed information on how to get started and use it. + ## TV and kiosk mode -We've improved the TV & kiosk mode to make it easier to use. There's now an icon in the top bar that will let you cycle through the different display modes. +{{< docs-imagebox img="/img/docs/v53/tv_mode_still.png" max-width="600px" class="docs-image--no-shadow docs-image--right" animated-gif="/img/docs/v53/tv_mode.gif" >}} -Clicks: +We've improved the TV & kiosk mode to make it easier to use. There's now an icon in the top bar that will let you cycle through the different view modes. -1. (TV mode) Removes the sidebar and most of the buttons in the top bar -2. (Kiosk mode) Removes the top bar completely so that only the dashboard itself is showing +1. In the first view mode the sidebar and most of the buttons in the top bar will be hidden +2. In the second view mode the top bar is completely hidden so that only the dashboard itself is showing +3. Hit the escape key to go back to the default view mode -Hit the escape key to go back to the default mode. +When switching view modes the url will be updated to reflect the view mode selected. This allows a dashboard to be opened with a +certain view mode enabled. Additionally, this also enables [playlists](/reference/playlist) to be started with a certain view mode enabled. -**gif here** +
## Notification reminders -Do you use Grafana alerting and have some notifications that are more important than others? Then it's possible to set reminders so that you get alerted until the problem is fixed. This is done on the notification channel itself and will affect all alerts that use that channel. Read more about reminders [here](http://docs.grafana.org/alerting/notifications/#send-reminders) +Do you use Grafana alerting and have some notifications that are more important than others? Then it's possible to set reminders so that you get alerted until the problem is fixed. This is done on the notification channel itself and will affect all alerts that use that channel. +For additional examples of why reminders might be useful for you, see [multiple series](/alerting/rules/#multiple-series). + +Learn how to enable and configure reminders [here](/alerting/notifications/#send-reminders). ## Postgres query builder -Grafana 5.3 comes with a new graphical query builder for Postgres. Bringing Postgres integration more in line with some of the other datasources and making it easier for both advanced and beginners to work with timeseries in Postgres. Learn more about it in the [documentation](http://docs.grafana.org/features/datasources/postgres/#query-editor). +Grafana 5.3 comes with a new graphical query builder for Postgres. Bringing Postgres integration more in line with some of the other datasources and making it easier for both advanced and beginners to work with timeseries in Postgres. Learn more about it in the [documentation](/features/datasources/postgres/#query-editor). {{< docs-imagebox img="/img/docs/v53/postgres_query_still.png" class="docs-image--no-shadow" animated-gif="/img/docs/v53/postgres_query.gif" >}} ## Improved OAuth support for Gitlab -Grafana 5.3 gets native support for Gitlab OAuth with filtering to specific groups. This is makes it possible to use Gitlab OAuth with Grafana in a shared environment without giving everyone access to Grafana. More on usage in the [documentation](http://docs.grafana.org/auth/gitlab/). +Grafana 5.3 comes with a new OAuth integration for Gitlab that enables configuration to only allow users that are member of certain Gitlab groups to authenticate. This makes it possible to use Gitlab OAuth with Grafana in a shared environment without giving everyone access to Grafana. +Learn how to enable and configure it in the [documentation](/auth/gitlab/). ## Changelog From 79929c1f001f3d59477a19625b722fcf39f2ec23 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Thu, 4 Oct 2018 17:42:34 +0200 Subject: [PATCH 015/155] mysql: note about connection max lifetime and wait_timeout --- public/app/plugins/datasource/mysql/partials/config.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/app/plugins/datasource/mysql/partials/config.html b/public/app/plugins/datasource/mysql/partials/config.html index 3d27dd38bf5..a35633c626a 100644 --- a/public/app/plugins/datasource/mysql/partials/config.html +++ b/public/app/plugins/datasource/mysql/partials/config.html @@ -50,7 +50,8 @@ Max lifetime - The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused forever. + The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused forever.

+ This should always be lower than configured wait_timeout in MySQL.
From a44e8c5917ddbe9c8cb0db6775f624c77baba3e9 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Thu, 4 Oct 2018 17:46:16 +0200 Subject: [PATCH 016/155] docs: whats new in 5.3 - a few tweaks --- docs/sources/guides/whats-new-in-v5-3.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/sources/guides/whats-new-in-v5-3.md b/docs/sources/guides/whats-new-in-v5-3.md index e52ad4aa7c3..faf6c410291 100644 --- a/docs/sources/guides/whats-new-in-v5-3.md +++ b/docs/sources/guides/whats-new-in-v5-3.md @@ -24,42 +24,42 @@ Grafana v5.3 brings new features, many enhancements and bug fixes. This article Grafana v5.3 ships with built-in support for [Google Stackdriver](https://cloud.google.com/stackdriver/) and enables you to visualize your Stackdriver metrics in Grafana. -The datasource is still in a `beta` phase meaning it's currently in active development and could be missing important features. +The datasource is still in the `beta` phase, meaning it's currently in active development and is still missing a few important features (templating queries, support for metrics with distribution type). Please try it out, but be aware of that it might be subject to changes and possible bugs. We would love to hear your feedback. Please read [Using Google Stackdriver in Grafana](/features/datasources/stackdriver/) for more detailed information on how to get started and use it. -## TV and kiosk mode +## TV and Kiosk Mode {{< docs-imagebox img="/img/docs/v53/tv_mode_still.png" max-width="600px" class="docs-image--no-shadow docs-image--right" animated-gif="/img/docs/v53/tv_mode.gif" >}} We've improved the TV & kiosk mode to make it easier to use. There's now an icon in the top bar that will let you cycle through the different view modes. -1. In the first view mode the sidebar and most of the buttons in the top bar will be hidden -2. In the second view mode the top bar is completely hidden so that only the dashboard itself is showing -3. Hit the escape key to go back to the default view mode +1. In the first view mode, the sidebar and most of the buttons in the top bar will be hidden. +2. In the second view mode, the top bar is completely hidden so that only the dashboard itself is shown. +3. Hit the escape key to go back to the default view mode. -When switching view modes the url will be updated to reflect the view mode selected. This allows a dashboard to be opened with a +When switching view modes, the url will be updated to reflect the view mode selected. This allows a dashboard to be opened with a certain view mode enabled. Additionally, this also enables [playlists](/reference/playlist) to be started with a certain view mode enabled.
-## Notification reminders +## Notification Reminders -Do you use Grafana alerting and have some notifications that are more important than others? Then it's possible to set reminders so that you get alerted until the problem is fixed. This is done on the notification channel itself and will affect all alerts that use that channel. +Do you use Grafana alerting and have some notifications that are more important than others? Then it's possible to set reminders so that you continue to be alerted until the problem is fixed. This is done on the notification channel itself and will affect all alerts that use that channel. For additional examples of why reminders might be useful for you, see [multiple series](/alerting/rules/#multiple-series). Learn how to enable and configure reminders [here](/alerting/notifications/#send-reminders). -## Postgres query builder +## Postgres Query Builder -Grafana 5.3 comes with a new graphical query builder for Postgres. Bringing Postgres integration more in line with some of the other datasources and making it easier for both advanced and beginners to work with timeseries in Postgres. Learn more about it in the [documentation](/features/datasources/postgres/#query-editor). +Grafana 5.3 comes with a new graphical query builder for Postgres. This brings Postgres integration more in line with some of the other datasources and makes it easier for both advanced users and beginners to work with timeseries in Postgres. Learn more about it in the [documentation](/features/datasources/postgres/#query-editor). {{< docs-imagebox img="/img/docs/v53/postgres_query_still.png" class="docs-image--no-shadow" animated-gif="/img/docs/v53/postgres_query.gif" >}} -## Improved OAuth support for Gitlab +## Improved OAuth Support for Gitlab -Grafana 5.3 comes with a new OAuth integration for Gitlab that enables configuration to only allow users that are member of certain Gitlab groups to authenticate. This makes it possible to use Gitlab OAuth with Grafana in a shared environment without giving everyone access to Grafana. +Grafana 5.3 comes with a new OAuth integration for Gitlab that enables configuration to only allow users that are a member of certain Gitlab groups to authenticate. This makes it possible to use Gitlab OAuth with Grafana in a shared environment without giving everyone access to Grafana. Learn how to enable and configure it in the [documentation](/auth/gitlab/). ## Changelog From b03a25198b7bb06f3720cd122f653bd9847c8947 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Thu, 4 Oct 2018 18:25:16 +0200 Subject: [PATCH 017/155] docs: annotations tag filter with template variable support --- docs/sources/guides/whats-new-in-v5-3.md | 8 ++++++++ docs/sources/reference/annotations.md | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/sources/guides/whats-new-in-v5-3.md b/docs/sources/guides/whats-new-in-v5-3.md index faf6c410291..6d82a98be56 100644 --- a/docs/sources/guides/whats-new-in-v5-3.md +++ b/docs/sources/guides/whats-new-in-v5-3.md @@ -19,6 +19,7 @@ Grafana v5.3 brings new features, many enhancements and bug fixes. This article - [Alerting]({{< relref "#notification-reminders" >}}) with notification reminders - [Postgres]({{< relref "#postgres-query-builder" >}}) gets a new query builder! - [OAuth]({{< relref "#improved-oauth-support-for-gitlab" >}}) support for Gitlab is improved +- [Annotations]({{< relref "#annotations" >}}) with template variable filtering ## Google Stackdriver @@ -62,6 +63,13 @@ Grafana 5.3 comes with a new graphical query builder for Postgres. This brings P Grafana 5.3 comes with a new OAuth integration for Gitlab that enables configuration to only allow users that are a member of certain Gitlab groups to authenticate. This makes it possible to use Gitlab OAuth with Grafana in a shared environment without giving everyone access to Grafana. Learn how to enable and configure it in the [documentation](/auth/gitlab/). +## Annotations + it possible to use template vari +Grafana 5.3 brings improved support for [native annotations](/reference/annotations/#native-annotations) and makes it possible to use template variables when filtering by tags. +Learn more about it in the [documentation](/reference/annotations/#query-by-tag). + +{{< docs-imagebox img="/img/docs/v53/annotation_tag_filter_variable.png" max-width="600px" >}} + ## Changelog Checkout the [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md) file for a complete list diff --git a/docs/sources/reference/annotations.md b/docs/sources/reference/annotations.md index 3bb50f4badf..8732c8c709b 100644 --- a/docs/sources/reference/annotations.md +++ b/docs/sources/reference/annotations.md @@ -47,7 +47,9 @@ can still show them if you add a new **Annotation Query** and filter by tags. Bu You can create new annotation queries that fetch annotations from the native annotation store via the `-- Grafana --` data source and by setting *Filter by* to `Tags`. Specify at least one tag. For example create an annotation query name `outages` and specify a tag named `outage`. This query will show all annotations you create (from any dashboard or via API) that have the `outage` tag. By default, if you add multiple tags in the annotation query, Grafana will only show annotations that have all the tags you supplied. You can invert the behavior by enabling `Match any` which means that Grafana will show annotations that contains at least one of the tags you supplied. -In 5.4+ it's possible to use template variables in the tag query. So if you have a dashboard showing stats for different services and an template variable that dictates which services to show, you can now use the same template variable in your annotation query to only show annotations for those services. +In Grafana v5.3+ it's possible to use template variables in the tag query. So if you have a dashboard showing stats for different services and a template variable that dictates which services to show, you can now use the same template variable in your annotation query to only show annotations for those services. + +{{< docs-imagebox img="/img/docs/v53/annotation_tag_filter_variable.png" max-width="600px" >}} ## Querying other data sources From c670897c6ade6295ee06521d0df4b0f8c33923fb Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Thu, 4 Oct 2018 18:45:47 +0200 Subject: [PATCH 018/155] docs: new variable type text box that allows free text input --- docs/sources/guides/whats-new-in-v5-3.md | 8 +++++++- docs/sources/reference/templating.md | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/sources/guides/whats-new-in-v5-3.md b/docs/sources/guides/whats-new-in-v5-3.md index 6d82a98be56..d99612c71e3 100644 --- a/docs/sources/guides/whats-new-in-v5-3.md +++ b/docs/sources/guides/whats-new-in-v5-3.md @@ -20,6 +20,7 @@ Grafana v5.3 brings new features, many enhancements and bug fixes. This article - [Postgres]({{< relref "#postgres-query-builder" >}}) gets a new query builder! - [OAuth]({{< relref "#improved-oauth-support-for-gitlab" >}}) support for Gitlab is improved - [Annotations]({{< relref "#annotations" >}}) with template variable filtering +- [Variables]({{< relref "#variables" >}}) with free text support ## Google Stackdriver @@ -64,12 +65,17 @@ Grafana 5.3 comes with a new OAuth integration for Gitlab that enables configura Learn how to enable and configure it in the [documentation](/auth/gitlab/). ## Annotations - it possible to use template vari + Grafana 5.3 brings improved support for [native annotations](/reference/annotations/#native-annotations) and makes it possible to use template variables when filtering by tags. Learn more about it in the [documentation](/reference/annotations/#query-by-tag). {{< docs-imagebox img="/img/docs/v53/annotation_tag_filter_variable.png" max-width="600px" >}} +## Variables + +Grafana 5.3 ships with a brand new variable type named `Text box` which makes it easier and more convenient to provide free text input to a variable. +This new variable type will display as a free text input field with an optional prefilled default value. + ## Changelog Checkout the [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md) file for a complete list diff --git a/docs/sources/reference/templating.md b/docs/sources/reference/templating.md index 31251fd6389..403dabba8ae 100644 --- a/docs/sources/reference/templating.md +++ b/docs/sources/reference/templating.md @@ -90,6 +90,7 @@ Type | Description *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. +*Text box* | This variable type will display as a free text input field with an optional default value. ### Query options From 5ec9adb7a77cd36d9f3d1f01c21864bb12657f87 Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Fri, 5 Oct 2018 17:09:40 +0200 Subject: [PATCH 019/155] Explore: compact state URLs - allow positional state array in URL - key-based parsing as fallback - fix issue where split state was kept in URL after closing split --- public/app/core/utils/explore.test.ts | 53 ++++++++++++++++++++++++- public/app/core/utils/explore.ts | 25 +++++++++++- public/app/features/explore/Explore.tsx | 12 +++--- public/app/features/explore/Wrapper.tsx | 9 ++++- 4 files changed, 87 insertions(+), 12 deletions(-) diff --git a/public/app/core/utils/explore.test.ts b/public/app/core/utils/explore.test.ts index c47321225fe..915b47e14e2 100644 --- a/public/app/core/utils/explore.test.ts +++ b/public/app/core/utils/explore.test.ts @@ -36,14 +36,40 @@ describe('state functions', () => { range: DEFAULT_RANGE, }); }); + + it('returns a valid Explore state from URL parameter', () => { + const paramValue = + '%7B"datasource":"Local","queries":%5B%7B"query":"metric"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D'; + expect(parseUrlState(paramValue)).toMatchObject({ + datasource: 'Local', + queries: [{ query: 'metric' }], + range: { + from: 'now-1h', + to: 'now', + }, + }); + }); + + it('returns a valid Explore state from a compact URL parameter', () => { + const paramValue = '%5B"now-1h","now","Local","metric"%5D'; + expect(parseUrlState(paramValue)).toMatchObject({ + datasource: 'Local', + queries: [{ query: 'metric' }], + range: { + from: 'now-1h', + to: 'now', + }, + }); + }); }); + describe('serializeStateToUrlParam', () => { it('returns url parameter value for a state object', () => { const state = { ...DEFAULT_EXPLORE_STATE, datasourceName: 'foo', range: { - from: 'now - 5h', + from: 'now-5h', to: 'now', }, queries: [ @@ -57,10 +83,33 @@ describe('state functions', () => { }; expect(serializeStateToUrlParam(state)).toBe( '{"datasource":"foo","queries":[{"query":"metric{test=\\"a/b\\"}"},' + - '{"query":"super{foo=\\"x/z\\"}"}],"range":{"from":"now - 5h","to":"now"}}' + '{"query":"super{foo=\\"x/z\\"}"}],"range":{"from":"now-5h","to":"now"}}' + ); + }); + + it('returns url parameter value for a state object', () => { + const state = { + ...DEFAULT_EXPLORE_STATE, + datasourceName: 'foo', + range: { + from: 'now-5h', + to: 'now', + }, + queries: [ + { + query: 'metric{test="a/b"}', + }, + { + query: 'super{foo="x/z"}', + }, + ], + }; + expect(serializeStateToUrlParam(state, true)).toBe( + '["now-5h","now","foo","metric{test=\\"a/b\\"}","super{foo=\\"x/z\\"}"]' ); }); }); + describe('interplay', () => { it('can parse the serialized state into the original state', () => { const state = { diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index cca841a1725..ecd11a495ad 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -60,7 +60,20 @@ export async function getExploreUrl( export function parseUrlState(initial: string | undefined): ExploreUrlState { if (initial) { try { - return JSON.parse(decodeURI(initial)); + const parsed = JSON.parse(decodeURI(initial)); + if (Array.isArray(parsed)) { + if (parsed.length <= 3) { + throw new Error('Error parsing compact URL state for Explore.'); + } + const range = { + from: parsed[0], + to: parsed[1], + }; + const datasource = parsed[2]; + const queries = parsed.slice(3).map(query => ({ query })); + return { datasource, queries, range }; + } + return parsed; } catch (e) { console.error(e); } @@ -68,11 +81,19 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState { return { datasource: null, queries: [], range: DEFAULT_RANGE }; } -export function serializeStateToUrlParam(state: ExploreState): string { +export function serializeStateToUrlParam(state: ExploreState, compact?: boolean): string { const urlState: ExploreUrlState = { datasource: state.datasourceName, queries: state.queries.map(q => ({ query: q.query })), range: state.range, }; + if (compact) { + return JSON.stringify([ + urlState.range.from, + urlState.range.to, + urlState.datasource, + ...urlState.queries.map(q => q.query), + ]); + } return JSON.stringify(urlState); } diff --git a/public/app/features/explore/Explore.tsx b/public/app/features/explore/Explore.tsx index c90ba0dd7cc..2ee9ba3bca3 100644 --- a/public/app/features/explore/Explore.tsx +++ b/public/app/features/explore/Explore.tsx @@ -275,7 +275,6 @@ export class Explore extends React.PureComponent { const { onChangeSplit } = this.props; if (onChangeSplit) { onChangeSplit(false); - this.saveState(); } }; @@ -292,7 +291,6 @@ export class Explore extends React.PureComponent { if (onChangeSplit) { const state = this.cloneState(); onChangeSplit(true, state); - this.saveState(); } }; @@ -534,12 +532,12 @@ export class Explore extends React.PureComponent { ) : ( -
- -
- )} + + )} {!datasourceMissing ? (