diff --git a/pkg/tsdb/opentsdb/opentsdb.go b/pkg/tsdb/opentsdb/opentsdb.go index 5d1902c7ac9..15a1fe27046 100644 --- a/pkg/tsdb/opentsdb/opentsdb.go +++ b/pkg/tsdb/opentsdb/opentsdb.go @@ -8,7 +8,6 @@ import ( "net/http" "net/url" "path" - "strconv" "strings" "time" @@ -121,6 +120,9 @@ func (s *Service) createRequest(ctx context.Context, logger log.Logger, dsInfo * return nil, err } u.Path = path.Join(u.Path, "api/query") + queryParams := u.Query() + queryParams.Set("arrays", "true") + u.RawQuery = queryParams.Encode() postData, err := json.Marshal(data) if err != nil { @@ -165,23 +167,25 @@ func (s *Service) parseResponse(logger log.Logger, res *http.Response, myRefID s frames := data.Frames{} for _, val := range responseData { - timeVector := make([]time.Time, 0, len(val.DataPoints)) - values := make([]float64, 0, len(val.DataPoints)) - name := val.Metric - tags := val.Tags - - for timeString, value := range val.DataPoints { - timestamp, err := strconv.ParseInt(timeString, 10, 64) - if err != nil { - logger.Info("Failed to unmarshal opentsdb timestamp", "timestamp", timeString) - return nil, err - } - timeVector = append(timeVector, time.Unix(timestamp, 0).UTC()) - values = append(values, value) + labels := data.Labels{} + for label, value := range val.Tags { + labels[label] = value } - frames = append(frames, data.NewFrame(name, - data.NewField("time", nil, timeVector), - data.NewField("value", tags, values))) + + frame := data.NewFrameOfFieldTypes(val.Metric, len(val.DataPoints), data.FieldTypeTime, data.FieldTypeFloat64) + frame.Meta = &data.FrameMeta{Type: data.FrameTypeTimeSeriesMulti, TypeVersion: data.FrameTypeVersion{0, 1}} + frame.RefID = myRefID + timeField := frame.Fields[0] + timeField.Name = data.TimeSeriesTimeFieldName + dataField := frame.Fields[1] + dataField.Name = "value" + dataField.Labels = labels + + points := val.DataPoints + for i, point := range points { + frame.SetRow(i, time.Unix(int64(point[0]), 0).UTC(), point[1]) + } + frames = append(frames, frame) } result := resp.Responses[myRefID] result.Frames = frames diff --git a/pkg/tsdb/opentsdb/opentsdb_test.go b/pkg/tsdb/opentsdb/opentsdb_test.go index a48c14188f4..6c5e142c250 100644 --- a/pkg/tsdb/opentsdb/opentsdb_test.go +++ b/pkg/tsdb/opentsdb/opentsdb_test.go @@ -43,9 +43,9 @@ func TestOpenTsdbExecutor(t *testing.T) { [ { "metric": "test", - "dps": { - "1405544146": 50.0 - }, + "dps": [ + [1405544146, 50.0] + ], "tags" : { "env": "prod", "app": "grafana" @@ -54,12 +54,17 @@ func TestOpenTsdbExecutor(t *testing.T) { ]` testFrame := data.NewFrame("test", - data.NewField("time", nil, []time.Time{ + data.NewField("Time", nil, []time.Time{ time.Date(2014, 7, 16, 20, 55, 46, 0, time.UTC), }), data.NewField("value", map[string]string{"env": "prod", "app": "grafana"}, []float64{ 50}), ) + testFrame.Meta = &data.FrameMeta{ + Type: data.FrameTypeTimeSeriesMulti, + TypeVersion: data.FrameTypeVersion{0, 1}, + } + testFrame.RefID = "A" resp := http.Response{Body: io.NopCloser(strings.NewReader(response))} resp.StatusCode = 200 @@ -80,9 +85,9 @@ func TestOpenTsdbExecutor(t *testing.T) { [ { "metric": "test", - "dps": { - "1405544146": 50.0 - }, + "dps": [ + [1405544146, 50.0] + ], "tags" : { "env": "prod", "app": "grafana" @@ -91,12 +96,17 @@ func TestOpenTsdbExecutor(t *testing.T) { ]` testFrame := data.NewFrame("test", - data.NewField("time", nil, []time.Time{ + data.NewField("Time", nil, []time.Time{ time.Date(2014, 7, 16, 20, 55, 46, 0, time.UTC), }), data.NewField("value", map[string]string{"env": "prod", "app": "grafana"}, []float64{ 50}), ) + testFrame.Meta = &data.FrameMeta{ + Type: data.FrameTypeTimeSeriesMulti, + TypeVersion: data.FrameTypeVersion{0, 1}, + } + testFrame.RefID = myRefid resp := http.Response{Body: io.NopCloser(strings.NewReader(response))} resp.StatusCode = 200 diff --git a/pkg/tsdb/opentsdb/types.go b/pkg/tsdb/opentsdb/types.go index 96c43ead02d..171a24e2067 100644 --- a/pkg/tsdb/opentsdb/types.go +++ b/pkg/tsdb/opentsdb/types.go @@ -7,7 +7,7 @@ type OpenTsdbQuery struct { } type OpenTsdbResponse struct { - Metric string `json:"metric"` - Tags map[string]string `json:"tags"` - DataPoints map[string]float64 `json:"dps"` + Metric string `json:"metric"` + Tags map[string]string `json:"tags"` + DataPoints [][]float64 `json:"dps"` }