【问题标题】:Is it possible to use New Relic to monitor Azure Function app?是否可以使用 New Relic 来监控 Azure Function 应用程序?
【发布时间】:2017-06-17 14:17:27
【问题描述】:

我们有一个每隔几秒运行一次的 Azure 函数。我们想使用 New Relic 让我们知道此代码是否引发异常或开始出现异常。我已经在 VM 上安装了 New Relic 代理,并通过 NuGet 引入了 NewRelic.Agent.Api DLL。我已将 NewRelic.AppName 设置为 AzureFunctionAppTest 并设置 NEWRELIC_LICENSEKEY 环境变量。日志文件表明我正在连接到 NewRelic。现在,我正在运行以下代码:

#r "Microsoft.windowsazure.storage"

using System;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Storage.Table;

public static void Run(TimerInfo myTimer, TraceWriter log, CloudTable syncTimesTable)
{
    NewRelic.Api.Agent.NewRelic.SetTransactionName("SyncEvents", "GetRoutineData");

    var rnd = new Random(DateTime.Now.Millisecond).Next(30);
    log.Info($"Logging {rnd}");

    var eventAttributes = new Dictionary<string, object>() {{"result", "Success!"}, {"Count", rnd.ToString()}};
    NewRelic.Api.Agent.NewRelic.RecordCustomEvent("DevicesSynced", eventAttributes);

    NewRelic.Api.Agent.NewRelic.NoticeError(new SyncException("This is another custom error"));
}

public class SyncException : Exception
{
    public SyncException(string msg) : base(msg)
    {
    }
}

所以,基本上我是在尝试设置事务名称,然后生成一个随机数并将其记录为自定义事件,然后尝试记录自定义错误。

我让它运行了一会儿,然后使用 New Relic 仪表板签入。这是我得到的:

  • 我看到我的新应用程序出现在 APM 仪表板上。
  • 在 Insights Dashboard 上,我可以查询 SELECT * FROM DevicesSynced SINCE 30 MINUTES AGO,然后我看到一个表格,其中包含一堆“成功!”的记录。计数列中有一个随机数。
  • 在 APM->Events->Errors 中,我看到“NewRelic.Api.Agent.NoticeError API 调用”的“URL 和类型” Submission#0+SyncException”以及消息“这是另一个自定义错误”和计数。
  • 在错误分析中,我看到“太好了!您在此时间窗口内没有错误!” (最后 30 分钟)
  • 在 Monitoring->Transactions 中,我只看到 HTTP 请求的事务,例如 /Home/Get、/Admin/GetHostStatus、/Keys/Get 和 /Admin/GetFunctionStatus。我认为这些 HTTP 请求来自 Azure Functions 的内部工作,并且可能在我在 Azure 控制台中单击时发生。我没有看到任何称为 GetRoutineData 的事务。如果我运行SELECT * FROM Transactions 我也看不到这个。

我有一种感觉,我实际上在我的 Azure 函数代码中的事务中,所以 New Relic 不允许我设置名称。我也有一种感觉,即使我使用 NoticeError 记录了一个错误,它也不会链接到任何事务,因此它不会显示在错误分析中。

我的问题:

  • 有没有办法让 New Relic 将此代码路径识别为事务?
  • 如果没有,是否至少有一种方法可以设置 New Relic 应用程序监控,以便在发生某种异常类型(例如我的 SyncException 类)或达到某个阈值时提醒我?

谢谢!

更新:

我尝试在Extensions 目录中添加一个名为CustomInstrumentation.xml 的文件,按照New Relic instructions 包含以下内容:

<?xml version="1.0" encoding="utf-8"?>
<extension
    xmlns="urn:newrelic-extension">
    <instrumentation>
        <!-- Define the method which triggers the creation of a transaction. -->
        <tracerFactory name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory" metricName="Background/AzureDeviceSync">
            <match assemblyName="Microsoft.Azure.WebJobs.Script" className="Microsoft.Azure.WebJobs.Script.Description.FunctionInvokerBase">
                <exactMethodMatcher methodName="Invoke" />
            </match>
        </tracerFactory>
    </instrumentation>
</extension>

但是,我看不出行为上有什么不同。我尝试了几种不同的方法名称匹配(例如InvokeCoreInvoke),但似乎没有什么不同。

几个问题:

新遗物文档说:

查看交易:从 New Relic 菜单栏中,选择 APM > 应用程序>(选定的应用程序)>监控>事务>类型> (选定类型)。 (类型由类别/名称定义。)然后您可以 查看所选类型的所有自定义交易。

它显示带有自定义选项的下拉菜单图片:

但是,我的 New Relic 界面没有任何类型的“类型”下拉菜单:

此外,如果我检测我的代码以从 Function 应用程序中显示堆栈跟踪,这就是我得到的结果。也许会有所帮助:

Stack:

   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at Submission#0.Run(TimerInfo myTimer, TraceWriter log, CloudTable syncTimesTable) in :line 9
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.Azure.WebJobs.Script.Description.DotNetFunctionInvoker.<InvokeCore>d__23.MoveNext()
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[TStateMachine](TStateMachine& stateMachine)
   at Microsoft.Azure.WebJobs.Script.Description.DotNetFunctionInvoker.InvokeCore(Object[] parameters, FunctionInvocationContext context)
   at Microsoft.Azure.WebJobs.Script.Description.FunctionInvokerBase.<Invoke>d__29.MoveNext()
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[TStateMachine](TStateMachine& stateMachine)
   at Microsoft.Azure.WebJobs.Script.Description.FunctionInvokerBase.Invoke(Object[] parameters)
   at Host.Functions.LogNewRelicAlert(TimerInfo myTimer, TraceWriter log, CloudTable syncTimesTable, ExecutionContext _context)
   at lambda_method(Closure , Functions , Object[] )
   at Microsoft.Azure.WebJobs.Host.Executors.TaskMethodInvoker`1.InvokeAsync(TReflected instance, Object[] arguments)
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`1.<InvokeAsync>d__8.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.InvokeMoveNext(Object stateMachine)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()
   at System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.RunAction(Object state)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

我想知道是否有任何类型的日志文件显示自定义事务设置是否确实已加载以及何时创建新事务。现在我猜我的 XML 匹配错误。

还有一件事。如果我添加该行:

NewRelic.Api.Agent.NewRelic.SetTransactionName("Custom", "Testing");

在我的 Function 应用中,我会在 New Relic 日志中看到以下警告:

2017-02-01 21:45:25,005 NewRelic 警告:代理 API 错误:错误 发生调用 API 方法“SetTransactionName” - “System.InvalidOperationException:调用的API方法只有效 从交易中。如果调用 API 会出现此错误 来自事务开始的线程以外的线程的方法。

我认为这清楚地表明我们此时实际上并未处于事务中,除非它发生在另一个线程上(如果是这种情况,我不会感到惊讶)。

其他想法?

【问题讨论】:

  • 这似乎是您要查找的日志:discuss.newrelic.com/t/… 您可以在 .scm.azurewebsites.net/DebugConsole 访问您的函数的文件系统
  • @MattMason-MSFT - 现在看起来我添加到 XML 文件中的工具可以正常工作,并且指标正在发送到 New Relic。但是,它不会在 New Relic 仪表板中显示为事务。我不确定是否应该这样做。我想我需要一位 New Relic 工程师来帮助我,因为我认为一切都设置正确。
  • @MattMason-MSFT - 成功了!好吧,反正90%。我希望异常跟踪也能正常工作,但我可以使用 NoticeError 手动完成。我在下面添加了我发现的内容。再次感谢您的帮助!

标签: azure newrelic azure-functions


【解决方案1】:

您应该试一试自定义交易:

https://docs.newrelic.com/docs/agents/net-agent/instrumentation/net-custom-transactions

以下是我认为适用的值:

  1. 程序集名称:Microsoft.Azure.WebJobs.Script
  2. 类名:Microsoft.Azure.WebJobs.Script.Description.FunctionInvokerBase
  3. 方法名:InvokeCore

我相信这会在 this method call 上添加一个事务,它是所有用户函数执行的通用包装器。

【讨论】:

  • 我会试一试,然后向您报告!谢谢!
  • 自定义交易不走运。我已经用更多信息更新了我上面的问题。非常感谢您的帮助!
【解决方案2】:

终于搞定了!好吧,至少我认为它会起作用的最好的。这是我在 /Extensions 目录中的 .XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<extension
    xmlns="urn:newrelic-extension">
    <instrumentation>
        <!-- Define the method which triggers the creation of a transaction. -->
        <tracerFactory
           name="NewRelic.Agent.Core.Tracer.Factories.BackgroundThreadTracerFactory"
           metricName="Limeade/AzureDeviceSync">
            <match assemblyName="Microsoft.Azure.WebJobs.Script" className="Microsoft.Azure.WebJobs.Script.Description.DotNetFunctionInvoker">
                <exactMethodMatcher methodName="InvokeCore" />
            </match>
        </tracerFactory>
    </instrumentation>
</extension>

不管你怎么称呼这个文件,New Relic 都会加载 Extensions 目录中的每个 XML 文件。

以下是我学到的一些东西:

  1. 当您更改任何 New Relic 配置(包括扩展 XML 文件)时,您必须重置 IIS。但是,SCM 上的“重新启动站点”按钮实际上并没有杀死 IIS 进程。您必须进入 Kudu 中的 Process Explorer 并关闭 w3wp.exe 进程。如果您无法确定要杀死哪个进程,可以将log.Info($"Currently running in PID: {System.Diagnostics.Process.GetCurrentProcess().Id}"); 添加到您的Function App 以查找。

  2. New Relic 默认会生成混淆的事务名称,例如 Microsoft.Azure.WebJobs.Script.Description.DotNetFunctionInvoker/InvokeCore。我找不到在 XML 文件中设置事务名称的方法。但是,您可以在 Azure 函数代码中设置新的事务名称,如下所示:

    NewRelic.Api.Agent.NewRelic.SetTransactionName("SyncEvents", "GetRoutineData");

  3. 如果从 Run 方法中抛出异常会在 New Relic 中将异常记录为错误,那就太好了,但经过相当多的尝试后,我无法让它工作。我认为这些异常正在某个地方被吃掉,我无法找出正确的跟踪器配置组合来在它们丢失之前拦截它们。但是,您可以使用 NoticeError() 调用: NewRelic.Api.Agent.NewRelic.NoticeError(new SyncException("This is a custom error")); 这似乎同样有效,这些错误将显示在 New Relic 的 ErrorsError analytics 中。缺点是您可能必须重构一堆 Azure Function 代码以捕获所有错误、注意它们,然后在必要时重新抛出它们。

我花了两天时间让这个工作,所以我希望这对某人有帮助!

【讨论】:

  • 我只想提一下,不能保证这些程序集类和方法名称在不同版本之间保持一致,所以这绝对是一个不受支持的场景。很高兴听到你让它工作了!
  • 是的,希望这些功能不会改变。也许 New Relic 会添加对 Azure Functions 的官方支持,并负责保持他们的检测文件是最新的。否则,也许我可以在 Azure Functions 之上编写自己的框架。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-11
  • 1970-01-01
  • 2012-07-13
相关资源
最近更新 更多