TestData: Change predictable csv scenario to multi-series (#33442)

Allow multiple series in Predictable CSV Wave testdata scenario

Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
Kyle Brandt
2021-04-27 16:35:43 -04:00
committed by GitHub
co-authored by Ryan McKinley
parent b590e95682
commit 968935b8b7
7 changed files with 213 additions and 112 deletions
+77 -56
View File
@@ -475,15 +475,15 @@ func (p *testDataPlugin) handlePredictableCSVWaveScenario(ctx context.Context, r
for _, q := range req.Queries {
model, err := simplejson.NewJson(q.JSON)
if err != nil {
continue
return nil, err
}
respD := resp.Responses[q.RefID]
frame, err := predictableCSVWave(q, model)
frames, err := predictableCSVWave(q, model)
if err != nil {
continue
return nil, err
}
respD.Frames = append(respD.Frames, frame)
respD.Frames = append(respD.Frames, frames...)
resp.Responses[q.RefID] = respD
}
@@ -786,60 +786,79 @@ func randomWalkTable(query backend.DataQuery, model *simplejson.Json) *data.Fram
return frame
}
func predictableCSVWave(query backend.DataQuery, model *simplejson.Json) (*data.Frame, error) {
options := model.Get("csvWave")
type pCSVOptions struct {
TimeStep int64 `json:"timeStep"`
ValuesCSV string `json:"valuesCSV"`
Labels string `json:"labels"`
Name string `json:"name"`
}
var timeStep int64
var err error
if timeStep, err = options.Get("timeStep").Int64(); err != nil {
return nil, fmt.Errorf("failed to parse timeStep value '%v' into integer: %v", options.Get("timeStep"), err)
}
rawValues := options.Get("valuesCSV").MustString()
rawValues = strings.TrimRight(strings.TrimSpace(rawValues), ",") // Strip Trailing Comma
rawValesCSV := strings.Split(rawValues, ",")
values := make([]*float64, len(rawValesCSV))
for i, rawValue := range rawValesCSV {
var val *float64
rawValue = strings.TrimSpace(rawValue)
switch rawValue {
case "null":
// val stays nil
case "nan":
f := math.NaN()
val = &f
default:
f, err := strconv.ParseFloat(rawValue, 64)
if err != nil {
return nil, errutil.Wrapf(err, "failed to parse value '%v' into nullable float", rawValue)
}
val = &f
}
values[i] = val
}
timeStep *= 1000 // Seconds to Milliseconds
valuesLen := int64(len(values))
getValue := func(mod int64) (*float64, error) {
var i int64
for i = 0; i < valuesLen; i++ {
if mod == i*timeStep {
return values[i], nil
}
}
return nil, fmt.Errorf("did not get value at point in waveform - should not be here")
}
fields, err := predictableSeries(query.TimeRange, timeStep, valuesLen, getValue)
func predictableCSVWave(query backend.DataQuery, model *simplejson.Json) ([]*data.Frame, error) {
rawQueries, err := model.Get("csvWave").ToDB()
if err != nil {
return nil, err
}
frame := newSeriesForQuery(query, model, 0)
frame.Fields = fields
frame.Fields[1].Labels = parseLabels(model)
queries := []pCSVOptions{}
err = json.Unmarshal(rawQueries, &queries)
if err != nil {
return nil, err
}
return frame, nil
frames := make([]*data.Frame, 0, len(queries))
for _, subQ := range queries {
var err error
rawValues := strings.TrimRight(strings.TrimSpace(subQ.ValuesCSV), ",") // Strip Trailing Comma
rawValesCSV := strings.Split(rawValues, ",")
values := make([]*float64, len(rawValesCSV))
for i, rawValue := range rawValesCSV {
var val *float64
rawValue = strings.TrimSpace(rawValue)
switch rawValue {
case "null":
// val stays nil
case "nan":
f := math.NaN()
val = &f
default:
f, err := strconv.ParseFloat(rawValue, 64)
if err != nil {
return nil, errutil.Wrapf(err, "failed to parse value '%v' into nullable float", rawValue)
}
val = &f
}
values[i] = val
}
subQ.TimeStep *= 1000 // Seconds to Milliseconds
valuesLen := int64(len(values))
getValue := func(mod int64) (*float64, error) {
var i int64
for i = 0; i < valuesLen; i++ {
if mod == i*subQ.TimeStep {
return values[i], nil
}
}
return nil, fmt.Errorf("did not get value at point in waveform - should not be here")
}
fields, err := predictableSeries(query.TimeRange, subQ.TimeStep, valuesLen, getValue)
if err != nil {
return nil, err
}
frame := newSeriesForQuery(query, model, 0)
frame.Fields = fields
frame.Fields[1].Labels = parseLabelsString(subQ.Labels)
if subQ.Name != "" {
frame.Name = subQ.Name
}
frames = append(frames, frame)
}
return frames, nil
}
func predictableSeries(timeRange backend.TimeRange, timeStep, length int64, getValue func(mod int64) (*float64, error)) (data.Fields, error) {
@@ -988,19 +1007,21 @@ func newSeriesForQuery(query backend.DataQuery, model *simplejson.Json, index in
* '{job="foo", instance="bar"} => {job: "foo", instance: "bar"}`
*/
func parseLabels(model *simplejson.Json) data.Labels {
tags := data.Labels{}
labelText := model.Get("labels").MustString("")
return parseLabelsString(labelText)
}
func parseLabelsString(labelText string) data.Labels {
if labelText == "" {
return data.Labels{}
}
text := strings.Trim(labelText, `{}`)
if len(text) < 2 {
return tags
return data.Labels{}
}
tags = make(data.Labels)
tags := make(data.Labels)
for _, keyval := range strings.Split(text, ",") {
idx := strings.Index(keyval, "=")