Commit 2732aca0 by Torkel Ödegaard Committed by GitHub

TestData: Adds important new features to the random walk scenario (#21613)

* test data refactor

* new random walk options

* fixed test

* Added automatic names
parent 79255faf
......@@ -101,7 +101,15 @@ func init() {
Name: "Random Walk",
Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
return getRandomWalk(query, context)
queryRes := tsdb.NewQueryResult()
seriesCount := query.Model.Get("seriesCount").MustInt(1)
for i := 0; i < seriesCount; i++ {
queryRes.Series = append(queryRes.Series, getRandomWalk(query, context, i))
}
return queryRes
},
})
......@@ -139,7 +147,10 @@ func init() {
stringInput := query.Model.Get("stringInput").MustString()
parsedInterval, _ := time.ParseDuration(stringInput)
time.Sleep(parsedInterval)
return getRandomWalk(query, context)
queryRes := tsdb.NewQueryResult()
queryRes.Series = append(queryRes.Series, getRandomWalk(query, context, 0))
return queryRes
},
})
......@@ -157,7 +168,7 @@ func init() {
Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
queryRes := tsdb.NewQueryResult()
series := newSeriesForQuery(query)
series := newSeriesForQuery(query, 0)
outsideTime := context.TimeRange.MustGetFrom().Add(-1*time.Hour).Unix() * 1000
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(10), float64(outsideTime)))
......@@ -175,7 +186,7 @@ func init() {
points := query.Model.Get("points").MustArray()
series := newSeriesForQuery(query)
series := newSeriesForQuery(query, 0)
startTime := context.TimeRange.GetFromAsMsEpoch()
endTime := context.TimeRange.GetToAsMsEpoch()
......@@ -230,7 +241,7 @@ func init() {
return queryRes
}
series := newSeriesForQuery(query)
series := newSeriesForQuery(query, 0)
startTime := context.TimeRange.GetFromAsMsEpoch()
endTime := context.TimeRange.GetToAsMsEpoch()
step := (endTime - startTime) / int64(len(values)-1)
......@@ -288,7 +299,8 @@ func init() {
Name: "Random Walk (with error)",
Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
queryRes := getRandomWalk(query, context)
queryRes := tsdb.NewQueryResult()
queryRes.Series = append(queryRes.Series, getRandomWalk(query, context, 0))
queryRes.ErrorString = "This is an error. It can include URLs http://grafana.com/"
return queryRes
},
......@@ -441,10 +453,11 @@ func getPredictablePulse(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.Query
return queryRes
}
series := newSeriesForQuery(query)
series := newSeriesForQuery(query, 0)
series.Points = *points
series.Tags = parseLabels(query)
queryRes.Series = append(queryRes.Series, series)
attachLabels(query, queryRes)
return queryRes
}
......@@ -491,10 +504,11 @@ func getPredictableCSVWave(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.Que
return queryRes
}
series := newSeriesForQuery(query)
series := newSeriesForQuery(query, 0)
series.Points = *points
series.Tags = parseLabels(query)
queryRes.Series = append(queryRes.Series, series)
attachLabels(query, queryRes)
return queryRes
}
......@@ -520,28 +534,42 @@ func predictableSeries(timeRange *tsdb.TimeRange, timeStep, length int64, getVal
return &points, nil
}
func getRandomWalk(query *tsdb.Query, tsdbQuery *tsdb.TsdbQuery) *tsdb.QueryResult {
func getRandomWalk(query *tsdb.Query, tsdbQuery *tsdb.TsdbQuery, index int) *tsdb.TimeSeries {
timeWalkerMs := tsdbQuery.TimeRange.GetFromAsMsEpoch()
to := tsdbQuery.TimeRange.GetToAsMsEpoch()
series := newSeriesForQuery(query, index)
series := newSeriesForQuery(query)
startValue := query.Model.Get("startValue").MustFloat64(rand.Float64() * 100)
spread := query.Model.Get("spread").MustFloat64(1)
noise := query.Model.Get("noise").MustFloat64(0)
min, hasMin := query.Model.Get("min").Float64()
max, hasMax := query.Model.Get("max").Float64()
points := make(tsdb.TimeSeriesPoints, 0)
walker := query.Model.Get("startValue").MustFloat64(rand.Float64() * 100)
walker := startValue
for i := int64(0); i < 10000 && timeWalkerMs < to; i++ {
points = append(points, tsdb.NewTimePoint(null.FloatFrom(walker), float64(timeWalkerMs)))
nextValue := walker + (rand.Float64() * noise)
if hasMin == nil && nextValue < min {
nextValue = min
walker = min
}
walker += rand.Float64() - 0.5
if hasMax == nil && nextValue > max {
nextValue = max
walker = max
}
points = append(points, tsdb.NewTimePoint(null.FloatFrom(nextValue), float64(timeWalkerMs)))
walker += (rand.Float64() - 0.5) * spread
timeWalkerMs += query.IntervalMs
}
series.Points = points
queryRes := tsdb.NewQueryResult()
queryRes.Series = append(queryRes.Series, series)
attachLabels(query, queryRes)
return queryRes
series.Tags = parseLabels(query)
return series
}
/**
......@@ -549,30 +577,19 @@ func getRandomWalk(query *tsdb.Query, tsdbQuery *tsdb.TsdbQuery) *tsdb.QueryResu
*
* '{job="foo", instance="bar"} => {job: "foo", instance: "bar"}`
*/
func attachLabels(query *tsdb.Query, queryRes *tsdb.QueryResult) {
func parseLabels(query *tsdb.Query) map[string]string {
tags := map[string]string{}
labelText := query.Model.Get("labels").MustString("")
if labelText == "" {
return
}
tags := parseLabels(labelText)
for _, series := range queryRes.Series {
series.Tags = tags
return map[string]string{}
}
}
// generous parser:
// {job="foo", instance="bar"}
// job="foo", instance="bar"
// job=foo, instance=bar
// should all equal {job=foo, instance=bar}
func parseLabels(text string) map[string]string {
var tags map[string]string
text = strings.Trim(text, `{}`)
text := strings.Trim(labelText, `{}`)
if len(text) < 2 {
return tags
}
tags = make(map[string]string)
for _, keyval := range strings.Split(text, ",") {
......@@ -648,10 +665,24 @@ func registerScenario(scenario *Scenario) {
ScenarioRegistry[scenario.Id] = scenario
}
func newSeriesForQuery(query *tsdb.Query) *tsdb.TimeSeries {
func newSeriesForQuery(query *tsdb.Query, index int) *tsdb.TimeSeries {
alias := query.Model.Get("alias").MustString("")
suffix := ""
if index > 0 {
suffix = strconv.Itoa(index)
}
if alias == "" {
alias = query.RefId + "-series"
alias = fmt.Sprintf("%s-series%s", query.RefId, suffix)
}
if alias == "__server_names" && len(serverNames) > index {
alias = serverNames[index]
}
if alias == "__house_locations" && len(houseLocations) > index {
alias = houseLocations[index]
}
return &tsdb.TimeSeries{Name: alias}
......@@ -671,3 +702,49 @@ func fromStringOrNumber(val *simplejson.Json) (null.Float, error) {
return null.Float{}, fmt.Errorf("failed to extract value")
}
}
var serverNames = []string{
"Backend-ops-01",
"Backend-ops-02",
"Backend-ops-03",
"Backend-ops-04",
"Frontend-web-01",
"Frontend-web-02",
"Frontend-web-03",
"Frontend-web-04",
"MySQL-01",
"MySQL-02",
"MySQL-03",
"MySQL-04",
"Postgres-01",
"Postgres-02",
"Postgres-03",
"Postgres-04",
"DB-01",
"DB-02",
"SAN-01",
"SAN-02",
"SAN-02",
"SAN-04",
"Kaftka-01",
"Kaftka-02",
"Kaftka-03",
"Zookeeper-01",
"Zookeeper-02",
"Zookeeper-03",
"Zookeeper-04",
}
var houseLocations = []string{
"Cellar",
"Living room",
"Porch",
"Bedroom",
"Guest room",
"Kitchen",
"Playroom",
"Bathroom",
"Outside",
"Roof",
"Terrace",
}
......@@ -99,9 +99,28 @@ func TestToLabels(t *testing.T) {
tags["job"] = "foo"
tags["instance"] = "bar"
So(parseLabels(`{job="foo", instance="bar"}`), ShouldResemble, tags)
So(parseLabels(`job="foo", instance="bar"`), ShouldResemble, tags)
So(parseLabels(`job=foo, instance=bar`), ShouldResemble, tags)
So(parseLabels(`job = foo,instance = bar`), ShouldResemble, tags)
query1 := tsdb.Query{
Model: simplejson.NewFromAny(map[string]interface{}{
"labels": `{job="foo", instance="bar"}`,
}),
}
So(parseLabels(&query1), ShouldResemble, tags)
query2 := tsdb.Query{
Model: simplejson.NewFromAny(map[string]interface{}{
"labels": `job=foo, instance=bar`,
}),
}
So(parseLabels(&query2), ShouldResemble, tags)
query3 := tsdb.Query{
Model: simplejson.NewFromAny(map[string]interface{}{
"labels": `job = foo,instance = bar`,
}),
}
So(parseLabels(&query3), ShouldResemble, tags)
})
}
......@@ -12,7 +12,7 @@
</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="ctrl.target.alias" ng-change="ctrl.refresh()" ng-model-onblur>
<input type="text" class="gf-form-input width-14" placeholder="optional" ng-model="ctrl.target.alias" ng-change="ctrl.refresh()" ng-model-onblur>
</div>
<div ng-if="ctrl.showLabels" class="gf-form gf-form--grow">
<label class="gf-form-label query-keyword">
......@@ -48,6 +48,68 @@
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<div class="gf-form-inline" ng-if="ctrl.scenario.id === 'random_walk'">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Series count</label>
<input type="number"
class="gf-form-input width-7"
placeholder="1"
ng-model="ctrl.target.seriesCount"
min="1"
step="1"
ng-change="ctrl.refresh()" />
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Start value</label>
<input type="number"
class="gf-form-input width-6"
placeholder="auto"
ng-model="ctrl.target.startValue"
min="1"
step="1"
ng-change="ctrl.refresh()" />
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Spread</label>
<input type="number"
class="gf-form-input width-6"
placeholder="1"
ng-model="ctrl.target.spread"
min="0.5"
step="0.1"
ng-change="ctrl.refresh()" />
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Noise</label>
<input type="number"
class="gf-form-input width-6"
placeholder="0"
ng-model="ctrl.target.noise"
min="0"
step="0.1"
ng-change="ctrl.refresh()" />
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Min</label>
<input type="number"
class="gf-form-input width-6"
placeholder="none"
ng-model="ctrl.target.min"
min="0"
step="0.1"
ng-change="ctrl.refresh()" />
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Max</label>
<input type="number"
class="gf-form-input width-6"
placeholder="none"
ng-model="ctrl.target.max"
min="0"
step="0.1"
ng-change="ctrl.refresh()" />
</div>
</div>
<div class="gf-form-inline" ng-if="ctrl.scenario.id === 'streaming_client'">
<div class="gf-form gf-form">
<label class="gf-form-label query-keyword width-7">Type</label>
......
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