Re-Factor EventSource to Support Writing to EventPipe.
<FeatureRandomizedStringHashing>true</FeatureRandomizedStringHashing>
<!-- The rejit feature is available only on supported architectures (x86 & x64) -->
<FeatureReJIT Condition="('$(TargetArch)' == 'i386') or ('$(TargetArch)' == 'amd64')">true</FeatureReJIT>
- <FeatureManagedEtw>true</FeatureManagedEtw>
+ <FeatureManagedEtw>false</FeatureManagedEtw>
<FeatureManagedEtwChannels>true</FeatureManagedEtwChannels>
<BinderDebugLog Condition="'$(_BuildType)'=='dbg'">true</BinderDebugLog>
<FeatureAppX>true</FeatureAppX>
<FeatureCominterop>false</FeatureCominterop>
<FeatureCominteropUnmanagedActivation>false</FeatureCominteropUnmanagedActivation>
<FeatureCominteropWinRTManagedActivation>false</FeatureCominteropWinRTManagedActivation>
- <FeatureManagedEtw>false</FeatureManagedEtw>
<FeatureCoreFxGlobalization>true</FeatureCoreFxGlobalization>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetsWindows)' == 'true'">
<FeatureArrayStubAsIL Condition="('$(TargetArch)' == 'arm') or ('$(TargetArch)' == 'amd64') or ('$(TargetArch)' == 'arm64')">true</FeatureArrayStubAsIL>
+ <FeatureManagedEtw>true</FeatureManagedEtw>
<FeatureStubsAsIL Condition="'$(TargetArch)' == 'arm64'">true</FeatureStubsAsIL>
<FeatureUseLcid>true</FeatureUseLcid>
<FeatureImplicitLongPath>true</FeatureImplicitLongPath>
</PropertyGroup>
+
+ <PropertyGroup Condition="'$(TargetsLinux)' == 'true'">
+ <FeatureManagedEtw>true</FeatureManagedEtw>
+ <FeaturePerfTracing>true</FeaturePerfTracing>
+ </PropertyGroup>
</Project>
<DefineConstants Condition="'$(FeatureManagedEtwChannels)' == 'true'">$(DefineConstants);FEATURE_MANAGED_ETW_CHANNELS</DefineConstants>
<DefineConstants Condition="'$(FeaturePal)' == 'true'">$(DefineConstants);FEATURE_PAL</DefineConstants>
<DefineConstants Condition="'$(FeaturePathCompat)' == 'true'">$(DefineConstants);FEATURE_PATHCOMPAT</DefineConstants>
+ <DefineConstants Condition="'$(FeaturePerfTracing)' == 'true'">$(DefineConstants);FEATURE_PERFTRACING</DefineConstants>
<DefineConstants Condition="'$(FeatureXplatEventSource)' == 'true'">$(DefineConstants);FEATURE_EVENTSOURCE_XPLAT</DefineConstants>
<DefineConstants Condition="'$(FeatureRandomizedStringHashing)' == 'true'">$(DefineConstants);FEATURE_RANDOMIZED_STRING_HASHING</DefineConstants>
<DefineConstants Condition="'$(FeatureSortTables)' == 'true'">$(DefineConstants);FEATURE_SORT_TABLES</DefineConstants>
endif(FEATURE_INTERPRETER)
add_definitions(-DFEATURE_ISYM_READER)
add_definitions(-DFEATURE_LOADER_OPTIMIZATION)
-if (NOT CLR_CMAKE_PLATFORM_UNIX)
+if (CLR_CMAKE_PLATFORM_LINUX OR WIN32)
add_definitions(-DFEATURE_MANAGED_ETW)
-endif(NOT CLR_CMAKE_PLATFORM_UNIX)
+endif(CLR_CMAKE_PLATFORM_LINUX OR WIN32)
add_definitions(-DFEATURE_MANAGED_ETW_CHANNELS)
if(FEATURE_MERGE_JIT_AND_ENGINE)
End
Crst EventPipe
- AcquiredBefore ThreadIdDispenser ThreadStore
+ AcquiredBefore ThreadIdDispenser ThreadStore DomainLocalBlock InstMethodHashTable
End
3, // CrstDynamicMT
3, // CrstDynLinkZapItems
7, // CrstEtwTypeLogHash
- 11, // CrstEventPipe
+ 17, // CrstEventPipe
0, // CrstEventStore
0, // CrstException
7, // CrstExecuteManLock
}
#endif // defined(__IN_CRST_CPP) && defined(_DEBUG)
-
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSource_CoreCLR.cs" />
<Compile Condition="'$(FeatureXplatEventSource)' == 'true'" Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\XplatEventLogger.cs" />
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\FrameworkEventSource.cs" />
+ <Compile Condition="'$(FeaturePerfTracing)' == 'true'" Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventPipeEventProvider.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(BclSourcesRoot)\System\Diagnostics\Contracts\Contracts.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\EventProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\EventSource.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\EventSourceException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\IEventProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\StubEnvironment.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\Winmeta.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\ArrayTypeInfo.cs" />
private static bool m_setInformationMissing;
+ private IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions.
UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function
private long m_regHandle; // Trace Registration Handle
private byte m_level; // Tracing Level
// EventSource has special logic to do this, no one else should be calling EventProvider.
internal EventProvider()
{
+#if PLATFORM_WINDOWS
+ m_eventProvider = new EtwEventProvider();
+#elif FEATURE_PERFTRACING
+ m_eventProvider = new EventPipeEventProvider();
+#endif
}
/// <summary>
// However the framework version of EventSource DOES have ES_SESSION_INFO defined and thus
// does not have this issue.
-#if ES_SESSION_INFO || !ES_BUILD_STANDALONE
+#if (PLATFORM_WINDOWS && (ES_SESSION_INFO || !ES_BUILD_STANDALONE))
int buffSize = 256; // An initial guess that probably works most of the time.
byte* buffer;
for (; ; )
userDataPtr[refObjPosition[7]].Ptr = (ulong)v7;
}
- status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
+ status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
}
}
else
}
}
- status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
+ status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
for (int i = 0; i < refObjIndex; ++i)
{
(EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop);
}
- int status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, dataCount, (EventData*)data);
+ int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, dataCount, (EventData*)data);
if (status != 0)
{
{
int status;
- status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(
+ status = m_eventProvider.EventWriteTransferWrapper(
m_regHandle,
ref eventDescriptor,
activityID,
{
m_providerId = providerId;
m_etwCallback = enableCallback;
- return UnsafeNativeMethods.ManifestEtw.EventRegister(ref providerId, enableCallback, null, ref m_regHandle);
+ return m_eventProvider.EventRegister(ref providerId, enableCallback, null, ref m_regHandle);
}
private uint EventUnregister(long registrationHandle)
{
- return UnsafeNativeMethods.ManifestEtw.EventUnregister(registrationHandle);
+ return m_eventProvider.EventUnregister(registrationHandle);
}
static int[] nibblebits = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
return idx;
}
}
+
+#if PLATFORM_WINDOWS
+
+ // A wrapper around the ETW-specific API calls.
+ internal sealed class EtwEventProvider : IEventProvider
+ {
+ // Register an event provider.
+ unsafe uint IEventProvider.EventRegister(
+ ref Guid providerId,
+ UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
+ void* callbackContext,
+ ref long registrationHandle)
+ {
+ return UnsafeNativeMethods.ManifestEtw.EventRegister(
+ ref providerId,
+ enableCallback,
+ callbackContext,
+ ref registrationHandle);
+ }
+
+ // Unregister an event provider.
+ uint IEventProvider.EventUnregister(long registrationHandle)
+ {
+ return UnsafeNativeMethods.ManifestEtw.EventUnregister(registrationHandle);
+ }
+
+ // Write an event.
+ unsafe int IEventProvider.EventWriteTransferWrapper(
+ long registrationHandle,
+ ref EventDescriptor eventDescriptor,
+ Guid* activityId,
+ Guid* relatedActivityId,
+ int userDataCount,
+ EventProvider.EventData* userData)
+ {
+ return UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(
+ registrationHandle,
+ ref eventDescriptor,
+ activityId,
+ relatedActivityId,
+ userDataCount,
+ userData);
+ }
+
+ // Get or set the per-thread activity ID.
+ int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId)
+ {
+ return UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+ ControlCode,
+ ref ActivityId);
+ }
+ }
+
+#endif
}
// This program uses code hyperlinks available as part of the HyperAddin Visual Studio plug-in.
// It is available from http://www.codeplex.com/hyperAddin
-#if PLATFORM_WINDOWS
-
-#define FEATURE_MANAGED_ETW
-
#if !ES_BUILD_STANDALONE && !CORECLR && !ES_BUILD_PN
#define FEATURE_ACTIVITYSAMPLING
#endif // !ES_BUILD_STANDALONE
-#endif // PLATFORM_WINDOWS
-
#if ES_BUILD_STANDALONE
#define FEATURE_MANAGED_ETW_CHANNELS
// #define FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
// Set m_provider, which allows this.
m_provider = provider;
-#if (!ES_BUILD_STANDALONE && !ES_BUILD_PN)
+#if (!ES_BUILD_STANDALONE && !ES_BUILD_PN && !PLATFORM_UNIX)
// API available on OS >= Win 8 and patched Win 7.
// Disable only for FrameworkEventSource to avoid recursion inside exception handling.
if (this.Name != "System.Diagnostics.Eventing.FrameworkEventSource" || Environment.IsWindows8OrAbove)
--- /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 Microsoft.Win32;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ // Represents the interface between EventProvider and an external logging mechanism.
+ internal interface IEventProvider
+ {
+ // Register an event provider.
+ unsafe uint EventRegister(
+ ref Guid providerId,
+ UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
+ void* callbackContext,
+ ref long registrationHandle);
+
+ // Unregister an event provider.
+ uint EventUnregister(long registrationHandle);
+
+ // Write an event.
+ unsafe int EventWriteTransferWrapper(
+ long registrationHandle,
+ ref EventDescriptor eventDescriptor,
+ Guid* activityId,
+ Guid* relatedActivityId,
+ int userDataCount,
+ EventProvider.EventData* userData);
+
+ // Get or set the per-thread activity ID.
+ int EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.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.Collections.Concurrent;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Tracing
+{
+ internal sealed class EventPipeEventProvider : IEventProvider
+ {
+ // The EventPipeProvider handle.
+ private IntPtr m_provHandle = IntPtr.Zero;
+
+ // Register an event provider.
+ unsafe uint IEventProvider.EventRegister(
+ ref Guid providerId,
+ UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
+ void* callbackContext,
+ ref long registrationHandle)
+ {
+ uint returnStatus = 0;
+ m_provHandle = EventPipeInternal.CreateProvider(providerId, enableCallback);
+ if(m_provHandle != IntPtr.Zero)
+ {
+ // Fixed registration handle because a new EventPipeEventProvider
+ // will be created for each new EventSource.
+ registrationHandle = 1;
+ }
+ else
+ {
+ // Unable to create the provider.
+ returnStatus = 1;
+ }
+
+ return returnStatus;
+ }
+
+ // Unregister an event provider.
+ uint IEventProvider.EventUnregister(long registrationHandle)
+ {
+ EventPipeInternal.DeleteProvider(m_provHandle);
+ return 0;
+ }
+
+ // Write an event.
+ unsafe int IEventProvider.EventWriteTransferWrapper(
+ long registrationHandle,
+ ref EventDescriptor eventDescriptor,
+ Guid* activityId,
+ Guid* relatedActivityId,
+ int userDataCount,
+ EventProvider.EventData* userData)
+ {
+ return 0;
+ }
+
+ // Get or set the per-thread activity ID.
+ int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId)
+ {
+ return 0;
+ }
+ }
+
+ // PInvokes into the runtime used to interact with the EventPipe.
+ internal static class EventPipeInternal
+ {
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern IntPtr CreateProvider(Guid providerID, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback callbackFunc);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern IntPtr AddEvent(IntPtr provHandle, Int64 keywords, uint eventID, uint eventVersion, uint level, bool needStack);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void DeleteProvider(IntPtr provHandle);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern unsafe void WriteEvent(IntPtr eventHandle, void* data, uint length);
+ }
+}
FCFuncEnd()
#endif // defined(FEATURE_EVENTSOURCE_XPLAT)
+#ifdef FEATURE_PERFTRACING
+FCFuncStart(gEventPipeInternalFuncs)
+ QCFuncElement("CreateProvider", EventPipeInternal::CreateProvider)
+ QCFuncElement("AddEvent", EventPipeInternal::AddEvent)
+ QCFuncElement("DeleteProvider", EventPipeInternal::DeleteProvider)
+ QCFuncElement("WriteEvent", EventPipeInternal::WriteEvent)
+FCFuncEnd()
+#endif // FEATURE_PERFTRACING
+
#ifdef FEATURE_COMINTEROP
FCFuncStart(gRuntimeClassFuncs)
FCFuncElement("GetRedirectedGetHashCodeMD", ComObject::GetRedirectedGetHashCodeMD)
#ifdef FEATURE_COMINTEROP
FCClassElement("EventArgsMarshaler", "System.StubHelpers", gEventArgsMarshalerFuncs)
#endif // FEATURE_COMINTEROP
+#if defined(FEATURE_PERFTRACING)
+FCClassElement("EventPipeInternal", "System.Diagnostics.Tracing", gEventPipeInternalFuncs)
+#endif // FEATURE_PERFTRACING
FCClassElement("Exception", "System", gExceptionFuncs)
FCClassElement("FileLoadException", "System.IO", gFileLoadExceptionFuncs)
FCClassElement("FormatterServices", "System.Runtime.Serialization", gSerializationFuncs)
length);
// Write to the EventPipeFile.
- _ASSERTE(s_pFile != NULL);
- s_pFile->WriteEvent(instance);
+ if(s_pFile != NULL)
+ {
+ s_pFile->WriteEvent(instance);
+ }
// Write to the EventPipeJsonFile if it exists.
if(s_pJsonFile != NULL)
return &s_configCrst;
}
+INT_PTR QCALLTYPE EventPipeInternal::CreateProvider(
+ GUID providerID,
+ EventPipeCallback pCallbackFunc)
+{
+ QCALL_CONTRACT;
+
+ EventPipeProvider *pProvider = NULL;
+
+ BEGIN_QCALL;
+
+ pProvider = new EventPipeProvider(providerID, pCallbackFunc, NULL);
+
+ END_QCALL;
+
+ return reinterpret_cast<INT_PTR>(pProvider);
+}
+
+INT_PTR QCALLTYPE EventPipeInternal::AddEvent(
+ INT_PTR provHandle,
+ __int64 keywords,
+ unsigned int eventID,
+ unsigned int eventVersion,
+ unsigned int level,
+ bool needStack)
+{
+ QCALL_CONTRACT;
+ BEGIN_QCALL;
+
+ // TODO
+
+ END_QCALL;
+
+ return 0;
+}
+
+void QCALLTYPE EventPipeInternal::DeleteProvider(
+ INT_PTR provHandle)
+{
+ QCALL_CONTRACT;
+ BEGIN_QCALL;
+
+ if(provHandle != NULL)
+ {
+ EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider*>(provHandle);
+ delete pProvider;
+ }
+
+ END_QCALL;
+}
+
+void QCALLTYPE EventPipeInternal::WriteEvent(
+ INT_PTR eventHandle,
+ void *pData,
+ unsigned int length)
+{
+ QCALL_CONTRACT;
+ BEGIN_QCALL;
+
+ // TODO
+
+ END_QCALL;
+}
+
#endif // FEATURE_PERFTRACING
#ifdef FEATURE_PERFTRACING
#include "crst.h"
+#include "eventpipeprovider.h"
#include "stackwalk.h"
class EventPipeConfiguration;
static EventPipeJsonFile *s_pJsonFile;
};
+class EventPipeInternal
+{
+
+public:
+
+ static INT_PTR QCALLTYPE CreateProvider(
+ GUID providerID,
+ EventPipeCallback pCallbackFunc);
+
+ static INT_PTR QCALLTYPE AddEvent(
+ INT_PTR provHandle,
+ __int64 keywords,
+ unsigned int eventID,
+ unsigned int eventVersion,
+ unsigned int level,
+ bool needStack);
+
+ static void QCALLTYPE DeleteProvider(
+ INT_PTR provHandle);
+
+ static void QCALLTYPE WriteEvent(
+ INT_PTR eventHandle,
+ void *pData,
+ unsigned int length);
+};
+
#endif // FEATURE_PERFTRACING
#endif // __EVENTPIPE_H__
// TODO: Set the provider configuration and enable it if we know
// anything about the provider before it is registered.
+ provider.SetConfiguration(true /* providerEnabled */, 0xFFFFFFFFFFFFFFFF /* keywords */, EventPipeEventLevel::Verbose /* level */);
return true;
}
#ifdef FEATURE_PERFTRACING
-EventPipeProvider::EventPipeProvider(const GUID &providerID)
+EventPipeProvider::EventPipeProvider(const GUID &providerID, EventPipeCallback pCallbackFunction, void *pCallbackData)
{
CONTRACTL
{
m_keywords = 0;
m_providerLevel = EventPipeEventLevel::Critical;
m_pEventList = new SList<SListElem<EventPipeEvent*>>();
- m_pCallbackFunction = NULL;
- m_pCallbackData = NULL;
+ m_pCallbackFunction = pCallbackFunction;
+ m_pCallbackData = pCallbackData;
// Register the provider.
EventPipeConfiguration* pConfig = EventPipe::GetConfiguration();
m_pEventList->InsertTail(new SListElem<EventPipeEvent*>(&event));
}
-void EventPipeProvider::RegisterCallback(EventPipeCallback pCallbackFunction, void *pData)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // Take the config lock before setting the callback.
- CrstHolder _crst(EventPipe::GetLock());
-
- if(m_pCallbackFunction == NULL)
- {
- m_pCallbackFunction = pCallbackFunction;
- m_pCallbackData = pData;
- }
-}
-
-void EventPipeProvider::UnregisterCallback(EventPipeCallback pCallbackFunction)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // Take the config lock before setting the callback.
- CrstHolder _crst(EventPipe::GetLock());
-
- if(m_pCallbackFunction == pCallbackFunction)
- {
- m_pCallbackFunction = NULL;
- m_pCallbackData = NULL;
- }
-}
-
void EventPipeProvider::InvokeCallback()
{
CONTRACTL
}
CONTRACTL_END;
- if(m_pCallbackFunction != NULL)
+ if(m_pCallbackFunction != NULL && !g_fEEShutDown)
{
(*m_pCallbackFunction)(
&m_providerID,
public:
- EventPipeProvider(const GUID &providerID);
+ EventPipeProvider(const GUID &providerID, EventPipeCallback pCallbackFunction = NULL, void *pCallbackData = NULL);
~EventPipeProvider();
// Get the provider ID.
// Create a new event.
EventPipeEvent* AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack);
- // Register a callback with the provider to be called on state change.
- void RegisterCallback(EventPipeCallback pCallbackFunction, void *pData);
-
- // Unregister a callback.
- void UnregisterCallback(EventPipeCallback pCallbackFunction);
-
private:
// Add an event to the provider.
#if defined(FEATURE_EVENTSOURCE_XPLAT)
#include "nativeeventsource.h"
+#include "eventpipe.h"
#endif //defined(FEATURE_EVENTSOURCE_XPLAT)
#endif // CROSSGEN_MSCORLIB