1

I have the following exception:

public class InvalidStatusCodeException : Exception
{
    public HttpStatusCode ReceivedStatusCode { get; set; }
    public string ApiUrl { get; set; }

    public InvalidStatusCodeException(HttpStatusCode receivedStatusCode, string apiUrl)
    {
        ReceivedStatusCode = receivedStatusCode;
        ApiUrl = apiUrl;
    }
}

throw it in some cases:

        string url = "api/group/1/getAll";
        var response = await _client.GetAsync(url);
        if (!response.IsSuccessStatusCode)
            throw new InvalidStatusCodeException(response.StatusCode, url);

if I catch and log this exception:

        catch(InvalidStatusCodeException status_ex)
        {
            string error = $"Invalid Status code for request: '{status_ex.ApiUrl}', received code: {status_ex.ReceivedStatusCode}";
            log.LogError(status_ex, error, "InvalidStatusCode");
        }

I don't see values of my custom properties (ReceivedStatusCode, ApiUrl) and can see details only in error message.

enter image description here

If I don't catch this exception at all and exception is being logged automatically then no way to see details at all.

Any way to see these custom properties without additional catching of exception?

Oleg Sh
  • 8,496
  • 17
  • 89
  • 159

2 Answers2

1

Add a message to the base Exception

public class InvalidStatusCodeException : Exception
{
    public HttpStatusCode ReceivedStatusCode { get; set; }
    public string ApiUrl { get; set; }

    public InvalidStatusCodeException(HttpStatusCode receivedStatusCode, string apiUrl) 
        : base($"Invalid Status code for request: '{apiUrl}', received code: {receivedStatusCode}")
    {
        ReceivedStatusCode = receivedStatusCode;
        ApiUrl = apiUrl;
    }
}
David Specht
  • 7,784
  • 1
  • 22
  • 30
  • probably, it's a solution. But I want to save on App Insights custom properties in anyway and don't want to prepare message on exception level (no way to sorting/filtering, can be localization etc) – Oleg Sh Dec 30 '20 at 03:47
1

You can use the concept of structure logging which logs the named constant as custom properties.

catch(InvalidStatusCodeException status_ex)
{
     log.LogError(status_ex, "Invalid Status code for request: '{ApiUrl}', received code: {ReceivedStatusCode}", status_ex.ApiUrl, status_ex.ReceivedStatusCode);
 }

The above log will add ApiUrl and ReceivedStatusCode as custom properties in application insights log.

Update

You don't need to throw and catch the exception. You can log in the else block of if (response.IsSuccessStatusCode) like shown below:

 if (response.IsSuccessStatusCode)
 {
     
 }
 else
 {
     log.LogError(status_ex, "Invalid Status code for request: '{ApiUrl}', received code: {ReceivedStatusCode}",
         apiUrl, response.StatusCode);
 }

Other way of logging custom properties is via Logging Scope (check this) and via TelemetryInitializer (check this)

user1672994
  • 10,509
  • 1
  • 19
  • 32
  • I used the same approach, but first at all, custom properties are not saved (only as message string) and, secondly, I have to catch and rethrow this exception – Oleg Sh Dec 30 '20 at 21:40
  • @OlegSh - I you notice, in the `LogError`, string interpolation is **not** used. The variables are passed as arguments and `{}` contains the string literal and those will be logged as custom properties. Have you used the same approach? – user1672994 Dec 31 '20 at 03:54
  • yes, you are right. But I would like to avoid catch error at all and write custom properties. Is it possible? – Oleg Sh Jan 02 '21 at 19:53
  • As such you don't need to throw the exception. You can add the log in the else condition of ` if (!response.IsSuccessStatusCode)` code condition. The other way of logging the custom properties are `Logging Scope` (check [this](https://github.com/amigup/CleanArchitecture-For-AzureFunctionV3/blob/master/CleanArchitecture.Functions/Triggers/Http/ToDoItemsController.cs#L33)) and via `TelemetryInitializer` (check [this](https://github.com/amigup/CleanArchitecture-For-AzureFunctionV3/blob/master/CleanArchitecture.Infrastructure/ApplicationInsightsInitializers/CorrelationTelemetryInitializer.cs)) – user1672994 Jan 03 '21 at 06:22
  • Another approach is to use `DelegatingHandler` to log the entry while sending request and receiving response. Check the sample implementation at [here](https://github.com/amigup/CleanArchitecture-For-AzureFunctionV3/blob/master/CleanArchitecture.Infrastructure/DelegatingHandlers/HeaderLoggingDelegatingHandler.cs). – user1672994 Jan 04 '21 at 06:49
  • thank you for such careful explanation and good examples. In any case, no way to say App Insights to log custom fields automatically :( – Oleg Sh Jan 04 '21 at 21:03
  • IMO, this solution doesn't scale. I don't want to have to manually log every exception, or provide a specific logging statement for each exception type. – mdarefull Aug 09 '22 at 15:50