Commit a4648607 by Torkel Ödegaard

feat(testdata): added csv test data scenario

parent 8d585766
......@@ -48,6 +48,7 @@ func GetTestDataScenarios(c *middleware.Context) Response {
"id": scenario.Id,
"name": scenario.Name,
"description": scenario.Description,
"stringInput": scenario.StringInput,
})
}
......
......@@ -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{
......
......@@ -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)}
}
......
......@@ -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 {
......
......@@ -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) {
......
......@@ -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)
......
{
"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
}
{
"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
}
///<reference path="../../../../headers/common.d.ts" />
import _ from 'lodash';
import angular from 'angular';
class TestDataDatasource {
......@@ -16,6 +17,8 @@ class TestDataDatasource {
scenarioId: item.scenarioId,
intervalMs: options.intervalMs,
maxDataPoints: options.maxDataPoints,
stringInput: item.stringInput,
jsonInput: angular.fromJson(item.jsonInput),
};
});
......
///<reference path="../../../../headers/common.d.ts" />
import _ from 'lodash';
import {TestDataDatasource} from './datasource';
import {QueryCtrl} from 'app/plugins/sdk';
......@@ -7,6 +9,7 @@ export class TestDataQueryCtrl extends QueryCtrl {
static templateUrl = 'partials/query.editor.html';
scenarioList: any;
scenario: any;
/** @ngInject **/
constructor($scope, $injector, private backendSrv) {
......@@ -19,7 +22,14 @@ export class TestDataQueryCtrl extends QueryCtrl {
$onInit() {
return this.backendSrv.get('/api/tsdb/testdata/scenarios').then(res => {
this.scenarioList = res;
this.scenario = _.find(this.scenarioList, {id: this.target.scenarioId});
});
}
scenarioChanged() {
this.scenario = _.find(this.scenarioList, {id: this.target.scenarioId});
this.target.stringInput = this.scenario.stringInput;
this.refresh();
}
}
......@@ -2,17 +2,17 @@
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label query-keyword">Scenario</label>
<div class="gf-form-select-wrapper width-25">
<select class="gf-form-input width-25" ng-model="ctrl.target.scenarioId" ng-options="v.id as v.name for v in ctrl.scenarioList" ng-change="ctrl.refresh()"></select>
<div class="gf-form-select-wrapper">
<select class="gf-form-input" ng-model="ctrl.target.scenarioId" ng-options="v.id as v.name for v in ctrl.scenarioList" ng-change="ctrl.scenarioChanged()"></select>
</div>
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword">With Options</label>
<input type="text" class="gf-form-input max-width-7" placeholder="optional" ng-model="target.param1" ng-change="ctrl.refresh()" ng-model-onblur>
<div class="gf-form gf-form gf-form--grow" ng-if="ctrl.scenario.stringInput">
<label class="gf-form-label query-keyword">String Input</label>
<input type="text" class="gf-form-input" placeholder="{{ctrl.scenario.stringInput}}" ng-model="ctrl.target.stringInput" ng-change="ctrl.refresh()" ng-model-onblur>
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword">Alias</label>
<input type="text" class="gf-form-input max-width-7" placeholder="optional" ng-model="target.alias" ng-change="ctrl.refresh()" ng-model-onblur>
<input type="text" class="gf-form-input max-width-7" placeholder="optional" ng-model="ctrl.target.alias" ng-change="ctrl.refresh()" ng-model-onblur>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
......
......@@ -9,7 +9,7 @@
"name": "Grafana Project",
"url": "http://grafana.org"
},
"version": "1.0.6",
"version": "1.0.7",
"updated": "2016-09-26"
},
......
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