.NET agent reports handled errors

Problem

The .NET agent reports handled errors as though they are standard errors. This is most common with Azure worker roles, console apps, async work, and similar operations.

Solution

To avoid these false error reports, instrument a method that directly or indirectly contains the exception handler. In this example, GetResponse() throws an error:

Instrument the target method by defining a custom instrumentation file, or by wrapping the method in a custom transaction:

GetResponse() throwing an error
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.IO;

namespace ErrorTester
{
    class Program
    {
        static void Main(string[] args)
        {
            var i = 0;
            while (true)
            {
                Foo(++i);
            }
        }
        static void Foo(int i)
        {
                try
                {
                    GetNotFound();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Got it " + i + "!");
                    Thread.Sleep(1000);
                }

        }
        static string GetNotFound()
        {
            string uri = "http://localhost/Test/this/is/not/a/real/page";
            var request = (HttpWebRequest)WebRequest.Create(uri);
            var response = request.GetResponse();
            var data = new StreamReader(response.GetResponseStream()).ReadToEnd();
            response.Close();
            return data;
        }
    }
}

In this example, New Relic reports an error from GetResponse() unless the method Foo() is instrumented. As long is Foo is instrumented, New Relic begins a transaction when Foo is called and ends the transaction when Foo ends. Because the error is handled before Foo ends, New Relic will not report an error. Note also that GetReponse becomes a segment of the Foo transaction.

Define a custom instrumentation file

To instrument Foo via custom instrumentation, define a custom instrumentation file. In this case, CustomInstrumentation.xml:

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2008-2014 New Relic, Inc. All rights reserved. -->
<!--
    When you edit this file, please use an XML aware editor (such as Visual Studio),
    and pair with the companion file extension.xsd to minimize the
    chance of introducing typos that may confuse the agent when it is run.
-->
<extension xmlns="urn:newrelic-extension">
  <instrumentation>
    <tracerFactory >
      <match assemblyName="ErrorTester" className="ErrorTester.Program">
        <exactMethodMatcher methodName="Foo" /> 
      </match>
    </tracerFactory>
  </instrumentation>
</extension>

Place CustomInstrumenation.xml in the New Relic extensions folder, alongside CoreInstrumentation.xml, and restart your application.

For more information, see Custom instrumentation.

Wrap the method in a custom transaction

To instrument Foo via custom transaction, "wrap" Foo in a custom transaction:

<extension xmlns="urn:newrelic-extension">
  <instrumentation>
     <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Background/Task">
       <match assemblyName="ErrorTester" className="ErrorTester.Program">
         <exactMethodMatcher methodName="Foo" />
       </match>
    </tracerFactory>
  </instrumentation>
</extension>

For more information, see Custom transactions.

Cause

The only errors New Relic for .NET reports are unhandled errors that end a transaction. Thus, if your app calls an exception handler before the transaction ends New Relic will not report an error. However, New Relic does not always detect exception handlers when the error occurs outside of a web transaction, WCF transaction, or custom transaction. This is because the agent creates "mini-transactions" for instrumented methods that are not associated with a transaction. When the instrumented method exits, the mini-transaction ends. If the mini-transaction throws an error and the instrumented method does not handle it then New Relic will report an error.

You can see this in a console app that calls GetResponse(). As seen in the example above, if GetResponse throws an error then New Relic will report it even though GetResponse is called within a try/catch block. The agent reports an error because the GetResponse "mini-transaction" ends. As far as the agent is concerned, the error was still unhandled on transaction exit.

For more help

Additional documentation resources include:

Join the discussion about .NET monitoring in the New Relic Online Technical Community! The Technical Community is a public platform to discuss and troubleshoot your New Relic toolset.

If you need additional help, get support at support.newrelic.com.