是否可以使用New Relic来监控Azure功能应用程序?

时间:2017-01-31 23:41:38

标签: azure newrelic azure-functions

我们有一个每几秒运行一次的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,我看到一张包含大量记录的表格,表示&#34;成功!&#34;在计数列中使用随机数。
  • 在APM-&gt;事件 - &gt;错误中,我看到一个&#34;网址并输入&#34; &#34; NewRelic.Api.Agent.NoticeError API调用 提交#0 + SyncException&#34;使用消息&#34;这是另一个自定义错误&#34;和计数。
  • 在错误分析中,我看到了#34;太棒了!这个时间窗口没有错误!&#34; (最后30分钟)
  • 在Monitoring-&gt;事务中,我只看到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 Application Monitoring,以便在出现某种异常类型(例如我的SyncException类)或达到特定阈值时提醒我?

谢谢!

更新

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

<?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 Docs说:

  

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

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

enter image description here

然而,我的New Relic界面并没有任何类型的&#34; Type&#34;下拉:

enter image description here

另外,如果我检测我的代码以显示功能应用程序中的堆栈跟踪,这就是我得到的。也许它会帮助:

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");

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

  

2017-02-01 21:45:25,005 NewRelic警告:代理API错误:错误   调用API方法&#34; SetTransactionName&#34; -   &#34; System.InvalidOperationException:调用的API方法仅有效   在交易中。如果调用API,则会发生此错误   来自除交易开始之外的线程的方法。

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

其他想法?

2 个答案:

答案 0 :(得分:2)

您应该为自定义交易提供一个镜头:

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

以下是我认为适用的值:

  1. AssemblyName:Microsoft.Azure.WebJobs.Script
  2. ClassName:Microsoft.Azure.WebJobs.Script.Description.FunctionInvokerBase
  3. MethodName:InvokeCore
  4. 我相信会在this method call上添加一个事务,这是所有用户函数执行的通用包装。

答案 1 :(得分: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配置(包括Extensions XML文件)进行更改时,您必须重置IIS。但是,SCM上的“重新启动站点”按钮实际上并不 kill IIS进程。您必须进入Kudu的Process Explorer并关闭w3wp.exe进程。如果您无法确定要杀死的进程,可以将log.Info($"Currently running in PID: {System.Diagnostics.Process.GetCurrentProcess().Id}");添加到功能应用程序中以查找。

  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中的错误错误分析中。缺点是您可能需要重构一堆Azure功能代码以捕获所有错误,注意它们,然后在必要时重新抛出它们。

  4. 我花了两天时间才开始工作,所以我希望这可以帮助别人!!