The .NET agent for New Relic can appear to be a black box, but it’s actually a sophisticated piece of middleware that hooks into your application’s runtime to collect performance telemetry.

Let’s see it in action. Imagine a simple ASP.NET Core application.

using Microsoft.AspNetCore.Mvc;

namespace MyWebApp.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class SampleController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            // Simulate some work
            System.Threading.Thread.Sleep(200);
            return "Hello from SampleController!";
        }
    }
}

With the New Relic agent installed and configured, a request to /sample would show up in New Relic as a transaction. You’d see metrics like:

  • Transaction Duration: The total time taken for the request (e.g., 250ms).
  • External Services: Calls to other services (e.g., database queries, external APIs).
  • Database Calls: Specific metrics for SQL queries.
  • CPU Usage: The percentage of CPU consumed by the process.
  • Memory Usage: The amount of managed and unmanaged memory used.

The core problem the agent solves is providing visibility into the performance of .NET applications without requiring manual code instrumentation. It achieves this by leveraging CLR (Common Language Runtime) hooks and event tracing (ETW on Windows, LTTng on Linux). When your application starts, the agent is injected into the CLR process. It then registers event listeners for various runtime events: method entry/exit, garbage collection, thread pool activity, and more. These events are aggregated, sampled, and sent to the New Relic New Relic platform for analysis and visualization.

Configuration is primarily handled through the newrelic.config file (on Windows) or environment variables (on Linux).

Key Configuration Parameters:

  • app_name: This is the most crucial setting. It defines how your application will appear in the New Relic UI.
    • Windows newrelic.config:
      <configuration>
          <service license="YOUR_LICENSE_KEY" >
              <application>
                  <name>My Awesome WebApp</name>
              </application>
          </service>
      </configuration>
      
    • Linux Environment Variable:
      export NEW_RELIC_APP_NAME="My Awesome WebApp"
      
  • license_key: Your New Relic license key, used for authentication.
    • Windows newrelic.config:
      <service license="YOUR_LICENSE_KEY" >
      
    • Linux Environment Variable:
      export NEW_RELIC_LICENSE_KEY="YOUR_LICENSE_KEY"
      
  • distributed_tracing.enabled: Enables distributed tracing, which links transactions across multiple services.
    • Windows newrelic.config:
      <distributed_tracing enabled="true"/>
      
    • Linux Environment Variable:
      export NEW_RELIC_DISTRIBUTED_TRACING_ENABLED="true"
      
  • attributes.include: Specify custom attributes to send to New Relic.
    • Windows newrelic.config:
      <application>
          <attributes>
              <include>Http\*</include>
              <include>Request\*</include>
          </attributes>
      </application>
      
    • Linux Environment Variable:
      export NEW_RELIC_ATTRIBUTES_INCLUDE="Http\*,Request\*"
      
  • log_level: Controls the verbosity of agent logs. Options include info, debug, warning, error.
    • Windows newrelic.config:
      <log level="debug"/>
      
    • Linux Environment Variable:
      export NEW_RELIC_LOG_LEVEL="debug"
      

The agent dynamically loads itself into the .NET process at startup. On Windows, this is often achieved by modifying the application’s web.config or app.config to include a modules or httpModules section that points to the agent’s DLL. On Linux, it’s typically done via environment variables that tell the CLR to load the agent library (libNewRelic.so) before your application code. The agent then uses a combination of CLR instrumentation APIs (like Assembly.Load and ModuleInitializers) and lower-level hooking mechanisms to intercept method calls and runtime events.

A common point of confusion is how the agent discovers your application. On Windows, it often relies on IIS integration or specific entries in web.config. On Linux, especially for self-hosted applications or containers, it’s usually initiated by setting the CORECLR_ENABLE_PROFILING and CORECLR_PROFILER environment variables before your .NET application starts, pointing to the agent’s profiler DLL. The NEW_RELIC_APP_NAME environment variable then tells the agent which application this specific process belongs to.

When troubleshooting, remember that the agent itself is a .NET assembly. If your application has dependency issues or is running on an unsupported .NET Framework/Core version, the agent might fail to load, often with cryptic errors in the application’s event logs or the agent’s own log files (located in /var/log/newrelic on Linux or C:\ProgramData\New Relic\.NET Agent\Logs on Windows).

The agent’s ability to automatically instrument database calls relies on specific ADO.NET providers. If your application uses a custom or less common data access method, you might need to enable custom instrumentation using newrelic.config or environment variables to ensure those operations are captured.

Want structured learning?

Take the full Newrelic course →