-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Nancy and New Relic
New Relic is a nice tool used to monitor applications and collect performance metrics running on pretty much any platform, including .NET. Wiring up Nancy with New Relic is a cinch!
Out of the box, the NewRelic agent traces all transactions as NancyHttpHandler
- not very useful! But with the .NET Agent API, it's possible to set an explicit identifier for each transaction logged.
First, install the corresponding NuGet package. Then, add or edit a Module
that will be the base for all your other modules:
using NewRelicAgent = NewRelic.Api.Agent.NewRelic; // protip: don't give class and namespace the same name. it's awkward.
public abstract class BaseModule : NancyModule
{
public BaseModule()
{
Before += ctx =>
{
var routeDescription = ctx.ResolvedRoute.Description;
NewRelicAgent.SetTransactionName("Custom/Endpoint", string.Format("{0} {1}", routeDescription.Method, routeDescription.Path));
return null;
};
}
}
Then you need to install New Relic's .Net agent on your system. Make sure that the architecture (32-bit or 64-bit) matches your system. Also, if you're running a non-IIS app, make sure you check the Instrument All .NET Applications
box.
Note: I added the request method because it doesn't seem to be traced by NewRelic...
Now that transactions get more usable, it's also interesting to add Nancy's internals to NewRelic's transaction timings. To achieve that, create and deploy a custom instrumentation file with the following content:
<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
<instrumentation>
<tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Custom/Endpoint">
<match assemblyName="Nancy" className="Nancy.NancyEngine">
<exactMethodMatcher methodName="HandleRequest" />
</match>
</tracerFactory>
</instrumentation>
</extension>
This file should be placed in C:\ProgramData\New Relic\.NET Agent\Extensions
.
You will now see the time spent by Nancy (and your application code) to handle the request.
If you don't want to change all of your base classes, another alternative is to hook into Nancy's module building process. To take this approach, first create a class that implements the INancyModuleBuilder
interface copying the DefaultNancyModuleBuilder
implementation as a starting point. Add a Before
handler with a method body similar to the one shown above.
using Nancy;
using Nancy.ModelBinding;
using Nancy.Routing;
using Nancy.Validation;
using Nancy.ViewEngines;
using NewRelicAgent = NewRelic.Api.Agent.NewRelic;
namespace MyServer
{
public class MyModuleBuilder : INancyModuleBuilder
{
private readonly IViewFactory viewFactory;
private readonly IResponseFormatterFactory responseFormatterFactory;
private readonly IModelBinderLocator modelBinderLocator;
private readonly IModelValidatorLocator validatorLocator;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultNancyModuleBuilder"/> class.
/// </summary>
/// <param name="viewFactory">The <see cref="IViewFactory"/> instance that should be assigned to the module.</param>
/// <param name="responseFormatterFactory">An <see cref="IResponseFormatterFactory"/> instance that should be used to create a response formatter for the module.</param>
/// <param name="modelBinderLocator">A <see cref="IModelBinderLocator"/> instance that should be assigned to the module.</param>
/// <param name="validatorLocator">A <see cref="IModelValidatorLocator"/> instance that should be assigned to the module.</param>
public MyModuleBuilder(IViewFactory viewFactory, IResponseFormatterFactory responseFormatterFactory, IModelBinderLocator modelBinderLocator, IModelValidatorLocator validatorLocator)
{
this.viewFactory = viewFactory;
this.responseFormatterFactory = responseFormatterFactory;
this.modelBinderLocator = modelBinderLocator;
this.validatorLocator = validatorLocator;
}
/// <summary>
/// Builds a fully configured <see cref="INancyModule"/> instance, based upon the provided <paramref name="module"/>.
/// </summary>
/// <param name="module">The <see cref="INancyModule"/> that should be configured.</param>
/// <param name="context">The current request context.</param>
/// <returns>A fully configured <see cref="INancyModule"/> instance.</returns>
public INancyModule BuildModule(INancyModule module, NancyContext context)
{
module.Context = context;
module.Response = this.responseFormatterFactory.Create(context);
module.ViewFactory = this.viewFactory;
module.ModelBinderLocator = this.modelBinderLocator;
module.ValidatorLocator = this.validatorLocator;
module.Before.AddItemToStartOfPipeline(ctx =>
{
var routeDescription = ctx.ResolvedRoute.Description;
NewRelicAgent.SetTransactionName(module.GetType().Name, string.Format("{0} {1}", routeDescription.Method, routeDescription.Path));
return null;
});
return module;
}
}
}
Then, in a custom bootstrapper class, tell Nancy to use your module builder instead of the default builder
public class MyBootstrapper : DefaultNancyBootstrapper
{
protected override NancyInternalConfiguration InternalConfiguration
{
get { return NancyInternalConfiguration.WithOverrides(x => x.NancyModuleBuilder = typeof(MyModuleBuilder)); }
}
}
- Introduction
- Exploring the Nancy module
- Routing
- Taking a look at the DynamicDictionary
- Async
- View Engines
- Using Models
- Managing static content
- Authentication
- Lifecycle of a Nancy Application
- Bootstrapper
- Adding a custom FavIcon
- Diagnostics
- Generating a custom error page
- Localization
- SSL Behind Proxy
- Testing your application
- The cryptography helpers
- Validation
- Hosting Nancy with ASP.NET
- Hosting Nancy with WCF
- Hosting Nancy with Azure
- Hosting Nancy with Suave.IO
- Hosting Nancy with OWIN
- Hosting Nancy with Umbraco
- Hosting Nancy with Nginx on Ubuntu
- Hosting Nancy with FastCgi
- Self Hosting Nancy
- Implementing a Host
- Accessing the client certificate when using SSL
- Running Nancy on your Raspberry Pi
- Running Nancy with ASP.NET Core 3.1