在EventSource中使用System.Exception对象

Bri*_*ney 3 .net c# event-flow etw-eventsource azure-application-insights

我正在尝试使用事件源(Microsoft.Diagnostics.EventFlow.Inputs.EventSource)来创建由事件流(Microsoft.Diagnostic.EventFlow)处理的事件,并将其输出传递给Application Insights(Microsoft.Diagnostics.EventFlow) .Outputs.ApplicationInsights)进行分析.

事件流库似乎要求我将完整的System.Exception对象传递给事件流,以便在Application Insights中将其成功分类为异常事件.

这是我在事件流程中使用的过滤器,用于我的异常:

    {
      "type": "metadata",
      "metadata": "exception",
      "include": "EventId == 21",
      "exceptionProperty": "shark"
    }
Run Code Online (Sandbox Code Playgroud)

这是我的方法,我目前正在生成我希望处理事件流的事件.目前这确实出现在应用程序见解中,但我相信我已经很难实现它,因为我在运行时在输出窗口中看到下面的消息.

Event方法的参数与WriteEvent方法的参数不匹配.这可能导致事件显示不正确.

    private const int TestExceptionEventId = 21;
    [NonEvent]
    public void TestException(string operationType, Exception ex)
    {
        string shark = ex.ToString();
        TestException(operationType, shark);
        WriteEvent(TestExceptionEventId, operationType, ex);
    }

    [Event(TestExceptionEventId, Level = EventLevel.Error, Message = "{0} - {1}, {2}", Keywords = Keywords.Exception)]
    public void TestException(string operationType, string shark)
    {

    }
Run Code Online (Sandbox Code Playgroud)

以下是触发日志记录事件的方法:

 //EXCEPTION
 //id = 21
 try
 {
     int value = 1 / int.Parse("0");
 }
 catch (DivideByZeroException exception)
 {
     //id = 21
     _eventSource.TestException("hello", exception);
 }`
Run Code Online (Sandbox Code Playgroud)

任何人都可以清楚地了解实现此方法的正确方法,以及通过Event Flow和Onto Application Insights传递System.Exception对象的正确方法.

非常感谢.

Pet*_*ons 6

这里有两个不同的问题.一个是你得到的错误,另一个是异常元数据的EventFlow配置.我会解决两个问题.

错误

使用该[Event]属性修饰的方法是应该调用的方法WriteEvent.例如:

private const int TestExceptionEventId = 21;

[NonEvent]
public void TestException(string operationType, Exception ex)
{
    string shark = ex.ToString();
    TestException(operationType, shark);
}

[Event(TestExceptionEventId, Level = EventLevel.Error, Message = "{0} - {1}", Keywords = Keywords.Exception)]
public void TestException(string operationType, string shark)
{
    WriteEvent(TestExceptionEventId, operationType, shark);
}
Run Code Online (Sandbox Code Playgroud)

注意:您的原始Message属性具有该值Message = "{0} - {1}, {2}",但您只为该方法提供了2个参数(字符串operationType和string shark).因此错误.这就是我改成它的原因Message = "{0} - {1}"

有一些特定的规则,以使其工作.来自文档:

实现在EventSource派生类中标识为ETW事件的方法时.您必须调用基类WriteEvent方法传递EventId和与实现的方法相同的参数

EventFlow配置

这是最大的问题.本EventSource类不允许你写使用非原语WriteEvent.那包括一个Exception.来自文档:

如果事件具有其他数据,则应将这些数据作为参数传递.目前,只允许使用事件记录基本类型,DateTime和字符串.

GitHub回购中存在一个问题,概述了您的可能性:

我想你有几个选择.

一种是使用EventSource.Write方法https://msdn.microsoft.com/en-us/library/system.diagnostics.tracing.eventsource.write(v=vs.110).aspx如果你使用它应该很好用.NET Core,虽然我会诚实 - 我还没有测试过它.不幸的是,对于完整框架,框架中存在一个错误,阻止EventFlow正确读取事件级别,因此如果您使用完整(桌面)框架,则不建议使用此方法.

第二个选项是使用不同的日志库(例如Serilog),它允许您将任意对象传递到EventFlow.

另一种选择是使用自定义EventFlow输入.这应该不像AI的自定义输出那么麻烦.我想你甚至可以将它与你的EventSource集成,例如通过使EventSource实现IObservable并使用[NonEvent]方法来引发携带异常对象的事件.这样,您将只有一个日志API,即您的EventSource,供应用程序使用.

我的2美分

我的建议(我最终这样做):忘记EventSource并使用另一个日志库.使用EventSource最好的部分是它具有结构化日志记录.我最终使用了具有此功能的SeriLog.它支持将非原始类型写入日志.EventFlow也支持 SeriLog作为输入,或者您可以为SeriLog 配置Application Insights(AI)接收器,将数据发送到Application Insights.

如果您决定选择该选项,可以查看我的实现