Dotnet Web API NewRelic Integration

Today I was having a bit more of a play with integrating NewRelic with a dotnet web API, and figured I’d document my findings. It’s worth taking a look at the NewRelic docs if you haven’t seen them already.

It’s worth noting I’d put a quick post together about this last year, but that approach was entirely in Docker, whereas today’s approach is a bit more polished and uses the NewRelic nuget packages.

Nuget

Add the NewRelic nuget packages to your API:

<PackageReference Include="NewRelic.Agent" Version="8.25.214"  />
<PackageReference Include="NewRelic.Agent.Api" Version="8.25.214"  />

newrelic.config

This has mostly been taken from docs.newrelic.com. You can ignore additional exceptions and http status codes here.

I’ve taken the license key out of here, and instead set those in environment variables below, as this config will be committed to source control.

<?xml version="1.0"?>
<!-- Copyright (c) 2008-2019 New Relic, Inc.  All rights reserved. -->
<!-- For more information see: https://newrelic.com/docs/dotnet/dotnet-agent-configuration -->
<configuration xmlns="urn:newrelic-config" agentEnabled="true">
    <log level="info"/>
    <transactionTracer enabled="true" transactionThreshold="apdex_f" stackTraceThreshold="500" recordSql="obfuscated" explainEnabled="false" explainThreshold="500"/>
    <crossApplicationTracer enabled="true"/>
    <errorCollector enabled="true">
        <ignoreErrors>
            <exception>System.IO.FileNotFoundException</exception>
            <exception>System.Threading.ThreadAbortException</exception>
        </ignoreErrors>
        <ignoreStatusCodes>
            <code>401</code>
            <code>404</code>
        </ignoreStatusCodes>
    </errorCollector>
    <browserMonitoring autoInstrument="true" />
    <attributes enabled="true">
    </attributes>
    <threadProfiling>
      <ignoreMethod>System.Threading.WaitHandle:InternalWaitOne</ignoreMethod>
      <ignoreMethod>System.Threading.WaitHandle:WaitAny</ignoreMethod>
    </threadProfiling>
</configuration>

Environment Variables

Set environment variables for the NewRelic runner. You can do this straight in the Dockerfile, but being as we’re including a license key here, it’s probably best to store these values somewhere more secure. I went with our locked down kubernetes manifest.

- name: "CORECLR_ENABLE_PROFILING"  
  value: "1"  
- name: "CORECLR_PROFILER"  
  value: "{36032161-FFC0-4B61-B559-F6C5D41BAE5A}"
- name: "CORECLR_NEWRELIC_HOME"  
  value: "/app/newrelic"    
- name: "CORECLR_PROFILER_PATH"  
  value: "/app/newrelic/libNewRelicProfiler.so"  
- name: "NEW_RELIC_LICENSE_KEY"  
  value: "{YOUR KEY HERE}"  
- name: "NEW_RELIC_APP_NAME"  
  value: "{YOUR API NAME HERE}"

Worth noting I got these variables from here and here.

Dockerfile

Copy the newrelic.config file into your final docker image

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine3.11 AS build
   WORKDIR /src
   ...
   # this is here just for context
   RUN dotnet build -c Release --no-restore
   RUN dotnet publish ./Your.Api/Your.Api.csproj -c Release -o  /app/publish --no-restore --no-build

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine3.11 AS final
   WORKDIR /app
   ...
   # this is the line you need to include!
   COPY ./newrelic.config .
   COPY --from=build /app/publish .
   ...

Ignore Requests In Code

If you need to ignore certain requests, such as calls to your /status endpoint that are perhaps being made by monitoring software, you can just add this to your controller method:

[HttpGet]
public StatusCodeResult Get()
{
   NewRelic.Api.Agent.NewRelic.IgnoreTransaction();
   return Ok();
}

Popular posts from this blog

Taking a memory dump of a w3wp process

GitLab Badges

sp_blitzIndex