0
votes

I have set up a custom ITelemetryProcessor for my .NET Core 2.1 Web API. I do not want HTTP status codes 400 or 401 to be displayed as error in Application Insights. The following class does this, but as soon as I use it SQL and HTTP client dependency tracking will no longer work:

ApplicationInsights400IsOkProcessor

public class ApplicationInsights400IsOkProcessor : ITelemetryProcessor {

    private ITelemetryProcessor Next { get; set; }


    /// <summary>
    /// Link processors to each other in a chain. 
    /// </summary>
    /// <param name="next"></param>
    public ApplicationInsights400IsOkProcessor(ITelemetryProcessor next) {
        this.Next = next;
    }

    /// <summary>
    /// API Aufrufe mit Rückgabecode 400 und 401 sind keine Fehler
    /// </summary>
    /// <param name="item">Telemetry zum Verarbeiten</param>
    public void Process(ITelemetry item) {
        var requestTelemetry = item as RequestTelemetry;          
        if (requestTelemetry == null) return;
        bool parsed = Int32.TryParse(requestTelemetry.ResponseCode, out int code);
        if (!parsed) return;
        switch (code) {
            case 400:
                requestTelemetry.Success = true;
                requestTelemetry.Context.Properties["Overridden400"] = "true";
                break;
            case 401:
                requestTelemetry.Context.Properties["Overridden401"] = "true";
                requestTelemetry.Success = true;
                break;
        }

        this.Next.Process(item);
    }

With .NET Core 2.0 I used a custom ITelemetryInitializer like this sample from Microsoft: https://docs.microsoft.com/en-us/azure/application-insights/app-insights-api-filtering-sampling#add-properties-itelemetryinitializer

This was used by adding the following to Configure Services():

TelemetryConfiguration.Active.TelemetryInitializers
    .Add(new MyTelemetryInitializer());

In .NET Core 2.1 this does not seem to work anymore

Update: Based on the answer of I cijothomas reviewed the code to ensure that this.Next.Process(item) is called in all cases. Below is the working version:

ApplicationInsights400IsOkProcessor

 public class ApplicationInsights400IsOkProcessor : ITelemetryProcessor {

    private ITelemetryProcessor Next { get; set; }

    public ApplicationInsights400IsOkProcessor(ITelemetryProcessor next) {
        this.Next = next;
    }

    public void Process(ITelemetry item) {
        if (item is RequestTelemetry requestTelemetry) {
            bool parsed = Int32.TryParse(requestTelemetry.ResponseCode, out int code);
            if (parsed) {
                switch (code) {
                    case 400:
                        requestTelemetry.Success = true;
                        requestTelemetry.Context.Properties["Overridden400"] = "true";
                        break;
                    case 401:
                        requestTelemetry.Context.Properties["Overridden401"] = "true";
                        requestTelemetry.Success = true;
                        break;
                }
            }
        }

        this.Next.Process(item);
    }

}
1
if (!parsed) return; << Here you return w/o calling the next processor in the lineTseng

1 Answers

3
votes

You are not calling the next.Process() in all the cases, hence causing items to be dropped. Your scenario calls for using a ITelemetryInitializer, rather than ITelemetryProcessor, as you are simply trying to modify auto-collected information, and not trying to drop items based on conditions.

https://docs.microsoft.com/en-us/azure/application-insights/app-insights-api-filtering-sampling#add-properties-itelemetryinitializer

Something like the following:

 public class ApplicationInsights400IsOkInitializer: ITelemetryInitializer
  {
    public void Initialize(ITelemetry telemetry)
    {
        var requestTelemetry = telemetry as RequestTelemetry;
        // Is this a TrackRequest() ?
        if (requestTelemetry == null) return;
        bool parsed = Int32.TryParse(requestTelemetry.ResponseCode, out int code);
        if (!parsed) return;
        switch (code) 
        {
        case 400:
            requestTelemetry.Success = true;
            requestTelemetry.Context.Properties["Overridden400"] = "true";
            break;
        case 401:
            requestTelemetry.Context.Properties["Overridden401"] = "true";
            requestTelemetry.Success = true;
            break;
         }
    }
  }