依赖关系在大型应用程序中实现EventSource以进行语义记录

时间:2014-10-12 18:30:04

标签: .net etw etw-eventsource

我正在开发一个包含三个Windows服务和几个普通Windows应用程序(.exe)的大型产品。现在我们要转向ETW和语义记录,并使用Microsoft.Diagnostics.Tracing.EventSource。

我在某处读到应用程序的所有逻辑连接部分都应使用相同的事件源。这意味着我们希望为我们的服务提供几乎一个EventSource。但是,如果不在产品中的几乎所有组件中引入依赖关系,我们怎么做呢?

该应用程序目前包含大约70个程序集。并且为了能够在EventSource中创建一个log-method(例如接受枚举值),包含事件源的程序集必须引用定义枚举的程序集,这意味着需要将枚举定义从使用它的程序集,或者.exe可能是所有程序集引用的东西。

是否有某种方法可以在一个仍然使用相同ETW EventSource的应用程序中从EventSource派生几个类?或者,如果不希望引入一大堆新的依赖项来创建日志类,那么在这样的场景中使用ETW实现语义日志记录的好方法是什么?

3 个答案:

答案 0 :(得分:0)

有三种策略:

  1. 创建一个仅包含EventSource派生类的程序集,该类定义所有应用程序的事件。将该程序集的引用添加到所有必需项目。为简单起见,您可以将其包装到nuget包中。
  2. 使用一个EventSource派生类创建一个测试项目。仅用于验证目的。将此类复制到所有必需的项目。这基本上是相同的解决方案,但没有二进制依赖。
  3. 为每个项目创建新的EventSource派生类,但为它们指定相同的Guid属性。在这种情况下,您需要确保所有这些事件源具有相同的重叠(具有相同ID)事件的声明。在这种情况下,您必须编写一些清单合并工具来生成组合清单。

答案 1 :(得分:0)

小心,EventSource课程必须密封! 如果您想使用EventSource使用依赖注入,则有一种解决方法......

定义一个简单的界面:

// A simple interface to log what you need ...
public interface ILog
{
    void Debug(string message);

    void Info(string message);

    void Warn(string message);

    void Error(string message);

    void Error(string message, Exception exception);
}

实现(接口的实现必须使用NonEventAttribute

进行修饰
[EventSource(Name = "MyLogEventsource")]
public class Log : EventSource, ILog
{
    public Log()
    {
        EventSourceAnalyzer.InspectAll(this);
    }

    [NonEvent]
    public void Debug(string message)
    {
        DebugInternal(message);
    }

    [Event(1)]
    private void DebugInternal(string message)
    {
        WriteEvent(1, message);
    }

    [NonEvent]
    public void Info(string message)
    {
        InfoInternal(message);
    }

    [Event(2)]
    private void InfoInternal(string message)
    {
        WriteEvent(2, message);
    }

    [NonEvent]
    public void Warn(string message)
    {
        WarnInternal(message);
    }

    [Event(3)]
    private void WarnInternal(string message)
    {
        WriteEvent(3, message);
    }

    [NonEvent]
    public void Error(string message)
    {
        ErrorInternal(message, "", "");
    }

    [NonEvent]
    public void Error(string message, Exception exception)
    {
        ErrorInternal(message, exception.Message, exception.ToString());
    }

    [Event(4)]
    private void ErrorInternal(string message, string exceptionMessage, string exceptionDetails)
    {
        WriteEvent(4, message, exceptionMessage, exceptionDetails);
    }
}

您现在可以注入您的日志记录类^^

答案 2 :(得分:0)

我通常这样做,即使它们使用事件源的单个实例,也存在接口隔离。在我的ioc中,所有使用ISingletonDependency的代码都注册为singleton。因此,您可以使用非常具体的方法调用接口,但它们仍然是相同的EventSource。

希望这有帮助。

public MyCompanyEventSource: IMyCompanyEventSource, ISingletonDependency{
}
public IMyCompanyEventSource: IComponentLogger1, IComponentLogger2, IComponentLogger3{
}
public Component1{
       public Component1(IComponentLogger logger){
       }
    }