func (rp *ResponseParser) parseTimepoint(valuePair []interface{}, valuePosition int) (tsdb.TimePoint, error) { var value null.Float = rp.parseValue(valuePair[valuePosition]) timestampNumber, _ := valuePair[0].(json.Number) timestamp, err := timestampNumber.Float64() if err != nil { return tsdb.TimePoint{}, err } return tsdb.NewTimePoint(value, timestamp), nil }
func testReducer(typ string, datapoints ...float64) float64 { reducer := NewSimpleReducer(typ) series := &tsdb.TimeSeries{ Name: "test time serie", } for idx := range datapoints { series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(datapoints[idx]), 1234134)) } return reducer.Reduce(series).Float64 }
func (parser *ResponseParser) Parse(res *http.Response, queryRef *Query) ([]*tsdb.TimeSeries, error) { body, err := ioutil.ReadAll(res.Body) defer res.Body.Close() if err != nil { return nil, err } if res.StatusCode/100 != 2 { parser.log.Error("Request failed", "status code", res.StatusCode, "body", string(body)) return nil, fmt.Errorf("Returned invalid statuscode") } var data *MQEResponse = &MQEResponse{} err = json.Unmarshal(body, data) if err != nil { parser.log.Info("Failed to unmarshal response", "error", err, "status", res.Status, "body", string(body)) return nil, err } if !data.Success { return nil, fmt.Errorf("Request failed.") } var series []*tsdb.TimeSeries for _, body := range data.Body { for _, mqeSerie := range body.Series { namePrefix := "" //append predefined tags to seriename for key, value := range mqeSerie.Tagset { if key == "cluster" && queryRef.AddClusterToAlias { namePrefix += value + " " } } for key, value := range mqeSerie.Tagset { if key == "host" && queryRef.AddHostToAlias { namePrefix += value + " " } } serie := &tsdb.TimeSeries{Name: namePrefix + body.Name} for i, value := range mqeSerie.Values { timestamp := body.TimeRange.Start + int64(i)*body.TimeRange.Resolution serie.Points = append(serie.Points, tsdb.NewTimePoint(value, float64(timestamp))) } series = append(series, serie) } } return series, nil }
func (e *OpenTsdbExecutor) parseResponse(query OpenTsdbQuery, res *http.Response) (map[string]*tsdb.QueryResult, error) { queryResults := make(map[string]*tsdb.QueryResult) queryRes := tsdb.NewQueryResult() body, err := ioutil.ReadAll(res.Body) defer res.Body.Close() if err != nil { return nil, err } if res.StatusCode/100 != 2 { plog.Info("Request failed", "status", res.Status, "body", string(body)) return nil, fmt.Errorf("Request failed status: %v", res.Status) } var data []OpenTsdbResponse err = json.Unmarshal(body, &data) if err != nil { plog.Info("Failed to unmarshal opentsdb response", "error", err, "status", res.Status, "body", string(body)) return nil, err } for _, val := range data { series := tsdb.TimeSeries{ Name: val.Metric, } for timeString, value := range val.DataPoints { timestamp, err := strconv.ParseFloat(timeString, 64) if err != nil { plog.Info("Failed to unmarshal opentsdb timestamp", "timestamp", timeString) return nil, err } series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(value), timestamp)) } queryRes.Series = append(queryRes.Series, &series) } queryResults["A"] = queryRes return queryResults, nil }
func parseResponse(value pmodel.Value, query *PrometheusQuery) (map[string]*tsdb.QueryResult, error) { queryResults := make(map[string]*tsdb.QueryResult) queryRes := tsdb.NewQueryResult() data, ok := value.(pmodel.Matrix) if !ok { return queryResults, fmt.Errorf("Unsupported result format: %s", value.Type().String()) } for _, v := range data { series := tsdb.TimeSeries{ Name: formatLegend(v.Metric, query), } for _, k := range v.Values { series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(float64(k.Value)), float64(k.Timestamp.Unix()*1000))) } queryRes.Series = append(queryRes.Series, &series) } queryResults["A"] = queryRes return queryResults, nil }
func TestSimpleReducer(t *testing.T) { Convey("Test simple reducer by calculating", t, func() { Convey("sum", func() { result := testReducer("sum", 1, 2, 3) So(result, ShouldEqual, float64(6)) }) Convey("min", func() { result := testReducer("min", 3, 2, 1) So(result, ShouldEqual, float64(1)) }) Convey("max", func() { result := testReducer("max", 1, 2, 3) So(result, ShouldEqual, float64(3)) }) Convey("count", func() { result := testReducer("count", 1, 2, 3000) So(result, ShouldEqual, float64(3)) }) Convey("last", func() { result := testReducer("last", 1, 2, 3000) So(result, ShouldEqual, float64(3000)) }) Convey("median odd amount of numbers", func() { result := testReducer("median", 1, 2, 3000) So(result, ShouldEqual, float64(2)) }) Convey("median even amount of numbers", func() { result := testReducer("median", 1, 2, 4, 3000) So(result, ShouldEqual, float64(3)) }) Convey("median with one values", func() { result := testReducer("median", 1) So(result, ShouldEqual, float64(1)) }) Convey("avg", func() { result := testReducer("avg", 1, 2, 3) So(result, ShouldEqual, float64(2)) }) Convey("avg of number values and null values should ignore nulls", func() { reducer := NewSimpleReducer("avg") series := &tsdb.TimeSeries{ Name: "test time serie", } series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(3), 1)) series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 2)) series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 3)) series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(3), 4)) So(reducer.Reduce(series).Float64, ShouldEqual, float64(3)) }) }) }
func init() { ScenarioRegistry = make(map[string]*Scenario) 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 { timeWalkerMs := context.TimeRange.GetFromAsMsEpoch() to := context.TimeRange.GetToAsMsEpoch() series := newSeriesForQuery(query) points := make(tsdb.TimeSeriesPoints, 0) walker := rand.Float64() * 100 for i := int64(0); i < 10000 && timeWalkerMs < to; i++ { points = append(points, tsdb.NewTimePoint(walker, float64(timeWalkerMs))) walker += rand.Float64() - 0.5 timeWalkerMs += query.IntervalMs } series.Points = points queryRes := tsdb.NewQueryResult() queryRes.Series = append(queryRes.Series, series) return queryRes }, }) registerScenario(&Scenario{ Id: "no_data_points", Name: "No Data Points", Handler: func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult { return tsdb.NewQueryResult() }, }) registerScenario(&Scenario{ Id: "datapoints_outside_range", Name: "Datapoints Outside Range", Handler: func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult { queryRes := tsdb.NewQueryResult() series := newSeriesForQuery(query) outsideTime := context.TimeRange.MustGetFrom().Add(-1*time.Hour).Unix() * 1000 series.Points = append(series.Points, tsdb.NewTimePoint(10, float64(outsideTime))) queryRes.Series = append(queryRes.Series, series) 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 }, }) }