使用ETW / EventSource Library为事件查看器指定不同的eventID和任务类别值

时间:2014-06-18 18:23:16

标签: .net etw

我们正在使用Microsoft EventSource Library(1.0.24)的NuGet pacakge来记录事件查看器的事件。

根据以下方法定义(例如,从EventSource继承的类),生成的事件查看器条目将显示,其中填充的任务类别字段由Task = XYZ参数指定:

public sealed class EventLogEventSource : EventSource
{
    static public EventLogEventSource Log = new EventLogEventSource();

    ...  
    [Event( 1, Keywords = Keywords.Debug, Message = "Custom Message={0}",
        Channel = EventChannel.Admin, Task = Tasks.CustomCategory1, Opcode = EventOpcode.Extension )]
    public void CustomEvent1( string strMessage ) { WriteEvent( 1, strMessage ); }

    [Event( 2, Keywords = Keywords.Debug, Message = "Custom Message={0}",
        Channel = EventChannel.Admin, Task = Tasks.CustomCategory2, Opcode = EventOpcode.Extension )]
    public void CustomEvent2( string strMessage ) { WriteEvent( 2, strMessage ); 
    ...  
}  

public class Tasks
{
    public const EventTask CustomCategory1 = (EventTask)0x1;
    public const EventTask CustomCategory2 = (EventTask)0x2;
}  

...  
EventLogEventSource.Log.CustomEvent1( "test1" );
EventLogEventSource.Log.CustomEvent2( "test2" );
...  

该框架允许人们非常容易地以声明方式定义要包含在每个记录条目中的所有相关细节。

虽然这很有效,但我们还希望能够在写入同一类别下的事件日志时更改eventID值。例如,早期的.Net编写事件日志(EventLog Class)的化身提供了一个更灵活的界面来控制eventID和任务类别:

public void WriteEntry( message, EventLogEntryType type, int eventID, short category )  

在ETW / EventSource中是否有类似的内容可以写入事件日志,并且能够为同一类别指定EventID值?

作为我们尝试实现的目标的示例,以下是针对相同任务类别(服务器)的具有不同事件ID的记录事件的快照:

enter image description here

1 个答案:

答案 0 :(得分:1)

能够在运行时为同一任务类别指定不同的事件ID值的关键是声明自定义EventOpcode值。然后,可以将这些不同的操作码映射到相同EventTask属性值的方法声明。

如Microsoft.Diagnostics.Tracing.EventOpcode枚举中所示,自定义值必须介于11到239之间

例如,这里是如何声明自定义操作码:

public class Opcodes
{
    public const EventOpcode Test111 = (EventOpcode)0x0b;
    public const EventOpcode Test555 = (EventOpcode)0x0c;
    public const EventOpcode TestGeneric = (EventOpcode)0x0d;
}  

现在,使用原始帖子中的示例方法声明,以下是同一任务的其他方法:

[Event( 111, Keywords = Keywords.Debug, Message = "Custom Message={0}",
    Channel = EventChannel.Admin, Task = Tasks.CustomCategory1, Opcode = Opcodes.Test111 )]
public void CustomEvent3( string strMessage ) { WriteEvent( 1111, strMessage ); }  

[Event( 555, Keywords = Keywords.Debug, Message = "Custom Message={0}",
    Channel = EventChannel.Admin, Task = Tasks.CustomCategory1, Opcode = Opcodes.Test555 )]
public void CustomEvent4( string strMessage ) { WriteEvent( 555, strMessage ); }  

[Event( 999, Keywords = Keywords.Debug, Message = "Custom Message={0}",
    Channel = EventChannel.Admin, Task = Tasks.CustomCategory1, Opcode = Opcodes.TestGeneric )]
public void CustomEventGeneric( int eventID, string strMessage ) { WriteEvent( eventID, strMessage ); }  

为了使用在运行时选择的eventID值写入事件日志,可以使用CustomEventGeneric():

EventLogEventSource.Log.CustomEventGeneric( 1, "test for EventID=1" );
EventLogEventSource.Log.CustomEventGeneric( 2, "test for EventID=2" );
EventLogEventSource.Log.CustomEventGeneric( 111, "test for EventID=111" );
EventLogEventSource.Log.CustomEventGeneric( 555, "test for EventID=555" );

重要的是要意识到第一个参数值必须都在EventLogEventSource类的先前定义的事件方法的集合中。换句话说,以下调用将导致运行时异常:

EventLogEventSource.Log.CustomEventGeneric( 123, "test for EventID=123" );  // EventID=123 is NOT DEFINED!  


总结一下:

  • 必须事先知道需要支持的所有EventID值。
  • 任务/操作码对在声明事件方法时必须是唯一的。
  • 必须有尽可能多的事件方法声明,因为支持任务/操作码值的组合。