3

I am trying to monitor methods inside a .NET app which is a background process using New Relic for which I know I need to add Custom Instrumentation.

I have re-installed the .NET Agent, and after configuring "Instrument all .NET Applications", and making changes within the app.config and newrelic.config files, I am getting basic data of the background process in the new relic dashboard.

Now, to add Custom Instrumentation, I have added another instrumentation config file inside the extensions directory. Restarted the app, but still can't see the new/custom methods I am trying to monitor.

This is my instrumentation file MyInstrumentation.xml

<?xml version="1.0" encoding="utf-8"?>

<!-- instrument EngineService.BestAgentSolver.Solve inside EngineService.BestAgentSolver -->
<tracerFactory metricName="Cast-a-Net.EngineService.BestAgentSolver.Solve-Metric">
  <match assemblyName="Cast-a-Net.EngineService" className="Cast-a-Net.EngineService.BestAgentSolver">
    <exactMethodMatcher methodName="Solve" />
  </match>
</tracerFactory>

<!-- instrument EngineService.SessonManager.BroadcastLeadCounts inside EngineService.SessionManager -->
<tracerFactory metricName="Cast-a-Net.EngineService.SessionManager.BroadcastLeadCounts-Metric">
  <match assemblyName="Cast-a-Net.EngineService" className="Cast-a-Net.EngineService.SessionManager">
    <exactMethodMatcher methodName="BroadcastLeadCounts" />
  </match>
</tracerFactory>

<tracerFactory metricName="myapp.Web.Controllers.CallListController.ActionResult-Metric">
  <match assemblyName="myapp.Web" className="myapp.Web.Controllers.CallListController">
    <exactMethodMatcher methodName="ActionResult" />
  </match>
</tracerFactory>

Am I missing a step or doing something wrong?

utsavanand
  • 329
  • 1
  • 3
  • 15

1 Answers1

4

Custom instrumentation in the .NET agent works with web transactions that use the HttpContext object. Our .NET agent API, on the other hand, allows you to collect metrics that can be displayed in a custom dashboard. In particular, RecordMetric, RecordResponseTimeMetric, and IncrementCounter are useful because they work with non-web applications.

Starting with version 2.24.218.0 of the .NET agent however, a new feature can be used to create transactions where the agent would normally not do so. This is a manual process via a custom instrumentation file.

Create a custom instrumentation file named, say CustomInstrumentation.xml, in C:\ProgramData\New Relic.NET Agent\Extensions along side CoreInstrumentation.xml. Add the following content to your custom instrumentation file:

<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
  <instrumentation>
    <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Category/Name">
      <match assemblyName="AssemblyName" className="NameSpace.ClassName">
        <exactMethodMatcher methodName="MethodName" />
      </match>
    </tracerFactory>
  </instrumentation>
</extension>

You must change the attribute values Category/Name, AssemblyName, NameSpace.ClassName, and MethodName above:

The transaction starts when an object of type NameSpace.ClassName from assembly AssemblyName invokes the method MethodName. The transaction ends when the method returns or throws an exception. The transaction will be named Name and will be grouped into the transaction type specified by Category. In the New Relic UI you can select the transaction type from the Type drop down menu when viewing the Monitoring > Transactions page.

Note that both Category and Name must be present and must be separated by a slash.

As you would expect, instrumented activity (methods, database, externals) occurring during the method's invocation will be shown in the transaction's breakdown table and in transaction traces.

Here is a more concrete example. First, the instrumentation file:

<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
  <instrumentation>
    <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>
    <tracerFactory metricName="Custom/some custom metric name">
      <match assemblyName="Foo" className="Foo.Bar">
        <exactMethodMatcher methodName="Bar3" />
      </match>
    </tracerFactory>
  </instrumentation>
</extension>

Now some code:

var foo = new Foo();
foo.Bar1(); // Creates a transaction named Bars in category Background
foo.Bar2(); // Same here.
foo.Bar3(); // Won't create a new transaction.  See notes below.

public class Foo
{
    // this will result in a transaction with an External Service request segment in the transaction trace
    public void Bar1()
    {
        new WebClient().DownloadString("http://www.google.com/);
    }

    // this will result in a transaction that has one segment with a category of "Custom" and a name of "some custom metric name"
    public void Bar2()
    {
        // the segment for Bar3 will contain your SQL query inside of it and possibly an execution plan
        Bar3();
    }

    // if Bar3 is called directly, it won't get a transaction made for it.
    // However, if it is called inside of Bar1 or Bar2 then it will show up as a segment containing the 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();
            }
        }
    }
}

Here is a simple console app that demonstrates Custom Transactions:

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();
            for (int i = 0; i < 100; ++i )
                t.StartTransaction();
        }
    }
    class CustomTransaction
    {
        public void StartTransaction()
        {
            Console.WriteLine("StartTransaction");     
            Dummy();
        }
        void Dummy()
        {
            System.Threading.Thread.Sleep(5000);
        }
    }

}

Use the following custom instrumentation file:

<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
    <instrumentation>
        <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Background/CustomTransaction">
          <match assemblyName="ConsoleApplication1" className="ConsoleApplication1.CustomTransaction">
            <exactMethodMatcher methodName="StartTransaction" />
          </match>
        </tracerFactory>
        <tracerFactory metricName="Custom/Dummy">
          <match assemblyName="ConsoleApplication1" className="ConsoleApplication1.CustomTransaction">
            <exactMethodMatcher methodName="Dummy" />
          </match>
        </tracerFactory>
    </instrumentation>
</extension>

After running the application a few times you should see a custom transaction in the Other Transactions, Background category. You should see the Dummy segment in the transactions breakdown table and transaction trace.

Wyatt Lindsey
  • 351
  • 1
  • 5
  • Is there a differens between using the NewRelic.Api and the XML? Or does it do the same, just with different syntaxes? – Snæbjørn Sep 15 '15 at 09:19
  • @Snæbjørn [custom instrumentation](https://newrelic.com/docs/dotnet/dotnet-agent-custom-metrics) with an XML file is significantly different from the functionality offered by the [.NET Agent API](https://newrelic.com/docs/dotnet/the-net-agent-api). Use the XML file to define instrumentation for methods you'd like the profiler to trace. Use the API for specific utilities like naming a transaction or recording an error. Recording metrics directly with the API results in metrics that can be viewed in [custom dashboards](https://docs.newrelic.com/docs/dashboards/new-relic-dashboards). – Wyatt Lindsey Sep 16 '15 at 23:27
  • I think I understand now after playing around with it for a bit :) – Snæbjørn Sep 18 '15 at 07:00