From d5844c35f8bbc2b3b6d7c1e0449a94465a841a82 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Wed, 10 May 2023 11:39:04 +0100 Subject: [PATCH] [v10.0.x] AzureMonitor: Correctly set resource parameter for Logs queries (#68196) AzureMonitor: Correctly set resource parameter for Logs queries (#68133) * Update to ensure the resources parameter is passed through for logs queries only * Use string slices for resources to ensure order remains the same * Fix lint * clarify test (cherry picked from commit e059ce9c8aae3f24fef4721de9ba524d4ae20df4) Co-authored-by: Andreas Christou --- .../azure-log-analytics-datasource.go | 26 ++++++++++++------- .../azure-log-analytics-datasource_test.go | 23 ++++++++++++++++ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go b/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go index f48b7dd93a6..3791c3674e8 100644 --- a/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go +++ b/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go @@ -162,14 +162,20 @@ func (e *AzureLogAnalyticsDatasource) buildQueries(ctx context.Context, logger l } } - queryString = buildTracesQuery(operationId, queryJSONModel.AzureTraces.TraceTypes, queryJSONModel.AzureTraces.Filters, &resultFormat, resourcesMap) + queryResources := make([]string, 0) + for resource := range resourcesMap { + queryResources = append(queryResources, resource) + } + sort.Strings(queryResources) + + queryString = buildTracesQuery(operationId, queryJSONModel.AzureTraces.TraceTypes, queryJSONModel.AzureTraces.Filters, &resultFormat, queryResources) traceIdVariable := "${__data.fields.traceID}" if operationId == "" { - traceExploreQuery = buildTracesQuery(traceIdVariable, queryJSONModel.AzureTraces.TraceTypes, queryJSONModel.AzureTraces.Filters, &resultFormat, resourcesMap) - traceLogsExploreQuery = buildTracesLogsQuery(traceIdVariable, resourcesMap) + traceExploreQuery = buildTracesQuery(traceIdVariable, queryJSONModel.AzureTraces.TraceTypes, queryJSONModel.AzureTraces.Filters, &resultFormat, queryResources) + traceLogsExploreQuery = buildTracesLogsQuery(traceIdVariable, queryResources) } else { traceExploreQuery = queryString - traceLogsExploreQuery = buildTracesLogsQuery(operationId, resourcesMap) + traceLogsExploreQuery = buildTracesLogsQuery(operationId, queryResources) } traceExploreQuery, err = macros.KqlInterpolate(logger, query, dsInfo, traceExploreQuery, "TimeGenerated") if err != nil { @@ -353,7 +359,7 @@ func (e *AzureLogAnalyticsDatasource) executeQuery(ctx context.Context, logger l ResultFormat *dataquery.AzureMonitorQueryAzureLogAnalyticsResultFormat "json:\"resultFormat,omitempty\"" Workspace *string "json:\"workspace,omitempty\"" }{ - Resources: queryJSONModel.AzureTraces.Resources, + Resources: []string{queryJSONModel.AzureTraces.Resources[0]}, Query: &query.TraceLogsExploreQuery, }, QueryType: &logsQueryType, @@ -405,7 +411,7 @@ func (e *AzureLogAnalyticsDatasource) createRequest(ctx context.Context, logger "query": query.Query, "timespan": timespan, } - if len(query.Resources) > 1 { + if len(query.Resources) > 1 && query.QueryType == string(dataquery.AzureQueryTypeAzureLogAnalytics) { body["workspaces"] = query.Resources } jsonValue, err := json.Marshal(body) @@ -674,7 +680,7 @@ func encodeQuery(rawQuery string) (string, error) { return base64.StdEncoding.EncodeToString(b.Bytes()), nil } -func buildTracesQuery(operationId string, traceTypes []string, filters []types.TracesFilters, resultFormat *string, resources map[string]bool) string { +func buildTracesQuery(operationId string, traceTypes []string, filters []types.TracesFilters, resultFormat *string, resources []string) string { types := traceTypes if len(types) == 0 { types = Tables @@ -696,7 +702,7 @@ func buildTracesQuery(operationId string, traceTypes []string, filters []types.T resourcesQuery := strings.Join(filteredTypes, ",") if len(resources) > 0 { intermediate := make([]string, 0) - for resource := range resources { + for _, resource := range resources { resourceSplit := strings.SplitAfter(resource, "/") resourceName := resourceSplit[len(resourceSplit)-1] for _, table := range filteredTypes { @@ -768,13 +774,13 @@ func buildTracesQuery(operationId string, traceTypes []string, filters []types.T return baseQuery + whereClause + propertiesStaticQuery + errorProperty + propertiesQuery + filtersClause + projectClause } -func buildTracesLogsQuery(operationId string, resources map[string]bool) string { +func buildTracesLogsQuery(operationId string, resources []string) string { types := Tables sort.Strings(types) selectors := "union " + strings.Join(types, ",\n") + "\n" if len(resources) > 0 { intermediate := make([]string, 0) - for resource := range resources { + for _, resource := range resources { resourceSplit := strings.SplitAfter(resource, "/") resourceName := resourceSplit[len(resourceSplit)-1] for _, table := range types { 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 28f4127ee93..a587e466fe4 100644 --- a/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource_test.go +++ b/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource_test.go @@ -1223,6 +1223,7 @@ func TestLogAnalyticsCreateRequest(t *testing.T) { req, err := ds.createRequest(ctx, logger, url, &AzureLogAnalyticsQuery{ Resources: []string{"r1", "r2"}, Query: "Perf", + QueryType: string(dataquery.AzureQueryTypeAzureLogAnalytics), }) require.NoError(t, err) expectedBody := `{"query":"Perf","timespan":"0001-01-01T00:00:00Z/0001-01-01T00:00:00Z","workspaces":["r1","r2"]}` @@ -1240,6 +1241,7 @@ func TestLogAnalyticsCreateRequest(t *testing.T) { req, err := ds.createRequest(ctx, logger, url, &AzureLogAnalyticsQuery{ Resources: []string{"r1", "r2"}, Query: "Perf", + QueryType: string(dataquery.AzureQueryTypeAzureLogAnalytics), TimeRange: backend.TimeRange{ From: from, To: to, @@ -1253,6 +1255,27 @@ func TestLogAnalyticsCreateRequest(t *testing.T) { t.Errorf("Unexpected Body: %v", cmp.Diff(string(body), expectedBody)) } }) + + t.Run("does not pass multiple resources for traces queries", 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"}, + QueryType: string(dataquery.AzureQueryTypeAzureTraces), + TimeRange: backend.TimeRange{ + From: from, + To: to, + }, + }) + require.NoError(t, err) + expectedBody := fmt.Sprintf(`{"query":"","timespan":"%s/%s"}`, from.Format(time.RFC3339), to.Format(time.RFC3339)) + 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)) + } + }) } func Test_executeQueryErrorWithDifferentLogAnalyticsCreds(t *testing.T) {