diff --git a/pkg/api/metrics.go b/pkg/api/metrics.go
index c3bd9062737..0fa6003d67a 100644
--- a/pkg/api/metrics.go
+++ b/pkg/api/metrics.go
@@ -48,6 +48,7 @@ func GetTestDataScenarios(c *middleware.Context) Response {
"id": scenario.Id,
"name": scenario.Name,
"description": scenario.Description,
+ "stringInput": scenario.StringInput,
})
}
diff --git a/pkg/tsdb/graphite/graphite.go b/pkg/tsdb/graphite/graphite.go
index 5f14f0302f7..78685d52371 100644
--- a/pkg/tsdb/graphite/graphite.go
+++ b/pkg/tsdb/graphite/graphite.go
@@ -79,7 +79,7 @@ func (e *GraphiteExecutor) Execute(queries tsdb.QuerySlice, context *tsdb.QueryC
}
result.QueryResults = make(map[string]*tsdb.QueryResult)
- queryRes := &tsdb.QueryResult{}
+ queryRes := tsdb.NewQueryResult()
for _, series := range data {
queryRes.Series = append(queryRes.Series, &tsdb.TimeSeries{
diff --git a/pkg/tsdb/models.go b/pkg/tsdb/models.go
index 008be3efa28..bbf7bba7ac7 100644
--- a/pkg/tsdb/models.go
+++ b/pkg/tsdb/models.go
@@ -66,6 +66,12 @@ type TimePoint [2]null.Float
type TimeSeriesPoints []TimePoint
type TimeSeriesSlice []*TimeSeries
+func NewQueryResult() *QueryResult {
+ return &QueryResult{
+ Series: make(TimeSeriesSlice, 0),
+ }
+}
+
func NewTimePoint(value float64, timestamp float64) TimePoint {
return TimePoint{null.FloatFrom(value), null.FloatFrom(timestamp)}
}
diff --git a/pkg/tsdb/prometheus/prometheus.go b/pkg/tsdb/prometheus/prometheus.go
index eba558ddaa7..f7e68662efa 100644
--- a/pkg/tsdb/prometheus/prometheus.go
+++ b/pkg/tsdb/prometheus/prometheus.go
@@ -132,7 +132,7 @@ func parseQuery(queries tsdb.QuerySlice, queryContext *tsdb.QueryContext) (*Prom
func parseResponse(value pmodel.Value, query *PrometheusQuery) (map[string]*tsdb.QueryResult, error) {
queryResults := make(map[string]*tsdb.QueryResult)
- queryRes := &tsdb.QueryResult{}
+ queryRes := tsdb.NewQueryResult()
data, ok := value.(pmodel.Matrix)
if !ok {
diff --git a/pkg/tsdb/testdata/scenarios.go b/pkg/tsdb/testdata/scenarios.go
index f34db7ac931..e90b0d4df79 100644
--- a/pkg/tsdb/testdata/scenarios.go
+++ b/pkg/tsdb/testdata/scenarios.go
@@ -2,8 +2,11 @@ package testdata
import (
"math/rand"
+ "strconv"
+ "strings"
"time"
+ "github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/tsdb"
)
@@ -12,6 +15,7 @@ type ScenarioHandler func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.Q
type Scenario struct {
Id string `json:"id"`
Name string `json:"name"`
+ StringInput string `json:"stringOption"`
Description string `json:"description"`
Handler ScenarioHandler `json:"-"`
}
@@ -20,15 +24,17 @@ var ScenarioRegistry map[string]*Scenario
func init() {
ScenarioRegistry = make(map[string]*Scenario)
- //logger := log.New("tsdb.testdata")
+ logger := log.New("tsdb.testdata")
+
+ logger.Debug("Initializing TestData Scenario")
registerScenario(&Scenario{
Id: "random_walk",
Name: "Random Walk",
Handler: func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult {
- to := context.TimeRange.MustGetTo().UnixNano() / int64(time.Millisecond)
- timeWalkerMs := context.TimeRange.MustGetFrom().UnixNano() / int64(time.Millisecond)
+ timeWalkerMs := context.TimeRange.GetFromAsMsEpoch()
+ to := context.TimeRange.GetToAsMsEpoch()
series := newSeriesForQuery(query)
@@ -44,7 +50,7 @@ func init() {
series.Points = points
- queryRes := &tsdb.QueryResult{}
+ queryRes := tsdb.NewQueryResult()
queryRes.Series = append(queryRes.Series, series)
return queryRes
},
@@ -54,9 +60,7 @@ func init() {
Id: "no_data_points",
Name: "No Data Points",
Handler: func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult {
- return &tsdb.QueryResult{
- Series: make(tsdb.TimeSeriesSlice, 0),
- }
+ return tsdb.NewQueryResult()
},
})
@@ -64,7 +68,7 @@ func init() {
Id: "datapoints_outside_range",
Name: "Datapoints Outside Range",
Handler: func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult {
- queryRes := &tsdb.QueryResult{}
+ queryRes := tsdb.NewQueryResult()
series := newSeriesForQuery(query)
outsideTime := context.TimeRange.MustGetFrom().Add(-1*time.Hour).Unix() * 1000
@@ -75,6 +79,41 @@ func init() {
return queryRes
},
})
+
+ registerScenario(&Scenario{
+ Id: "csv_metric_values",
+ Name: "CSV Metric Values",
+ StringInput: "1,20,90,30,5,0",
+ Handler: func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult {
+ queryRes := tsdb.NewQueryResult()
+
+ stringInput := query.Model.Get("stringInput").MustString()
+ values := []float64{}
+ for _, strVal := range strings.Split(stringInput, ",") {
+ if val, err := strconv.ParseFloat(strVal, 64); err == nil {
+ values = append(values, val)
+ }
+ }
+
+ if len(values) == 0 {
+ return queryRes
+ }
+
+ series := newSeriesForQuery(query)
+ startTime := context.TimeRange.GetFromAsMsEpoch()
+ endTime := context.TimeRange.GetToAsMsEpoch()
+ step := (endTime - startTime) / int64(len(values)-1)
+
+ for _, val := range values {
+ series.Points = append(series.Points, tsdb.NewTimePoint(val, float64(startTime)))
+ startTime += step
+ }
+
+ queryRes.Series = append(queryRes.Series, series)
+
+ return queryRes
+ },
+ })
}
func registerScenario(scenario *Scenario) {
diff --git a/pkg/tsdb/time_range.go b/pkg/tsdb/time_range.go
index 67227b834dc..cf6bc6a5048 100644
--- a/pkg/tsdb/time_range.go
+++ b/pkg/tsdb/time_range.go
@@ -21,6 +21,14 @@ type TimeRange struct {
Now time.Time
}
+func (tr *TimeRange) GetFromAsMsEpoch() int64 {
+ return tr.MustGetFrom().UnixNano() / int64(time.Millisecond)
+}
+
+func (tr *TimeRange) GetToAsMsEpoch() int64 {
+ return tr.MustGetTo().UnixNano() / int64(time.Millisecond)
+}
+
func (tr *TimeRange) MustGetFrom() time.Time {
if res, err := tr.ParseFrom(); err != nil {
return time.Unix(0, 0)
diff --git a/public/app/plugins/app/testdata/dashboards/alerts.json b/public/app/plugins/app/testdata/dashboards/alerts.json
new file mode 100644
index 00000000000..c510ec220ea
--- /dev/null
+++ b/public/app/plugins/app/testdata/dashboards/alerts.json
@@ -0,0 +1,286 @@
+{
+ "title": "TestData - Alerts",
+ "tags": [
+ "grafana-test"
+ ],
+ "style": "dark",
+ "timezone": "browser",
+ "editable": true,
+ "hideControls": false,
+ "sharedCrosshair": false,
+ "rows": [
+ {
+ "collapse": false,
+ "editable": true,
+ "height": 255.625,
+ "panels": [
+ {
+ "alert": {
+ "conditions": [
+ {
+ "evaluator": {
+ "params": [
+ 111
+ ],
+ "type": "gt"
+ },
+ "query": {
+ "params": [
+ "A",
+ "5m",
+ "now"
+ ]
+ },
+ "reducer": {
+ "params": [],
+ "type": "avg"
+ },
+ "type": "query"
+ }
+ ],
+ "enabled": true,
+ "frequency": "60s",
+ "handler": 1,
+ "name": "Should always be green",
+ "noDataState": "no_data",
+ "notifications": []
+ },
+ "aliasColors": {},
+ "bars": false,
+ "datasource": "Grafana TestData",
+ "editable": true,
+ "error": false,
+ "fill": 1,
+ "id": 3,
+ "isNew": true,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 2,
+ "links": [],
+ "nullPointMode": "connected",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "span": 6,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "refId": "A",
+ "scenario": "random_walk",
+ "scenarioId": "csv_metric_values",
+ "target": "",
+ "stringInput": "1,20,90,30,5,0"
+ }
+ ],
+ "thresholds": [
+ {
+ "colorMode": "critical",
+ "fill": true,
+ "line": true,
+ "op": "gt",
+ "value": 111
+ }
+ ],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Always OK",
+ "tooltip": {
+ "msResolution": false,
+ "shared": true,
+ "sort": 0,
+ "value_type": "cumulative"
+ },
+ "type": "graph",
+ "xaxis": {
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "max": "125",
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ },
+ {
+ "alert": {
+ "conditions": [
+ {
+ "evaluator": {
+ "params": [
+ 177
+ ],
+ "type": "gt"
+ },
+ "query": {
+ "params": [
+ "A",
+ "5m",
+ "now"
+ ]
+ },
+ "reducer": {
+ "params": [],
+ "type": "avg"
+ },
+ "type": "query"
+ }
+ ],
+ "enabled": true,
+ "frequency": "60s",
+ "handler": 1,
+ "name": "Always Alerting",
+ "noDataState": "no_data",
+ "notifications": []
+ },
+ "aliasColors": {},
+ "bars": false,
+ "datasource": "Grafana TestData",
+ "editable": true,
+ "error": false,
+ "fill": 1,
+ "id": 4,
+ "isNew": true,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 2,
+ "links": [],
+ "nullPointMode": "connected",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "span": 6,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "refId": "A",
+ "scenario": "random_walk",
+ "scenarioId": "csv_metric_values",
+ "target": "",
+ "stringInput": "200,445,100,150,200,220,190"
+ }
+ ],
+ "thresholds": [
+ {
+ "value": 177,
+ "op": "gt",
+ "fill": true,
+ "line": true,
+ "colorMode": "critical"
+ }
+ ],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Always Alerting",
+ "tooltip": {
+ "msResolution": false,
+ "shared": true,
+ "sort": 0,
+ "value_type": "cumulative"
+ },
+ "type": "graph",
+ "xaxis": {
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ }
+ ],
+ "title": "New row"
+ }
+ ],
+ "time": {
+ "from": "now-6h",
+ "to": "now"
+ },
+ "timepicker": {
+ "refresh_intervals": [
+ "5s",
+ "10s",
+ "30s",
+ "1m",
+ "5m",
+ "15m",
+ "30m",
+ "1h",
+ "2h",
+ "1d"
+ ],
+ "time_options": [
+ "5m",
+ "15m",
+ "1h",
+ "6h",
+ "12h",
+ "24h",
+ "2d",
+ "7d",
+ "30d"
+ ]
+ },
+ "templating": {
+ "list": []
+ },
+ "annotations": {
+ "list": []
+ },
+ "schemaVersion": 13,
+ "version": 10,
+ "links": [],
+ "gnetId": null
+}
diff --git a/public/app/plugins/app/testdata/dashboards/graph_last_1h.json b/public/app/plugins/app/testdata/dashboards/graph_last_1h.json
index 0cca7b6c331..757dd48e50f 100644
--- a/public/app/plugins/app/testdata/dashboards/graph_last_1h.json
+++ b/public/app/plugins/app/testdata/dashboards/graph_last_1h.json
@@ -1,5 +1,5 @@
{
- "revision": 3,
+ "revision": 4,
"title": "TestData - Graph Panel Last 1h",
"tags": [
"grafana-test"
@@ -284,7 +284,7 @@
}
],
"thresholds": [],
- "timeFrom": "5d",
+ "timeFrom": "2s",
"timeShift": null,
"title": "Millisecond res x-axis and tooltip",
"tooltip": {
@@ -318,9 +318,126 @@
"show": true
}
]
+ },
+ {
+ "title": "",
+ "error": false,
+ "span": 4,
+ "editable": true,
+ "type": "text",
+ "isNew": true,
+ "id": 6,
+ "mode": "markdown",
+ "content": "Just verify that the tooltip time has millisecond resolution ",
+ "links": []
}
],
"title": "New row"
+ },
+ {
+ "title": "New row",
+ "height": 336,
+ "editable": true,
+ "collapse": false,
+ "panels": [
+ {
+ "title": "2 yaxis and axis lables",
+ "error": false,
+ "span": 7.99561403508772,
+ "editable": true,
+ "type": "graph",
+ "isNew": true,
+ "id": 5,
+ "targets": [
+ {
+ "target": "",
+ "refId": "A",
+ "scenarioId": "csv_metric_values",
+ "stringInput": "1,20,90,30,5,0"
+ },
+ {
+ "target": "",
+ "refId": "B",
+ "scenarioId": "csv_metric_values",
+ "stringInput": "2000,3000,4000,1000,3000,10000"
+ }
+ ],
+ "datasource": "Grafana TestData",
+ "renderer": "flot",
+ "yaxes": [
+ {
+ "label": "Perecent",
+ "show": true,
+ "logBase": 1,
+ "min": null,
+ "max": null,
+ "format": "percent"
+ },
+ {
+ "label": "Pressure",
+ "show": true,
+ "logBase": 1,
+ "min": null,
+ "max": null,
+ "format": "short"
+ }
+ ],
+ "xaxis": {
+ "show": true,
+ "mode": "time",
+ "name": null,
+ "values": []
+ },
+ "lines": true,
+ "fill": 1,
+ "linewidth": 2,
+ "points": false,
+ "pointradius": 5,
+ "bars": false,
+ "stack": false,
+ "percentage": false,
+ "legend": {
+ "show": true,
+ "values": false,
+ "min": false,
+ "max": false,
+ "current": false,
+ "total": false,
+ "avg": false
+ },
+ "nullPointMode": "connected",
+ "steppedLine": false,
+ "tooltip": {
+ "value_type": "cumulative",
+ "shared": true,
+ "sort": 0,
+ "msResolution": false
+ },
+ "timeFrom": null,
+ "timeShift": null,
+ "aliasColors": {},
+ "seriesOverrides": [
+ {
+ "alias": "B-series",
+ "yaxis": 2
+ }
+ ],
+ "thresholds": [],
+ "links": []
+ },
+ {
+ "title": "",
+ "error": false,
+ "span": 4.00438596491228,
+ "editable": true,
+ "type": "text",
+ "isNew": true,
+ "id": 7,
+ "mode": "markdown",
+ "content": "Verify that axis labels look ok",
+ "links": []
+ }
+ ]
}
],
"time": {
@@ -360,7 +477,7 @@
},
"refresh": false,
"schemaVersion": 13,
- "version": 4,
+ "version": 3,
"links": [],
"gnetId": null
}
diff --git a/public/app/plugins/app/testdata/datasource/datasource.ts b/public/app/plugins/app/testdata/datasource/datasource.ts
index a06daa19262..e0846d99ab6 100644
--- a/public/app/plugins/app/testdata/datasource/datasource.ts
+++ b/public/app/plugins/app/testdata/datasource/datasource.ts
@@ -1,6 +1,7 @@
///