忽略New Relic中持久的SignalR连接

29

在我的SignalR中心中,我应该在哪里调用NewRelic.Api.Agent.NewRelic.IgnoreApdex()NewRelic.Api.Agent.NewRelic.IgnoreTransaction() 来防止长时间持久连接掩盖我的应用程序监视日志?

New Relic截图,显示SignalR主导监视

8个回答

16

继续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 命令。


确认。谢谢Juho! - Jason Kealey
1
这个文件应该叫什么名字才能完整呢? - Arthur Stankevich
1
@ArthurStankevich 你可以随意命名它。只需确保以 .xml 结尾即可。请参阅 New Relic 文档 - AntonR
有没有任何想法可以使其与Azure网站一起工作,因为我们无法访问文件系统? - Cam Langsford
@CamLangsford 很简单。从 Azure 门户打开 Web 应用程序,然后查找“应用服务编辑器”,它将打开您的整个代码库,准备进行编辑。现在浏览到 newrelic\extension 并在其中添加 IgnoreSignalR.xml。如果您找不到该门户,则表示您尚未在此 Web 应用程序中设置 New Relic。我发现最简单的解决方案是安装 New Relic Azure Site Extension https://www.siteextensions.net/packages/NewRelic.Azure.WebSites/。 - Korayem

9

哦,好问题,我自己还没有考虑过这个问题。我认为你需要编写一个自定义模块,因为模块在所有处理程序之前执行,可以检测到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()
    {

    }
}

显然,您需要在配置文件中注册该模块,方法如下:
IIS 集成模式:
<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>

更新:2013年6月25日

正如@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。目前,我将其留给读者自行解决。


它完美地运行了。我只是在通过web.config在我的开发服务器上运行HttpModule时遇到了一些麻烦,所以我使用WebActivator添加了一个PreStart事件来显式加载它。 - Petrus Theron
1
下一个版本中这样做效果不好,因为处理程序会更改。总的来说,依赖于诸如此类的内部细节是不好的 :) - davidfowl
3
考虑到这一点,是否会有一个可扩展的点来达到这个级别?我应该在GitHub上提交一个问题吗? - Drew Marsh
更新后的解决方案忽略了所有NewRelic事务。找到了一个链接(http://darrenkopp.com/posts/2014/05/07/Ignoring-SignalR-in-NewRelic/),只排除了SignalR。 - pexxxy
2
看起来@pexxxy发布的链接有一个斜杠,GitHub不喜欢。正确的链接是:http://darrenkopp.com/posts/2014/05/07/Ignoring-SignalR-in-NewRelic - Darren Kopp
显示剩余2条评论

8

你可以使用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相同。


这样会更好,无需重新部署。 - Ryan

5

整个问题似乎是由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);
    }

}

1
嗯,不,我会阻止所有的SignalR流量。 - davidfowl

1
在SignalR.Core 2.2.2中,有两种AuthorizeRequest方法。因此,New Relic的仪表文件应该如下所示:
<?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>

将此文件放置在“C:\ ProgramData \ New Relic.NET Agent \ Extensions”中可以解决问题。

1

对于使用旧版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>

如何在我的 Web 应用程序中检查 SignalR 版本? - Somnath Kadam

0

我无法忽略带有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);
    }
}

0
    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);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接