From 7b6c1bf198f12033e828c9ac0e278275f7f1f207 Mon Sep 17 00:00:00 2001 From: Noah Falk Date: Mon, 4 Apr 2022 18:00:37 -0700 Subject: [PATCH] Clarify WriteEventCore arguments Fixes: https://github.com/dotnet/diagnostics/issues/2608 WriteEventCore takes an array of EventData arguments but only provided a few sparse examples on how to initialize these values. Several of the types not shown have non-intuitive encodings that can't be inferred from the few examples. This change provides a more complete listing, in particular including bool, DateTime, string, and byte[] which are non-obvious. --- .../EventSource.xml | 104 +++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/xml/System.Diagnostics.Tracing/EventSource.xml b/xml/System.Diagnostics.Tracing/EventSource.xml index c10de4d6d2b..a5d2da848f0 100644 --- a/xml/System.Diagnostics.Tracing/EventSource.xml +++ b/xml/System.Diagnostics.Tracing/EventSource.xml @@ -3505,6 +3505,106 @@ class AnotherEventSource : EventSource { ``` + These are the expected sizes and data encodings for standard serializable types: + +```csharp +// bool arg +int temp = arg ? 1 : 0; +desc.DataPointer = (IntPtr)(&temp); +desc.Size = 4; + +// byte arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 1; + +// sbyte arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 1; + +// sbyte arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 1; + +// char arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 2; + +// short arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 2; + +// ushort arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 2; + +// int arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 4; + +// uint arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 4; + +// long arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 8; + +// ulong arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 8; + +// float arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 4; + +// double arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 8; + +// decimal arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 16; + +// Guid arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = 16; + +// IntPtr arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = IntPtr.Size; + +// UIntPtr arg +desc.DataPointer = (IntPtr)(&arg); +desc.Size = UIntPtr.Size; + +// DateTime arg +long fileTime = arg.ToFileTimeUtc(); +desc.DataPointer = (IntPtr)(&fileTime); +desc.Size = 8; + +// string arg +fixed(byte* ptr = arg) +{ + int length = arg.Length; + desc.DataPointer = ptr; + desc.Size = (arg.Length+1)*2; +} + +// byte[] arg +// This one is encoded using two adjacent EventData elements. +fixed(byte* ptr = arg) +{ + int length = arg.Length; + desc[i].DataPointer = (IntPtr)(&length); + desc[i].Size = 4; + desc[i+1].DataPointer = (IntPtr)ptr; + desc[i+1].Size = arg.Length; +} + +// enums should be converted to their underlying type and then serialized +// as byte, short, or int. + +``` ]]> @@ -3674,7 +3774,7 @@ class AnotherEventSource : EventSource { is similar to the method but offers better performance, bevcause it does not have to unbox the `childActivityID` and `data` arguments. + is similar to the method but offers better performance, because it does not have to unbox the `childActivityID` and `data` arguments. Your ETW event method calling this function must follow these guidelines: @@ -3684,7 +3784,7 @@ class AnotherEventSource : EventSource { 3. Call passing in the event ID, followed by the related ID GUID, followed by all the parameters the event method is passed, in the same order. - + This method uses the same rules as for the `args` parameter. See WriteEventCore documentation for more details. ## Examples The following C# code example shows how to define a method overload that calls .