From f6194931f59382e4e9089d1e0a79936c9ccc1b3c Mon Sep 17 00:00:00 2001 From: Andreas Christou Date: Thu, 16 Jan 2025 18:38:20 +0000 Subject: [PATCH] Azure: Improve resource request error handling (#99017) * Improve resource request error handling - Correctly parse JSON responses - Log erroneous failures in JSON marshalling/unmarshalling - Correctly set response status code - Do not attempt to use the response writer as it will be nil * Minor change * Improve type assertion handling --- .../azuremonitor-resource-handler.go | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/pkg/tsdb/azuremonitor/azuremonitor-resource-handler.go b/pkg/tsdb/azuremonitor/azuremonitor-resource-handler.go index c761b271f88..0ee66507768 100644 --- a/pkg/tsdb/azuremonitor/azuremonitor-resource-handler.go +++ b/pkg/tsdb/azuremonitor/azuremonitor-resource-handler.go @@ -33,30 +33,36 @@ func (s *httpServiceProxy) writeErrorResponse(rw http.ResponseWriter, statusCode rw.Header().Set("Content-Type", "application/json") rw.WriteHeader(statusCode) + // Set error response to initial error message + errorBody := map[string]string{"error": message} + // Attempt to locate JSON portion in error message re := regexp.MustCompile(`\{.*?\}`) jsonPart := re.FindString(message) - - var jsonData map[string]interface{} - if unmarshalErr := json.Unmarshal([]byte(jsonPart), &jsonData); unmarshalErr != nil { - errorMsg, _ := json.Marshal(map[string]string{"error": "Invalid JSON format in error message"}) - _, err := rw.Write(errorMsg) - if err != nil { - return fmt.Errorf("unable to write HTTP response: %v", err) + if jsonPart != "" { + var jsonData map[string]interface{} + if unmarshalErr := json.Unmarshal([]byte(jsonPart), &jsonData); unmarshalErr != nil { + errorBody["error"] = fmt.Sprintf("Invalid JSON format in error message. Raw error: %s", message) + s.logger.Error("failed to unmarshal JSON error message", "error", unmarshalErr) + } else { + // Extract relevant fields for a formatted error message + errorType, _ := jsonData["error"].(string) + errorDescription, ok := jsonData["error_description"].(string) + if !ok { + s.logger.Error("unable to convert error_description to string", "rawError", jsonData["error_description"]) + // Attempt to just format the error as a string + errorDescription = fmt.Sprintf("%v", jsonData["error_description"]) + } + if errorType == "" { + errorType = "UnknownError" + } + + errorBody["error"] = fmt.Sprintf("%s: %s", errorType, errorDescription) } - return unmarshalErr - } - - // Extract relevant fields for a formatted error message - errorType, _ := jsonData["error"].(string) - errorDescription, _ := jsonData["error_description"].(string) - if errorType == "" { - errorType = "UnknownError" } - formattedError := fmt.Sprintf("%s: %s", errorType, errorDescription) - errorMsg, _ := json.Marshal(map[string]string{"error": formattedError}) - _, err := rw.Write(errorMsg) + jsonRes, _ := json.Marshal(errorBody) + _, err := rw.Write(jsonRes) if err != nil { return fmt.Errorf("unable to write HTTP response: %v", err) } @@ -117,7 +123,7 @@ func (s *Service) getDataSourceFromHTTPReq(req *http.Request) (types.DatasourceI } func writeErrorResponse(rw http.ResponseWriter, code int, msg string) { - rw.WriteHeader(http.StatusBadRequest) + rw.WriteHeader(code) errorBody := map[string]string{ "error": msg, } @@ -154,9 +160,11 @@ func (s *Service) handleResourceReq(subDataSource string) func(rw http.ResponseW req.URL.Host = serviceURL.Host req.URL.Scheme = serviceURL.Scheme - rw, err = s.executors[subDataSource].ResourceRequest(rw, req, service.HTTPClient) + _, err = s.executors[subDataSource].ResourceRequest(rw, req, service.HTTPClient) if err != nil { - writeErrorResponse(rw, http.StatusInternalServerError, fmt.Sprintf("unexpected error %v", err)) + // The ResourceRequest function should handle writing the error response + // We log the error here to ensure it's captured + s.logger.Error("error in resource request", "error", err) return } }