---
title: Custom instrumentation via attributes (.NET)
source: https://docs.newrelic.com/docs/apm/agents/net-agent/custom-instrumentation/custom-instrumentation-attributes-net
---

New Relic's .NET agent provides several options for [custom instrumentation](https://docs.newrelic.com/docs/agents/net-agent/instrumentation/net-custom-instrumentation). Custom instrumentation allows you to instrument parts of your app that are not instrumented automatically. This document describes how to instrument your app by decorating the methods in your app code with attributes.

-   Use the `Transaction` attribute to create a custom transaction. You can also mark the custom transaction as a web transaction with the attribute's `Web` property.
-   Use the `Trace` attribute to add custom instrumentation to methods that are invoked within a preexisting transaction.

## Requirements and recommendations [#requirements]

Requirements include:

-   .NET agent version [6.16.178.0](https://docs.newrelic.com/docs/release-notes/agent-release-notes/net-release-notes/net-agent-6161780) or higher.
-   You must be willing to modify your source code. If you can't or don't want to modify your source code, use [custom instrumentation via XML](https://docs.newrelic.com/docs/agents/net-agent/custom-instrumentation/custom-instrumentation-xml-net).
-   Your project must have a reference to `NewRelic.Api.Agent.dll` (for example, installing the package and placing `using NewRelic.Api.Agent;` in your code). This package is in the [NuGet gallery](https://www.nuget.org/packages/NewRelic.Agent.Api/).
-   The `Transaction` and `Trace` attributes must be applied to concrete implementations of methods. They cannot be applied on interfaces or super class method definitions.
-   Avoid instrumenting top-level methods such as `Main()`, as these methods do not conclude until the application terminates, which may prevent data from being sent to New Relic.

## Transactions called within transactions [#tx-vs-trace]

Methods decorated with the `[Transaction]` attribute will only create a new transaction when one doesn't already exist. When a method decorated with `[Transaction]` is called from **within** a previously started transaction, it will be treated as the `[Trace]` attribute instead, and will provide more information about the existing transaction.

**Example: Calling `Transaction` in an already-started transaction**

During the execution of this console application, `OuterMethod` will be called first and create a new transaction. The `InnerMethod` is called from within the transaction started by `OuterMethod`, so it will not create a new transaction. Instead, information about the execution of `InnerMethod` will be tracked as if the `[Trace]` attribute had been applied.

````cs
static void Main(string[] args)
{
    OuterMethod();
}

[Transaction]
public void OuterMethod()
{
    InnerMethod();
}

[Transaction]
public void InnerMethod()
{
    // inner method code
}
```

````

## Create a new non-web transaction [#create-background-txn]

To start a non-web transaction (also known as a background request) with the `Transaction` attribute:

```cs
[Transaction]
public void Run()
{
    // your background task
}
```

For details about why to use either web or non-web, see [Classify as web or non-web](https://docs.newrelic.com/docs/agents/net-agent/custom-instrumentation/introduction-net-custom-instrumentation#web-background).

## Create a new web transaction [#create-web-txn]

To tell the agent to mark a non-web task as a web browser transaction, use either of these options:

-   Set the `Web` property of the `Transaction` attribute to `true`.
-   Set the transaction's URI with [`SetTransactionUri()`](https://docs.newrelic.com/docs/agents/net-agent/net-agent-api).

```cs
[Transaction(Web = true)]
public void Run()
{
    var uri = new Uri("https://www.mydomain.com/path");
    NewRelic.Api.Agent.NewRelic.SetTransactionUri(uri);

    // your web task
}
```

When used inside a [previously started transaction](#tx-vs-trace), this will be treated as a `[Trace]` attribute.

For details about why to use either web or non-web, see [Classify as web or non-web](https://docs.newrelic.com/docs/agents/net-agent/custom-instrumentation/introduction-net-custom-instrumentation#web-background).

## Add detail to existing transactions with `Trace` [#add-trace]

If your transaction traces show large blocks of un-instrumented time and you want to include additional methods within the trace, you can use the `Trace` attribute:

```cs
[Trace]
protected void MethodWithinTransaction()
{
    // your app code
}
```

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

> #### ⚠️ IMPORTANT
>
> Running your application from Visual Studio in **debug** mode may prevent some methods from appearing in New Relic traces. To ensure methods appear in New Relic, run the application in release mode via the command line.

## Properties for `Transaction` [#properties]

The `Transaction` attribute supports the following properties:

**`Web`**

| Type:    | Boolean |
| -------- | ------- |
| Default: | `false` |

If `true`, the agent starts a web transaction when it reaches this `Transaction` attribute. If a transaction is in progress, then that transaction will continue.

If `false` (default), the agent starts a non-web transaction when it reaches this `Transaction` attribute. For example:

````cs
[Transaction(Web = true)]
```

````

## Example: Instrument four methods [#example-app]

**Example app**

````cs
namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            var test = new MyClass();
            test.Method1(); // Creates a transaction named Method1 in the Web category.
            test.Method2(); // Creates a transaction named Method2 in the Custom category.
            test.Method3(); // Creates a transaction named Method3 in the Custom category.

            // Method4 won't create a new transaction, 
            // only add a segment to an existing transaction
            test.Method4();
        }
    }

    public class MyClass
    {
        // The agent creates a Web transaction that includes an external service 
        // request in its transaction traces.
        [Transaction(Web = true)]
        public void Method1()
        {
            new WebClient().DownloadString("https://www.google.com/");
        }

        // Creates a Custom transaction containing one segment.
        [Transaction]
        public void Method2()
        {
            // The Method3 segment will be created
            Method3();

            // The Method4 segment will contain your SQL query inside of it and 
            // possibly an execution plan.
            Method4();
        }

        // Method3 will be appear as a segment when called in Method2()
        // but will create a transaction when called directly in Main()
        [Transaction]
        public void Method3()
        {
            Thread.Sleep(1000);
        }

        // When Method4 is called directly in Main() the agent will not create a transaction.
        // However, when Method4 is called from Method2, Method4 will 
        // appear as a segment containing its SQL query.
        [Trace]
        public void Method4()
        {
            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();
                }
            }
        }
    }
}
```

````

## Read forum posts about instrumentation [#discuss-posts]

For more specific recommendations, check out these posts in our Support Forum community:

-   [Troubleshoot attribute-based custom instrumentation issues](https://support.newrelic.com/s/hubtopic/aAX8W0000008a5g/relic-solution-troubleshooting-attributebased-custom-instrumentation-issues)
-   [Build custom instrumentation tracer factories from .NET agent log files](https://knowledge.newrelic.com/s/article/Building-Custom-Instrumentation-Tracer-Factories-From-dot-NET-Agent)

## Use other API functions [#other-api]

For more about the .NET agent API and its functionality, see New Relic's [.NET agent API guide](https://docs.newrelic.com/docs/agents/net-agent/api-guides/guide-using-net-agent-api). For custom instrumentation without modifying your source code, see [Create transactions via XML](https://docs.newrelic.com/docs/agents/net-agent/instrumentation/net-custom-transactions) and [Add detail to transactions via XML](https://docs.newrelic.com/docs/agents/net-agent/custom-instrumentation/add-detail-transactions-xml-net).
