在我的SignalR中心中,我应该在哪里调用NewRelic.Api.Agent.NewRelic.IgnoreApdex()
或 NewRelic.Api.Agent.NewRelic.IgnoreTransaction()
来防止长时间持久连接掩盖我的应用程序监视日志?
在我的SignalR中心中,我应该在哪里调用NewRelic.Api.Agent.NewRelic.IgnoreApdex()
或 NewRelic.Api.Agent.NewRelic.IgnoreTransaction()
来防止长时间持久连接掩盖我的应用程序监视日志?
继续Micah的回答,这是用于忽略所有SignalR调用的自定义仪表文件。
请将其创建到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>
记得要执行 iisreset 命令。
哦,好问题,我自己还没有考虑过这个问题。我认为你需要编写一个自定义模块,因为模块在所有处理程序之前执行,可以检测到SignalR AspNetHandler处理程序是否被请求,并在这一点上调用NewRelic IgnoreXXX方法。
只是随意猜测(例如,我没有测试过),该模块可能如下所示:
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()
{
}
}
<configuration>
<system.webServer>
<modules>
<add name="SignalRNewRelicIgnoreHttpModule" type="WhateverNamespace.SignalRNewRelicIgnoreHttpModule, WhateverAssemblyName" />
</modules>
</system.webServer>
</configuration>
IIS经典模式:
<configuration>
<system.web>
<httpModules>
<add name="SignalRNewRelicIgnoreHttpModule" type="WhateverNamespace.SignalRNewRelicIgnoreHttpModule, WhateverAssemblyName" />
</httpModules>
</system.web>
</configuration>
正如@dfowler在评论中警告的那样,SignalR已经改变了其托管方式,现在依赖于基于Owin的托管。这很好,因为它将SignalR直接与ASP.NET/IIS解耦,但这意味着上述方法显然不再适用。相反,您需要确保使用像下面示例模块(在此处的gist中也可用)配置Owin管道以禁用管道跟踪:
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);
}
}
然后,在你的Startup::Configuration方法中,确保在映射任何SignalR连接/中心之前将此模块添加到IAppBuilder
。应该看起来像这样:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use(typeof(NewRelicIgnoreTransactionOwinModule));
app.MapHubs();
}
}
最后,需要注意的是,目前这种方法非常简单,它假定您在应用程序范围内不会有任何其他的Owin请求。如果您正在将SignalR混合到另一个具有其他Owin请求的Web应用程序中,则该特定模块实现也会忽略这些请求,因此可能需要更高级的模块,例如检查传入请求是否实际针对SignalR URL。目前,我将其留给读者自行解决。
你可以使用IgnoreTransactionTracerFactory通过自定义仪器忽略一个事务。当你不想添加API到你的项目中或者你想忽略一个你无法更改的框架方法时,这特别有用。
你的自定义仪表文件应该如下所示:
<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
<instrumentation>
<tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.IgnoreTransactionTracerFactory">
<match assemblyName="System.Web.Extensions" className="System.Web.Handlers.ScriptResourceHandler">
<exactMethodMatcher methodName="Throw404" />
</match>
</tracerFactory>
</instrumentation>
</extension>
如果你能找到一个在请求线程上总是被调用的SignalR框架方法(你只能在请求线程上调用IgnoreTransaction,而不能在异步线程上进行调用),你可以在上面填写assemblyName/className/methodName,这与在该方法内部调用IgnoreTransaction API相同。
整个问题似乎是由SignalR控制器上的"connect"方法引起的。我创建了一个hub管道模块,通过覆盖OnBeforeConnect方法来忽略NewRelic记录。
在您的Web应用程序的Application_Start()方法(global.asax.cs)中的maphubs调用之后的某个位置添加以下内容:
GlobalHost.HubPipeline.AddModule(new IgnoreNewRelicConnectionsModule());
接下来创建这个类:
private class IgnoreNewRelicConnectionsModule : HubPipelineModule
{
protected override bool OnBeforeConnect(IHub hub)
{
NewRelic.Api.Agent.NewRelic.IgnoreTransaction();
return base.OnBeforeConnect(hub);
}
}
<?xml version="1.0" encoding="utf-8"?>
<extension xmlns="urn:newrelic-extension">
<instrumentation>
<tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.IgnoreTransactionTracerFactory">
<match assemblyName="Microsoft.AspNet.SignalR.Core" className="Microsoft.AspNet.SignalR.PersistentConnection">
<exactMethodMatcher methodName="AuthorizeRequest"/>
</match>
<match assemblyName="Microsoft.AspNet.SignalR.Core" className="Microsoft.AspNet.SignalR.Hubs.HubDispatcher">
<exactMethodMatcher methodName="AuthorizeRequest"/>
</match>
</tracerFactory>
</instrumentation>
</extension>
对于使用旧版SignalR的人,这里是xml仪表板
<tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.IgnoreTransactionTracerFactory">
<match assemblyName="SignalR.Hosting.AspNet" className="SignalR.Hosting.AspNet.AspNetHandler">
<exactMethodMatcher methodName="ProcessRequestAsync"/>
</match>
</tracerFactory>
我无法忽略带有NewRelic扩展XML文件的ASP.NET Core SignalR请求。 因此,受@Pali答案的启发,这个中间件适用于ASP.NET Core SignalR:
public class IgnoreSignalrNewRelicMiddleware
{
private readonly RequestDelegate _next;
public IgnoreSignalrNewRelicMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
//This will block all signalr request, but we can configure according to requirements
if (httpContext.Request.Path.Value?.Contains("/signalr") ?? false)
{
// Tell NewRelic to ignore this particular transaction
NewRelic.Api.Agent.NewRelic.IgnoreTransaction();
NewRelic.Api.Agent.NewRelic.IgnoreApdex();
}
// Call the pipeline ...
await _next(httpContext);
}
}
public Task Invoke(IDictionary<string, object> environment)
{
object value = "";
//Check if the OWIN key is present
if (environment.ContainsKey("owin.RequestPath"))
{
//Get the value of the key
environment.TryGetValue("owin.RequestPath", out value);
//This will block all signalr request, but we can configure according to requirements
if (value.ToString().Contains("/signalr"))
{
// Tell NewRelic to ignore this particular transaction
NewRelic.Api.Agent.NewRelic.IgnoreTransaction();
NewRelic.Api.Agent.NewRelic.IgnoreApdex();
}
}
return _nextAppFunc(environment);
}
newrelic\extension
并在其中添加 IgnoreSignalR.xml。如果您找不到该门户,则表示您尚未在此 Web 应用程序中设置 New Relic。我发现最简单的解决方案是安装 New Relic Azure Site Extension https://www.siteextensions.net/packages/NewRelic.Azure.WebSites/。 - Korayem