Where should I call NewRelic.Api.Agent.NewRelic.IgnoreApdex()
or NewRelic.Api.Agent.NewRelic.IgnoreTransaction()
in my SignalR hubs to prevent long-running persistent connections from overshadowing my application monitoring logs?
To continue with Micah's answer, here is the custom instrumentation file for ignoring all signalr calls.
Create it to C:\ProgramData\New Relic.NET Agent\Extensions\IgnoreSignalR.xml
<?xml version="1.0" encoding="utf-8"?> <extension xmlns="urn:newrelic-extension"> <instrumentation> <!-- Optional for basic traces. --> <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.IgnoreTransactionTracerFactory"> <match assemblyName="Microsoft.AspNet.SignalR.Core" className="Microsoft.AspNet.SignalR.PersistentConnection"> <exactMethodMatcher methodName="ProcessRequest"/> </match> </tracerFactory> </instrumentation> </extension>
Remember to do iisreset.
Oooh, great question and one I hadn't thought about yet myself. I think what you would have to do is write a custom module, since modules execute before all handlers, that detect that the SignalR AspNetHandler handler is the one being requested and, if so, call the NewRelic IgnoreXXX methods at that point.
Just spitballing (e.g. I haven't tested this) that module might look something like this:
public class SignalRNewRelicIgnoreHttpModule : IHttpModule { public void Init(HttpApplication context) { context.PostMapRequestHandler += (s, a) => { if(HttpContext.Current.Handler is SignalR.Hosting.AspNet.AspNetHandler) { NewRelic.Api.Agent.NewRelic.IgnoreTransaction(); } }; } public void Dispose() { } }
Then (obviously?) you need to register that module in config like so...
IIS Integrated mode:
<configuration> <system.webServer> <modules> <add name="SignalRNewRelicIgnoreHttpModule" type="WhateverNamespace.SignalRNewRelicIgnoreHttpModule, WhateverAssemblyName" /> </modules> </system.webServer> </configuration>
IIS Classic mode:
<configuration> <system.web> <httpModules> <add name="SignalRNewRelicIgnoreHttpModule" type="WhateverNamespace.SignalRNewRelicIgnoreHttpModule, WhateverAssemblyName" /> </httpModules> </system.web> </configuration>
As warned by @dfowler in the comments, SignalR has since changed its approach to hosting and instead now relies on Owin based hosting instead. This is great because it decouples SignalR directly from ASP.NET/IIS, but that means the above approach obviously won't work anymore. Instead what you would need to do is to make sure to configure the Owin pipeline with a module like the sample one below (available here in a gist as well) to disable tracing for the pipeline:
public class NewRelicIgnoreTransactionOwinModule { private AppFunc _nextAppFunc; public NewRelicIgnoreTransactionOwinModule(AppFunc nextAppFunc) { _nextAppFunc = nextAppFunc; } public Task Invoke(IDictionary<string, object> environment) { // Tell NewRelic to ignore this particular transaction NewRelic.Api.Agent.NewRelic.IgnoreTransaction(); return _nextAppFunc(environment); } }
And then, in your Startup::Configuration method just make sure you add this module to the IAppBuilder
before you map any SignalR connections/hubs. That should look something like this:
public class Startup { public void Configuration(IAppBuilder app) { app.Use(typeof(NewRelicIgnoreTransactionOwinModule)); app.MapHubs(); } }
Finally, it should be noted that, right now this takes a very simplistic approach that assumes you're not going to have any other Owin requests in your application scope. If you're mixing SignalR into another web app that has other Owin requests this particular module implementation would cause those to be ignored as well, so a more advanced module that maybe checks that the incoming request is actually targeting a SignalR URL would be required. For now, I leave that up to the reader to figure out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With