diff options
author | Noah Falk <noahfalk@users.noreply.github.com> | 2019-06-21 15:27:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-21 15:27:21 -0700 |
commit | 961e8d7bd1bdd058ee5f8f34937e9f3f9d80b65b (patch) | |
tree | 06c18fd142f826966f051c908252089e6e5ec55b | |
parent | 205e01fc5020f597ee69643c24fd56268cdf1b50 (diff) | |
download | coreclr-961e8d7bd1bdd058ee5f8f34937e9f3f9d80b65b.tar.gz coreclr-961e8d7bd1bdd058ee5f8f34937e9f3f9d80b65b.tar.bz2 coreclr-961e8d7bd1bdd058ee5f8f34937e9f3f9d80b65b.zip |
Add EventPipe Processor Number support and make NetTrace the default … (#25276)
* Add EventPipe Processor Number support and make NetTrace the default format
The EventPipe header now has a Processor Number field. On windows we query the correct value, on other OSes we currently have a -1 placeholder, but the field is written to the format regardless.
NetTrace is now the default format when using the environment variable, and the format must be explicitly configured when using the IPC channel or managed API. A parallel change in the diagnostics repo is changing dotnet-trace and dotnet-counter to specify nettrace format which means .NET devs should see nettrace almost exclusively from now on. If for whatever reason it is needed, NetPerf remains available if a scenario explicitly requests to use it.
* PR feedback + attempting to fix broken tests
-rw-r--r-- | dependencies.props | 2 | ||||
-rw-r--r-- | src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs | 16 | ||||
-rw-r--r-- | src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeController.cs | 3 | ||||
-rw-r--r-- | src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs | 2 | ||||
-rw-r--r-- | src/inc/clrconfigvalues.h | 3 | ||||
-rw-r--r-- | src/vm/eventpipe.cpp | 24 | ||||
-rw-r--r-- | src/vm/eventpipe.h | 22 | ||||
-rw-r--r-- | src/vm/eventpipeblock.cpp | 9 | ||||
-rw-r--r-- | src/vm/eventpipeblock.h | 1 | ||||
-rw-r--r-- | src/vm/eventpipebuffer.cpp | 2 | ||||
-rw-r--r-- | src/vm/eventpipeconfiguration.cpp | 1 | ||||
-rw-r--r-- | src/vm/eventpipeeventinstance.cpp | 3 | ||||
-rw-r--r-- | src/vm/eventpipeeventinstance.h | 16 | ||||
-rw-r--r-- | src/vm/eventpipeinternal.cpp | 13 | ||||
-rw-r--r-- | src/vm/eventpipeinternal.h | 1 | ||||
-rw-r--r-- | src/vm/eventpipeprotocolhelper.cpp | 17 | ||||
-rw-r--r-- | src/vm/eventpipeprotocolhelper.h | 3 | ||||
-rw-r--r-- | tests/src/tracing/common/TraceConfiguration.cs | 18 | ||||
-rw-r--r-- | tests/src/tracing/regress/GitHub_22247/GitHub_22247.cs | 15 |
19 files changed, 141 insertions, 30 deletions
diff --git a/dependencies.props b/dependencies.props index a661e93db8..b04a88545f 100644 --- a/dependencies.props +++ b/dependencies.props @@ -25,7 +25,7 @@ <MicrosoftNETCoreRuntimeCoreCLRPackageVersion>3.0.0-preview6.19280.1</MicrosoftNETCoreRuntimeCoreCLRPackageVersion> <XunitPackageVersion>2.4.1-pre.build.4059</XunitPackageVersion> <XunitPerformanceApiPackageVersion>1.0.0-beta-build0015</XunitPerformanceApiPackageVersion> - <MicrosoftDiagnosticsTracingTraceEventPackageVersion>2.0.40</MicrosoftDiagnosticsTracingTraceEventPackageVersion> + <MicrosoftDiagnosticsTracingTraceEventPackageVersion>2.0.43</MicrosoftDiagnosticsTracingTraceEventPackageVersion> <CommandLineParserVersion>2.2.0</CommandLineParserVersion> <!-- Scenario tests install this version of Microsoft.NetCore.App, then patch coreclr binaries via xcopy. At the moment it is diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs index a7fb7cc2cb..f3f48b4583 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs @@ -79,15 +79,23 @@ namespace System.Diagnostics.Tracing internal string? FilterData => m_filterData; } + internal enum EventPipeSerializationFormat + { + NetPerf, + NetTrace + } + internal sealed class EventPipeConfiguration { private string m_outputFile; + private EventPipeSerializationFormat m_format; private uint m_circularBufferSizeInMB; private List<EventPipeProviderConfiguration> m_providers; private TimeSpan m_minTimeBetweenSamples = TimeSpan.FromMilliseconds(1); internal EventPipeConfiguration( string outputFile, + EventPipeSerializationFormat format, uint circularBufferSizeInMB) { if(string.IsNullOrEmpty(outputFile)) @@ -99,6 +107,7 @@ namespace System.Diagnostics.Tracing throw new ArgumentOutOfRangeException(nameof(circularBufferSizeInMB)); } m_outputFile = outputFile; + m_format = format; m_circularBufferSizeInMB = circularBufferSizeInMB; m_providers = new List<EventPipeProviderConfiguration>(); } @@ -108,6 +117,11 @@ namespace System.Diagnostics.Tracing get { return m_outputFile; } } + internal EventPipeSerializationFormat Format + { + get { return m_format; } + } + internal uint CircularBufferSizeInMB { get { return m_circularBufferSizeInMB; } @@ -176,6 +190,7 @@ namespace System.Diagnostics.Tracing s_sessionID = EventPipeInternal.Enable( configuration.OutputFile, + configuration.Format, configuration.CircularBufferSizeInMB, providers, (uint)providers.Length); @@ -195,6 +210,7 @@ namespace System.Diagnostics.Tracing [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] internal static extern UInt64 Enable( string? outputFile, + EventPipeSerializationFormat format, uint circularBufferSizeInMB, EventPipeProviderConfiguration[] providers, uint numProviders); diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeController.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeController.cs index 8409078bb3..af68aefc8f 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeController.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeController.cs @@ -68,6 +68,7 @@ namespace System.Diagnostics.Tracing // Create a new configuration object. EventPipeConfiguration config = new EventPipeConfiguration( outputFilePath, + (Config_NetTraceFormat != 0) ? EventPipeSerializationFormat.NetTrace : EventPipeSerializationFormat.NetPerf, Config_EventPipeCircularMB); // Get the configuration. @@ -89,7 +90,7 @@ namespace System.Diagnostics.Tracing private static string BuildTraceFileName() { return GetAppName() + "." + Interop.GetCurrentProcessId().ToString() + - ((Config_NetTraceFormat > 0) ? NetTraceFileExtension : NetPerfFileExtension); + ((Config_NetTraceFormat != 0) ? NetTraceFileExtension : NetPerfFileExtension); } private static string GetAppName() diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs index 4ef9c515e8..a58d4eb750 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs @@ -110,7 +110,7 @@ namespace System.Diagnostics.Tracing new EventPipeProviderConfiguration(NativeRuntimeEventSource.EventSourceName, (ulong) aggregatedKeywords, (uint) highestLevel, null) }; - m_sessionID = EventPipeInternal.Enable(null, 1024, providerConfiguration, 1); + m_sessionID = EventPipeInternal.Enable(null, EventPipeSerializationFormat.NetTrace, 1024, providerConfiguration, 1); Debug.Assert(m_sessionID != 0); // Get the session information that is required to properly dispatch events. diff --git a/src/inc/clrconfigvalues.h b/src/inc/clrconfigvalues.h index 7713af5040..4343ef4942 100644 --- a/src/inc/clrconfigvalues.h +++ b/src/inc/clrconfigvalues.h @@ -719,11 +719,12 @@ RETAIL_CONFIG_DWORD_INFO(EXTERNAL_AllowDComReflection, W("AllowDComReflection"), // EventPipe // RETAIL_CONFIG_DWORD_INFO(INTERNAL_EnableEventPipe, W("EnableEventPipe"), 0, "Enable/disable event pipe. Non-zero values enable tracing.") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeNetTraceFormat, W("EventPipeNetTraceFormat"), 0, "Enable/disable using the newer nettrace file format.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeNetTraceFormat, W("EventPipeNetTraceFormat"), 1, "Enable/disable using the newer nettrace file format.") RETAIL_CONFIG_STRING_INFO(INTERNAL_EventPipeOutputPath, W("EventPipeOutputPath"), "The full path excluding file name for the trace file that will be written when COMPlus_EnableEventPipe=1") RETAIL_CONFIG_STRING_INFO(INTERNAL_EventPipeConfig, W("EventPipeConfig"), "Configuration for EventPipe.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeRundown, W("EventPipeRundown"), 1, "Enable/disable eventpipe rundown.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeCircularMB, W("EventPipeCircularMB"), 1024, "The EventPipe circular buffer size in megabytes.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers"), 0, "Enable/disable capturing processor numbers in EventPipe event headers") #ifdef FEATURE_GDBJIT /// diff --git a/src/vm/eventpipe.cpp b/src/vm/eventpipe.cpp index adec56bd16..81b588f485 100644 --- a/src/vm/eventpipe.cpp +++ b/src/vm/eventpipe.cpp @@ -33,6 +33,9 @@ Volatile<bool> EventPipe::s_tracingInitialized = false; EventPipeConfiguration EventPipe::s_config; EventPipeEventSource *EventPipe::s_pEventSource = nullptr; VolatilePtr<EventPipeSession> EventPipe::s_pSessions[MaxNumberOfSessions]; +#ifndef FEATURE_PAL +unsigned int * EventPipe::s_pProcGroupOffsets = nullptr; +#endif #ifdef FEATURE_PAL // This function is auto-generated from /src/scripts/genEventPipe.py @@ -71,6 +74,26 @@ void EventPipe::Initialize() const unsigned long DefaultProfilerSamplingRateInNanoseconds = 1000000; // 1 msec. SampleProfiler::SetSamplingRate(DefaultProfilerSamplingRateInNanoseconds); + + if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EventPipeProcNumbers) != 0) + { +#ifndef FEATURE_PAL + // setup the windows processor group offset table + WORD numGroups = ::GetActiveProcessorGroupCount(); + s_pProcGroupOffsets = new (nothrow) unsigned int[numGroups]; + if (s_pProcGroupOffsets) + { + unsigned int countProcs = 0; + for (WORD i = 0; i < numGroups; i++) + { + s_pProcGroupOffsets[i] = countProcs; + countProcs += GetActiveProcessorCount(i); + } + } +#endif + } + + { CrstHolder _crst(GetLock()); s_tracingInitialized = tracingInitialized; @@ -577,6 +600,7 @@ void EventPipe::WriteEventInternal( // as opposed a a buffer copy here EventPipeEventInstance instance( event, + GetCurrentProcessorNumber(), pEventPipeThread->GetOSThreadId(), pData, payload.GetSize(), diff --git a/src/vm/eventpipe.h b/src/vm/eventpipe.h index 20f6c1fc7f..7a8df26343 100644 --- a/src/vm/eventpipe.h +++ b/src/vm/eventpipe.h @@ -114,6 +114,21 @@ public: InvokeCallback(eventPipeProviderCallbackData); } + // Returns the a number 0...N representing the processor number this thread is currently + // running on. If for any reason we can't tell then return 0xFFFFFFFF. + static unsigned int GetCurrentProcessorNumber() + { +#ifndef FEATURE_PAL + if (s_pProcGroupOffsets) + { + PROCESSOR_NUMBER procNum; + GetCurrentProcessorNumberEx(&procNum); + return s_pProcGroupOffsets[procNum.Group] + procNum.Number; + } +#endif + return 0xFFFFFFFF; + } + private: static void InvokeCallback(EventPipeProviderCallbackData eventPipeProviderCallbackData); @@ -174,6 +189,13 @@ private: static EventPipeConfiguration s_config; static VolatilePtr<EventPipeSession> s_pSessions[MaxNumberOfSessions]; static EventPipeEventSource *s_pEventSource; + + // A mapping from windows processor group index to the total number of processors + // in all groups preceding it. For example if there are three groups with sizes: + // 1, 7, 6 the table would be 0, 1, 8 +#ifndef FEATURE_PAL + static unsigned int * s_pProcGroupOffsets; +#endif }; static_assert(EventPipe::MaxNumberOfSessions == 64, "Maximum number of EventPipe sessions is not 64."); diff --git a/src/vm/eventpipeblock.cpp b/src/vm/eventpipeblock.cpp index a2d561e1cd..fb9d6c721e 100644 --- a/src/vm/eventpipeblock.cpp +++ b/src/vm/eventpipeblock.cpp @@ -179,6 +179,7 @@ bool EventPipeEventBlockBase::WriteEvent(EventPipeEventInstance &instance, unsigned int dataLength = 0; BYTE* alignedEnd = NULL; + unsigned int captureProcNumber = instance.GetProcNumber(); if (!m_fUseHeaderCompression) { @@ -217,6 +218,9 @@ bool EventPipeEventBlockBase::WriteEvent(EventPipeEventInstance &instance, memcpy(m_pWritePointer, &captureThreadId, sizeof(captureThreadId)); m_pWritePointer += sizeof(captureThreadId); + memcpy(m_pWritePointer, &captureProcNumber, sizeof(captureProcNumber)); + m_pWritePointer += sizeof(captureProcNumber); + memcpy(m_pWritePointer, &stackId, sizeof(stackId)); m_pWritePointer += sizeof(stackId); } @@ -253,10 +257,12 @@ bool EventPipeEventBlockBase::WriteEvent(EventPipeEventInstance &instance, } if (m_lastHeader.SequenceNumber + (instance.GetMetadataId() != 0 ? 1 : 0) != sequenceNumber || - m_lastHeader.CaptureThreadId != captureThreadId) + m_lastHeader.CaptureThreadId != captureThreadId || + m_lastHeader.CaptureProcNumber != captureProcNumber) { WriteVarUInt32(pWritePointer, sequenceNumber - m_lastHeader.SequenceNumber - 1); WriteVarUInt64(pWritePointer, captureThreadId); + WriteVarUInt32(pWritePointer, captureProcNumber); flags |= (1 << 1); } @@ -307,6 +313,7 @@ bool EventPipeEventBlockBase::WriteEvent(EventPipeEventInstance &instance, m_lastHeader.SequenceNumber = sequenceNumber; m_lastHeader.ThreadId = instance.GetThreadId64(); m_lastHeader.CaptureThreadId = captureThreadId; + m_lastHeader.CaptureProcNumber = captureProcNumber; m_lastHeader.StackId = stackId; m_lastHeader.TimeStamp.QuadPart = timeStamp->QuadPart; memcpy(&m_lastHeader.ActivityId, instance.GetActivityId(), sizeof(GUID)); diff --git a/src/vm/eventpipeblock.h b/src/vm/eventpipeblock.h index e7e9516fe5..1ce54dedb3 100644 --- a/src/vm/eventpipeblock.h +++ b/src/vm/eventpipeblock.h @@ -96,6 +96,7 @@ struct EventPipeEventHeader DWORD SequenceNumber; ULONGLONG ThreadId; ULONGLONG CaptureThreadId; + DWORD CaptureProcNumber; DWORD StackId; LARGE_INTEGER TimeStamp; GUID ActivityId; diff --git a/src/vm/eventpipebuffer.cpp b/src/vm/eventpipebuffer.cpp index 913fc57fcb..69eec1e268 100644 --- a/src/vm/eventpipebuffer.cpp +++ b/src/vm/eventpipebuffer.cpp @@ -88,8 +88,10 @@ bool EventPipeBuffer::WriteEvent(Thread *pThread, EventPipeSession &session, Eve pStack = &s; } + unsigned int procNumber = EventPipe::GetCurrentProcessorNumber(); EventPipeEventInstance *pInstance = new (m_pCurrent) EventPipeEventInstance( event, + procNumber, (pThread == NULL) ? #ifdef FEATURE_PAL ::PAL_GetCurrentOSThreadId() diff --git a/src/vm/eventpipeconfiguration.cpp b/src/vm/eventpipeconfiguration.cpp index 84512b50fd..b6c9f01df1 100644 --- a/src/vm/eventpipeconfiguration.cpp +++ b/src/vm/eventpipeconfiguration.cpp @@ -453,6 +453,7 @@ EventPipeEventInstance *EventPipeConfiguration::BuildEventMetadataEvent(EventPip // Construct the event instance. EventPipeEventInstance *pInstance = new EventPipeEventInstance( *m_pMetadataEvent, + EventPipe::GetCurrentProcessorNumber(), #ifdef FEATURE_PAL PAL_GetCurrentOSThreadId(), #else diff --git a/src/vm/eventpipeeventinstance.cpp b/src/vm/eventpipeeventinstance.cpp index 19ce26919b..5b214a13b3 100644 --- a/src/vm/eventpipeeventinstance.cpp +++ b/src/vm/eventpipeeventinstance.cpp @@ -13,6 +13,7 @@ EventPipeEventInstance::EventPipeEventInstance( EventPipeEvent &event, + unsigned int procNumber, ULONGLONG threadId, BYTE *pData, unsigned int length, @@ -32,6 +33,7 @@ EventPipeEventInstance::EventPipeEventInstance( m_debugEventEnd = 0xCAFEBABE; #endif // _DEBUG m_pEvent = &event; + m_procNumber = procNumber; m_threadId = threadId; if (pActivityId != NULL) { @@ -101,6 +103,7 @@ unsigned int EventPipeEventInstance::GetAlignedTotalSize(EventPipeSerializationF sizeof(unsigned int) + // Sequence number (implied by the buffer containing the event instance) sizeof(m_threadId) + // Thread ID sizeof(ULONGLONG) + // Capture Thread ID (implied by the buffer containing the event instance) + sizeof(m_procNumber) + // ProcNumber sizeof(unsigned int) + // Stack intern table id sizeof(m_timeStamp) + // TimeStamp sizeof(m_activityId) + // Activity ID diff --git a/src/vm/eventpipeeventinstance.h b/src/vm/eventpipeeventinstance.h index 2ecb1118b6..a7fd4975f8 100644 --- a/src/vm/eventpipeeventinstance.h +++ b/src/vm/eventpipeeventinstance.h @@ -24,7 +24,13 @@ class EventPipeEventInstance public: - EventPipeEventInstance(EventPipeEvent &event, ULONGLONG threadID, BYTE *pData, unsigned int length, LPCGUID pActivityId, LPCGUID pRelatedActivityId); + EventPipeEventInstance(EventPipeEvent &event, + unsigned int procNumber, + ULONGLONG threadID, + BYTE *pData, + unsigned int length, + LPCGUID pActivityId, + LPCGUID pRelatedActivityId); void EnsureStack(const EventPipeSession &session); @@ -63,6 +69,13 @@ public: m_metadataId = metadataId; } + unsigned int GetProcNumber() const + { + LIMITED_METHOD_CONTRACT; + + return m_procNumber; + } + DWORD GetThreadId32() const { LIMITED_METHOD_CONTRACT; @@ -129,6 +142,7 @@ protected: EventPipeEvent *m_pEvent; unsigned int m_metadataId; + unsigned int m_procNumber; ULONGLONG m_threadId; LARGE_INTEGER m_timeStamp; GUID m_activityId; diff --git a/src/vm/eventpipeinternal.cpp b/src/vm/eventpipeinternal.cpp index 093d1620c8..90c51d46ab 100644 --- a/src/vm/eventpipeinternal.cpp +++ b/src/vm/eventpipeinternal.cpp @@ -19,6 +19,7 @@ UINT64 QCALLTYPE EventPipeInternal::Enable( __in_z LPCWSTR outputFile, + EventPipeSerializationFormat format, UINT32 circularBufferSizeInMB, EventPipeProviderConfiguration *pProviders, UINT32 numProviders) @@ -29,6 +30,7 @@ UINT64 QCALLTYPE EventPipeInternal::Enable( // Invalid input! if (circularBufferSizeInMB == 0 || + format >= EventPipeSerializationFormat::Count || numProviders == 0 || pProviders == nullptr) { @@ -37,17 +39,6 @@ UINT64 QCALLTYPE EventPipeInternal::Enable( BEGIN_QCALL; { - // This was a quick and dirty mechanism for testing but it may not be the final - // configuration scheme we want. This path handles both the AI profiler scenario - // doing private reflection and the EnableEventPipe env var. If we want to flip - // the default for one but not the other we'll have to hoist the configuration - // check into managed code. - EventPipeSerializationFormat format = EventPipeSerializationFormat::NetPerfV3; - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EventPipeNetTraceFormat) > 0) - { - format = EventPipeSerializationFormat::NetTraceV4; - } - sessionID = EventPipe::Enable( outputFile, circularBufferSizeInMB, diff --git a/src/vm/eventpipeinternal.h b/src/vm/eventpipeinternal.h index 2e95657658..ab280c357d 100644 --- a/src/vm/eventpipeinternal.h +++ b/src/vm/eventpipeinternal.h @@ -46,6 +46,7 @@ public: //! static UINT64 QCALLTYPE Enable( __in_z LPCWSTR outputFile, + EventPipeSerializationFormat format, UINT32 circularBufferSizeInMB, EventPipeProviderConfiguration *pProviders, UINT32 numProviders); diff --git a/src/vm/eventpipeprotocolhelper.cpp b/src/vm/eventpipeprotocolhelper.cpp index 00de406dd4..de5d1df105 100644 --- a/src/vm/eventpipeprotocolhelper.cpp +++ b/src/vm/eventpipeprotocolhelper.cpp @@ -32,6 +32,12 @@ static bool TryParseCircularBufferSize(uint8_t*& bufferCursor, uint32_t& bufferL return CanParse && (circularBufferSizeInMB > 0); } +static bool TryParseSerializationFormat(uint8_t*& bufferCursor, uint32_t& bufferLen, EventPipeSerializationFormat& serializationFormat) +{ + const bool CanParse = TryParse(bufferCursor, bufferLen, (uint32_t&)serializationFormat); + return CanParse && (0 <= (int)serializationFormat) && ((int)serializationFormat < (int)EventPipeSerializationFormat::Count); +} + const EventPipeCollectTracingCommandPayload* EventPipeCollectTracingCommandPayload::TryParse(BYTE* lpBuffer, uint16_t& BufferSize) { CONTRACTL @@ -54,6 +60,7 @@ const EventPipeCollectTracingCommandPayload* EventPipeCollectTracingCommandPaylo uint8_t* pBufferCursor = payload->incomingBuffer; uint32_t bufferLen = BufferSize; if (!TryParseCircularBufferSize(pBufferCursor, bufferLen, payload->circularBufferSizeInMB) || + !TryParseSerializationFormat(pBufferCursor, bufferLen, payload->serializationFormat) || !TryParseString(pBufferCursor, bufferLen, payload->outputPath) || !EventPipeProtocolHelper::TryParseProviderConfiguration(pBufferCursor, bufferLen, payload->providerConfigs)) { @@ -187,21 +194,13 @@ void EventPipeProtocolHelper::CollectTracing(DiagnosticsIpc::IpcMessage& message return; } - // IPC should produce nettrace by default or be selectable via protocol - // but this is a simple starting point for testing - EventPipeSerializationFormat format = EventPipeSerializationFormat::NetPerfV3; - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EventPipeNetTraceFormat) > 0) - { - format = EventPipeSerializationFormat::NetTraceV4; - } - auto sessionId = EventPipe::Enable( nullptr, // strOutputPath (ignored in this scenario) payload->circularBufferSizeInMB, // circularBufferSizeInMB payload->providerConfigs.Ptr(), // pConfigs static_cast<uint32_t>(payload->providerConfigs.Size()), // numConfigs EventPipeSessionType::IpcStream, // EventPipeSessionType - format, // EventPipeSerializationFormat + payload->serializationFormat, // EventPipeSerializationFormat pStream); // IpcStream if (sessionId == 0) diff --git a/src/vm/eventpipeprotocolhelper.h b/src/vm/eventpipeprotocolhelper.h index 2961b41726..743df5e600 100644 --- a/src/vm/eventpipeprotocolhelper.h +++ b/src/vm/eventpipeprotocolhelper.h @@ -30,13 +30,14 @@ struct EventPipeCollectTracingCommandPayload // The protocol buffer is defined as: // X, Y, Z means encode bytes for X followed by bytes for Y followed by bytes for Z - // message = uint circularBufferMB, string outputPath, array<provider_config> providers + // message = uint circularBufferMB, uint format, string outputPath, array<provider_config> providers // uint = 4 little endian bytes // wchar = 2 little endian bytes, UTF16 encoding // array<T> = uint length, length # of Ts // string = (array<char> where the last char must = 0) or (length = 0) // provider_config = ulong keywords, uint logLevel, string provider_name, string filter_data uint32_t circularBufferSizeInMB; + EventPipeSerializationFormat serializationFormat; LPCWSTR outputPath; CQuickArray<EventPipeProviderConfiguration> providerConfigs; static const EventPipeCollectTracingCommandPayload* TryParse(BYTE* lpBuffer, uint16_t& BufferSize); diff --git a/tests/src/tracing/common/TraceConfiguration.cs b/tests/src/tracing/common/TraceConfiguration.cs index ad986c3608..afb7db24fc 100644 --- a/tests/src/tracing/common/TraceConfiguration.cs +++ b/tests/src/tracing/common/TraceConfiguration.cs @@ -7,6 +7,12 @@ using System.Reflection; namespace Tracing.Tests.Common { + public enum EventPipeSerializationFormat + { + NetPerf, + NetTrace + } + public sealed class TraceConfiguration { private ConstructorInfo m_configurationCtor; @@ -29,6 +35,7 @@ namespace Tracing.Tests.Common new object[] { outputFile, + EventPipeSerializationFormat.NetTrace, circularBufferMB }); } @@ -79,10 +86,17 @@ namespace Tracing.Tests.Common return false; } - m_configurationCtor = configurationType.GetConstructor( + Type formatType = SPC.GetType("System.Diagnostics.Tracing.EventPipeSerializationFormat"); + if (formatType == null) + { + Console.WriteLine("formatType == null"); + return false; + } + + m_configurationCtor = configurationType.GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, - new Type[] { typeof(string), typeof(uint) }, + new Type[] { typeof(string), formatType, typeof(uint) }, null); if(m_configurationCtor == null) { diff --git a/tests/src/tracing/regress/GitHub_22247/GitHub_22247.cs b/tests/src/tracing/regress/GitHub_22247/GitHub_22247.cs index a35c2b7ced..2e555444ed 100644 --- a/tests/src/tracing/regress/GitHub_22247/GitHub_22247.cs +++ b/tests/src/tracing/regress/GitHub_22247/GitHub_22247.cs @@ -4,6 +4,12 @@ using System.Reflection; namespace EventPipe.Issue22247 { + public enum EventPipeSerializationFormat + { + NetPerf, + NetTrace + } + public sealed class TraceConfiguration { private ConstructorInfo m_configurationCtor; @@ -26,6 +32,7 @@ namespace EventPipe.Issue22247 new object[] { outputFile, + EventPipeSerializationFormat.NetTrace, circularBufferMB }); } @@ -75,11 +82,17 @@ namespace EventPipe.Issue22247 Console.WriteLine("configurationType == null"); return false; } + Type formatType = SPC.GetType("System.Diagnostics.Tracing.EventPipeSerializationFormat"); + if (formatType == null) + { + Console.WriteLine("formatType == null"); + return false; + } m_configurationCtor = configurationType.GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, - new Type[] { typeof(string), typeof(uint) }, + new Type[] { typeof(string), formatType, typeof(uint) }, null); if (m_configurationCtor == null) { |