<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventPipeMetadataGenerator.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventPipePayloadDecoder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\RuntimeEventSource.cs" Condition="'$(FeaturePerfTracing)' == 'true'"/>
- <Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSource_CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingEventHandleTable.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\ICustomDebuggerNotification.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\StackFrame.CoreCLR.cs" />
internal static class UnsafeNativeMethods
{
- internal static unsafe class ManifestEtw
- {
- //
- // Constants error coded returned by ETW APIs
- //
-
- // The event size is larger than the allowed maximum (64k - header).
- internal const int ERROR_ARITHMETIC_OVERFLOW = 534;
-
- // Occurs when filled buffers are trying to flush to disk,
- // but disk IOs are not happening fast enough.
- // This happens when the disk is slow and event traffic is heavy.
- // Eventually, there are no more free (empty) buffers and the event is dropped.
- internal const int ERROR_NOT_ENOUGH_MEMORY = 8;
-
- internal const int ERROR_MORE_DATA = 0xEA;
- internal const int ERROR_NOT_SUPPORTED = 50;
- internal const int ERROR_INVALID_PARAMETER = 0x57;
-
- //
- // ETW Methods
- //
-
- internal const int EVENT_CONTROL_CODE_DISABLE_PROVIDER = 0;
- internal const int EVENT_CONTROL_CODE_ENABLE_PROVIDER = 1;
- internal const int EVENT_CONTROL_CODE_CAPTURE_STATE = 2;
-
- //
- // Callback
- //
- internal delegate void EtwEnableCallback(
- [In] ref Guid sourceId,
- [In] int isEnabled,
- [In] byte level,
- [In] long matchAnyKeywords,
- [In] long matchAllKeywords,
- [In] EVENT_FILTER_DESCRIPTOR* filterData,
- [In] void* callbackContext
- );
-
- //
- // Registration APIs
- //
- [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventRegister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- internal static extern unsafe uint EventRegister(
- [In] ref Guid providerId,
- [In]EtwEnableCallback enableCallback,
- [In]void* callbackContext,
- [In][Out]ref long registrationHandle
- );
-
- //
- [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventUnregister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- internal static extern uint EventUnregister([In] long registrationHandle);
-
- [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventWriteString", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- internal static extern int EventWriteString(
- [In] long registrationHandle,
- [In] byte level,
- [In] long keyword,
- [In] string msg
- );
-
- [StructLayout(LayoutKind.Sequential)]
- internal struct EVENT_FILTER_DESCRIPTOR
- {
- public long Ptr;
- public int Size;
- public int Type;
- };
-
- /// <summary>
- /// Call the ETW native API EventWriteTransfer and checks for invalid argument error.
- /// The implementation of EventWriteTransfer on some older OSes (Windows 2008) does not accept null relatedActivityId.
- /// So, for these cases we will retry the call with an empty Guid.
- /// </summary>
- internal static int EventWriteTransferWrapper(long registrationHandle,
- ref EventDescriptor eventDescriptor,
- Guid* activityId,
- Guid* relatedActivityId,
- int userDataCount,
- EventProvider.EventData* userData)
- {
- int HResult = EventWriteTransfer(registrationHandle, ref eventDescriptor, activityId, relatedActivityId, userDataCount, userData);
- if (HResult == ERROR_INVALID_PARAMETER && relatedActivityId == null)
- {
- Guid emptyGuid = Guid.Empty;
- HResult = EventWriteTransfer(registrationHandle, ref eventDescriptor, activityId, &emptyGuid, userDataCount, userData);
- }
-
- return HResult;
- }
-
- [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventWriteTransfer", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- private static extern int EventWriteTransfer(
- [In] long registrationHandle,
- [In] ref EventDescriptor eventDescriptor,
- [In] Guid* activityId,
- [In] Guid* relatedActivityId,
- [In] int userDataCount,
- [In] EventProvider.EventData* userData
- );
-
- internal enum ActivityControl : uint
- {
- EVENT_ACTIVITY_CTRL_GET_ID = 1,
- EVENT_ACTIVITY_CTRL_SET_ID = 2,
- EVENT_ACTIVITY_CTRL_CREATE_ID = 3,
- EVENT_ACTIVITY_CTRL_GET_SET_ID = 4,
- EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
- };
-
- [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventActivityIdControl", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- internal static extern int EventActivityIdControl([In] ActivityControl ControlCode, [In][Out] ref Guid ActivityId);
-
- internal enum EVENT_INFO_CLASS
- {
- BinaryTrackInfo,
- SetEnableAllKeywords,
- SetTraits,
- }
-
- [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventSetInformation", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- internal static extern int EventSetInformation(
- [In] long registrationHandle,
- [In] EVENT_INFO_CLASS informationClass,
- [In] void* eventInformation,
- [In] int informationLength);
-
- // Support for EnumerateTraceGuidsEx
- internal enum TRACE_QUERY_INFO_CLASS
- {
- TraceGuidQueryList,
- TraceGuidQueryInfo,
- TraceGuidQueryProcess,
- TraceStackTracingInfo,
- MaxTraceSetInfoClass
- };
-
- internal struct TRACE_GUID_INFO
- {
- public int InstanceCount;
- public int Reserved;
- };
-
- internal struct TRACE_PROVIDER_INSTANCE_INFO
- {
- public int NextOffset;
- public int EnableCount;
- public int Pid;
- public int Flags;
- };
-
- internal struct TRACE_ENABLE_INFO
- {
- public int IsEnabled;
- public byte Level;
- public byte Reserved1;
- public ushort LoggerId;
- public int EnableProperty;
- public int Reserved2;
- public long MatchAnyKeyword;
- public long MatchAllKeyword;
- };
-
- [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EnumerateTraceGuidsEx", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
- internal static extern int EnumerateTraceGuidsEx(
- TRACE_QUERY_INFO_CLASS TraceQueryInfoClass,
- void* InBuffer,
- int InBufferSize,
- void* OutBuffer,
- int OutBufferSize,
- ref int ReturnLength);
- }
-
#if FEATURE_COMINTEROP
[DllImport("api-ms-win-core-winrt-l1-1-0.dll", PreserveSig = true)]
internal static extern int RoGetActivationFactory(
// These PInvokes are used by EventSource to interact with the EventPipe.
//
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
- internal static extern IntPtr CreateProvider(string providerName, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback callbackFunc);
+ internal static extern IntPtr CreateProvider(string providerName, Interop.Advapi32.EtwEnableCallback callbackFunc);
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
internal static extern unsafe IntPtr DefineEvent(IntPtr provHandle, uint eventID, long keywords, uint eventVersion, uint level, void *pMetadata, uint metadataLength);
// Register an event provider.
unsafe uint IEventProvider.EventRegister(
EventSource eventSource,
- UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
+ Interop.Advapi32.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle)
{
}
// Write an event.
- unsafe int IEventProvider.EventWriteTransferWrapper(
+ unsafe EventProvider.WriteEventErrorCode IEventProvider.EventWriteTransfer(
long registrationHandle,
- ref EventDescriptor eventDescriptor,
+ in EventDescriptor eventDescriptor,
IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
if (userDataCount == 0)
{
EventPipeInternal.WriteEventData(eventHandle, eventID, null, 0, activityId, relatedActivityId);
- return 0;
+ return EventProvider.WriteEventErrorCode.NoError;
}
// If Channel == 11, this is a TraceLogging event.
}
EventPipeInternal.WriteEventData(eventHandle, eventID, userData, (uint) userDataCount, activityId, relatedActivityId);
}
- return 0;
+ return EventProvider.WriteEventErrorCode.NoError;
}
// Get or set the per-thread activity ID.
- int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId)
+ int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId)
{
return EventPipeInternal.EventActivityIdControl((uint)ControlCode, ref ActivityId);
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Runtime.InteropServices;
-using System.Threading.Tasks;
-using Microsoft.Reflection;
-using Microsoft.Win32;
-
-namespace System.Diagnostics.Tracing
-{
- public partial class EventSource
- {
- // ActivityID support (see also WriteEventWithRelatedActivityIdCore)
- /// <summary>
- /// When a thread starts work that is on behalf of 'something else' (typically another
- /// thread or network request) it should mark the thread as working on that other work.
- /// This API marks the current thread as working on activity 'activityID'. This API
- /// should be used when the caller knows the thread's current activity (the one being
- /// overwritten) has completed. Otherwise, callers should prefer the overload that
- /// return the oldActivityThatWillContinue (below).
- ///
- /// All events created with the EventSource on this thread are also tagged with the
- /// activity ID of the thread.
- ///
- /// It is common, and good practice after setting the thread to an activity to log an event
- /// with a 'start' opcode to indicate that precise time/thread where the new activity
- /// started.
- /// </summary>
- /// <param name="activityId">A Guid that represents the new activity with which to mark
- /// the current thread</param>
- public static void SetCurrentThreadActivityId(Guid activityId)
- {
- if (TplEventSource.Log != null)
- TplEventSource.Log.SetActivityId(activityId);
-
- // We ignore errors to keep with the convention that EventSources do not throw errors.
- // Note we can't access m_throwOnWrites because this is a static method.
-#if FEATURE_MANAGED_ETW
-#if FEATURE_PERFTRACING
- // Set the activity id via EventPipe.
- EventPipeInternal.EventActivityIdControl(
- (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
- ref activityId);
-#endif // FEATURE_PERFTRACING
-#if PLATFORM_WINDOWS
- // Set the activity id via ETW.
- UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
- UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
- ref activityId);
-#endif // PLATFORM_WINDOWS
-#endif // FEATURE_MANAGED_ETW
- }
-
- /// <summary>
- /// When a thread starts work that is on behalf of 'something else' (typically another
- /// thread or network request) it should mark the thread as working on that other work.
- /// This API marks the current thread as working on activity 'activityID'. It returns
- /// whatever activity the thread was previously marked with. There is a convention that
- /// callers can assume that callees restore this activity mark before the callee returns.
- /// To encourage this, this API returns the old activity, so that it can be restored later.
- ///
- /// All events created with the EventSource on this thread are also tagged with the
- /// activity ID of the thread.
- ///
- /// It is common, and good practice after setting the thread to an activity to log an event
- /// with a 'start' opcode to indicate that precise time/thread where the new activity
- /// started.
- /// </summary>
- /// <param name="activityId">A Guid that represents the new activity with which to mark
- /// the current thread</param>
- /// <param name="oldActivityThatWillContinue">The Guid that represents the current activity
- /// which will continue at some point in the future, on the current thread</param>
- public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
- {
- oldActivityThatWillContinue = activityId;
-#if FEATURE_MANAGED_ETW
- // We ignore errors to keep with the convention that EventSources do not throw errors.
- // Note we can't access m_throwOnWrites because this is a static method.
-
-#if FEATURE_PERFTRACING && PLATFORM_WINDOWS
- EventPipeInternal.EventActivityIdControl(
- (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
- ref oldActivityThatWillContinue);
-#elif FEATURE_PERFTRACING
- EventPipeInternal.EventActivityIdControl(
- (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
- ref oldActivityThatWillContinue);
-#endif // FEATURE_PERFTRACING && PLATFORM_WINDOWS
-
-#if PLATFORM_WINDOWS
- UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
- UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
- ref oldActivityThatWillContinue);
-#endif // PLATFORM_WINDOWS
-#endif // FEATURE_MANAGED_ETW
-
- // We don't call the activityDying callback here because the caller has declared that
- // it is not dying.
- if (TplEventSource.Log != null)
- TplEventSource.Log.SetActivityId(activityId);
- }
-
- /// <summary>
- /// Retrieves the ETW activity ID associated with the current thread.
- /// </summary>
- public static Guid CurrentThreadActivityId
- {
- get
- {
- // We ignore errors to keep with the convention that EventSources do not throw
- // errors. Note we can't access m_throwOnWrites because this is a static method.
- Guid retVal = new Guid();
-#if FEATURE_MANAGED_ETW
-#if PLATFORM_WINDOWS
- UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
- UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
- ref retVal);
-#elif FEATURE_PERFTRACING
- EventPipeInternal.EventActivityIdControl(
- (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
- ref retVal);
-#endif // PLATFORM_WINDOWS
-#endif // FEATURE_MANAGED_ETW
- return retVal;
- }
- }
-
- private int GetParameterCount(EventMetadata eventData)
- {
- return eventData.Parameters.Length;
- }
-
- private Type GetDataType(EventMetadata eventData, int parameterId)
- {
- return eventData.Parameters[parameterId].ParameterType;
- }
-
- private static string GetResourceString(string key, params object[] args)
- {
- return SR.Format(SR.GetResourceString(key), args);
- }
-
- private static readonly bool m_EventSourcePreventRecursion = false;
- }
-
- internal partial class ManifestBuilder
- {
- private string GetTypeNameHelper(Type type)
- {
- switch (type.GetTypeCode())
- {
- case TypeCode.Boolean:
- return "win:Boolean";
- case TypeCode.Byte:
- return "win:UInt8";
- case TypeCode.Char:
- case TypeCode.UInt16:
- return "win:UInt16";
- case TypeCode.UInt32:
- return "win:UInt32";
- case TypeCode.UInt64:
- return "win:UInt64";
- case TypeCode.SByte:
- return "win:Int8";
- case TypeCode.Int16:
- return "win:Int16";
- case TypeCode.Int32:
- return "win:Int32";
- case TypeCode.Int64:
- return "win:Int64";
- case TypeCode.String:
- return "win:UnicodeString";
- case TypeCode.Single:
- return "win:Float";
- case TypeCode.Double:
- return "win:Double";
- case TypeCode.DateTime:
- return "win:FILETIME";
- default:
- if (type == typeof(Guid))
- return "win:GUID";
- else if (type == typeof(IntPtr))
- return "win:Pointer";
- else if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte))
- return "win:Binary";
-
- ManifestError(Resources.GetResourceString("EventSource_UnsupportedEventTypeInManifest", type.Name), true);
- return string.Empty;
- }
- }
- }
-
- internal partial class EventProvider
- {
- internal unsafe int SetInformation(
- UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS eventInfoClass,
- IntPtr data,
- uint dataSize)
- {
- int status = UnsafeNativeMethods.ManifestEtw.ERROR_NOT_SUPPORTED;
-
- if (!m_setInformationMissing)
- {
- try
- {
- status = UnsafeNativeMethods.ManifestEtw.EventSetInformation(
- m_regHandle,
- eventInfoClass,
- (void*)data,
- (int)dataSize);
- }
- catch (TypeLoadException)
- {
- m_setInformationMissing = true;
- }
- }
-
- return status;
- }
- }
-
- internal static class Resources
- {
- internal static string GetResourceString(string key, params object[] args)
- {
- return SR.Format(SR.GetResourceString(key), args);
- }
- }
-}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ internal enum ActivityControl : uint
+ {
+ EVENT_ACTIVITY_CTRL_GET_ID = 1,
+ EVENT_ACTIVITY_CTRL_SET_ID = 2,
+ EVENT_ACTIVITY_CTRL_CREATE_ID = 3,
+ EVENT_ACTIVITY_CTRL_GET_SET_ID = 4,
+ EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ internal enum EVENT_INFO_CLASS
+ {
+ BinaryTrackInfo,
+ SetEnableAllKeywords,
+ SetTraits,
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ internal const int EVENT_CONTROL_CODE_DISABLE_PROVIDER = 0;
+ internal const int EVENT_CONTROL_CODE_ENABLE_PROVIDER = 1;
+ internal const int EVENT_CONTROL_CODE_CAPTURE_STATE = 2;
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct EVENT_FILTER_DESCRIPTOR
+ {
+ public long Ptr;
+ public int Size;
+ public int Type;
+ }
+
+ internal unsafe delegate void EtwEnableCallback(
+ in Guid sourceId,
+ int isEnabled,
+ byte level,
+ long matchAnyKeywords,
+ long matchAllKeywords,
+ EVENT_FILTER_DESCRIPTOR* filterData,
+ void* callbackContext);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, ExactSpelling = true)]
+ internal static extern int EventActivityIdControl(ActivityControl ControlCode, ref Guid ActivityId);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, ExactSpelling = true)]
+ internal static extern unsafe uint EventRegister(
+ in Guid providerId,
+ EtwEnableCallback enableCallback,
+ void* callbackContext,
+ ref long registrationHandle);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, ExactSpelling = true)]
+ internal static unsafe extern int EventSetInformation(
+ long registrationHandle,
+ EVENT_INFO_CLASS informationClass,
+ void* eventInformation,
+ int informationLength);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ internal enum TRACE_QUERY_INFO_CLASS
+ {
+ TraceGuidQueryList,
+ TraceGuidQueryInfo,
+ TraceGuidQueryProcess,
+ TraceStackTracingInfo,
+ MaxTraceSetInfoClass
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TRACE_GUID_INFO
+ {
+ public int InstanceCount;
+ public int Reserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TRACE_PROVIDER_INSTANCE_INFO
+ {
+ public int NextOffset;
+ public int EnableCount;
+ public int Pid;
+ public int Flags;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TRACE_ENABLE_INFO
+ {
+ public int IsEnabled;
+ public byte Level;
+ public byte Reserved1;
+ public ushort LoggerId;
+ public int EnableProperty;
+ public int Reserved2;
+ public long MatchAnyKeyword;
+ public long MatchAllKeyword;
+ }
+
+ [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true)]
+ internal static unsafe extern int EnumerateTraceGuidsEx(
+ TRACE_QUERY_INFO_CLASS TraceQueryInfoClass,
+ void* InBuffer,
+ int InBufferSize,
+ void* OutBuffer,
+ int OutBufferSize,
+ out int ReturnLength);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, ExactSpelling = true)]
+ internal static extern uint EventUnregister(long registrationHandle);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, ExactSpelling = true)]
+ internal static extern int EventWriteString(
+ long registrationHandle,
+ byte level,
+ long keyword,
+ string msg);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+#if ES_BUILD_STANDALONE
+using Microsoft.Diagnostics.Tracing;
+#else
+using System.Diagnostics.Tracing;
+#endif
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ /// <summary>
+ /// Call the ETW native API EventWriteTransfer and checks for invalid argument error.
+ /// The implementation of EventWriteTransfer on some older OSes (Windows 2008) does not accept null relatedActivityId.
+ /// So, for these cases we will retry the call with an empty Guid.
+ /// </summary>
+ internal static unsafe int EventWriteTransfer(
+ long registrationHandle,
+ in EventDescriptor eventDescriptor,
+ Guid* activityId,
+ Guid* relatedActivityId,
+ int userDataCount,
+ EventProvider.EventData* userData)
+ {
+ int HResult = EventWriteTransfer_PInvoke(registrationHandle, in eventDescriptor, activityId, relatedActivityId, userDataCount, userData);
+ if (HResult == Errors.ERROR_INVALID_PARAMETER && relatedActivityId == null)
+ {
+ Guid emptyGuid = Guid.Empty;
+ HResult = EventWriteTransfer_PInvoke(registrationHandle, in eventDescriptor, activityId, &emptyGuid, userDataCount, userData);
+ }
+
+ return HResult;
+ }
+
+ [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventWriteTransfer")]
+ private static unsafe extern int EventWriteTransfer_PInvoke(
+ long registrationHandle,
+ in EventDescriptor eventDescriptor,
+ Guid* activityId,
+ Guid* relatedActivityId,
+ int userDataCount,
+ EventProvider.EventData* userData);
+ }
+}
internal const int ERROR_NOT_READY = 0x15;
internal const int ERROR_SHARING_VIOLATION = 0x20;
internal const int ERROR_HANDLE_EOF = 0x26;
+ internal const int ERROR_NOT_SUPPORTED = 0x32;
internal const int ERROR_FILE_EXISTS = 0x50;
internal const int ERROR_INVALID_PARAMETER = 0x57;
internal const int ERROR_BROKEN_PIPE = 0x6D;
<Compile Include="$(MSBuildThisFileDirectory)System\Void.cs" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.ActivityControl.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.EtwEnableCallback.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.EVENT_INFO_CLASS.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\ActivityTracker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\DiagnosticCounter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\CounterGroup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector_Operations.cs" />
</ItemGroup>
<ItemGroup Condition="$(TargetsWindows)">
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.EventActivityIdControl.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.EventRegister.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.EventSetInformation.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.EventTraceGuidsEx.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.EventUnregister.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.EventWriteString.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.EventWriteTransfer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.LookupAccountNameW.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\BCrypt\Interop.BCryptGenRandom.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\BCrypt\Interop.BCryptGenRandom.GetRandomBytes.cs" />
#if ES_BUILD_STANDALONE
[System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
#endif
- internal partial class EventProvider : IDisposable
+ internal class EventProvider : IDisposable
{
// This is the windows EVENT_DATA_DESCRIPTOR structure. We expose it because this is what
// subclasses of EventProvider use when creating efficient (but unsafe) version of
{ sessionIdBit = sessionIdBit_; etwSessionId = etwSessionId_; }
}
- private static bool m_setInformationMissing;
-
internal IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions.
- UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function
+ Interop.Advapi32.EtwEnableCallback m_etwCallback; // Trace Callback function
private long m_regHandle; // Trace Registration Handle
private byte m_level; // Tracing Level
private long m_anyKeywordMask; // Trace Enable Flags
/// reason the ETW Register call failed a NotSupported exception will be thrown.
/// </summary>
// <SecurityKernel Critical="True" Ring="0">
- // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventRegister(System.Guid&,Microsoft.Win32.UnsafeNativeMethods.ManifestEtw+EtwEnableCallback,System.Void*,System.Int64&):System.UInt32" />
+ // <CallsSuppressUnmanagedCode Name="Interop.Advapi32.EventRegister(System.Guid&,Microsoft.Win32.Interop.Advapi32+EtwEnableCallback,System.Void*,System.Int64&):System.UInt32" />
// <SatisfiesLinkDemand Name="Win32Exception..ctor(System.Int32)" />
// <ReferencesCritical Name="Method: EtwEnableCallBack(Guid&, Int32, Byte, Int64, Int64, Void*, Void*):Void" Ring="1" />
// </SecurityKernel>
internal unsafe void Register(EventSource eventSource)
{
uint status;
- m_etwCallback = new UnsafeNativeMethods.ManifestEtw.EtwEnableCallback(EtwEnableCallBack);
+ m_etwCallback = new Interop.Advapi32.EtwEnableCallback(EtwEnableCallBack);
status = EventRegister(eventSource, m_etwCallback);
if (status != 0)
// <UsesUnsafeCode Name="Parameter callbackContext of type: Void*" />
// </SecurityKernel>
unsafe void EtwEnableCallBack(
- [In] ref System.Guid sourceId,
- [In] int controlCode,
- [In] byte setLevel,
- [In] long anyKeyword,
- [In] long allKeyword,
- [In] UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
- [In] void* callbackContext
+ in System.Guid sourceId,
+ int controlCode,
+ byte setLevel,
+ long anyKeyword,
+ long allKeyword,
+ Interop.Advapi32.EVENT_FILTER_DESCRIPTOR* filterData,
+ void* callbackContext
)
{
// This is an optional callback API. We will therefore ignore any failures that happen as a
ControllerCommand command = ControllerCommand.Update;
IDictionary<string, string> args = null;
bool skipFinalOnControllerCommand = false;
- if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_ENABLE_PROVIDER)
+ if (controlCode == Interop.Advapi32.EVENT_CONTROL_CODE_ENABLE_PROVIDER)
{
m_enabled = true;
m_level = setLevel;
OnControllerCommand(command, args, (bEnabling ? sessionChanged : -sessionChanged), etwSessionId);
}
}
- else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_DISABLE_PROVIDER)
+ else if (controlCode == Interop.Advapi32.EVENT_CONTROL_CODE_DISABLE_PROVIDER)
{
m_enabled = false;
m_level = 0;
m_allKeywordMask = 0;
m_liveSessions = null;
}
- else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_CAPTURE_STATE)
+ else if (controlCode == Interop.Advapi32.EVENT_CONTROL_CODE_CAPTURE_STATE)
{
command = ControllerCommand.SendManifest;
}
fixed (Guid* provider = &m_providerId)
{
- hr = UnsafeNativeMethods.ManifestEtw.EnumerateTraceGuidsEx(UnsafeNativeMethods.ManifestEtw.TRACE_QUERY_INFO_CLASS.TraceGuidQueryInfo,
- provider, sizeof(Guid), buffer, buffSize, ref buffSize);
+ hr = Interop.Advapi32.EnumerateTraceGuidsEx(Interop.Advapi32.TRACE_QUERY_INFO_CLASS.TraceGuidQueryInfo,
+ provider, sizeof(Guid), buffer, buffSize, out buffSize);
}
if (hr == 0)
break;
- if (hr != 122 /* ERROR_INSUFFICIENT_BUFFER */)
+ if (hr != Interop.Errors.ERROR_INSUFFICIENT_BUFFER)
return;
}
- var providerInfos = (UnsafeNativeMethods.ManifestEtw.TRACE_GUID_INFO*)buffer;
- var providerInstance = (UnsafeNativeMethods.ManifestEtw.TRACE_PROVIDER_INSTANCE_INFO*)&providerInfos[1];
+ var providerInfos = (Interop.Advapi32.TRACE_GUID_INFO*)buffer;
+ var providerInstance = (Interop.Advapi32.TRACE_PROVIDER_INSTANCE_INFO*)&providerInfos[1];
int processId = unchecked((int)Interop.Kernel32.GetCurrentProcessId());
// iterate over the instances of the EventProvider in all processes
for (int i = 0; i < providerInfos->InstanceCount; i++)
{
if (providerInstance->Pid == processId)
{
- var enabledInfos = (UnsafeNativeMethods.ManifestEtw.TRACE_ENABLE_INFO*)&providerInstance[1];
+ var enabledInfos = (Interop.Advapi32.TRACE_ENABLE_INFO*)&providerInstance[1];
// iterate over the list of active ETW sessions "listening" to the current provider
for (int j = 0; j < providerInstance->EnableCount; j++)
action(enabledInfos[j].LoggerId, enabledInfos[j].MatchAllKeyword, ref sessionList);
break;
Debug.Assert(0 <= providerInstance->NextOffset && providerInstance->NextOffset < buffSize);
var structBase = (byte*)providerInstance;
- providerInstance = (UnsafeNativeMethods.ManifestEtw.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset];
+ providerInstance = (Interop.Advapi32.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset];
}
#else
#if !ES_BUILD_PCL && PLATFORM_WINDOWS // TODO command arguments don't work on PCL builds...
/// starts, and the command being issued associated with that data.
/// </summary>
private unsafe bool GetDataFromController(int etwSessionId,
- UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
+ Interop.Advapi32.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
{
data = null;
dataStart = 0;
//
// Helper function to set the last error on the thread
//
- private static void SetLastError(int error)
+ private static void SetLastError(WriteEventErrorCode error)
{
- switch (error)
- {
- case UnsafeNativeMethods.ManifestEtw.ERROR_ARITHMETIC_OVERFLOW:
- case UnsafeNativeMethods.ManifestEtw.ERROR_MORE_DATA:
- s_returnCode = WriteEventErrorCode.EventTooBig;
- break;
- case UnsafeNativeMethods.ManifestEtw.ERROR_NOT_ENOUGH_MEMORY:
- s_returnCode = WriteEventErrorCode.NoFreeBuffers;
- break;
- }
+ s_returnCode = error;
}
// <SecurityKernel Critical="True" Ring="0">
/// Payload for the ETW event.
/// </param>
// <SecurityKernel Critical="True" Ring="0">
- // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
+ // <CallsSuppressUnmanagedCode Name="Interop.Advapi32.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
// <UsesUnsafeCode Name="Local dataBuffer of type: Byte*" />
// <UsesUnsafeCode Name="Local pdata of type: Char*" />
// <UsesUnsafeCode Name="Local userData of type: EventData*" />
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, params object[] eventPayload)
{
- int status = 0;
+ WriteEventErrorCode status = WriteEventErrorCode.NoError;
if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
{
userDataPtr[refObjPosition[7]].Ptr = (ulong)v7;
}
- status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
+ status = m_eventProvider.EventWriteTransfer(m_regHandle, in eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
}
}
else
}
}
- status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
+ status = m_eventProvider.EventWriteTransfer(m_regHandle, in eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
for (int i = 0; i < refObjIndex; ++i)
{
}
}
- if (status != 0)
+ if (status != WriteEventErrorCode.NoError)
{
- SetLastError((int)status);
+ SetLastError(status);
return false;
}
/// pointer do the event data
/// </param>
// <SecurityKernel Critical="True" Ring="0">
- // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
+ // <CallsSuppressUnmanagedCode Name="Interop.Advapi32.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
// </SecurityKernel>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
internal protected unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
(EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop);
}
- int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, dataCount, (EventData*)data);
+ WriteEventErrorCode status = m_eventProvider.EventWriteTransfer(m_regHandle, in eventDescriptor, eventHandle, activityID, childActivityID, dataCount, (EventData*)data);
if (status != 0)
{
int dataCount,
IntPtr data)
{
- int status;
+ WriteEventErrorCode status;
- status = m_eventProvider.EventWriteTransferWrapper(
+ status = m_eventProvider.EventWriteTransfer(
m_regHandle,
- ref eventDescriptor,
+ in eventDescriptor,
eventHandle,
activityID,
relatedActivityID,
dataCount,
(EventData*)data);
- if (status != 0)
+ if (status != WriteEventErrorCode.NoError)
{
SetLastError(status);
return false;
}
+
return true;
}
// These are look-alikes to the Manifest based ETW OS APIs that have been shimmed to work
// either with Manifest ETW or Classic ETW (if Manifest based ETW is not available).
- private unsafe uint EventRegister(EventSource eventSource, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback)
+ private unsafe uint EventRegister(EventSource eventSource, Interop.Advapi32.EtwEnableCallback enableCallback)
{
m_providerName = eventSource.Name;
m_providerId = eventSource.Guid;
{
return m_eventProvider.EventUnregister(registrationHandle);
}
+
+#if PLATFORM_WINDOWS
+ private static bool m_setInformationMissing;
+
+ internal unsafe int SetInformation(
+ Interop.Advapi32.EVENT_INFO_CLASS eventInfoClass,
+ IntPtr data,
+ uint dataSize)
+ {
+ int status = Interop.Errors.ERROR_NOT_SUPPORTED;
+
+ if (!m_setInformationMissing)
+ {
+ try
+ {
+ status = Interop.Advapi32.EventSetInformation(
+ m_regHandle,
+ eventInfoClass,
+ (void*)data,
+ (int)dataSize);
+ }
+ catch (TypeLoadException)
+ {
+ m_setInformationMissing = true;
+ }
+ }
+
+ return status;
+ }
+#endif
}
#if PLATFORM_WINDOWS
// Register an event provider.
unsafe uint IEventProvider.EventRegister(
EventSource eventSource,
- UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
+ Interop.Advapi32.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle)
{
Guid providerId = eventSource.Guid;
- return UnsafeNativeMethods.ManifestEtw.EventRegister(
- ref providerId,
+ return Interop.Advapi32.EventRegister(
+ in providerId,
enableCallback,
callbackContext,
ref registrationHandle);
// Unregister an event provider.
uint IEventProvider.EventUnregister(long registrationHandle)
{
- return UnsafeNativeMethods.ManifestEtw.EventUnregister(registrationHandle);
+ return Interop.Advapi32.EventUnregister(registrationHandle);
}
// Write an event.
- unsafe int IEventProvider.EventWriteTransferWrapper(
+ unsafe EventProvider.WriteEventErrorCode IEventProvider.EventWriteTransfer(
long registrationHandle,
- ref EventDescriptor eventDescriptor,
+ in EventDescriptor eventDescriptor,
IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
EventProvider.EventData* userData)
{
- return UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(
+ int error = Interop.Advapi32.EventWriteTransfer(
registrationHandle,
- ref eventDescriptor,
+ in eventDescriptor,
activityId,
relatedActivityId,
userDataCount,
userData);
+
+ switch (error)
+ {
+ case Interop.Errors.ERROR_ARITHMETIC_OVERFLOW:
+ case Interop.Errors.ERROR_MORE_DATA:
+ return EventProvider.WriteEventErrorCode.EventTooBig;
+ case Interop.Errors.ERROR_NOT_ENOUGH_MEMORY:
+ return EventProvider.WriteEventErrorCode.NoFreeBuffers;
+ }
+
+ return EventProvider.WriteEventErrorCode.NoError;
}
// Get or set the per-thread activity ID.
- int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId)
+ int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId)
{
- return UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+ return Interop.Advapi32.EventActivityIdControl(
ControlCode,
ref ActivityId);
}
{
unsafe uint IEventProvider.EventRegister(
EventSource eventSource,
- UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
+ Interop.Advapi32.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle)
{
return 0;
}
- unsafe int IEventProvider.EventWriteTransferWrapper(
+ unsafe EventProvider.WriteEventErrorCode IEventProvider.EventWriteTransfer(
long registrationHandle,
- ref EventDescriptor eventDescriptor,
+ in EventDescriptor eventDescriptor,
IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
EventProvider.EventData* userData)
{
- return 0;
+ return EventProvider.WriteEventErrorCode.NoError;
}
- int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId)
+ int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId)
{
return 0;
}
// where it will write it to
//
// All ETW writes eventually call
-// EventWriteTransfer (native PINVOKE wrapper)
-// EventWriteTransferWrapper (fixes compat problem if you pass null as the related activityID)
+// EventWriteTransfer
// EventProvider.WriteEventRaw - sets last error
// EventSource.WriteEventRaw - Does EventSource exception handling logic
// WriteMultiMerge
}
}
+#region ActivityID
+
+ /// <summary>
+ /// When a thread starts work that is on behalf of 'something else' (typically another
+ /// thread or network request) it should mark the thread as working on that other work.
+ /// This API marks the current thread as working on activity 'activityID'. This API
+ /// should be used when the caller knows the thread's current activity (the one being
+ /// overwritten) has completed. Otherwise, callers should prefer the overload that
+ /// return the oldActivityThatWillContinue (below).
+ ///
+ /// All events created with the EventSource on this thread are also tagged with the
+ /// activity ID of the thread.
+ ///
+ /// It is common, and good practice after setting the thread to an activity to log an event
+ /// with a 'start' opcode to indicate that precise time/thread where the new activity
+ /// started.
+ /// </summary>
+ /// <param name="activityId">A Guid that represents the new activity with which to mark
+ /// the current thread</param>
+ public static void SetCurrentThreadActivityId(Guid activityId)
+ {
+ if (TplEventSource.Log != null)
+ TplEventSource.Log.SetActivityId(activityId);
+
+ // We ignore errors to keep with the convention that EventSources do not throw errors.
+ // Note we can't access m_throwOnWrites because this is a static method.
+#if FEATURE_MANAGED_ETW
+#if FEATURE_PERFTRACING
+ // Set the activity id via EventPipe.
+ EventPipeInternal.EventActivityIdControl(
+ (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
+ ref activityId);
+#endif // FEATURE_PERFTRACING
+#if PLATFORM_WINDOWS
+ // Set the activity id via ETW.
+ Interop.Advapi32.EventActivityIdControl(
+ Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
+ ref activityId);
+#endif // PLATFORM_WINDOWS
+#endif // FEATURE_MANAGED_ETW
+ }
+
+ /// <summary>
+ /// Retrieves the ETW activity ID associated with the current thread.
+ /// </summary>
+ public static Guid CurrentThreadActivityId
+ {
+ get
+ {
+ // We ignore errors to keep with the convention that EventSources do not throw
+ // errors. Note we can't access m_throwOnWrites because this is a static method.
+ Guid retVal = new Guid();
+#if FEATURE_MANAGED_ETW
+#if PLATFORM_WINDOWS
+ Interop.Advapi32.EventActivityIdControl(
+ Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
+ ref retVal);
+#elif FEATURE_PERFTRACING
+ EventPipeInternal.EventActivityIdControl(
+ (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
+ ref retVal);
+#endif // PLATFORM_WINDOWS
+#endif // FEATURE_MANAGED_ETW
+ return retVal;
+ }
+ }
+
+ /// <summary>
+ /// When a thread starts work that is on behalf of 'something else' (typically another
+ /// thread or network request) it should mark the thread as working on that other work.
+ /// This API marks the current thread as working on activity 'activityID'. It returns
+ /// whatever activity the thread was previously marked with. There is a convention that
+ /// callers can assume that callees restore this activity mark before the callee returns.
+ /// To encourage this, this API returns the old activity, so that it can be restored later.
+ ///
+ /// All events created with the EventSource on this thread are also tagged with the
+ /// activity ID of the thread.
+ ///
+ /// It is common, and good practice after setting the thread to an activity to log an event
+ /// with a 'start' opcode to indicate that precise time/thread where the new activity
+ /// started.
+ /// </summary>
+ /// <param name="activityId">A Guid that represents the new activity with which to mark
+ /// the current thread</param>
+ /// <param name="oldActivityThatWillContinue">The Guid that represents the current activity
+ /// which will continue at some point in the future, on the current thread</param>
+ public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
+ {
+ oldActivityThatWillContinue = activityId;
+#if FEATURE_MANAGED_ETW
+ // We ignore errors to keep with the convention that EventSources do not throw errors.
+ // Note we can't access m_throwOnWrites because this is a static method.
+
+#if FEATURE_PERFTRACING && PLATFORM_WINDOWS
+ EventPipeInternal.EventActivityIdControl(
+ (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
+ ref oldActivityThatWillContinue);
+#elif FEATURE_PERFTRACING
+ EventPipeInternal.EventActivityIdControl(
+ (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
+ ref oldActivityThatWillContinue);
+#endif // FEATURE_PERFTRACING && PLATFORM_WINDOWS
+
+#if PLATFORM_WINDOWS
+ Interop.Advapi32.EventActivityIdControl(
+ Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
+ ref oldActivityThatWillContinue);
+#endif // PLATFORM_WINDOWS
+#endif // FEATURE_MANAGED_ETW
+
+ // We don't call the activityDying callback here because the caller has declared that
+ // it is not dying.
+ if (TplEventSource.Log != null)
+ TplEventSource.Log.SetActivityId(activityId);
+ }
+#endregion
+
#region protected
/// <summary>
/// This is the constructor that most users will use to create their eventSource. It takes
IntPtr providerMetadata = metadataHandle.AddrOfPinnedObject();
setInformationResult = m_etwProvider.SetInformation(
- UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS.SetTraits,
+ Interop.Advapi32.EVENT_INFO_CLASS.SetTraits,
providerMetadata,
(uint)this.providerMetadata.Length);
root them and modify shared library definition to force export them.
*/
#if ES_BUILD_PN
- public
+ public
#else
- internal
+ internal
#endif
partial struct EventMetadata
{
+#if ES_BUILD_PN
+ public EventMetadata(EventDescriptor descriptor,
+ EventTags tags,
+ bool enabledForAnyListener,
+ bool enabledForETW,
+ string name,
+ string message,
+ EventParameterType[] parameterTypes)
+ {
+ this.Descriptor = descriptor;
+ this.Tags = tags;
+ this.EnabledForAnyListener = enabledForAnyListener;
+ this.EnabledForETW = enabledForETW;
+#if FEATURE_PERFTRACING
+ this.EnabledForEventPipe = false;
+#endif
+ this.TriggersActivityTracking = 0;
+ this.Name = name;
+ this.Message = message;
+ this.Parameters = null;
+ this.TraceLoggingEventTypes = null;
+ this.ActivityOptions = EventActivityOptions.None;
+ this.ParameterTypes = parameterTypes;
+ this.HasRelatedActivityID = false;
+ this.EventHandle = IntPtr.Zero;
+ }
+#endif
+
public EventDescriptor Descriptor;
public IntPtr EventHandle; // EventPipeEvent handle.
public EventTags Tags;
#endif
};
+#if !ES_BUILD_PN
+ private int GetParameterCount(EventMetadata eventData)
+ {
+ return eventData.Parameters.Length;
+ }
+
+ private Type GetDataType(EventMetadata eventData, int parameterId)
+ {
+ return eventData.Parameters[parameterId].ParameterType;
+ }
+
+ private static readonly bool m_EventSourcePreventRecursion = false;
+#else
+ private int GetParameterCount(EventMetadata eventData)
+ {
+ int paramCount;
+ if(eventData.Parameters == null)
+ {
+ paramCount = eventData.ParameterTypes.Length;
+ }
+ else
+ {
+ paramCount = eventData.Parameters.Length;
+ }
+
+ return paramCount;
+ }
+
+ private Type GetDataType(EventMetadata eventData, int parameterId)
+ {
+ Type dataType;
+ if(eventData.Parameters == null)
+ {
+ dataType = EventTypeToType(eventData.ParameterTypes[parameterId]);
+ }
+ else
+ {
+ dataType = eventData.Parameters[parameterId].ParameterType;
+ }
+
+ return dataType;
+ }
+
+ private static readonly bool m_EventSourcePreventRecursion = true;
+
+ public enum EventParameterType
+ {
+ Boolean,
+ Byte,
+ SByte,
+ Char,
+ Int16,
+ UInt16,
+ Int32,
+ UInt32,
+ Int64,
+ UInt64,
+ IntPtr,
+ Single,
+ Double,
+ Decimal,
+ Guid,
+ String
+ }
+
+ private Type EventTypeToType(EventParameterType type)
+ {
+ switch (type)
+ {
+ case EventParameterType.Boolean:
+ return typeof(bool);
+ case EventParameterType.Byte:
+ return typeof(byte);
+ case EventParameterType.SByte:
+ return typeof(sbyte);
+ case EventParameterType.Char:
+ return typeof(char);
+ case EventParameterType.Int16:
+ return typeof(short);
+ case EventParameterType.UInt16:
+ return typeof(ushort);
+ case EventParameterType.Int32:
+ return typeof(int);
+ case EventParameterType.UInt32:
+ return typeof(uint);
+ case EventParameterType.Int64:
+ return typeof(long);
+ case EventParameterType.UInt64:
+ return typeof(ulong);
+ case EventParameterType.IntPtr:
+ return typeof(IntPtr);
+ case EventParameterType.Single:
+ return typeof(float);
+ case EventParameterType.Double:
+ return typeof(double);
+ case EventParameterType.Decimal:
+ return typeof(decimal);
+ case EventParameterType.Guid:
+ return typeof(Guid);
+ case EventParameterType.String:
+ return typeof(string);
+ default:
+ // TODO: should I throw an exception here?
+ return null;
+ }
+ }
+#endif
+
// This is the internal entry point that code:EventListeners call when wanting to send a command to a
// eventSource. The logic is as follows
//
/// ManifestBuilder is designed to isolate the details of the message of the event from the
/// rest of EventSource. This one happens to create XML.
/// </summary>
- internal partial class ManifestBuilder
+ internal class ManifestBuilder
{
/// <summary>
/// Build a manifest for 'providerName' with the given GUID, which will be packaged into 'dllName'.
return typeName.Replace("win:Int", "win:UInt"); // ETW requires enums to be unsigned.
}
- return GetTypeNameHelper(type);
+ switch (type.GetTypeCode())
+ {
+ case TypeCode.Boolean:
+ return "win:Boolean";
+ case TypeCode.Byte:
+ return "win:UInt8";
+ case TypeCode.Char:
+ case TypeCode.UInt16:
+ return "win:UInt16";
+ case TypeCode.UInt32:
+ return "win:UInt32";
+ case TypeCode.UInt64:
+ return "win:UInt64";
+ case TypeCode.SByte:
+ return "win:Int8";
+ case TypeCode.Int16:
+ return "win:Int16";
+ case TypeCode.Int32:
+ return "win:Int32";
+ case TypeCode.Int64:
+ return "win:Int64";
+ case TypeCode.String:
+ return "win:UnicodeString";
+ case TypeCode.Single:
+ return "win:Float";
+ case TypeCode.Double:
+ return "win:Double";
+ case TypeCode.DateTime:
+ return "win:FILETIME";
+ default:
+ if (type == typeof(Guid))
+ return "win:GUID";
+ else if (type == typeof(IntPtr))
+ return "win:Pointer";
+ else if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte))
+ return "win:Binary";
+
+ ManifestError(SR.Format(SR.EventSource_UnsupportedEventTypeInManifest, type.Name), true);
+ return string.Empty;
+ }
}
private static void UpdateStringBuilder(ref StringBuilder stringBuilder, string eventMessage, int startIndex, int count)
// Register an event provider.
unsafe uint EventRegister(
EventSource eventSource,
- UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
+ Interop.Advapi32.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle);
uint EventUnregister(long registrationHandle);
// Write an event.
- unsafe int EventWriteTransferWrapper(
+ unsafe EventProvider.WriteEventErrorCode EventWriteTransfer(
long registrationHandle,
- ref EventDescriptor eventDescriptor,
+ in EventDescriptor eventDescriptor,
IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
EventProvider.EventData* userData);
// Get or set the per-thread activity ID.
- int EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId);
+ int EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId);
// Define an EventPipeEvent handle.
unsafe IntPtr DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength);