From 105b3d680478e6408c8035ad4053742312060eac Mon Sep 17 00:00:00 2001 From: Austin Winstanley Date: Mon, 25 Jun 2018 20:11:58 +0000 Subject: [PATCH 01/16] Switched MySQL and MSSQL macros for timeFilter and related to use BETWEEN and calculate UNIX time server side instead of database side. Fixes #11618 #11619 --- pkg/tsdb/mssql/macros.go | 7 ++++--- pkg/tsdb/mssql/macros_test.go | 18 +++++++++--------- pkg/tsdb/mysql/macros.go | 7 ++++--- pkg/tsdb/mysql/macros_test.go | 18 +++++++++--------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/pkg/tsdb/mssql/macros.go b/pkg/tsdb/mssql/macros.go index bb9489cd654..2621110ee99 100644 --- a/pkg/tsdb/mssql/macros.go +++ b/pkg/tsdb/mssql/macros.go @@ -82,11 +82,12 @@ func (m *MsSqlMacroEngine) evaluateMacro(name string, args []string) (string, er if len(args) == 0 { return "", fmt.Errorf("missing time column argument for macro %v", name) } - return fmt.Sprintf("%s >= DATEADD(s, %d, '1970-01-01') AND %s <= DATEADD(s, %d, '1970-01-01')", args[0], m.TimeRange.GetFromAsSecondsEpoch(), args[0], m.TimeRange.GetToAsSecondsEpoch()), nil + + return fmt.Sprintf("%s BETWEEN '%s' AND '%s'", args[0], time.Unix(m.TimeRange.GetFromAsSecondsEpoch(), 0), time.Unix(m.TimeRange.GetToAsSecondsEpoch(), 0)), nil case "__timeFrom": - return fmt.Sprintf("DATEADD(second, %d, '1970-01-01')", m.TimeRange.GetFromAsSecondsEpoch()), nil + return fmt.Sprintf("'%s'", time.Unix(m.TimeRange.GetFromAsSecondsEpoch(), 0)), nil case "__timeTo": - return fmt.Sprintf("DATEADD(second, %d, '1970-01-01')", m.TimeRange.GetToAsSecondsEpoch()), nil + return fmt.Sprintf("'%s'", time.Unix(m.TimeRange.GetToAsSecondsEpoch(), 0)), nil case "__timeGroup": if len(args) < 2 { return "", fmt.Errorf("macro %v needs time column and interval", name) diff --git a/pkg/tsdb/mssql/macros_test.go b/pkg/tsdb/mssql/macros_test.go index ae0d4f67d2b..46f67e7d169 100644 --- a/pkg/tsdb/mssql/macros_test.go +++ b/pkg/tsdb/mssql/macros_test.go @@ -49,7 +49,7 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column >= DATEADD(s, %d, '1970-01-01') AND time_column <= DATEADD(s, %d, '1970-01-01')", from.Unix(), to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) }) Convey("interpolate __timeGroup function", func() { @@ -96,14 +96,14 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select DATEADD(second, %d, '1970-01-01')", from.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select DATEADD(second, %d, '1970-01-01')", to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) }) Convey("interpolate __unixEpochFilter function", func() { @@ -137,21 +137,21 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column >= DATEADD(s, %d, '1970-01-01') AND time_column <= DATEADD(s, %d, '1970-01-01')", from.Unix(), to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) }) Convey("interpolate __timeFrom function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select DATEADD(second, %d, '1970-01-01')", from.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select DATEADD(second, %d, '1970-01-01')", to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) }) Convey("interpolate __unixEpochFilter function", func() { @@ -185,21 +185,21 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column >= DATEADD(s, %d, '1970-01-01') AND time_column <= DATEADD(s, %d, '1970-01-01')", from.Unix(), to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) }) Convey("interpolate __timeFrom function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select DATEADD(second, %d, '1970-01-01')", from.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select DATEADD(second, %d, '1970-01-01')", to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) }) Convey("interpolate __unixEpochFilter function", func() { diff --git a/pkg/tsdb/mysql/macros.go b/pkg/tsdb/mysql/macros.go index fadcbe4edbc..6dfe6ad952f 100644 --- a/pkg/tsdb/mysql/macros.go +++ b/pkg/tsdb/mysql/macros.go @@ -77,11 +77,12 @@ func (m *MySqlMacroEngine) evaluateMacro(name string, args []string) (string, er if len(args) == 0 { return "", fmt.Errorf("missing time column argument for macro %v", name) } - return fmt.Sprintf("%s >= FROM_UNIXTIME(%d) AND %s <= FROM_UNIXTIME(%d)", args[0], m.TimeRange.GetFromAsSecondsEpoch(), args[0], m.TimeRange.GetToAsSecondsEpoch()), nil + + return fmt.Sprintf("%s BETWEEN '%s' AND '%s'", args[0], time.Unix(m.TimeRange.GetFromAsSecondsEpoch(), 0), time.Unix(m.TimeRange.GetToAsSecondsEpoch(), 0)), nil case "__timeFrom": - return fmt.Sprintf("FROM_UNIXTIME(%d)", m.TimeRange.GetFromAsSecondsEpoch()), nil + return fmt.Sprintf("'%s'", time.Unix(m.TimeRange.GetFromAsSecondsEpoch(), 0)), nil case "__timeTo": - return fmt.Sprintf("FROM_UNIXTIME(%d)", m.TimeRange.GetToAsSecondsEpoch()), nil + return fmt.Sprintf("'%s'", time.Unix(m.TimeRange.GetToAsSecondsEpoch(), 0)), nil case "__timeGroup": if len(args) < 2 { return "", fmt.Errorf("macro %v needs time column and interval", name) diff --git a/pkg/tsdb/mysql/macros_test.go b/pkg/tsdb/mysql/macros_test.go index 66ec143eac8..11ac6d8b2f3 100644 --- a/pkg/tsdb/mysql/macros_test.go +++ b/pkg/tsdb/mysql/macros_test.go @@ -54,21 +54,21 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column >= FROM_UNIXTIME(%d) AND time_column <= FROM_UNIXTIME(%d)", from.Unix(), to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) }) Convey("interpolate __timeFrom function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select FROM_UNIXTIME(%d)", from.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select FROM_UNIXTIME(%d)", to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) }) Convey("interpolate __unixEpochFilter function", func() { @@ -102,21 +102,21 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column >= FROM_UNIXTIME(%d) AND time_column <= FROM_UNIXTIME(%d)", from.Unix(), to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) }) Convey("interpolate __timeFrom function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select FROM_UNIXTIME(%d)", from.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select FROM_UNIXTIME(%d)", to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) }) Convey("interpolate __unixEpochFilter function", func() { @@ -150,21 +150,21 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column >= FROM_UNIXTIME(%d) AND time_column <= FROM_UNIXTIME(%d)", from.Unix(), to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) }) Convey("interpolate __timeFrom function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select FROM_UNIXTIME(%d)", from.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select FROM_UNIXTIME(%d)", to.Unix())) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) }) Convey("interpolate __unixEpochFilter function", func() { From a0e8437f8f70f33490d6c57dce46bf0de441048b Mon Sep 17 00:00:00 2001 From: Austin Winstanley Date: Fri, 29 Jun 2018 03:48:14 +0000 Subject: [PATCH 02/16] Used PostgreSQL TSDB as a model the set up the __timeFilter, __timeFrom, and __timeTo macros for Microsoft SQL and MySQL --- pkg/tsdb/mssql/macros.go | 6 +++--- pkg/tsdb/mssql/macros_test.go | 18 +++++++++--------- pkg/tsdb/mysql/macros.go | 6 +++--- pkg/tsdb/mysql/macros_test.go | 18 +++++++++--------- yarn.lock | 12 ++++++------ 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/pkg/tsdb/mssql/macros.go b/pkg/tsdb/mssql/macros.go index 2621110ee99..b136bdfb459 100644 --- a/pkg/tsdb/mssql/macros.go +++ b/pkg/tsdb/mssql/macros.go @@ -83,11 +83,11 @@ func (m *MsSqlMacroEngine) evaluateMacro(name string, args []string) (string, er return "", fmt.Errorf("missing time column argument for macro %v", name) } - return fmt.Sprintf("%s BETWEEN '%s' AND '%s'", args[0], time.Unix(m.TimeRange.GetFromAsSecondsEpoch(), 0), time.Unix(m.TimeRange.GetToAsSecondsEpoch(), 0)), nil + return fmt.Sprintf("%s BETWEEN '%s' AND '%s'", args[0], m.TimeRange.GetFromAsTimeUTC().Format(time.RFC3339), m.TimeRange.GetToAsTimeUTC().Format(time.RFC3339)), nil case "__timeFrom": - return fmt.Sprintf("'%s'", time.Unix(m.TimeRange.GetFromAsSecondsEpoch(), 0)), nil + return fmt.Sprintf("'%s'", m.TimeRange.GetFromAsTimeUTC().Format(time.RFC3339)), nil case "__timeTo": - return fmt.Sprintf("'%s'", time.Unix(m.TimeRange.GetToAsSecondsEpoch(), 0)), nil + return fmt.Sprintf("'%s'", m.TimeRange.GetToAsTimeUTC().Format(time.RFC3339)), nil case "__timeGroup": if len(args) < 2 { return "", fmt.Errorf("macro %v needs time column and interval", name) diff --git a/pkg/tsdb/mssql/macros_test.go b/pkg/tsdb/mssql/macros_test.go index 46f67e7d169..67ee1da7561 100644 --- a/pkg/tsdb/mssql/macros_test.go +++ b/pkg/tsdb/mssql/macros_test.go @@ -49,7 +49,7 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", from.Format(time.RFC3339), to.Format(time.RFC3339))) }) Convey("interpolate __timeGroup function", func() { @@ -96,14 +96,14 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", from.Format(time.RFC3339))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", to.Format(time.RFC3339))) }) Convey("interpolate __unixEpochFilter function", func() { @@ -137,21 +137,21 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", from.Format(time.RFC3339), to.Format(time.RFC3339))) }) Convey("interpolate __timeFrom function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", from.Format(time.RFC3339))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", to.Format(time.RFC3339))) }) Convey("interpolate __unixEpochFilter function", func() { @@ -185,21 +185,21 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", from.Format(time.RFC3339), to.Format(time.RFC3339))) }) Convey("interpolate __timeFrom function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", from.Format(time.RFC3339))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", to.Format(time.RFC3339))) }) Convey("interpolate __unixEpochFilter function", func() { diff --git a/pkg/tsdb/mysql/macros.go b/pkg/tsdb/mysql/macros.go index 6dfe6ad952f..1855670e863 100644 --- a/pkg/tsdb/mysql/macros.go +++ b/pkg/tsdb/mysql/macros.go @@ -78,11 +78,11 @@ func (m *MySqlMacroEngine) evaluateMacro(name string, args []string) (string, er return "", fmt.Errorf("missing time column argument for macro %v", name) } - return fmt.Sprintf("%s BETWEEN '%s' AND '%s'", args[0], time.Unix(m.TimeRange.GetFromAsSecondsEpoch(), 0), time.Unix(m.TimeRange.GetToAsSecondsEpoch(), 0)), nil + return fmt.Sprintf("%s BETWEEN '%s' AND '%s'", args[0], m.TimeRange.GetFromAsTimeUTC().Format(time.RFC3339), m.TimeRange.GetToAsTimeUTC().Format(time.RFC3339)), nil case "__timeFrom": - return fmt.Sprintf("'%s'", time.Unix(m.TimeRange.GetFromAsSecondsEpoch(), 0)), nil + return fmt.Sprintf("'%s'", m.TimeRange.GetFromAsTimeUTC().Format(time.RFC3339)), nil case "__timeTo": - return fmt.Sprintf("'%s'", time.Unix(m.TimeRange.GetToAsSecondsEpoch(), 0)), nil + return fmt.Sprintf("'%s'", m.TimeRange.GetToAsTimeUTC().Format(time.RFC3339)), nil case "__timeGroup": if len(args) < 2 { return "", fmt.Errorf("macro %v needs time column and interval", name) diff --git a/pkg/tsdb/mysql/macros_test.go b/pkg/tsdb/mysql/macros_test.go index 11ac6d8b2f3..6af1d180737 100644 --- a/pkg/tsdb/mysql/macros_test.go +++ b/pkg/tsdb/mysql/macros_test.go @@ -54,21 +54,21 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", from.Format(time.RFC3339), to.Format(time.RFC3339))) }) Convey("interpolate __timeFrom function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", from.Format(time.RFC3339))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", to.Format(time.RFC3339))) }) Convey("interpolate __unixEpochFilter function", func() { @@ -102,21 +102,21 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", from.Format(time.RFC3339), to.Format(time.RFC3339))) }) Convey("interpolate __timeFrom function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", from.Format(time.RFC3339))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", to.Format(time.RFC3339))) }) Convey("interpolate __unixEpochFilter function", func() { @@ -150,21 +150,21 @@ func TestMacroEngine(t *testing.T) { sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", time.Unix(from.Unix(), 0), time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", from.Format(time.RFC3339), to.Format(time.RFC3339))) }) Convey("interpolate __timeFrom function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(from.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", from.Format(time.RFC3339))) }) Convey("interpolate __timeTo function", func() { sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") So(err, ShouldBeNil) - So(sql, ShouldEqual, fmt.Sprintf("select '%s'", time.Unix(to.Unix(), 0))) + So(sql, ShouldEqual, fmt.Sprintf("select '%s'", to.Format(time.RFC3339))) }) Convey("interpolate __unixEpochFilter function", func() { diff --git a/yarn.lock b/yarn.lock index 6cc48a7c79d..6772d7c14a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1114,7 +1114,7 @@ babel-plugin-istanbul@^4.1.5, babel-plugin-istanbul@^4.1.6: istanbul-lib-instrument "^1.10.1" test-exclude "^4.2.1" -babel-plugin-jest-hoist@^22.4.4: +babel-plugin-jest-hoist@^22.4.3, babel-plugin-jest-hoist@^22.4.4: version "22.4.4" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.4.4.tgz#b9851906eab34c7bf6f8c895a2b08bea1a844c0b" @@ -6498,7 +6498,7 @@ jest-docblock@^22.4.0, jest-docblock@^22.4.3: dependencies: detect-newline "^2.1.0" -jest-environment-jsdom@^22.4.1: +jest-environment-jsdom@^22.4.1, jest-environment-jsdom@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-22.4.3.tgz#d67daa4155e33516aecdd35afd82d4abf0fa8a1e" dependencies: @@ -6506,7 +6506,7 @@ jest-environment-jsdom@^22.4.1: jest-util "^22.4.3" jsdom "^11.5.1" -jest-environment-node@^22.4.1: +jest-environment-node@^22.4.1, jest-environment-node@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-22.4.3.tgz#54c4eaa374c83dd52a9da8759be14ebe1d0b9129" dependencies: @@ -6533,7 +6533,7 @@ jest-haste-map@^22.4.2: micromatch "^2.3.11" sane "^2.0.0" -jest-jasmine2@^22.4.4: +jest-jasmine2@^22.4.3, jest-jasmine2@^22.4.4: version "22.4.4" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-22.4.4.tgz#c55f92c961a141f693f869f5f081a79a10d24e23" dependencies: @@ -6587,7 +6587,7 @@ jest-resolve-dependencies@^22.1.0: dependencies: jest-regex-util "^22.4.3" -jest-resolve@^22.4.2: +jest-resolve@^22.4.2, jest-resolve@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-22.4.3.tgz#0ce9d438c8438229aa9b916968ec6b05c1abb4ea" dependencies: @@ -6671,7 +6671,7 @@ jest-validate@^21.1.0: leven "^2.1.0" pretty-format "^21.2.1" -jest-validate@^22.4.4: +jest-validate@^22.4.3, jest-validate@^22.4.4: version "22.4.4" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-22.4.4.tgz#1dd0b616ef46c995de61810d85f57119dbbcec4d" dependencies: From 9823da1cc51e3a6e0222cd8c9c36a97b4f978fd3 Mon Sep 17 00:00:00 2001 From: Austin Winstanley Date: Fri, 29 Jun 2018 03:54:43 +0000 Subject: [PATCH 03/16] Reverted yarn.lock to master --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6772d7c14a4..6cc48a7c79d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1114,7 +1114,7 @@ babel-plugin-istanbul@^4.1.5, babel-plugin-istanbul@^4.1.6: istanbul-lib-instrument "^1.10.1" test-exclude "^4.2.1" -babel-plugin-jest-hoist@^22.4.3, babel-plugin-jest-hoist@^22.4.4: +babel-plugin-jest-hoist@^22.4.4: version "22.4.4" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.4.4.tgz#b9851906eab34c7bf6f8c895a2b08bea1a844c0b" @@ -6498,7 +6498,7 @@ jest-docblock@^22.4.0, jest-docblock@^22.4.3: dependencies: detect-newline "^2.1.0" -jest-environment-jsdom@^22.4.1, jest-environment-jsdom@^22.4.3: +jest-environment-jsdom@^22.4.1: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-22.4.3.tgz#d67daa4155e33516aecdd35afd82d4abf0fa8a1e" dependencies: @@ -6506,7 +6506,7 @@ jest-environment-jsdom@^22.4.1, jest-environment-jsdom@^22.4.3: jest-util "^22.4.3" jsdom "^11.5.1" -jest-environment-node@^22.4.1, jest-environment-node@^22.4.3: +jest-environment-node@^22.4.1: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-22.4.3.tgz#54c4eaa374c83dd52a9da8759be14ebe1d0b9129" dependencies: @@ -6533,7 +6533,7 @@ jest-haste-map@^22.4.2: micromatch "^2.3.11" sane "^2.0.0" -jest-jasmine2@^22.4.3, jest-jasmine2@^22.4.4: +jest-jasmine2@^22.4.4: version "22.4.4" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-22.4.4.tgz#c55f92c961a141f693f869f5f081a79a10d24e23" dependencies: @@ -6587,7 +6587,7 @@ jest-resolve-dependencies@^22.1.0: dependencies: jest-regex-util "^22.4.3" -jest-resolve@^22.4.2, jest-resolve@^22.4.3: +jest-resolve@^22.4.2: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-22.4.3.tgz#0ce9d438c8438229aa9b916968ec6b05c1abb4ea" dependencies: @@ -6671,7 +6671,7 @@ jest-validate@^21.1.0: leven "^2.1.0" pretty-format "^21.2.1" -jest-validate@^22.4.3, jest-validate@^22.4.4: +jest-validate@^22.4.4: version "22.4.4" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-22.4.4.tgz#1dd0b616ef46c995de61810d85f57119dbbcec4d" dependencies: From 59675dc564a53b49dd02e5538f703a140d2a2e85 Mon Sep 17 00:00:00 2001 From: Austin Winstanley Date: Fri, 29 Jun 2018 13:07:48 -0500 Subject: [PATCH 04/16] Changed documentation for MSSQL and MySQL to reflect macro changes --- docs/sources/features/datasources/mssql.md | 6 +++--- docs/sources/features/datasources/mysql.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/sources/features/datasources/mssql.md b/docs/sources/features/datasources/mssql.md index 1676cffa0a8..d4d5cc6d73e 100644 --- a/docs/sources/features/datasources/mssql.md +++ b/docs/sources/features/datasources/mssql.md @@ -77,9 +77,9 @@ Macro example | Description ------------ | ------------- *$__time(dateColumn)* | Will be replaced by an expression to rename the column to *time*. For example, *dateColumn as time* *$__timeEpoch(dateColumn)* | Will be replaced by an expression to convert a DATETIME column type to unix timestamp and rename it to *time*.
For example, *DATEDIFF(second, '1970-01-01', dateColumn) AS time* -*$__timeFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name.
For example, *dateColumn >= DATEADD(s, 1494410783, '1970-01-01') AND dateColumn <= DATEADD(s, 1494410783, '1970-01-01')* -*$__timeFrom()* | Will be replaced by the start of the currently active time selection. For example, *DATEADD(second, 1494410783, '1970-01-01')* -*$__timeTo()* | Will be replaced by the end of the currently active time selection. For example, *DATEADD(second, 1494410783, '1970-01-01')* +*$__timeFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name.
For example, *dateColumn BETWEEN '2017-04-21T05:01:17Z' AND '2017-04-21T05:06:17Z'* +*$__timeFrom()* | Will be replaced by the start of the currently active time selection. For example, *'2017-04-21T05:01:17Z'* +*$__timeTo()* | Will be replaced by the end of the currently active time selection. For example, *'2017-04-21T05:06:17Z'* *$__timeGroup(dateColumn,'5m'[, fillvalue])* | Will be replaced by an expression usable in GROUP BY clause. Providing a *fillValue* of *NULL* or *floating value* will automatically fill empty series in timerange with that value.
For example, *CAST(ROUND(DATEDIFF(second, '1970-01-01', time_column)/300.0, 0) as bigint)\*300*. *$__timeGroup(dateColumn,'5m', 0)* | Same as above but with a fill parameter so all null values will be converted to the fill value (all null values would be set to zero using this example). *$__unixEpochFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name with times represented as unix timestamp. For example, *dateColumn > 1494410783 AND dateColumn < 1494497183* diff --git a/docs/sources/features/datasources/mysql.md b/docs/sources/features/datasources/mysql.md index f91417a43b7..ce50053c7ea 100644 --- a/docs/sources/features/datasources/mysql.md +++ b/docs/sources/features/datasources/mysql.md @@ -60,9 +60,9 @@ Macro example | Description ------------ | ------------- *$__time(dateColumn)* | Will be replaced by an expression to convert to a UNIX timestamp and rename the column to `time_sec`. For example, *UNIX_TIMESTAMP(dateColumn) as time_sec* *$__timeEpoch(dateColumn)* | Will be replaced by an expression to convert to a UNIX timestamp and rename the column to `time_sec`. For example, *UNIX_TIMESTAMP(dateColumn) as time_sec* -*$__timeFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name. For example, *dateColumn > FROM_UNIXTIME(1494410783) AND dateColumn < FROM_UNIXTIME(1494497183)* -*$__timeFrom()* | Will be replaced by the start of the currently active time selection. For example, *FROM_UNIXTIME(1494410783)* -*$__timeTo()* | Will be replaced by the end of the currently active time selection. For example, *FROM_UNIXTIME(1494497183)* +*$__timeFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name. For example, *dateColumn BETWEEN '2017-04-21T05:01:17Z' AND '2017-04-21T05:06:17Z'* +*$__timeFrom()* | Will be replaced by the start of the currently active time selection. For example, *'2017-04-21T05:01:17Z'* +*$__timeTo()* | Will be replaced by the end of the currently active time selection. For example, *'2017-04-21T05:06:17Z'* *$__timeGroup(dateColumn,'5m')* | Will be replaced by an expression usable in GROUP BY clause. For example, *cast(cast(UNIX_TIMESTAMP(dateColumn)/(300) as signed)*300 as signed),* *$__timeGroup(dateColumn,'5m',0)* | Same as above but with a fill parameter so all null values will be converted to the fill value (all null values would be set to zero using this example). *$__unixEpochFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name with times represented as unix timestamp. For example, *dateColumn > 1494410783 AND dateColumn < 1494497183* From 845724e8b91eba4bb2607aec44bfa31ab8ca4beb Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 29 Jun 2018 20:39:06 +0200 Subject: [PATCH 05/16] update mysql/mssql query/annotation help sections --- .../datasource/mssql/partials/annotations.editor.html | 6 +++--- .../app/plugins/datasource/mssql/partials/query.editor.html | 6 +++--- .../datasource/mysql/partials/annotations.editor.html | 6 +++--- .../app/plugins/datasource/mysql/partials/query.editor.html | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/public/app/plugins/datasource/mssql/partials/annotations.editor.html b/public/app/plugins/datasource/mssql/partials/annotations.editor.html index b2c0d7b97a6..0ad8b0c01f0 100644 --- a/public/app/plugins/datasource/mssql/partials/annotations.editor.html +++ b/public/app/plugins/datasource/mssql/partials/annotations.editor.html @@ -28,12 +28,12 @@ An annotation is an event that is overlaid on top of graphs. The query can have Macros: - $__time(column) -> column AS time - $__timeEpoch(column) -> DATEDIFF(second, '1970-01-01', column) AS time -- $__timeFilter(column) -> column >= DATEADD(s, 18446744066914186738, '1970-01-01') AND column <= DATEADD(s, 18446744066914187038, '1970-01-01') +- $__timeFilter(column) -> column BETWEEN '2017-04-21T05:01:17Z' AND '2017-04-21T05:01:17Z' - $__unixEpochFilter(column) -> column >= 1492750877 AND column <= 1492750877 Or build your own conditionals using these macros which just return the values: -- $__timeFrom() -> DATEADD(second, 1492750877, '1970-01-01') -- $__timeTo() -> DATEADD(second, 1492750877, '1970-01-01') +- $__timeFrom() -> '2017-04-21T05:01:17Z' +- $__timeTo() -> '2017-04-21T05:01:17Z' - $__unixEpochFrom() -> 1492750877 - $__unixEpochTo() -> 1492750877 diff --git a/public/app/plugins/datasource/mssql/partials/query.editor.html b/public/app/plugins/datasource/mssql/partials/query.editor.html index f29dfa18db2..ddc24475d60 100644 --- a/public/app/plugins/datasource/mssql/partials/query.editor.html +++ b/public/app/plugins/datasource/mssql/partials/query.editor.html @@ -49,7 +49,7 @@ Table: Macros: - $__time(column) -> column AS time - $__timeEpoch(column) -> DATEDIFF(second, '1970-01-01', column) AS time -- $__timeFilter(column) -> column >= DATEADD(s, 18446744066914186738, '1970-01-01') AND column <= DATEADD(s, 18446744066914187038, '1970-01-01') +- $__timeFilter(column) -> column BETWEEN '2017-04-21T05:01:17Z' AND '2017-04-21T05:01:17Z' - $__unixEpochFilter(column) -> column >= 1492750877 AND column <= 1492750877 - $__timeGroup(column, '5m'[, fillvalue]) -> CAST(ROUND(DATEDIFF(second, '1970-01-01', column)/300.0, 0) as bigint)*300. Providing a fillValue of NULL or floating value will automatically fill empty series in timerange with that value. @@ -62,8 +62,8 @@ GROUP BY $__timeGroup(date_time_col, '1h') ORDER BY 1 Or build your own conditionals using these macros which just return the values: -- $__timeFrom() -> DATEADD(second, 1492750877, '1970-01-01') -- $__timeTo() -> DATEADD(second, 1492750877, '1970-01-01') +- $__timeFrom() -> '2017-04-21T05:01:17Z' +- $__timeTo() -> '2017-04-21T05:01:17Z' - $__unixEpochFrom() -> 1492750877 - $__unixEpochTo() -> 1492750877 diff --git a/public/app/plugins/datasource/mysql/partials/annotations.editor.html b/public/app/plugins/datasource/mysql/partials/annotations.editor.html index 23ec726a9f0..5f2e44887ba 100644 --- a/public/app/plugins/datasource/mysql/partials/annotations.editor.html +++ b/public/app/plugins/datasource/mysql/partials/annotations.editor.html @@ -28,12 +28,12 @@ An annotation is an event that is overlaid on top of graphs. The query can have Macros: - $__time(column) -> UNIX_TIMESTAMP(column) as time (or as time_sec) - $__timeEpoch(column) -> UNIX_TIMESTAMP(column) as time (or as time_sec) -- $__timeFilter(column) -> UNIX_TIMESTAMP(time_date_time) > 1492750877 AND UNIX_TIMESTAMP(time_date_time) < 1492750877 +- $__timeFilter(column) -> column BETWEEN '2017-04-21T05:01:17Z' AND '2017-04-21T05:01:17Z' - $__unixEpochFilter(column) -> time_unix_epoch > 1492750877 AND time_unix_epoch < 1492750877 Or build your own conditionals using these macros which just return the values: -- $__timeFrom() -> FROM_UNIXTIME(1492750877) -- $__timeTo() -> FROM_UNIXTIME(1492750877) +- $__timeFrom() -> '2017-04-21T05:01:17Z' +- $__timeTo() -> '2017-04-21T05:01:17Z' - $__unixEpochFrom() -> 1492750877 - $__unixEpochTo() -> 1492750877 diff --git a/public/app/plugins/datasource/mysql/partials/query.editor.html b/public/app/plugins/datasource/mysql/partials/query.editor.html index 9acf32405c1..df68982fcfa 100644 --- a/public/app/plugins/datasource/mysql/partials/query.editor.html +++ b/public/app/plugins/datasource/mysql/partials/query.editor.html @@ -48,7 +48,7 @@ Table: Macros: - $__time(column) -> UNIX_TIMESTAMP(column) as time_sec - $__timeEpoch(column) -> UNIX_TIMESTAMP(column) as time_sec -- $__timeFilter(column) -> UNIX_TIMESTAMP(time_date_time) ≥ 1492750877 AND UNIX_TIMESTAMP(time_date_time) ≤ 1492750877 +- $__timeFilter(column) -> column BETWEEN '2017-04-21T05:01:17Z' AND '2017-04-21T05:01:17Z' - $__unixEpochFilter(column) -> time_unix_epoch > 1492750877 AND time_unix_epoch < 1492750877 - $__timeGroup(column,'5m') -> cast(cast(UNIX_TIMESTAMP(column)/(300) as signed)*300 as signed) @@ -61,8 +61,8 @@ GROUP BY 1 ORDER BY 1 Or build your own conditionals using these macros which just return the values: -- $__timeFrom() -> FROM_UNIXTIME(1492750877) -- $__timeTo() -> FROM_UNIXTIME(1492750877) +- $__timeFrom() -> '2017-04-21T05:01:17Z' +- $__timeTo() -> '2017-04-21T05:01:17Z' - $__unixEpochFrom() -> 1492750877 - $__unixEpochTo() -> 1492750877 From 240cf63ba6ad8c07a137d1c01f5034ee90422379 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Wed, 4 Jul 2018 20:07:43 +0200 Subject: [PATCH 06/16] changelog: add notes about closing #11618 #11619 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ddc9497dbc..0177546b643 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,10 @@ * **Prometheus**: Fix graph panel bar width issue in aligned prometheus queries [#12379](https://github.com/grafana/grafana/issues/12379) * **Variables**: Skip unneeded extra query request when de-selecting variable values used for repeated panels [#8186](https://github.com/grafana/grafana/issues/8186), thx [@mtanda](https://github.com/mtanda) * **Postgres/MySQL/MSSQL**: Use floor rounding in $__timeGroup macro function [#12460](https://github.com/grafana/grafana/issues/12460), thx [@svenklemm](https://github.com/svenklemm) +* **MySQL/MSSQL**: Use datetime format instead of epoch for $__timeFilter, $__timeFrom and $__timeTo macros [#11618](https://github.com/grafana/grafana/issues/11618) [#11619](https://github.com/grafana/grafana/issues/11619), thx [@AustinWinstanley](https://github.com/AustinWinstanley) * **Github OAuth**: Allow changes of user info at Github to be synched to Grafana when signing in [#11818](https://github.com/grafana/grafana/issues/11818), thx [@rwaweber](https://github.com/rwaweber) + # 5.2.1 (2018-06-29) ### Minor From 50a522d418406955d82d0e08c21d28a4f0069fea Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Thu, 5 Jul 2018 13:01:10 +0200 Subject: [PATCH 07/16] fix caret for help button is ds http settings --- public/app/features/plugins/partials/ds_http_settings.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/features/plugins/partials/ds_http_settings.html b/public/app/features/plugins/partials/ds_http_settings.html index 3af185d862c..6d014af567c 100644 --- a/public/app/features/plugins/partials/ds_http_settings.html +++ b/public/app/features/plugins/partials/ds_http_settings.html @@ -32,8 +32,8 @@
From 36f08994ccd3f2275472ef39a1714a7c50bba1c5 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Thu, 5 Jul 2018 16:12:03 +0300 Subject: [PATCH 08/16] prometheus heatmap: fix unhandled error when some points are missing --- .../prometheus/result_transformer.ts | 18 ++++++++--- .../specs/result_transformer.jest.ts | 30 +++++++++++++++++++ .../app/plugins/panel/heatmap/heatmap_ctrl.ts | 4 +++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/result_transformer.ts b/public/app/plugins/datasource/prometheus/result_transformer.ts index 7f5430bf7d6..b6d8a32af5f 100644 --- a/public/app/plugins/datasource/prometheus/result_transformer.ts +++ b/public/app/plugins/datasource/prometheus/result_transformer.ts @@ -28,15 +28,20 @@ export class ResultTransformer { } } - transformMetricData(md, options, start, end) { + transformMetricData(metricData, options, start, end) { let dps = [], metricLabel = null; - metricLabel = this.createMetricLabel(md.metric, options); + metricLabel = this.createMetricLabel(metricData.metric, options); const stepMs = parseInt(options.step) * 1000; let baseTimestamp = start * 1000; - for (let value of md.values) { + + if (metricData.values === undefined) { + throw new Error('Prometheus heatmap error: data should be a time series'); + } + + for (let value of metricData.values) { let dp_value = parseFloat(value[1]); if (_.isNaN(dp_value)) { dp_value = null; @@ -164,8 +169,13 @@ export class ResultTransformer { for (let i = seriesList.length - 1; i > 0; i--) { let topSeries = seriesList[i].datapoints; let bottomSeries = seriesList[i - 1].datapoints; + if (!topSeries || !bottomSeries) { + throw new Error('Prometheus heatmap transform error: data should be a time series'); + } + for (let j = 0; j < topSeries.length; j++) { - topSeries[j][0] -= bottomSeries[j][0]; + const bottomPoint = bottomSeries[j] || [0]; + topSeries[j][0] -= bottomPoint[0]; } } diff --git a/public/app/plugins/datasource/prometheus/specs/result_transformer.jest.ts b/public/app/plugins/datasource/prometheus/specs/result_transformer.jest.ts index b94cca79059..c0f2609f5b4 100644 --- a/public/app/plugins/datasource/prometheus/specs/result_transformer.jest.ts +++ b/public/app/plugins/datasource/prometheus/specs/result_transformer.jest.ts @@ -126,6 +126,36 @@ describe('Prometheus Result Transformer', () => { { target: '3', datapoints: [[10, 1445000010000], [0, 1445000020000], [10, 1445000030000]] }, ]); }); + + it('should handle missing datapoints', () => { + const seriesList = [ + { datapoints: [[1, 1000], [2, 2000]] }, + { datapoints: [[2, 1000], [5, 2000], [1, 3000]] }, + { datapoints: [[3, 1000], [7, 2000]] }, + ]; + const expected = [ + { datapoints: [[1, 1000], [2, 2000]] }, + { datapoints: [[1, 1000], [3, 2000], [1, 3000]] }, + { datapoints: [[1, 1000], [2, 2000]] }, + ]; + const result = ctx.resultTransformer.transformToHistogramOverTime(seriesList); + expect(result).toEqual(expected); + }); + + it('should throw error when data in wrong format', () => { + const seriesList = [{ rows: [] }, { datapoints: [] }]; + expect(() => { + ctx.resultTransformer.transformToHistogramOverTime(seriesList); + }).toThrow(); + }); + + it('should throw error when prometheus returned non-timeseries', () => { + // should be { metric: {}, values: [] } for timeseries + const metricData = { metric: {}, value: [] }; + expect(() => { + ctx.resultTransformer.transformMetricData(metricData, { step: 1 }, 1000, 2000); + }).toThrow(); + }); }); describe('When resultFormat is time series', () => { diff --git a/public/app/plugins/panel/heatmap/heatmap_ctrl.ts b/public/app/plugins/panel/heatmap/heatmap_ctrl.ts index 11fbad47b99..31a5afa630e 100644 --- a/public/app/plugins/panel/heatmap/heatmap_ctrl.ts +++ b/public/app/plugins/panel/heatmap/heatmap_ctrl.ts @@ -302,6 +302,10 @@ export class HeatmapCtrl extends MetricsPanelCtrl { } seriesHandler(seriesData) { + if (seriesData.datapoints === undefined) { + throw new Error('Heatmap error: data should be a time series'); + } + let series = new TimeSeries({ datapoints: seriesData.datapoints, alias: seriesData.target, From 5e4d6958d6258ee396cc03ff3479c982d44e0ace Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 6 Jul 2018 11:54:37 +0200 Subject: [PATCH 09/16] fix links not updating after changing variables --- public/app/features/dashlinks/module.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/public/app/features/dashlinks/module.ts b/public/app/features/dashlinks/module.ts index f9482049c40..380144dbcd5 100644 --- a/public/app/features/dashlinks/module.ts +++ b/public/app/features/dashlinks/module.ts @@ -41,20 +41,20 @@ function dashLink($compile, $sanitize, linkSrv) { elem.html(template); $compile(elem.contents())(scope); - var anchor = elem.find('a'); - var icon = elem.find('i'); - var span = elem.find('span'); - function update() { var linkInfo = linkSrv.getAnchorInfo(link); + + const anchor = elem.find('a'); + const span = elem.find('span'); span.text(linkInfo.title); + if (!link.asDropdown) { anchor.attr('href', linkInfo.href); sanitizeAnchor(); } - elem.find('a').attr('data-placement', 'bottom'); + anchor.attr('data-placement', 'bottom'); // tooltip - elem.find('a').tooltip({ + anchor.tooltip({ title: $sanitize(scope.link.tooltip), html: true, container: 'body', @@ -62,12 +62,13 @@ function dashLink($compile, $sanitize, linkSrv) { } function sanitizeAnchor() { + const anchor = elem.find('a'); const anchorSanitized = $sanitize(anchor.parent().html()); anchor.parent().html(anchorSanitized); } - icon.attr('class', 'fa fa-fw ' + scope.link.icon); - anchor.attr('target', scope.link.target); + elem.find('i').attr('class', 'fa fa-fw ' + scope.link.icon); + elem.find('a').attr('target', scope.link.target); // fix for menus on the far right if (link.asDropdown && scope.$last) { From af434df5a37fcc090a0b7f38d333a87fe2558bb4 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 6 Jul 2018 12:35:19 +0200 Subject: [PATCH 10/16] changelog: add notes about closing #12506 [skip ci] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0177546b643..cb0b95c211f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * **Postgres/MySQL/MSSQL**: Use floor rounding in $__timeGroup macro function [#12460](https://github.com/grafana/grafana/issues/12460), thx [@svenklemm](https://github.com/svenklemm) * **MySQL/MSSQL**: Use datetime format instead of epoch for $__timeFilter, $__timeFrom and $__timeTo macros [#11618](https://github.com/grafana/grafana/issues/11618) [#11619](https://github.com/grafana/grafana/issues/11619), thx [@AustinWinstanley](https://github.com/AustinWinstanley) * **Github OAuth**: Allow changes of user info at Github to be synched to Grafana when signing in [#11818](https://github.com/grafana/grafana/issues/11818), thx [@rwaweber](https://github.com/rwaweber) +* **Dashboard**: Dashboard links not updated when changing variables [#12506](https://github.com/grafana/grafana/issues/12506) # 5.2.1 (2018-06-29) From cbdf6ef355d6cae33c4d770dcc1a676f53028980 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 6 Jul 2018 12:53:10 +0200 Subject: [PATCH 11/16] changelog: add notes about closing #12506 [skip ci] --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb0b95c211f..e478315f1a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,8 +14,12 @@ * **Postgres/MySQL/MSSQL**: Use floor rounding in $__timeGroup macro function [#12460](https://github.com/grafana/grafana/issues/12460), thx [@svenklemm](https://github.com/svenklemm) * **MySQL/MSSQL**: Use datetime format instead of epoch for $__timeFilter, $__timeFrom and $__timeTo macros [#11618](https://github.com/grafana/grafana/issues/11618) [#11619](https://github.com/grafana/grafana/issues/11619), thx [@AustinWinstanley](https://github.com/AustinWinstanley) * **Github OAuth**: Allow changes of user info at Github to be synched to Grafana when signing in [#11818](https://github.com/grafana/grafana/issues/11818), thx [@rwaweber](https://github.com/rwaweber) -* **Dashboard**: Dashboard links not updated when changing variables [#12506](https://github.com/grafana/grafana/issues/12506) +# 5.2.2 (unreleased) + +### Minor + +* **Dashboard**: Dashboard links not updated when changing variables [#12506](https://github.com/grafana/grafana/issues/12506) # 5.2.1 (2018-06-29) From f2980bb9785243ef999eb7b9ce599b9c861af489 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 6 Jul 2018 12:55:12 +0200 Subject: [PATCH 12/16] changelog: add notes about closing #12484 [skip ci] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e478315f1a5..2c2b4f8cd33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * **Singlestat**: Make colorization of prefix and postfix optional in singlestat [#11892](https://github.com/grafana/grafana/pull/11892), thx [@ApsOps](https://github.com/ApsOps) * **Table**: Make table sorting stable when null values exist [#12362](https://github.com/grafana/grafana/pull/12362), thx [@bz2](https://github.com/bz2) * **Prometheus**: Fix graph panel bar width issue in aligned prometheus queries [#12379](https://github.com/grafana/grafana/issues/12379) +* **Prometheus**: Heatmap - fix unhandled error when some points are missing [#12484](https://github.com/grafana/grafana/issues/12484) * **Variables**: Skip unneeded extra query request when de-selecting variable values used for repeated panels [#8186](https://github.com/grafana/grafana/issues/8186), thx [@mtanda](https://github.com/mtanda) * **Postgres/MySQL/MSSQL**: Use floor rounding in $__timeGroup macro function [#12460](https://github.com/grafana/grafana/issues/12460), thx [@svenklemm](https://github.com/svenklemm) * **MySQL/MSSQL**: Use datetime format instead of epoch for $__timeFilter, $__timeFrom and $__timeTo macros [#11618](https://github.com/grafana/grafana/issues/11618) [#11619](https://github.com/grafana/grafana/issues/11619), thx [@AustinWinstanley](https://github.com/AustinWinstanley) From 7ddcaf22d5a55d4178f16c9157bf68079a9d37ad Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Fri, 6 Jul 2018 15:32:08 +0200 Subject: [PATCH 13/16] Fix datasource sorting with template variables - fixes sorting when template variables are present - simplified existing test cases - added test to cover variable usage in datasource service --- public/app/features/plugins/datasource_srv.ts | 6 ++- .../plugins/specs/datasource_srv.jest.ts | 47 ++++++++++++------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/public/app/features/plugins/datasource_srv.ts b/public/app/features/plugins/datasource_srv.ts index b5e0316163c..bff6f8b9f6a 100644 --- a/public/app/features/plugins/datasource_srv.ts +++ b/public/app/features/plugins/datasource_srv.ts @@ -142,10 +142,12 @@ export class DatasourceSrv { var ds = config.datasources[first]; if (ds) { + const key = `$${variable.name}`; list.push({ - name: '$' + variable.name, - value: '$' + variable.name, + name: key, + value: key, meta: ds.meta, + sort: key, }); } } diff --git a/public/app/features/plugins/specs/datasource_srv.jest.ts b/public/app/features/plugins/specs/datasource_srv.jest.ts index f261c4e2249..5458662ef9b 100644 --- a/public/app/features/plugins/specs/datasource_srv.jest.ts +++ b/public/app/features/plugins/specs/datasource_srv.jest.ts @@ -2,8 +2,21 @@ import config from 'app/core/config'; import 'app/features/plugins/datasource_srv'; import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; +// Datasource variable $datasource with current value 'BBB' +const templateSrv = { + variables: [ + { + type: 'datasource', + name: 'datasource', + current: { + value: 'BBB', + }, + }, + ], +}; + describe('datasource_srv', function() { - let _datasourceSrv = new DatasourceSrv({}, {}, {}, {}); + let _datasourceSrv = new DatasourceSrv({}, {}, {}, templateSrv); let metricSources; describe('when loading metric sources', () => { @@ -35,25 +48,27 @@ describe('datasource_srv', function() { }; beforeEach(() => { config.datasources = unsortedDatasources; - metricSources = _datasourceSrv.getMetricSources({ skipVariables: true }); - }); - - it('should return a list of sources sorted case insensitively with builtin sources last', () => { - expect(metricSources[0].name).toBe('aaa'); - expect(metricSources[1].name).toBe('BBB'); - expect(metricSources[2].name).toBe('mmm'); - expect(metricSources[3].name).toBe('ZZZ'); - expect(metricSources[4].name).toBe('--Grafana--'); - expect(metricSources[5].name).toBe('--Mixed--'); - }); - - beforeEach(() => { + metricSources = _datasourceSrv.getMetricSources({}); config.defaultDatasource = 'BBB'; }); + it('should return a list of sources sorted case insensitively with builtin sources last', () => { + expect(metricSources[1].name).toBe('aaa'); + expect(metricSources[2].name).toBe('BBB'); + expect(metricSources[3].name).toBe('mmm'); + expect(metricSources[4].name).toBe('ZZZ'); + expect(metricSources[5].name).toBe('--Grafana--'); + expect(metricSources[6].name).toBe('--Mixed--'); + }); + it('should set default data source', () => { - expect(metricSources[2].name).toBe('default'); - expect(metricSources[2].sort).toBe('BBB'); + expect(metricSources[3].name).toBe('default'); + expect(metricSources[3].sort).toBe('BBB'); + }); + + it('should set default inject the variable datasources', () => { + expect(metricSources[0].name).toBe('$datasource'); + expect(metricSources[0].sort).toBe('$datasource'); }); }); }); From 922371ba76738670d44a44cfcf634d3a0a9ade4c Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 6 Jul 2018 17:48:39 +0200 Subject: [PATCH 14/16] changelog: add notes about closing #12379 [skip ci] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c2b4f8cd33..1f9cc951e34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ ### Minor +* **Prometheus**: Fix graph panel bar width issue in aligned prometheus queries [#12379](https://github.com/grafana/grafana/issues/12379) * **Dashboard**: Dashboard links not updated when changing variables [#12506](https://github.com/grafana/grafana/issues/12506) # 5.2.1 (2018-06-29) From 645974ec8dd59e876cb73280072561d1b07280fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sat, 7 Jul 2018 10:25:41 +0200 Subject: [PATCH 15/16] ux: minor fix/tweak to inactive view mode, think logo should be visible & fixes dashboard title alignment --- public/sass/components/_view_states.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/public/sass/components/_view_states.scss b/public/sass/components/_view_states.scss index c14590b4ec9..5e9d037e924 100644 --- a/public/sass/components/_view_states.scss +++ b/public/sass/components/_view_states.scss @@ -36,10 +36,6 @@ } } - .sidemenu { - display: none; - } - .gf-timepicker-nav-btn { transform: translate3d(40px, 0, 0); } From b464a28cca12b3f786f91cc425a213e60262a40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sat, 7 Jul 2018 14:40:17 +0200 Subject: [PATCH 16/16] devenv: updated devenv provision scripts --- .gitignore | 1 + .../bulk-dashboards.yaml | 0 .../bulkdash.jsonnet | 0 devenv/dashboards.yaml | 9 ++++++ .../dev-dashboards/dev-dashboards.yaml | 9 ------ .../default/default.yaml => datasources.yaml} | 28 +++++++++---------- .../dev-dashboards/dashboard_with_rows.json | 0 devenv/setup.sh | 25 +++++++---------- 8 files changed, 34 insertions(+), 38 deletions(-) rename devenv/{dashboards/bulk-testing => bulk-dashboards}/bulk-dashboards.yaml (100%) rename devenv/{dashboards/bulk-testing => bulk-dashboards}/bulkdash.jsonnet (100%) create mode 100644 devenv/dashboards.yaml delete mode 100644 devenv/dashboards/dev-dashboards/dev-dashboards.yaml rename devenv/{datasources/default/default.yaml => datasources.yaml} (81%) rename devenv/{dashboards => }/dev-dashboards/dashboard_with_rows.json (100%) diff --git a/.gitignore b/.gitignore index accc24d84cd..11df66360d9 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ fig.yml docker-compose.yml docker-compose.yaml /conf/provisioning/**/custom.yaml +/conf/provisioning/**/dev.yaml /conf/ldap_dev.toml profile.cov /grafana diff --git a/devenv/dashboards/bulk-testing/bulk-dashboards.yaml b/devenv/bulk-dashboards/bulk-dashboards.yaml similarity index 100% rename from devenv/dashboards/bulk-testing/bulk-dashboards.yaml rename to devenv/bulk-dashboards/bulk-dashboards.yaml diff --git a/devenv/dashboards/bulk-testing/bulkdash.jsonnet b/devenv/bulk-dashboards/bulkdash.jsonnet similarity index 100% rename from devenv/dashboards/bulk-testing/bulkdash.jsonnet rename to devenv/bulk-dashboards/bulkdash.jsonnet diff --git a/devenv/dashboards.yaml b/devenv/dashboards.yaml new file mode 100644 index 00000000000..226c1a8b335 --- /dev/null +++ b/devenv/dashboards.yaml @@ -0,0 +1,9 @@ +apiVersion: 1 + +providers: + - name: 'gdev dashboards' + folder: 'gdev dashboards' + type: file + options: + path: devenv/dev-dashboards + diff --git a/devenv/dashboards/dev-dashboards/dev-dashboards.yaml b/devenv/dashboards/dev-dashboards/dev-dashboards.yaml deleted file mode 100644 index 343910de738..00000000000 --- a/devenv/dashboards/dev-dashboards/dev-dashboards.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: 1 - -providers: - - name: 'dev dashboards' - folder: 'dev dashboards' - type: file - options: - path: devenv/dashboards/dev-dashboards - diff --git a/devenv/datasources/default/default.yaml b/devenv/datasources.yaml similarity index 81% rename from devenv/datasources/default/default.yaml rename to devenv/datasources.yaml index dc2310f15aa..e93c0217f27 100644 --- a/devenv/datasources/default/default.yaml +++ b/devenv/datasources.yaml @@ -1,38 +1,38 @@ apiVersion: 1 datasources: - - name: Graphite + - name: gdev-graphite type: graphite access: proxy url: http://localhost:8080 jsonData: graphiteVersion: "1.1" - - - name: Prometheus + + - name: gdev-prometheus type: prometheus access: proxy isDefault: true url: http://localhost:9090 - - - name: InfluxDB + + - name: gdev-influxdb type: influxdb access: proxy database: site user: grafana password: grafana url: http://localhost:8086 - jsonData: + jsonData: timeInterval: "15s" - - name: OpenTsdb + - name: gdev-opentsdb type: opentsdb access: proxy url: http://localhost:4242 - jsonData: + jsonData: tsdbResolution: 1 tsdbVersion: 1 - - name: Elastic + - name: gdev-elasticsearch-metrics type: elasticsearch access: proxy database: "[metrics-]YYYY.MM.DD" @@ -40,22 +40,22 @@ datasources: jsonData: interval: Daily timeField: "@timestamp" - - - name: MySQL + + - name: gdev-mysql type: mysql url: localhost:3306 database: grafana user: grafana password: password - - name: MSSQL + - name: gdev-mssql type: mssql url: localhost:1433 database: grafana user: grafana password: "Password!" - - name: Postgres + - name: gdev-postgres type: postgres url: localhost:5432 database: grafana @@ -64,7 +64,7 @@ datasources: jsonData: sslmode: "disable" - - name: Cloudwatch + - name: gdev-cloudwatch type: cloudwatch editable: true jsonData: diff --git a/devenv/dashboards/dev-dashboards/dashboard_with_rows.json b/devenv/dev-dashboards/dashboard_with_rows.json similarity index 100% rename from devenv/dashboards/dev-dashboards/dashboard_with_rows.json rename to devenv/dev-dashboards/dashboard_with_rows.json diff --git a/devenv/setup.sh b/devenv/setup.sh index 0900b57e583..78dbfc1a366 100755 --- a/devenv/setup.sh +++ b/devenv/setup.sh @@ -23,41 +23,36 @@ requiresJsonnet() { } defaultDashboards() { - requiresJsonnet - - ln -s -f -r ./dashboards/dev-dashboards/dev-dashboards.yaml ../conf/provisioning/dashboards/custom.yaml + ln -s -f ../../../devenv/dashboards.yaml ../conf/provisioning/dashboards/dev.yaml } defaultDatasources() { echo "setting up all default datasources using provisioning" - ln -s -f -r ./datasources/default/default.yaml ../conf/provisioning/datasources/custom.yaml + ln -s -f ../../../devenv/datasources.yaml ../conf/provisioning/datasources/dev.yaml } usage() { - echo -e "install.sh\n\tThis script installs my basic setup for a debian laptop\n" + echo -e "install.sh\n\tThis script setups dev provision for datasources and dashboards" echo "Usage:" echo " bulk-dashboards - create and provisioning 400 dashboards" - echo " default-datasources - provisiong all core datasources" + echo " no args - provisiong core datasources and dev dashboards" } main() { local cmd=$1 - if [[ -z "$cmd" ]]; then - usage - exit 1 - fi - if [[ $cmd == "bulk-dashboards" ]]; then bulkDashboard - elif [[ $cmd == "default-datasources" ]]; then - defaultDatasources - elif [[ $cmd == "default-dashboards" ]]; then - defaultDashboards else + defaultDashboards + defaultDatasources + fi + + if [[ -z "$cmd" ]]; then usage fi + } main "$@"