---
title: Add detail to transactions via XML (.NET)
source: https://docs.newrelic.com/docs/apm/agents/net-agent/custom-instrumentation/add-detail-transactions-xml-net
---

New Relic collects and reports information on web browser transactions and non-web transactions (background tasks). Normally the .NET agent produces complete information automatically, without any need for you to modify your application code. However, if New Relic does not support your [framework](https://docs.newrelic.com/docs/agents/net-agent/getting-started/compatibility-requirements-net-agent#architecture), you may need to add [custom instrumentation](https://docs.newrelic.com/docs/agents/net-agent/instrumentation/net-custom-instrumentation).

New Relic uses method tracers to implement custom instrumentation. A method tracer is a software probe that you can put on a method of any class. The .NET agent loads the instrumentation directives that define which methods should be traced from all XML files in the extensions directory.

This document describes instrumenting work when the agent is already collecting transactions, but you want to add more detail to those transactions. To instrument work when the agent isn't creating transactions automatically, see [Create transactions via XML](https://docs.newrelic.com/docs/agents/net-agent/instrumentation/net-custom-transactions). You can also add detail and create transactions by [decorating your code with attributes](https://docs.newrelic.com/docs/agents/net-agent/api-guides/net-agent-api-instrument-using-attributes).

## Add detail with custom instrumentation [#procedures]

Extension files define a number of tracer factories in an instrumentation element. Each tracer factory contains match elements that define the assembly, fully qualified class name, and method name to match. To define a new custom instrumentation XML file:

1.  Create a new `.xml` file in the extensions directory used by the .NET agent to read every XML file and define its instrumentation set. For the .NET Framework agent, use the following location:

    ```
    C:\ProgramData\New Relic\.NET Agent\Extensions
    ```

    > #### ⚠️ IMPORTANT
    >
    > Do **not** put the .xml file in the `C:\Program Files\New Relic\.NET agent\Extensions` directory. The file must be in the `ProgramData` file location for custom instrumentation to work.
    >
    > Do not modify the distributed xml files. These files are overwritten whenever the agent is upgraded.
2.  Copy this template into the file you created use [the sample](#sample) as an example. This instruments two methods but you can add methods to your instrumentation file.

    > #### 💡 TIP
    >
    > The values `AssemblyName`, `NameSpace.ClassName`, and `MethodName` are case sensitive.

    ```xml
    <?xml version="1.0" encoding="utf-8"?>
    <extension xmlns="urn:newrelic-extension">
      <instrumentation>
        <!-- These methods appear in the transactions breakdown table and in transaction traces -->
        <tracerFactory metricName="Category/Name">
          <match assemblyName="AssemblyName" className="NameSpace.ClassName">
            <exactMethodMatcher methodName="MethodName" />
          </match>
        </tracerFactory>
        <tracerFactory metricName="Category/Name2"> 
           <match assemblyName="AssemblyName" className="NameSpace.ClassName2"> 
            <exactMethodMatcher methodName="MethodName2" /> 
           </match>
        </tracerFactory>
      </instrumentation>
    </extension>
    ```
3.  [Validate the `.xml` instrumentation file](#xsd-validate) against `extension.xsd`.
4.  Non-IIS apps (such as a console app or background process): You must also [create transactions via XML](https://docs.newrelic.com/docs/agents/net-agent/instrumentation/net-custom-transactions) to contain the methods you instrument. Custom methods instrumented outside of a transaction will not be reported to New Relic.
5.  > #### ⚠️ IMPORTANT
    >
    > If your .NET agent version is 7.0 or higher, this is the end of the procedure.
    >
    > If your .NET agent version is lower than 7.0, continue to the next steps.
6.  If your app is IIS-hosted, restart IIS.
7.  For non-IIS applications, restart your application's host process or the application itself.

> #### ⚠️ IMPORTANT
>
> If some of your methods still don't show up in traces after adding XML custom instrumentation, disable method inlining for those methods with `[MethodImpl(MethodImplOptions.NoInlining)]`.

## Ignore a transaction [#blocking-instrumentation]

You can stop a transaction from being reported by using a custom instrumentation file. Whenever an ignored method is called, the .NET agent ignores the entire parent transaction. This is the same as calling `IgnoreTransaction()`.

To ignore a transaction:

1.  [Add custom instrumentation](#procedures).
2.  Add a `tracerFactory` whose name is `NewRelic.Agent.Core.Tracer.Factories.IgnoreTransactionTracerFactory`:

    ```xml
    <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.IgnoreTransactionTracerFactory">
      <match assemblyName="System.Web.Extensions" className="System.Web.Handlers.ScriptResourceHandler">
        <exactMethodMatcher methodName="Throw404" />
      </match>
    </tracerFactory>
    ```

## Track async work in a separate transaction [#track-async]

In some cases, asynchronous work can be tracked as a separate transaction by applying the `AsyncForceNewTransactionWrapper` instrumentation:

```xml
<tracerFactory name="AsyncForceNewTransactionWrapper">
  <match assemblyName="AssemblyName" className="Namespace.ClassName">
    <exactMethodMatcher methodName="MethodName" />
  </match>
</tracerFactory>
```

| Async usage considerations | Comments                                                                                                                                                                  |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Instrumented method        | The instrumented method must be invoked using `Task.Run`, `Task.Factory.StartNew`, or `new Thread()`. It cannot be invoked using the `await` keyword.                     |
| Return type                | The instrumented method is not required to be `async`. However, if it is `async`, it must have a return type of `Task` or `Task<T>`. It cannot have a `void` return type. |
| Attribute instrumentation  | The instrumented method cannot have attribute instrumentation applied to it. It cannot be decorated with the `[Transaction]` or `[Trace]` attributes.                     |

**Example method definitions**

The following methods can be instrumented using the `AsyncForceNewTransactionWrapper` custom instrumentation:

````cs
private void SyncMethod()
{
}

private async Task AsyncMethod_Task()
{
}

private async Task<string> AsyncMethod_TypedTask()
{
    return "ok";
}
```

The following methods <DNT>**cannot**</DNT> be instrumented using the `AsyncForceNewTransactionWrapper` custom instrumentation:

```cs
private async void AsyncMethod_Void()
{
}

[Transaction]
private void TransactionAttributedMethod()
{
}

[Trace]
private void TracedAttributedMethod()
{
}
```

````

**Example method invocations**

The following method calls can be used with `AsyncForceNewTransactionWrapper` instrumentation:

````cs
Task.Run(SyncMethod);

Task.Factory.StartNew(AsyncMethod_Task);

var newThread = new Thread(new ThreadStart(SyncMethod));
newThread.Start();
```

The following method calls <DNT>**cannot**</DNT> be used with `AsyncForceNewTransactionWrapper` instrumentation:

```cs
SyncMethod();              // This is not an asynchronous call

await AsyncMethod_Task();  // Not started with Task.Run, Task.Factor.StartNew, or new Thread()

AsyncMethod_Void();        // Async Void is not supported
```

````

## Example MyInstrumentation.xml [#sample]

This example instruments two methods and ignores another method:

-   **Instrument**: `CustomInstrumentDemo.Controllers.FirstController.FirstExample()`
-   **Instrument**: `CustomInstrumentDemo.Controllers.SecondController.SecondExample()`
-   **Ignore**: `CustomInstrumentDemo.Controllers.SecondController.ThirdExample()`
-   **Instrument**: `CustomInstrumentDemo.Controllers.SecondController.FourthExample(int id, string name)`

To implement this custom instrumentation scheme, use the following example file and instrumented methods:

**Example custom instrumentation file**

The following is an example custom instrumentation file named `MyInstrumentation.xml`:

````xml
<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
  <instrumentation>
    <!-- instrument CustomInstrumentDemo.Controllers.FirstController.FirstExample and creates metric named Custom/Foo1 -->
    <tracerFactory metricName="Custom/Foo1">
      <match assemblyName="CustomInstrumentDemo" className="CustomInstrumentDemo.Controllers.FirstController">
        <exactMethodMatcher methodName="FirstExample" />
      </match>
    </tracerFactory>

    <!-- instrument CustomInstrumentDemo.Controllers.SecondController.SecondExample -->
    <tracerFactory>
      <match assemblyName="CustomInstrumentDemo" className="CustomInstrumentDemo.Controllers.SecondController">
        <exactMethodMatcher methodName="SecondExample" />
      </match>
    </tracerFactory>

    <!-- ignore CustomInstrumentDemo.Controllers.SecondController.ThirdExample -->
    <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.IgnoreTransactionTracerFactory">
      <match assemblyName="CustomInstrumentDemo" className="CustomInstrumentDemo.Controllers.SecondController">
        <exactMethodMatcher methodName="ThirdExample" />
      </match>
    </tracerFactory>

    <!-- instrument CustomInstrumentDemo.Controllers.SecondController.FourthExample and creates metric named Custom/{value},
         where {value} is the value of the first string parameter of the instrumented method
         (in this case, the first string parameter is "name"). -->
    <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.CustomSegmentTracerFactory">
      <match assemblyName="CustomInstrumentDemo" className="CustomInstrumentDemo.Controllers.SecondController">
        <exactMethodMatcher methodName="FourthExample" />
      </match>
    </tracerFactory>
  </instrumentation>
</extension>
```

````

**Example methods to be instrumented**

This code contains the three methods specified by the [example custom instrumentation file](#example-file):

````cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Threading;

namespace CustomInstrumentDemo.Controllers
{
    public class FirstController : Controller
    {
        public ActionResult Foo1()
        {
            ViewBag.Message = "Your Sample Page";
            FirstExample();
            return View();
        }

        public void FirstExample()
        {
            int firstVar = 1;
            for (int i = 0; i <= 500; i++)
            {
                firstVar *= 5;
                Thread.Sleep(50);
            } 
        }
    }

    public class SecondController : Controller
    {
        public ActionResult Foo2()
        {
            ViewBag.Message = "This view will include detailed information on the SecondExample method";
            SecondExample();
            return view;
        }

        public ActionResult Foo3()
        {
            ViewBag.Message = "This view will be ignored because of the inclusion of the ThirdExample method";
            ThirdExample();
        }

        public void SecondExample()
        {
            int secondVar = 2;

            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();
                }
            }
        }

        public void ThirdExample()
        {
            try
            {
                var ImNotABool = "43";
                bool.Parse(ImNotABool);
            }
            catch (Exception ex)
            {
                NewRelic.Api.Agent.NewRelic.NoticeError(ex);
            }
        }

        public void FourthExample(int id, string name)
        {
            Console.WriteLine("The ID passed in was " + id + " and the name passed in was " + name);
        }
    }
}
```

````

## Name metrics

Metrics created from tracers will be named using the class name and method name of the matched method. You can override this name with the `metricName` attribute. Begin `metricName` with `Custom/` (for example, `metricName="Custom/OrderSubmissions"`).

```xml
<!-- instruments MyCompany.Order.Submit() and creates a metric named Custom/OrderSubmissions -->
<tracerFactory metricName="Custom/OrderSubmissions">
  <match assemblyName="MyCompany" className="MyCompany.Order">
    <exactMethodMatcher methodName="Submit" />
  </match>
</tracerFactory>
```

## Name transactions

The agent names transactions using the tracer in the transaction with the highest naming priority.

-   Web transactions may be named using the HTTP handler, ASP name, MVC controller name, or web service name, depending on the tracers invoked in the transaction's execution.
-   Background transactions with no tracer that explicitly names the transaction are rolled up into a single transaction name.

Use the `transactionNamingPriority` attribute to tell the agent to give a tracer transaction naming priority. Valid values are `1` to `7`, where `7` takes precedence over `1` to `6`. Also, the `metricName` attribute must begin with `Custom/` (for example, `metricName="Custom/instance"`).

```xml
<!-- instructs the agent to create a metric for MyControllerBase.Execute and to name the transaction using this tracer's metric name -->
<tracerFactory metricName="Custom/instance" transactionNamingPriority="7">
  <match assemblyName="MyCompany" className="MyCompany.MyControllerBase">
    <exactMethodMatcher methodName="Execute" />
  </match>
</tracerFactory>
```

## XSD validation [#xsd-validate]

The XML instrumentation file can be checked against the XSD file (located at `C:\ProgramData\New Relic\.NET Agent\Extensions\extension.xsd`) with any XSD validator.

## Troubleshooting

The .NET agent will write a log message to `NewRelic.Profiler.####.log` (where `####` is the PID of the instrumented process) as it rewrites methods. This helps to verify that custom instrumentation is being read and that the proper methods are being instrumented.

> #### 💡 TIP
>
> Avoid using the `name` attribute of the `tracerFactory` element in custom instrumentation. For more information, review the `extension.xsd` schema file in the agent directory.
