GoogleCloudMonitoring: Refactor parseResponse (#59595)
* GoogleCloudMonitoring: Remove duplicated code from buildDeepLink (#59600)
This commit is contained in:
@@ -9,7 +9,9 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
@@ -155,3 +157,193 @@ func runTimeSeriesRequest(ctx context.Context, logger log.Logger, req *backend.Q
|
||||
|
||||
return dr, d, r.URL.RawQuery, nil
|
||||
}
|
||||
|
||||
func bucketFrame(
|
||||
bucketOptions cloudMonitoringBucketOptions,
|
||||
bucketBoundIndex int,
|
||||
metricType string,
|
||||
defaultMetricName string,
|
||||
query cloudMonitoringQueryExecutor,
|
||||
seriesLabels map[string]string,
|
||||
frameMeta *data.FrameMeta,
|
||||
) *data.Frame {
|
||||
// set lower bounds
|
||||
// https://cloud.google.com/monitoring/api/ref_v3/rest/v3/TimeSeries#Distribution
|
||||
bucketBound := calcBucketBound(bucketOptions, bucketBoundIndex)
|
||||
additionalLabels := map[string]string{"bucket": bucketBound}
|
||||
|
||||
timeField := data.NewField(data.TimeSeriesTimeFieldName, nil, []time.Time{})
|
||||
valueField := data.NewField(data.TimeSeriesValueFieldName, nil, []float64{})
|
||||
|
||||
frameName := formatLegendKeys(metricType, defaultMetricName, nil, additionalLabels, query)
|
||||
valueField.Name = frameName
|
||||
valueField.Labels = seriesLabels
|
||||
setDisplayNameAsFieldName(valueField)
|
||||
|
||||
return &data.Frame{
|
||||
Name: frameName,
|
||||
Fields: []*data.Field{
|
||||
timeField,
|
||||
valueField,
|
||||
},
|
||||
RefID: query.getRefID(),
|
||||
Meta: frameMeta,
|
||||
}
|
||||
}
|
||||
|
||||
func handleDistributionSeries(
|
||||
it pointIterator,
|
||||
descriptorIndex int,
|
||||
defaultMetricName string,
|
||||
query cloudMonitoringQueryExecutor,
|
||||
seriesLabels map[string]string,
|
||||
frameMeta *data.FrameMeta,
|
||||
) (map[int]*data.Frame, error) {
|
||||
buckets := make(map[int]*data.Frame)
|
||||
for i := it.length() - 1; i >= 0; i-- {
|
||||
point := it.getPoint(i)
|
||||
if len(point.bucketCounts(descriptorIndex)) == 0 {
|
||||
continue
|
||||
}
|
||||
maxKey := 0
|
||||
for i := 0; i < len(point.bucketCounts(descriptorIndex)); i++ {
|
||||
value, err := strconv.ParseFloat(point.bucketValue(descriptorIndex, i), 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := buckets[i]; !ok {
|
||||
buckets[i] = bucketFrame(
|
||||
point.bucketOptions(descriptorIndex), i,
|
||||
it.metricType(), defaultMetricName, query,
|
||||
seriesLabels,
|
||||
frameMeta,
|
||||
)
|
||||
if maxKey < i {
|
||||
maxKey = i
|
||||
}
|
||||
}
|
||||
buckets[i].AppendRow(point.endTime(), value)
|
||||
}
|
||||
|
||||
// fill empty bucket
|
||||
for i := 0; i < maxKey; i++ {
|
||||
if _, ok := buckets[i]; !ok {
|
||||
buckets[i] = bucketFrame(
|
||||
point.bucketOptions(descriptorIndex), i,
|
||||
it.metricType(), defaultMetricName, query,
|
||||
seriesLabels,
|
||||
frameMeta,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return buckets, nil
|
||||
}
|
||||
|
||||
func handleNonDistributionSeries(
|
||||
series pointIterator,
|
||||
descriptorIndex int,
|
||||
defaultMetricName string,
|
||||
seriesLabels map[string]string,
|
||||
frame *data.Frame,
|
||||
query cloudMonitoringQueryExecutor,
|
||||
) {
|
||||
for i := 0; i < series.length(); i++ {
|
||||
point := series.getPoint(i)
|
||||
value := point.doubleValue(descriptorIndex)
|
||||
|
||||
if series.valueType() == "INT64" {
|
||||
parsedValue, err := strconv.ParseFloat(point.int64Value(descriptorIndex), 64)
|
||||
if err == nil {
|
||||
value = parsedValue
|
||||
}
|
||||
}
|
||||
|
||||
if series.valueType() == "BOOL" {
|
||||
if point.boolValue(descriptorIndex) {
|
||||
value = 1
|
||||
} else {
|
||||
value = 0
|
||||
}
|
||||
}
|
||||
frame.SetRow(series.length()-1-i, point.endTime(), value)
|
||||
}
|
||||
|
||||
metricName := formatLegendKeys(series.metricType(), defaultMetricName, seriesLabels, nil, query)
|
||||
dataField := frame.Fields[1]
|
||||
dataField.Name = metricName
|
||||
dataField.Labels = seriesLabels
|
||||
setDisplayNameAsFieldName(dataField)
|
||||
}
|
||||
|
||||
func appendFrames(
|
||||
frames data.Frames,
|
||||
series pointIterator,
|
||||
descriptorIndex int,
|
||||
defaultMetricName string,
|
||||
seriesLabels map[string]string,
|
||||
frame *data.Frame,
|
||||
query cloudMonitoringQueryExecutor,
|
||||
) (data.Frames, error) {
|
||||
if series.valueType() != "DISTRIBUTION" {
|
||||
handleNonDistributionSeries(series, descriptorIndex, defaultMetricName, seriesLabels, frame, query)
|
||||
return append(frames, frame), nil
|
||||
}
|
||||
buckets, err := handleDistributionSeries(series, descriptorIndex, defaultMetricName, query, seriesLabels, frame.Meta)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(buckets); i++ {
|
||||
frames = append(frames, buckets[i])
|
||||
}
|
||||
if len(buckets) == 0 {
|
||||
frames = append(frames, frame)
|
||||
}
|
||||
return frames, nil
|
||||
}
|
||||
|
||||
func generateLink(projectName string, dataSets []map[string]interface{}, start, end string) (string, error) {
|
||||
u, err := url.Parse("https://console.cloud.google.com/monitoring/metrics-explorer")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
rawQuery := u.Query()
|
||||
rawQuery.Set("project", projectName)
|
||||
rawQuery.Set("Grafana_deeplink", "true")
|
||||
|
||||
pageState := map[string]interface{}{
|
||||
"xyChart": map[string]interface{}{
|
||||
"constantLines": []string{},
|
||||
"dataSets": dataSets,
|
||||
"timeshiftDuration": "0s",
|
||||
"y1Axis": map[string]string{
|
||||
"label": "y1Axis",
|
||||
"scale": "LINEAR",
|
||||
},
|
||||
},
|
||||
"timeSelection": map[string]string{
|
||||
"timeRange": "custom",
|
||||
"start": start,
|
||||
"end": end,
|
||||
},
|
||||
}
|
||||
|
||||
blob, err := json.Marshal(pageState)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
rawQuery.Set("pageState", string(blob))
|
||||
u.RawQuery = rawQuery.Encode()
|
||||
|
||||
accountChooserURL, err := url.Parse("https://accounts.google.com/AccountChooser")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
accountChooserQuery := accountChooserURL.Query()
|
||||
accountChooserQuery.Set("continue", u.String())
|
||||
accountChooserURL.RawQuery = accountChooserQuery.Encode()
|
||||
|
||||
return accountChooserURL.String(), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user