Commit 4bb8249f by Torkel Ödegaard Committed by GitHub

Merge pull request #14627 from cykl/influxdb-timezone-clause

Add support for InfluxDB's time zone clause
parents a138bf27 c29c9d16
...@@ -16,6 +16,7 @@ func (qp *InfluxdbQueryParser) Parse(model *simplejson.Json, dsInfo *models.Data ...@@ -16,6 +16,7 @@ func (qp *InfluxdbQueryParser) Parse(model *simplejson.Json, dsInfo *models.Data
rawQuery := model.Get("query").MustString("") rawQuery := model.Get("query").MustString("")
useRawQuery := model.Get("rawQuery").MustBool(false) useRawQuery := model.Get("rawQuery").MustBool(false)
alias := model.Get("alias").MustString("") alias := model.Get("alias").MustString("")
tz := model.Get("tz").MustString("")
measurement := model.Get("measurement").MustString("") measurement := model.Get("measurement").MustString("")
...@@ -55,6 +56,7 @@ func (qp *InfluxdbQueryParser) Parse(model *simplejson.Json, dsInfo *models.Data ...@@ -55,6 +56,7 @@ func (qp *InfluxdbQueryParser) Parse(model *simplejson.Json, dsInfo *models.Data
Interval: parsedInterval, Interval: parsedInterval,
Alias: alias, Alias: alias,
UseRawQuery: useRawQuery, UseRawQuery: useRawQuery,
Tz: tz,
}, nil }, nil
} }
......
...@@ -41,6 +41,7 @@ func TestInfluxdbQueryParser(t *testing.T) { ...@@ -41,6 +41,7 @@ func TestInfluxdbQueryParser(t *testing.T) {
} }
], ],
"measurement": "logins.count", "measurement": "logins.count",
"tz": "Europe/Paris",
"policy": "default", "policy": "default",
"refId": "B", "refId": "B",
"resultFormat": "time_series", "resultFormat": "time_series",
...@@ -115,6 +116,7 @@ func TestInfluxdbQueryParser(t *testing.T) { ...@@ -115,6 +116,7 @@ func TestInfluxdbQueryParser(t *testing.T) {
So(len(res.GroupBy), ShouldEqual, 3) So(len(res.GroupBy), ShouldEqual, 3)
So(len(res.Selects), ShouldEqual, 3) So(len(res.Selects), ShouldEqual, 3)
So(len(res.Tags), ShouldEqual, 2) So(len(res.Tags), ShouldEqual, 2)
So(res.Tz, ShouldEqual, "Europe/Paris")
So(res.Interval, ShouldEqual, time.Second*20) So(res.Interval, ShouldEqual, time.Second*20)
So(res.Alias, ShouldEqual, "serie alias") So(res.Alias, ShouldEqual, "serie alias")
}) })
......
...@@ -13,6 +13,7 @@ type Query struct { ...@@ -13,6 +13,7 @@ type Query struct {
UseRawQuery bool UseRawQuery bool
Alias string Alias string
Interval time.Duration Interval time.Duration
Tz string
} }
type Tag struct { type Tag struct {
......
...@@ -26,6 +26,7 @@ func (query *Query) Build(queryContext *tsdb.TsdbQuery) (string, error) { ...@@ -26,6 +26,7 @@ func (query *Query) Build(queryContext *tsdb.TsdbQuery) (string, error) {
res += query.renderWhereClause() res += query.renderWhereClause()
res += query.renderTimeFilter(queryContext) res += query.renderTimeFilter(queryContext)
res += query.renderGroupBy(queryContext) res += query.renderGroupBy(queryContext)
res += query.renderTz()
} }
calculator := tsdb.NewIntervalCalculator(&tsdb.IntervalOptions{}) calculator := tsdb.NewIntervalCalculator(&tsdb.IntervalOptions{})
...@@ -154,3 +155,12 @@ func (query *Query) renderGroupBy(queryContext *tsdb.TsdbQuery) string { ...@@ -154,3 +155,12 @@ func (query *Query) renderGroupBy(queryContext *tsdb.TsdbQuery) string {
return groupBy return groupBy
} }
func (query *Query) renderTz() string {
tz := query.Tz
if tz == "" {
return ""
} else {
return fmt.Sprintf(" tz('%s')", tz)
}
}
...@@ -47,6 +47,20 @@ func TestInfluxdbQueryBuilder(t *testing.T) { ...@@ -47,6 +47,20 @@ func TestInfluxdbQueryBuilder(t *testing.T) {
So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "policy"."cpu" WHERE time > now() - 5m GROUP BY time(10s) fill(null)`) So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "policy"."cpu" WHERE time > now() - 5m GROUP BY time(10s) fill(null)`)
}) })
Convey("can build query with tz", func() {
query := &Query{
Selects: []*Select{{*qp1, *qp2}},
Measurement: "cpu",
GroupBy: []*QueryPart{groupBy1},
Tz: "Europe/Paris",
Interval: time.Second * 5,
}
rawQuery, err := query.Build(queryContext)
So(err, ShouldBeNil)
So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "cpu" WHERE time > now() - 5m GROUP BY time(5s) tz('Europe/Paris')`)
})
Convey("can build query with group bys", func() { Convey("can build query with group bys", func() {
query := &Query{ query := &Query{
Selects: []*Select{{*qp1, *qp2}}, Selects: []*Select{{*qp1, *qp2}},
......
...@@ -256,6 +256,10 @@ export default class InfluxQuery { ...@@ -256,6 +256,10 @@ export default class InfluxQuery {
query += ' SLIMIT ' + target.slimit; query += ' SLIMIT ' + target.slimit;
} }
if (target.tz) {
query += " tz('" + target.tz + "')";
}
return query; return query;
} }
......
...@@ -119,6 +119,16 @@ ...@@ -119,6 +119,16 @@
</div> </div>
</div> </div>
<div class="gf-form-inline" ng-if="ctrl.target.tz">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">tz</label>
<input type="text" class="gf-form-input width-9" ng-model="ctrl.target.tz" spellcheck='false' placeholder="No Timezone" ng-blur="ctrl.refresh()">
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form"> <div class="gf-form">
<label class="gf-form-label query-keyword width-7">FORMAT AS</label> <label class="gf-form-label query-keyword width-7">FORMAT AS</label>
......
...@@ -100,6 +100,9 @@ export class InfluxQueryCtrl extends QueryCtrl { ...@@ -100,6 +100,9 @@ export class InfluxQueryCtrl extends QueryCtrl {
if (!this.target.slimit) { if (!this.target.slimit) {
options.push(this.uiSegmentSrv.newSegment({ value: 'SLIMIT' })); options.push(this.uiSegmentSrv.newSegment({ value: 'SLIMIT' }));
} }
if (!this.target.tz) {
options.push(this.uiSegmentSrv.newSegment({ value: 'tz' }));
}
if (this.target.orderByTime === 'ASC') { if (this.target.orderByTime === 'ASC') {
options.push(this.uiSegmentSrv.newSegment({ value: 'ORDER BY time DESC' })); options.push(this.uiSegmentSrv.newSegment({ value: 'ORDER BY time DESC' }));
} }
...@@ -124,6 +127,10 @@ export class InfluxQueryCtrl extends QueryCtrl { ...@@ -124,6 +127,10 @@ export class InfluxQueryCtrl extends QueryCtrl {
this.target.slimit = 10; this.target.slimit = 10;
break; break;
} }
case 'tz': {
this.target.tz = 'UTC';
break;
}
case 'ORDER BY time DESC': { case 'ORDER BY time DESC': {
this.target.orderByTime = 'DESC'; this.target.orderByTime = 'DESC';
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment