(ETW) 公共组件中的 EventSource
(ETW) EventSource in a common component
我想知道您对将 EventSource 用于常见且可在同一过程中使用几次的组件有何经验。
一个简单的例子。我的共享组件是 TestQueue,我想在我的进程中使用它几次,然后在 PerfView 中再次使用它来查看哪个事件属于哪个队列。
public class TestQueue<T>
{
private readonly IEtwQueue _etwQueue;
private readonly Queue<T> _instance = new Queue<T>();
public TestQueue(IEtwQueue etwQueue)
{
_etwQueue = etwQueue;
}
public void Enqueue(T item)
{
_instance.Enqueue(item);
_etwQueue.CommandEnqueued(_instance.Count);
}
public T Dequeue()
{
_etwQueue.CommandDequed(_instance.Count);
return _instance.Dequeue();
}
}
public interface IEtwQueue
{
void CommandEnqueued(int items);
void CommandDequed(int items);
}
[EventSource(Name = "Test-ETW-Queue")]
public class EtwQueue : EventSource, IEtwQueue
{
public static EtwQueue Log = new EtwQueue();
private EtwQueue() { }
[Event(1)]
public void CommandEnqueued(int items) { if (IsEnabled()) WriteEvent(1, items); }
[Event(2)]
public void CommandDequed(int items) { if (IsEnabled()) WriteEvent(2, items); }
}
我想这样使用它:
TestQueue<string> testStringQueue = new TestQueue<string>(EtwQueue.Log);
TestQueue<int> testIntQueue = new TestQueue<int>(EtwQueue.Log);
testIntQueue.Enqueue(15);
testStringQueue.Enqueue("X");
这是我在 PerfView 中的内容:
这两个事件没有区别。
我想知道如何识别它们,以便将某些名称(字符串)或 ID 作为事件名称的一部分计算出来?
我知道我可以使用任务对事件进行逻辑分组,但这不是我在这里所期望的,特别是因为它们必须在事件源中预定义。
Activity ID在用例中也是一样的
干杯!
比实现两个 EventSources 更好的方法是通过自定义实现的构造函数传递事件源名称。也许这就是方法:)
因此自定义事件源上没有 EventSource 属性 class 并且构造函数具有事件源名称参数:
public class EtwQueueEventSource : EventSource, IEtwQueue
{
public EtwQueueEventSource(string sourceName) : base(sourceName) { }
[Event(1)]
public void CommandEnqueued(int items) { if (IsEnabled()) WriteEvent(1, items); }
[Event(2)]
public void CommandDequed(int items) { if (IsEnabled()) WriteEvent(2, items); }
}
所以之前的用法示例变成了这样的:
TestQueue<string> testStringQueue = new TestQueue<string>(new EtwQueueEventSource("Test-ETW-Queue-String"));
TestQueue<int> testIntQueue = new TestQueue<int>(new EtwQueueEventSource("Test-ETW-Queue-Integer"));
testIntQueue.Enqueue(15);
testStringQueue.Enqueue("X");
我不会使用两个源,而是添加一个参数,您可以在其中传递队列的名称和对象的 ToString 表示形式。
public class TestQueue<T>
{
private readonly IEtwQueue _etwQueue;
private readonly string _queueName;
private readonly Queue<T> _instance = new Queue<T>();
public TestQueue(IEtwQueue etwQueue, string queueName)
{
_etwQueue = etwQueue;
_queueName = queueName;
}
public void Enqueue(T item)
{
_instance.Enqueue(item);
if(_etwQueue.IsEnabled()) //So we only call item.ToString() if the queue is enabled.
{
_etwQueue.CommandEnqueued(_instance.Count, item.ToString(), queueName);
}
}
public T Dequeue()
{
T item = _instance.Dequeue();
if(_etwQueue.IsEnabled()) //So we only call item.ToString() if the queue is enabled.
{
_etwQueue.CommandDequed(_instance.Count, item.ToString(), queueName);
}
return
}
}
public interface IEtwQueue
{
void CommandEnqueued(int items, string itemDescription, string queueName);
void CommandDequed(int items, string itemDescription, string queueName);
}
[EventSource(Name = "Test-ETW-Queue")]
public class EtwQueue : EventSource, IEtwQueue
{
public static EtwQueue Log = new EtwQueue();
private EtwQueue() { }
[Event(1)]
public void CommandEnqueued(int items, string itemDescription, string queueName)
{
if (IsEnabled()) WriteEvent(1, items, itemDescription, queueName);
}
[Event(2)]
public void CommandDequed(int items, string itemDescription, string queueName)
{
if (IsEnabled()) WriteEvent(2, items, itemDescription, queueName);
}
但是,如果您预计会引发 > 1000 / 秒 事件,您可能希望通过调用 WriteEventCore
to make a overload of WriteEvent
that takes a int, int, string, string
as the 4 arguments instead of using the slower int, params object[]
` 重载的不安全代码来提高性能。
[EventSource(Name = "Test-ETW-Queue")]
public class EtwQueue : EventSource
{
public static EtwQueue Log = new EtwQueue();
private EtwQueue() { }
[Event(1)]
public void CommandEnqueued(int items, string itemDescription, string queueName)
{
if (IsEnabled()) WriteEvent(1, items, itemDescription, queueName);
}
[Event(2)]
public void CommandDequed(int items, string itemDescription, string queueName)
{
if (IsEnabled()) WriteEvent(2, items, itemDescription, queueName);
}
[NonEvent]
public unsafe void WriteEvent(int eventId, int arg1, string arg2, string arg3)
{
if (arg2 == null) arg2 = "";
if (arg3 == null) arg3 = "";
fixed (char* string2Bytes = arg2)
fixed (char* string3Bytes = arg3)
{
EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
descrs[0].DataPointer = (IntPtr)(&arg1);
descrs[0].Size = 4;
descrs[1].DataPointer = (IntPtr)string2Bytes;
descrs[1].Size = ((arg2.Length + 1) * 2);
descrs[2].DataPointer = (IntPtr)string3Bytes;
descrs[2].Size = ((arg3.Length + 1) * 2);
WriteEventCore(eventId, 3, descrs);
}
}
}
我想知道您对将 EventSource 用于常见且可在同一过程中使用几次的组件有何经验。
一个简单的例子。我的共享组件是 TestQueue,我想在我的进程中使用它几次,然后在 PerfView 中再次使用它来查看哪个事件属于哪个队列。
public class TestQueue<T>
{
private readonly IEtwQueue _etwQueue;
private readonly Queue<T> _instance = new Queue<T>();
public TestQueue(IEtwQueue etwQueue)
{
_etwQueue = etwQueue;
}
public void Enqueue(T item)
{
_instance.Enqueue(item);
_etwQueue.CommandEnqueued(_instance.Count);
}
public T Dequeue()
{
_etwQueue.CommandDequed(_instance.Count);
return _instance.Dequeue();
}
}
public interface IEtwQueue
{
void CommandEnqueued(int items);
void CommandDequed(int items);
}
[EventSource(Name = "Test-ETW-Queue")]
public class EtwQueue : EventSource, IEtwQueue
{
public static EtwQueue Log = new EtwQueue();
private EtwQueue() { }
[Event(1)]
public void CommandEnqueued(int items) { if (IsEnabled()) WriteEvent(1, items); }
[Event(2)]
public void CommandDequed(int items) { if (IsEnabled()) WriteEvent(2, items); }
}
我想这样使用它:
TestQueue<string> testStringQueue = new TestQueue<string>(EtwQueue.Log);
TestQueue<int> testIntQueue = new TestQueue<int>(EtwQueue.Log);
testIntQueue.Enqueue(15);
testStringQueue.Enqueue("X");
这是我在 PerfView 中的内容:
这两个事件没有区别。 我想知道如何识别它们,以便将某些名称(字符串)或 ID 作为事件名称的一部分计算出来? 我知道我可以使用任务对事件进行逻辑分组,但这不是我在这里所期望的,特别是因为它们必须在事件源中预定义。 Activity ID在用例中也是一样的
干杯!
比实现两个 EventSources 更好的方法是通过自定义实现的构造函数传递事件源名称。也许这就是方法:)
因此自定义事件源上没有 EventSource 属性 class 并且构造函数具有事件源名称参数:
public class EtwQueueEventSource : EventSource, IEtwQueue
{
public EtwQueueEventSource(string sourceName) : base(sourceName) { }
[Event(1)]
public void CommandEnqueued(int items) { if (IsEnabled()) WriteEvent(1, items); }
[Event(2)]
public void CommandDequed(int items) { if (IsEnabled()) WriteEvent(2, items); }
}
所以之前的用法示例变成了这样的:
TestQueue<string> testStringQueue = new TestQueue<string>(new EtwQueueEventSource("Test-ETW-Queue-String"));
TestQueue<int> testIntQueue = new TestQueue<int>(new EtwQueueEventSource("Test-ETW-Queue-Integer"));
testIntQueue.Enqueue(15);
testStringQueue.Enqueue("X");
我不会使用两个源,而是添加一个参数,您可以在其中传递队列的名称和对象的 ToString 表示形式。
public class TestQueue<T>
{
private readonly IEtwQueue _etwQueue;
private readonly string _queueName;
private readonly Queue<T> _instance = new Queue<T>();
public TestQueue(IEtwQueue etwQueue, string queueName)
{
_etwQueue = etwQueue;
_queueName = queueName;
}
public void Enqueue(T item)
{
_instance.Enqueue(item);
if(_etwQueue.IsEnabled()) //So we only call item.ToString() if the queue is enabled.
{
_etwQueue.CommandEnqueued(_instance.Count, item.ToString(), queueName);
}
}
public T Dequeue()
{
T item = _instance.Dequeue();
if(_etwQueue.IsEnabled()) //So we only call item.ToString() if the queue is enabled.
{
_etwQueue.CommandDequed(_instance.Count, item.ToString(), queueName);
}
return
}
}
public interface IEtwQueue
{
void CommandEnqueued(int items, string itemDescription, string queueName);
void CommandDequed(int items, string itemDescription, string queueName);
}
[EventSource(Name = "Test-ETW-Queue")]
public class EtwQueue : EventSource, IEtwQueue
{
public static EtwQueue Log = new EtwQueue();
private EtwQueue() { }
[Event(1)]
public void CommandEnqueued(int items, string itemDescription, string queueName)
{
if (IsEnabled()) WriteEvent(1, items, itemDescription, queueName);
}
[Event(2)]
public void CommandDequed(int items, string itemDescription, string queueName)
{
if (IsEnabled()) WriteEvent(2, items, itemDescription, queueName);
}
但是,如果您预计会引发 > 1000 / 秒 事件,您可能希望通过调用 WriteEventCore
to make a overload of WriteEvent
that takes a int, int, string, string
as the 4 arguments instead of using the slower int, params object[]
` 重载的不安全代码来提高性能。
[EventSource(Name = "Test-ETW-Queue")]
public class EtwQueue : EventSource
{
public static EtwQueue Log = new EtwQueue();
private EtwQueue() { }
[Event(1)]
public void CommandEnqueued(int items, string itemDescription, string queueName)
{
if (IsEnabled()) WriteEvent(1, items, itemDescription, queueName);
}
[Event(2)]
public void CommandDequed(int items, string itemDescription, string queueName)
{
if (IsEnabled()) WriteEvent(2, items, itemDescription, queueName);
}
[NonEvent]
public unsafe void WriteEvent(int eventId, int arg1, string arg2, string arg3)
{
if (arg2 == null) arg2 = "";
if (arg3 == null) arg3 = "";
fixed (char* string2Bytes = arg2)
fixed (char* string3Bytes = arg3)
{
EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
descrs[0].DataPointer = (IntPtr)(&arg1);
descrs[0].Size = 4;
descrs[1].DataPointer = (IntPtr)string2Bytes;
descrs[1].Size = ((arg2.Length + 1) * 2);
descrs[2].DataPointer = (IntPtr)string3Bytes;
descrs[2].Size = ((arg3.Length + 1) * 2);
WriteEventCore(eventId, 3, descrs);
}
}
}