From bcdc8cd5abf001569b975381eb66d4ba45c9471c Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Fri, 5 May 2023 18:19:04 +0100 Subject: [PATCH] [v9.4.x] AzureMonitor: Fix logs query multi-resource and timespan values (#67931) AzureMonitor: Fix logs query multi-resource and timespan values (#67914) * Update TimeGrain interface methods - Make them util functions because it's simpler * Update logs ds to appropiately set resources and timespan * Set timespan using RCF times * Update tests (cherry picked from commit 9d16718accd11f8db53b30ea79aac16c07e99090) Co-authored-by: Andreas Christou --- .../azure-log-analytics-datasource.go | 8 ++++-- .../azure-log-analytics-datasource_test.go | 25 +++++++++++++++++-- .../azuremonitor/time/azuremonitor-time.go | 3 +-- pkg/tsdb/azuremonitor/time/time-grain.go | 8 +++--- pkg/tsdb/azuremonitor/time/time-grain_test.go | 8 ++---- 5 files changed, 35 insertions(+), 17 deletions(-) diff --git a/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go b/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go index f1fe2a21785..6c6b74695ca 100644 --- a/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go +++ b/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go @@ -238,11 +238,15 @@ func appendErrorNotice(frame *data.Frame, err *AzureLogAnalyticsAPIError) *data. } func (e *AzureLogAnalyticsDatasource) createRequest(ctx context.Context, logger log.Logger, queryURL string, query *AzureLogAnalyticsQuery) (*http.Request, error) { + from := query.TimeRange.From.Format(time.RFC3339) + to := query.TimeRange.To.Format(time.RFC3339) + timespan := fmt.Sprintf("%s/%s", from, to) body := map[string]interface{}{ - "query": query.Query, + "query": query.Query, + "timespan": timespan, } if len(query.Resources) > 1 { - body["resources"] = query.Resources + body["workspaces"] = query.Resources } jsonValue, err := json.Marshal(body) if err != nil { diff --git a/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource_test.go b/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource_test.go index 41b21d28ad5..07a598a8125 100644 --- a/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource_test.go +++ b/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource_test.go @@ -240,7 +240,7 @@ func TestLogAnalyticsCreateRequest(t *testing.T) { if !cmp.Equal(req.Header, expectedHeaders) { t.Errorf("Unexpected HTTP headers: %v", cmp.Diff(req.Header, expectedHeaders)) } - expectedBody := `{"query":"Perf"}` + expectedBody := `{"query":"Perf","timespan":"0001-01-01T00:00:00Z/0001-01-01T00:00:00Z"}` body, err := io.ReadAll(req.Body) require.NoError(t, err) if !cmp.Equal(string(body), expectedBody) { @@ -255,7 +255,28 @@ func TestLogAnalyticsCreateRequest(t *testing.T) { Query: "Perf", }) require.NoError(t, err) - expectedBody := `{"query":"Perf","resources":["r1","r2"]}` + expectedBody := `{"query":"Perf","timespan":"0001-01-01T00:00:00Z/0001-01-01T00:00:00Z","workspaces":["r1","r2"]}` + body, err := io.ReadAll(req.Body) + require.NoError(t, err) + if !cmp.Equal(string(body), expectedBody) { + t.Errorf("Unexpected Body: %v", cmp.Diff(string(body), expectedBody)) + } + }) + + t.Run("creates a request with timerange from query", func(t *testing.T) { + ds := AzureLogAnalyticsDatasource{} + from := time.Now() + to := from.Add(3 * time.Hour) + req, err := ds.createRequest(ctx, logger, url, &AzureLogAnalyticsQuery{ + Resources: []string{"r1", "r2"}, + Query: "Perf", + TimeRange: backend.TimeRange{ + From: from, + To: to, + }, + }) + require.NoError(t, err) + expectedBody := fmt.Sprintf(`{"query":"Perf","timespan":"%s/%s","workspaces":["r1","r2"]}`, from.Format(time.RFC3339), to.Format(time.RFC3339)) body, err := io.ReadAll(req.Body) require.NoError(t, err) if !cmp.Equal(string(body), expectedBody) { diff --git a/pkg/tsdb/azuremonitor/time/azuremonitor-time.go b/pkg/tsdb/azuremonitor/time/azuremonitor-time.go index 3a29f24f8dc..cc6736eb93b 100644 --- a/pkg/tsdb/azuremonitor/time/azuremonitor-time.go +++ b/pkg/tsdb/azuremonitor/time/azuremonitor-time.go @@ -10,8 +10,7 @@ var ( // instead of the default list of intervals func SetAutoTimeGrain(intervalMs int64, timeGrains []int64) (string, error) { autoInterval := FindClosestAllowedIntervalMS(intervalMs, timeGrains) - tg := &TimeGrain{} - autoTimeGrain, err := tg.createISO8601DurationFromIntervalMS(autoInterval) + autoTimeGrain, err := CreateISO8601DurationFromIntervalMS(autoInterval) if err != nil { return "", err } diff --git a/pkg/tsdb/azuremonitor/time/time-grain.go b/pkg/tsdb/azuremonitor/time/time-grain.go index c7be8890fe5..6c69642482c 100644 --- a/pkg/tsdb/azuremonitor/time/time-grain.go +++ b/pkg/tsdb/azuremonitor/time/time-grain.go @@ -12,13 +12,11 @@ import ( // TimeGrain handles conversions between // the ISO 8601 Duration format (PT1H), Kbn units (1h) and Time Grains (1 hour) // Also handles using the automatic Grafana interval to calculate a ISO 8601 Duration. -type TimeGrain struct{} - var ( smallTimeUnits = []string{"hour", "minute", "h", "m"} ) -func (tg *TimeGrain) createISO8601DurationFromIntervalMS(it int64) (string, error) { +func CreateISO8601DurationFromIntervalMS(it int64) (string, error) { formatted := intervalv2.FormatDuration(time.Duration(it) * time.Millisecond) if strings.Contains(formatted, "ms") { @@ -38,10 +36,10 @@ func (tg *TimeGrain) createISO8601DurationFromIntervalMS(it int64) (string, erro return "PT1M", nil } - return tg.createISO8601Duration(timeValue, unit), nil + return createISO8601Duration(timeValue, unit), nil } -func (tg *TimeGrain) createISO8601Duration(timeValue int, timeUnit string) string { +func createISO8601Duration(timeValue int, timeUnit string) string { for _, smallTimeUnit := range smallTimeUnits { if timeUnit == smallTimeUnit { return fmt.Sprintf("PT%v%v", timeValue, strings.ToUpper(timeUnit[0:1])) diff --git a/pkg/tsdb/azuremonitor/time/time-grain_test.go b/pkg/tsdb/azuremonitor/time/time-grain_test.go index 4ff6813bec7..fa988d89c9e 100644 --- a/pkg/tsdb/azuremonitor/time/time-grain_test.go +++ b/pkg/tsdb/azuremonitor/time/time-grain_test.go @@ -8,8 +8,6 @@ import ( ) func TestTimeGrain_createISO8601Duration(t *testing.T) { - tg := &TimeGrain{} - testCases := []struct { name string value int @@ -26,15 +24,13 @@ func TestTimeGrain_createISO8601Duration(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - d := tg.createISO8601Duration(tc.value, tc.unit) + d := createISO8601Duration(tc.value, tc.unit) assert.Equal(t, tc.expected, d) }) } } func TestTimeGrain_createISO8601DurationFromIntervalMS(t *testing.T) { - tg := &TimeGrain{} - testCases := []struct { name string interval int64 @@ -48,7 +44,7 @@ func TestTimeGrain_createISO8601DurationFromIntervalMS(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - d, err := tg.createISO8601DurationFromIntervalMS(tc.interval) + d, err := CreateISO8601DurationFromIntervalMS(tc.interval) require.NoError(t, err) assert.Equal(t, tc.expected, d) })