question

AronKovacs-1688 avatar image
0 Votes"
AronKovacs-1688 asked AronKovacs-1688 commented

Error reporting in Azure Functions vs App Insights

We call REST based APIs hosted by Azure Functions and fail to implement a consistent error handling supporting App Insights and wonder what can be done about it: - If we don't handle exceptions of the function, then App Insights reports a 'failure', but the service returns only the the error code to the caller, but no error content: Hence, the client receives a 500 and thats it. - - If we handle the exception and log it (to AppInsights) then App Insights stops reporting a 'failure' hence monitoring on function level is broken. We can query for the exception, but they are out-of-context (i.e. we can see the exception by a custom query only) and we don't know which function is impacted actually. How to marry up the two needs: 1. Let the function fail so that AppInsights reports the failure (and monitor can alert) 2. Return a bit more meaningful error message to the caller than 500. Example on how it looks currently in AppInsights: ![139349-2021-10-11-13-07-40-presentation1-powerpoint.png][1] The failures are unhandled exceptions (but the client receives purely 500) The exceptions are handled exceptions logged with ILogger.LogError(ex, ex.Message...) (but App Insights doesn't see it as failure) [1]: /answers/storage/attachments/139349-2021-10-11-13-07-40-presentation1-powerpoint.png

azure-functions
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

SamaraSoucy-3060 avatar image
0 Votes"
SamaraSoucy-3060 answered

Unfortunately "success" in Functions is whether or not is successfully pushed something to the output binding for any type of output- it doesn't have a special case for HTTP error codes.

Using `ILogger.LogError() won't show up on the graph, but you can still alert on it by creating a log alert on the requests table. Your 500 response should show up as success == "false" in the requests table in App Insights, even if Functions successfully completed its task. This is likely your best option if you would like to send a custom 500 response.

 requests
 | where success == "False" 

There is a similar question on Stack Overflow with more info: https://stackoverflow.com/questions/51646904/is-this-application-insight-azure-functions-bug-or-my-understanding-is-incorr?rq=1

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

AronKovacs-1688 avatar image
0 Votes"
AronKovacs-1688 answered AronKovacs-1688 edited

Given we throw an exception in the function, is there a way how the error message of the exception is returned to the client? Is there a configuration setting somewhere? Currently, the client gets only 500 without anything else

Your proposal unfortunately would always result in an empty result set if we handle the exception in order to return a more meaningful error to the client.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

SamaraSoucy-3060 avatar image
0 Votes"
SamaraSoucy-3060 answered AronKovacs-1688 commented

I'm a bit confused as to what you mean by empty result set. There is no setting to change this default behavior.

Let's say I have 2 functions, one where I catch the error, log it and return a custom response, and the other I let the error bubble up.

 public static IActionResult Run(HttpRequest req, ILogger log)
 {
     log.LogInformation("C# HTTP trigger function processed a request.");
    
     try {
         throw new Exception("caught exception");
    
     } catch (Exception e){
         log.LogError(e, "Bad request");
    
         return new ObjectResult("There was an error") {StatusCode = 500};
     }
    
     return new OkObjectResult("OK Response");
 }
    
 public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
 {
     log.LogInformation("C# HTTP trigger function processed a request.");
    
     throw new Exception("uncaught exception");
    
     return new OkObjectResult("OK Response");
 }

When I catch the exception I do have the option of returning a custom message:

139908-image.png

As I mentioned, the function will count this as a success since it successfully returned a value to the output binding:

139899-image.png

And it is indeed missing from the default error graph:

139992-image.png

However, because of the log.LogError() call the stack trace and related information is retained and the request is marked as failed in App Insights.

139880-image.png

I can then use that query to create appropriate alert rules while still returning a custom response:

139947-image.png



image.png (192.2 KiB)
image.png (23.6 KiB)
image.png (68.2 KiB)
image.png (135.7 KiB)
image.png (308.1 KiB)
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks for the very detailed explanation, but it seems that you confirm that it is impossible to let an operation fail and return an error message to the caller. This is in my view a feature gap since it forces us to
a) throw the exception and not tell the client(s) why/what which then leads to useless application support requests (request fails, but it was wrong user input)
b) handle the exception and return a message which then deactivates all benefits with the monitoring of the operation is bringing. We are back to where we were in 2004 -in a list of decorrelated exceptions which require professional judgement on severities.

1 Vote 1 ·