Frage

I would like to know if there's a way I can monitor performance of a standalone .NET desktop application? (E.g., foobar.exe)

This is a client–side application that eventually may interact with a web service or a database, so in case of a database connection is concerned, ideally I would like to;

  1. monitor application performance (e.g., time spent or number of methods called, etc.)
  2. monitor SQL queries/procedures that are executed

Any help is greatly appreciated.

Thank you,

War es hilfreich?

Lösung

I work for New Relic.

It is possible to monitor the performance of non-IIS applications as long as they meet these requirements:

  • The Instrument All .NET Applications feature must be enabled

  • App.config and/or newrelic.config will need to be configured for the .exe

You can read more about these requirements on our documentation site here: https://docs.newrelic.com/docs/dotnet/instrumenting-custom-applications

You may need gather custom metrics by using our .NET agent API. The methods RecordMetric, RecordResponseTimeMetric, and IncrementCounter specifically work with non-web applications. Our .NET agent API documentation is located here: https://docs.newrelic.com/docs/dotnet/net-agent-api

You can also set up custom transactions to trace non-web transactions. We can normally trace functions that use HttpObjects, but the following is a new feature implemented in agent version 2.24.218.0. In the cases of non-web apps and async calls where there is no transaction context the following 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>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top