.NET custom transactions

New Relic instruments most web application frameworks automatically, without any configuration required. However, New Relic cannot automatically instrument non-web applications because they do not have an HttpContext object. You can manually instrument these methods by defining a custom instrumentation file.

Custom transactions are available on New Relic for .NET version 2.24.218.0 or higher.

Create custom transactions

Custom transactions are defined in a custom instrumentation file. You define a method which triggers the creation of a transaction. You can also instrument additional methods called by the trigger method. These additional methods appear in the transaction's breakdown table and in transaction traces. Database and external calls do not need manual instrumentation, because they are automatically instrumented by the agent.

These techniques only work for synchronous methods. Custom transactions cannot yet be created for asynchronous methods.

To create a custom instrumentation file:

  1. In C:\ProgramData\New Relic\.NET Agent\Extensions, create a file named CustomInstrumentation.xml.
  2. Copy this template into CustomInstrumentation.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <extension xmlns="urn:newrelic-extension">
      <instrumentation>
        <!-- Define the method which triggers the creation of a transaction. -->
        <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Category/Name">
          <match assemblyName="AssemblyName" className="NameSpace.ClassName">
            <exactMethodMatcher methodName="MethodName" />
          </match>
        </tracerFactory>
        <!-- Instrument 0 or more methods called by the trigger method. These methods appear in the transaction breakdown table and in transaction traces. -->
        <tracerFactory metricName="Category/Name">
          <match assemblyName="AssemblyName" className="NameSpace.ClassName">
            <exactMethodMatcher methodName="MethodName" />
          </match>
        </tracerFactory>
      </instrumentation>
    </extension>
  3. In CustomInstrumentation.xml, customize the attribute values Category/Name, AssemblyName, NameSpace.ClassName, and MethodName. Customize these values for both the trigger method and for any methods called by the trigger method.
    • Category/Name: Defines the transaction type. The New Relic UI groups transactions under these names in the transaction type field. The Category and Name must both be specified, and must be separated by a slash.
    • AssemblyName: The assembly that contains the trigger method.
    • NameSpace.ClassName: The fully-qualified class name that contains the trigger method.
    • MethodName: The exact name of the trigger method.

Do not use brackets [suffix] at the end of your transaction name. New Relic automatically strips brackets from the name. Instead, use parentheses (suffix) or other symbols if needed.

View custom transactions

As of .NET agent version 4.3, custom transactions support key transactions.

The custom transaction starts when the method specified by methodName is invoked in the assembly specified by assemblyName. The transaction ends when the method returns or throws an exception.

You can view these metrics in the Transactions page and in transaction traces.

To view the transaction: Go to rpm.newrelic.com > APM > Applications > (select an app) > Monitoring > Transactions > Type > (selected a type). The type is defined by Category/Name. You can then view all custom transactions of the selected type.

screen-custom-transactions-rpm
APM > Applications > (selected app) > Monitoring > Transactions > Type > (selected type): Use the Type menu to view your custom transactions.

Example custom transaction

This example presents a simple implementation of custom transactions. For an example of asynchronous methods, see .NET custom instrumentation.

Example custom instrumentation file

This custom instrumentation file defines the three methods to instrument:

<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
  <instrumentation>
    <!-- Define the method which triggers the creation of a transaction. -->
    <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Background/Bars">
      <match assemblyName="Foo" className="Foo.Bar">
        <exactMethodMatcher methodName="Bar1" />
        <exactMethodMatcher methodName="Bar2" />
      </match>
    </tracerFactory>
    <!-- Instrument 0 or more methods called by the trigger method. These methods appear in the transaction breakdown table and in transaction traces. -->
    <tracerFactory>
      <match assemblyName="Foo" className="Foo.Bar">
        <exactMethodMatcher methodName="Bar3" />
      </match>
    </tracerFactory>
  </instrumentation>
</extension>
Example methods to be instrumented

This code contains the three methods, with comments explaining when each one will be instrumented by the agent:

var bar = new Bar();
bar.Bar1(); // Creates a transaction named Bars in the Background category.
bar.Bar2(); // Creates a transaction named Bars in the Background category.
bar.Bar3(); // Won't create a new transaction. See `If Bar3 is called directly`, below.

namespace Foo
{
    public class Bar
    {
        // The agent creates a transaction that includes an external service request in its transaction traces.
        public void Bar1()
        {
            new WebClient().DownloadString("http://www.google.com/");
        }
 
        // Creates  a transaction containing one segment.
        public void Bar2()
        {
            // The Bar3 segment will contain your SQL query inside of it and possibly an execution plan.
            Bar3();
        }
 
        // If Bar3 is called directly, the agent will not create a transaction.
        // However, if Bar3 is called from Bar1 or Bar2, Bar3 will appear as a segment containing its SQL query.
        private void Bar3()
        {
            using (var connection = new SqlConnection(ConnectionStrings["MsSqlConnection"].ConnectionString))
            {
                connection.Open();
                using (var command = new SqlCommand("SELECT * FROM table", connection))
                using (var reader = command.ExecuteReader())
                {
                    reader.Read();
                }
            }
        }
    }
}

Example application

This simple console app demonstrates custom transactions. After running the application a few times, you see custom transaction in the Other Transactions > Background category. The Dummy segment will be visible in the transactions breakdown table and in any transaction traces.

Example custom instrumentation file

This custom instrumentation file defines two methods to instrument:

<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
    <instrumentation>
        <!-- Define the method which triggers the creation of a transaction. -->
        <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Background/CustomTransaction">
          <match assemblyName="ConsoleApplication1" className="ConsoleApplication1.CustomTransaction">
            <exactMethodMatcher methodName="StartTransaction" />
          </match>
        </tracerFactory>
        <!-- Instrument 0 or more methods called by the trigger method. These methods appear in the transaction breakdown table and in transaction traces. -->
        <tracerFactory>
          <match assemblyName="ConsoleApplication1" className="ConsoleApplication1.CustomTransaction">
            <exactMethodMatcher methodName="Dummy" />
          </match>
        </tracerFactory>
    </instrumentation>
</extension>
Example app using custom transactions

This code contains the two methods specified by the custom instrumentation file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Custom Transactions");
            var t = new CustomTransaction();
            while (true)
                t.StartTransaction();
        }
    }
    class CustomTransaction
    {
        public void StartTransaction()
        {
            Console.WriteLine("StartTransaction");     
            Dummy();
        }
        void Dummy()
        {
            System.Threading.Thread.Sleep(5000);
        }
    }
 
}

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.