mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Cloud Monitoring: Use new annotation API (#49026)
* remove angular code * format annotation on backend * format time with time type instead of string * update annotation query tests * update get alignment data function * update annotation query editor * add annotation query editor test * update struct * add tests * remove extracted function * remove non-null assertion * remove stray commented out console.log * fix jest haste map warning * add alignment period * add AnnotationMetricQuery type
This commit is contained in:
@@ -4,11 +4,19 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
)
|
||||
|
||||
type annotationEvent struct {
|
||||
Title string
|
||||
Time time.Time
|
||||
Tags string
|
||||
Text string
|
||||
}
|
||||
|
||||
func (s *Service) executeAnnotationQuery(ctx context.Context, req *backend.QueryDataRequest, dsInfo datasourceInfo) (
|
||||
*backend.QueryDataResponse, error) {
|
||||
resp := backend.NewQueryDataResponse()
|
||||
@@ -24,8 +32,10 @@ func (s *Service) executeAnnotationQuery(ctx context.Context, req *backend.Query
|
||||
}
|
||||
|
||||
mq := struct {
|
||||
Title string `json:"title"`
|
||||
Text string `json:"text"`
|
||||
MetricQuery struct {
|
||||
Title string `json:"title"`
|
||||
Text string `json:"text"`
|
||||
} `json:"metricQuery"`
|
||||
}{}
|
||||
|
||||
firstQuery := req.Queries[0]
|
||||
@@ -33,32 +43,23 @@ func (s *Service) executeAnnotationQuery(ctx context.Context, req *backend.Query
|
||||
if err != nil {
|
||||
return resp, nil
|
||||
}
|
||||
err = queries[0].parseToAnnotations(queryRes, dr, mq.Title, mq.Text)
|
||||
err = queries[0].parseToAnnotations(queryRes, dr, mq.MetricQuery.Title, mq.MetricQuery.Text)
|
||||
resp.Responses[firstQuery.RefID] = *queryRes
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (timeSeriesQuery cloudMonitoringTimeSeriesQuery) transformAnnotationToFrame(annotations []map[string]string, result *backend.DataResponse) {
|
||||
frames := data.Frames{}
|
||||
func (timeSeriesQuery cloudMonitoringTimeSeriesQuery) transformAnnotationToFrame(annotations []*annotationEvent, result *backend.DataResponse) {
|
||||
frame := data.NewFrame(timeSeriesQuery.RefID,
|
||||
data.NewField("time", nil, []time.Time{}),
|
||||
data.NewField("title", nil, []string{}),
|
||||
data.NewField("tags", nil, []string{}),
|
||||
data.NewField("text", nil, []string{}),
|
||||
)
|
||||
for _, a := range annotations {
|
||||
frame := &data.Frame{
|
||||
RefID: timeSeriesQuery.getRefID(),
|
||||
Fields: []*data.Field{
|
||||
data.NewField("time", nil, a["time"]),
|
||||
data.NewField("title", nil, a["title"]),
|
||||
data.NewField("tags", nil, a["tags"]),
|
||||
data.NewField("text", nil, a["text"]),
|
||||
},
|
||||
Meta: &data.FrameMeta{
|
||||
Custom: map[string]interface{}{
|
||||
"rowCount": len(a),
|
||||
},
|
||||
},
|
||||
}
|
||||
frames = append(frames, frame)
|
||||
frame.AppendRow(a.Time, a.Title, a.Tags, a.Text)
|
||||
}
|
||||
result.Frames = frames
|
||||
result.Frames = append(result.Frames, frame)
|
||||
slog.Info("anno", "len", len(annotations))
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,15 @@ func TestExecutor_parseToAnnotations(t *testing.T) {
|
||||
"atext {{resource.label.zone}}")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, res.Frames, 3)
|
||||
require.Len(t, res.Frames, 1)
|
||||
assert.Equal(t, "time", res.Frames[0].Fields[0].Name)
|
||||
assert.Equal(t, "title", res.Frames[0].Fields[1].Name)
|
||||
assert.Equal(t, "tags", res.Frames[0].Fields[2].Name)
|
||||
assert.Equal(t, "text", res.Frames[0].Fields[3].Name)
|
||||
assert.Equal(t, 9, res.Frames[0].Fields[0].Len())
|
||||
assert.Equal(t, 9, res.Frames[0].Fields[1].Len())
|
||||
assert.Equal(t, 9, res.Frames[0].Fields[2].Len())
|
||||
assert.Equal(t, 9, res.Frames[0].Fields[3].Len())
|
||||
}
|
||||
|
||||
func TestCloudMonitoringExecutor_parseToAnnotations_emptyTimeSeries(t *testing.T) {
|
||||
@@ -37,7 +42,15 @@ func TestCloudMonitoringExecutor_parseToAnnotations_emptyTimeSeries(t *testing.T
|
||||
err := query.parseToAnnotations(res, response, "atitle", "atext")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, res.Frames, 0)
|
||||
require.Len(t, res.Frames, 1)
|
||||
assert.Equal(t, "time", res.Frames[0].Fields[0].Name)
|
||||
assert.Equal(t, "title", res.Frames[0].Fields[1].Name)
|
||||
assert.Equal(t, "tags", res.Frames[0].Fields[2].Name)
|
||||
assert.Equal(t, "text", res.Frames[0].Fields[3].Name)
|
||||
assert.Equal(t, 0, res.Frames[0].Fields[0].Len())
|
||||
assert.Equal(t, 0, res.Frames[0].Fields[1].Len())
|
||||
assert.Equal(t, 0, res.Frames[0].Fields[2].Len())
|
||||
assert.Equal(t, 0, res.Frames[0].Fields[3].Len())
|
||||
}
|
||||
|
||||
func TestCloudMonitoringExecutor_parseToAnnotations_noPointsInSeries(t *testing.T) {
|
||||
@@ -53,5 +66,13 @@ func TestCloudMonitoringExecutor_parseToAnnotations_noPointsInSeries(t *testing.
|
||||
err := query.parseToAnnotations(res, response, "atitle", "atext")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, res.Frames, 0)
|
||||
require.Len(t, res.Frames, 1)
|
||||
assert.Equal(t, "time", res.Frames[0].Fields[0].Name)
|
||||
assert.Equal(t, "title", res.Frames[0].Fields[1].Name)
|
||||
assert.Equal(t, "tags", res.Frames[0].Fields[2].Name)
|
||||
assert.Equal(t, "text", res.Frames[0].Fields[3].Name)
|
||||
assert.Equal(t, 0, res.Frames[0].Fields[0].Len())
|
||||
assert.Equal(t, 0, res.Frames[0].Fields[1].Len())
|
||||
assert.Equal(t, 0, res.Frames[0].Fields[2].Len())
|
||||
assert.Equal(t, 0, res.Frames[0].Fields[3].Len())
|
||||
}
|
||||
|
||||
@@ -250,33 +250,36 @@ func (timeSeriesFilter *cloudMonitoringTimeSeriesFilter) handleNonDistributionSe
|
||||
|
||||
func (timeSeriesFilter *cloudMonitoringTimeSeriesFilter) parseToAnnotations(dr *backend.DataResponse,
|
||||
response cloudMonitoringResponse, title, text string) error {
|
||||
frames := data.Frames{}
|
||||
frame := data.NewFrame(timeSeriesFilter.RefID,
|
||||
data.NewField("time", nil, []time.Time{}),
|
||||
data.NewField("title", nil, []string{}),
|
||||
data.NewField("tags", nil, []string{}),
|
||||
data.NewField("text", nil, []string{}),
|
||||
)
|
||||
|
||||
for _, series := range response.TimeSeries {
|
||||
if len(series.Points) == 0 {
|
||||
continue
|
||||
}
|
||||
annotation := make(map[string][]string)
|
||||
|
||||
for i := len(series.Points) - 1; i >= 0; i-- {
|
||||
point := series.Points[i]
|
||||
value := strconv.FormatFloat(point.Value.DoubleValue, 'f', 6, 64)
|
||||
if series.ValueType == "STRING" {
|
||||
value = point.Value.StringValue
|
||||
}
|
||||
annotation["time"] = append(annotation["time"], point.Interval.EndTime.UTC().Format(time.RFC3339))
|
||||
annotation["title"] = append(annotation["title"], formatAnnotationText(title, value, series.Metric.Type,
|
||||
series.Metric.Labels, series.Resource.Labels))
|
||||
annotation["tags"] = append(annotation["tags"], "")
|
||||
annotation["text"] = append(annotation["text"], formatAnnotationText(text, value, series.Metric.Type,
|
||||
series.Metric.Labels, series.Resource.Labels))
|
||||
annotation := &annotationEvent{
|
||||
Time: point.Interval.EndTime,
|
||||
Title: formatAnnotationText(title, value, series.Metric.Type,
|
||||
series.Metric.Labels, series.Resource.Labels),
|
||||
Tags: "",
|
||||
Text: formatAnnotationText(text, value, series.Metric.Type,
|
||||
series.Metric.Labels, series.Resource.Labels),
|
||||
}
|
||||
frame.AppendRow(annotation.Time, annotation.Title, annotation.Tags, annotation.Text)
|
||||
}
|
||||
frames = append(frames, data.NewFrame(timeSeriesFilter.getRefID(),
|
||||
data.NewField("time", nil, annotation["time"]),
|
||||
data.NewField("title", nil, annotation["title"]),
|
||||
data.NewField("tags", nil, annotation["tags"]),
|
||||
data.NewField("text", nil, annotation["text"]),
|
||||
))
|
||||
}
|
||||
dr.Frames = frames
|
||||
dr.Frames = append(dr.Frames, frame)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ func (timeSeriesQuery cloudMonitoringTimeSeriesQuery) parseResponse(queryRes *ba
|
||||
|
||||
func (timeSeriesQuery cloudMonitoringTimeSeriesQuery) parseToAnnotations(queryRes *backend.DataResponse,
|
||||
data cloudMonitoringResponse, title, text string) error {
|
||||
annotations := make([]map[string]string, 0)
|
||||
annotations := make([]*annotationEvent, 0)
|
||||
|
||||
for _, series := range data.TimeSeriesData {
|
||||
metricLabels := make(map[string]string)
|
||||
@@ -302,12 +302,12 @@ func (timeSeriesQuery cloudMonitoringTimeSeriesQuery) parseToAnnotations(queryRe
|
||||
if d.ValueType == "STRING" {
|
||||
value = point.Values[n].StringValue
|
||||
}
|
||||
annotation := make(map[string]string)
|
||||
annotation["time"] = point.TimeInterval.EndTime.UTC().Format(time.RFC3339)
|
||||
annotation["title"] = formatAnnotationText(title, value, d.MetricKind, metricLabels, resourceLabels)
|
||||
annotation["tags"] = ""
|
||||
annotation["text"] = formatAnnotationText(text, value, d.MetricKind, metricLabels, resourceLabels)
|
||||
annotations = append(annotations, annotation)
|
||||
annotations = append(annotations, &annotationEvent{
|
||||
Time: point.TimeInterval.EndTime,
|
||||
Title: formatAnnotationText(title, value, d.MetricKind, metricLabels, resourceLabels),
|
||||
Tags: "",
|
||||
Text: formatAnnotationText(text, value, d.MetricKind, metricLabels, resourceLabels),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user