Add More Process Information to EventPipe Traces (#17080)
authorBrian Robbins <brianrob@microsoft.com>
Wed, 21 Mar 2018 20:31:04 +0000 (13:31 -0700)
committerGitHub <noreply@github.com>
Wed, 21 Mar 2018 20:31:04 +0000 (13:31 -0700)
12 files changed:
src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs
src/mscorlib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs
src/vm/CMakeLists.txt
src/vm/corhost.cpp
src/vm/eventpipe.cpp
src/vm/eventpipe.h
src/vm/eventpipeeventsource.cpp [new file with mode: 0644]
src/vm/eventpipeeventsource.h [new file with mode: 0644]
src/vm/eventpipefile.cpp
src/vm/eventpipemetadatagenerator.cpp [new file with mode: 0644]
src/vm/eventpipemetadatagenerator.h [new file with mode: 0644]
tests/src/tracing/tracevalidation/tracelogging/EventSourceTest.cs

index 57c3b8f..58091be 100644 (file)
@@ -175,6 +175,6 @@ namespace System.Diagnostics.Tracing
         internal static extern unsafe void WriteEvent(IntPtr eventHandle, uint eventID, void* pData, uint length, Guid* activityId, Guid* relatedActivityId);
 
         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
-        internal static extern unsafe void WriteEventData(IntPtr eventHandle, uint eventID, EventProvider.EventData** pEventData, uint dataCount, Guid* activityId, Guid* relatedActivityId);
+        internal static extern unsafe void WriteEventData(IntPtr eventHandle, uint eventID, EventProvider.EventData* pEventData, uint dataCount, Guid* activityId, Guid* relatedActivityId);
     }
 }
index adda1b6..42061df 100644 (file)
@@ -75,7 +75,7 @@ namespace System.Diagnostics.Tracing
                     userDataCount = userDataCount - 3;
                     Debug.Assert(userDataCount >= 0);
                 }
-                EventPipeInternal.WriteEventData(eventHandle, eventID, &userData, (uint) userDataCount, activityId, relatedActivityId);
+                EventPipeInternal.WriteEventData(eventHandle, eventID, userData, (uint) userDataCount, activityId, relatedActivityId);
             }
             return 0;
         }
index dec64f7..cb75a09 100644 (file)
@@ -184,9 +184,11 @@ set(VM_SOURCES_WKS
     eventpipeconfiguration.cpp
     eventpipeevent.cpp
     eventpipeeventinstance.cpp
+    eventpipeeventsource.cpp
     eventpipeblock.cpp
     eventpipefile.cpp
     eventpipejsonfile.cpp
+    eventpipemetadatagenerator.cpp
     eventpipeprovider.cpp
     eventpipebuffer.cpp
     eventpipebuffermanager.cpp
index 5b31c8a..2b67f19 100644 (file)
@@ -43,6 +43,7 @@
 #endif // !FEATURE_PAL
 
 #include "stringarraylist.h"
+#include "eventpipe.h"
 
 #ifdef FEATURE_COMINTEROP
 #include "winrttypenameconverter.h"
@@ -368,6 +369,10 @@ void SetCommandLineArgs(LPCWSTR pwzAssemblyPath, int argc, LPCWSTR* argv)
     }
     CONTRACTL_END;
 
+    // Send the command line to EventPipe.
+    EventPipe::SaveCommandLine(pwzAssemblyPath, argc, argv);
+
+    // Send the command line to System.Environment.
     struct _gc
     {
         PTRARRAYREF cmdLineArgs;
index 910dee5..ade5dbc 100644 (file)
@@ -9,10 +9,12 @@
 #include "eventpipebuffermanager.h"
 #include "eventpipeconfiguration.h"
 #include "eventpipeevent.h"
+#include "eventpipeeventsource.h"
 #include "eventpipefile.h"
 #include "eventpipeprovider.h"
 #include "eventpipesession.h"
 #include "eventpipejsonfile.h"
+#include "eventtracebase.h"
 #include "sampleprofiler.h"
 
 #ifdef FEATURE_PAL
@@ -27,6 +29,8 @@ EventPipeConfiguration* EventPipe::s_pConfig = NULL;
 EventPipeSession* EventPipe::s_pSession = NULL;
 EventPipeBufferManager* EventPipe::s_pBufferManager = NULL;
 EventPipeFile* EventPipe::s_pFile = NULL;
+EventPipeEventSource* EventPipe::s_pEventSource = NULL;
+LPCWSTR EventPipe::s_pCommandLine = NULL;
 #ifdef _DEBUG
 EventPipeFile* EventPipe::s_pSyncFile = NULL;
 EventPipeJsonFile* EventPipe::s_pJsonFile = NULL;
@@ -57,7 +61,7 @@ EventPipeEventPayload::EventPipeEventPayload(BYTE *pData, unsigned int length)
     m_size = length;
 }
 
-EventPipeEventPayload::EventPipeEventPayload(EventData **pEventData, unsigned int eventDataCount)
+EventPipeEventPayload::EventPipeEventPayload(EventData *pEventData, unsigned int eventDataCount)
 {
     CONTRACTL
     {
@@ -75,7 +79,7 @@ EventPipeEventPayload::EventPipeEventPayload(EventData **pEventData, unsigned in
     S_UINT32 tmp_size = S_UINT32(0);
     for (unsigned int i=0; i<m_eventDataCount; i++)
     {
-        tmp_size += S_UINT32((*m_pEventData)[i].Size);
+        tmp_size += S_UINT32(m_pEventData[i].Size);
     }
 
     if (tmp_size.IsOverflow())
@@ -155,8 +159,8 @@ void EventPipeEventPayload::CopyData(BYTE *pDst)
             unsigned int offset = 0;
             for(unsigned int i=0; i<m_eventDataCount; i++)
             {
-                memcpy(pDst + offset, (BYTE*)(*m_pEventData)[i].Ptr, (*m_pEventData)[i].Size);
-                offset += (*m_pEventData)[i].Size;
+                memcpy(pDst + offset, (BYTE*) m_pEventData[i].Ptr, m_pEventData[i].Size);
+                offset += m_pEventData[i].Size;
             }
         }
     }
@@ -192,6 +196,8 @@ void EventPipe::Initialize()
 
     s_pBufferManager = new EventPipeBufferManager();
 
+    s_pEventSource = new EventPipeEventSource();
+
     // This calls into auto-generated code to initialize the runtime providers
     // and events so that the EventPipe configuration lock isn't taken at runtime
     InitProvidersAndEvents();
@@ -258,9 +264,18 @@ void EventPipe::Shutdown()
     s_pBufferManager = NULL;
     FlushProcessWriteBuffers();
 
-    // Free the configuration and buffer manager.
+    // Free resources.
     delete(pConfig);
     delete(pBufferManager);
+    delete(s_pEventSource);
+    s_pEventSource = NULL;
+
+    // On Windows, this is just a pointer to the return value from
+    // GetCommandLineW(), so don't attempt to free it.
+#ifdef FEATURE_PAL
+    delete[](s_pCommandLine);
+    s_pCommandLine = NULL;
+#endif
 }
 
 void EventPipe::Enable(
@@ -307,6 +322,9 @@ void EventPipe::Enable(LPCWSTR strOutputPath, EventPipeSession *pSession)
         return;
     }
 
+    // Enable the EventPipe EventSource.
+    s_pEventSource->Enable(pSession);
+
     // Take the lock before enabling tracing.
     CrstHolder _crst(GetLock());
 
@@ -360,6 +378,12 @@ void EventPipe::Disable()
         // Disable the profiler.
         SampleProfiler::Disable();
 
+        // Log the process information event.
+        s_pEventSource->SendProcessInfo(s_pCommandLine);
+
+        // Log the runtime information event.
+        ETW::InfoLog::RuntimeInformation(ETW::InfoLog::InfoStructs::Normal);
+
         // Disable tracing.
         s_pConfig->Disable(s_pSession);
 
@@ -447,7 +471,7 @@ EventPipeProvider* EventPipe::CreateProvider(const SString &providerName, EventP
     CONTRACTL
     {
         THROWS;
-        GC_TRIGGERS;
+        GC_NOTRIGGER;
         MODE_ANY;
     }
     CONTRACTL_END;
@@ -509,7 +533,7 @@ void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int leng
     EventPipe::WriteEventInternal(event, payload, pActivityId, pRelatedActivityId);
 }
 
-void EventPipe::WriteEvent(EventPipeEvent &event, EventData **pEventData, unsigned int eventDataCount, LPCGUID pActivityId, LPCGUID pRelatedActivityId)
+void EventPipe::WriteEvent(EventPipeEvent &event, EventData *pEventData, unsigned int eventDataCount, LPCGUID pActivityId, LPCGUID pRelatedActivityId)
 {
     CONTRACTL
     {
@@ -901,6 +925,47 @@ void EventPipe::GetConfigurationFromEnvironment(SString &outputPath, EventPipeSe
     }
 }
 
+void EventPipe::SaveCommandLine(LPCWSTR pwzAssemblyPath, int argc, LPCWSTR *argv)
+{
+    CONTRACTL
+    {
+        THROWS;
+        GC_TRIGGERS;
+        MODE_COOPERATIVE;
+        PRECONDITION(pwzAssemblyPath != NULL);
+        PRECONDITION(argc <= 0 || argv != NULL);
+    }
+    CONTRACTL_END;
+
+    // Get the command line.
+    LPCWSTR osCommandLine = GetCommandLineW();
+
+#ifndef FEATURE_PAL
+    // On Windows, osCommandLine contains the executable and all arguments.
+    s_pCommandLine = osCommandLine;
+#else
+    // On UNIX, the PAL doesn't have the command line arguments, so we must build the command line.
+    // osCommandLine contains the full path to the executable.
+    SString commandLine(osCommandLine);
+    commandLine.Append((WCHAR)' ');
+    commandLine.Append(pwzAssemblyPath);
+
+    for(int i=0; i<argc; i++)
+    {
+        commandLine.Append((WCHAR)' ');
+        commandLine.Append(argv[i]);
+    }
+
+    // Allocate a new string for the command line.
+    SIZE_T commandLineLen = commandLine.GetCount();
+    WCHAR *pCommandLine = new WCHAR[commandLineLen + 1];
+    wcsncpy(pCommandLine, commandLine.GetUnicode(), commandLineLen);
+    pCommandLine[commandLineLen] = '\0';
+
+    s_pCommandLine = pCommandLine;
+#endif
+}
+
 void QCALLTYPE EventPipeInternal::Enable(
         __in_z LPCWSTR outputFile,
         UINT32 circularBufferSizeInMB,
@@ -1064,7 +1129,7 @@ void QCALLTYPE EventPipeInternal::WriteEvent(
 void QCALLTYPE EventPipeInternal::WriteEventData(
     INT_PTR eventHandle,
     UINT32 eventID,
-    EventData **pEventData,
+    EventData *pEventData,
     UINT32 eventDataCount,
     LPCGUID pActivityId,
     LPCGUID pRelatedActivityId)
index 907e0d7..2becb5c 100644 (file)
@@ -16,6 +16,7 @@ class EventPipeFile;
 class EventPipeJsonFile;
 class EventPipeBuffer;
 class EventPipeBufferManager;
+class EventPipeEventSource;
 class EventPipeProvider;
 class MethodDesc;
 class SampleProfilerEventInstance;
@@ -35,7 +36,7 @@ typedef void (*EventPipeCallback)(
 struct EventData
 {
 public:
-    unsigned long Ptr;
+    UINT64 Ptr;
     unsigned int Size;
     unsigned int Reserved;
 };
@@ -44,7 +45,7 @@ class EventPipeEventPayload
 {
 private:
     BYTE *m_pData;
-    EventData **m_pEventData;
+    EventData *m_pEventData;
     unsigned int m_eventDataCount;
     unsigned int m_size;
     bool m_allocatedData;
@@ -57,7 +58,7 @@ public:
     EventPipeEventPayload(BYTE *pData, unsigned int length);
 
     // Build this payload to contain an array of EventData objects
-    EventPipeEventPayload(EventData **pEventData, unsigned int eventDataCount);
+    EventPipeEventPayload(EventData *pEventData, unsigned int eventDataCount);
 
     // If a buffer was allocated internally, delete it
     ~EventPipeEventPayload();
@@ -87,7 +88,7 @@ public:
         return m_size;
     }
 
-    EventData** GetEventDataArray() const
+    EventData* GetEventDataArray() const
     {
         LIMITED_METHOD_CONTRACT;
 
@@ -258,7 +259,7 @@ class EventPipe
 
         // Write out an event from an EventData array.
         // Data is written as a serialized blob matching the ETW serialization conventions.
-        static void WriteEvent(EventPipeEvent &event, EventData **pEventData, unsigned int eventDataCount, LPCGUID pActivityId = NULL, LPCGUID pRelatedActivityId = NULL);
+        static void WriteEvent(EventPipeEvent &event, EventData *pEventData, unsigned int eventDataCount, LPCGUID pActivityId = NULL, LPCGUID pRelatedActivityId = NULL);
 
         // Write out a sample profile event.
         static void WriteSampleProfileEvent(Thread *pSamplingThread, EventPipeEvent *pEvent, Thread *pTargetThread, StackContents &stackContents, BYTE *pData = NULL, unsigned int length = 0);
@@ -269,6 +270,9 @@ class EventPipe
         // Get the managed call stack for the specified thread.
         static bool WalkManagedStackForThread(Thread *pThread, StackContents &stackContents);
 
+        // Save the command line for the current process.
+        static void SaveCommandLine(LPCWSTR pwzAssemblyPath, int argc, LPCWSTR *argv);
+
     protected:
 
         // The counterpart to WriteEvent which after the payload is constructed
@@ -299,6 +303,8 @@ class EventPipe
         static EventPipeSession *s_pSession;
         static EventPipeBufferManager *s_pBufferManager;
         static EventPipeFile *s_pFile;
+        static EventPipeEventSource *s_pEventSource;
+        static LPCWSTR s_pCommandLine;
 #ifdef _DEBUG
         static EventPipeFile *s_pSyncFile;
         static EventPipeJsonFile *s_pJsonFile;
@@ -408,7 +414,7 @@ public:
     static void QCALLTYPE WriteEventData(
         INT_PTR eventHandle,
         UINT32 eventID,
-        EventData **pEventData,
+        EventData *pEventData,
         UINT32 eventDataCount,
         LPCGUID pActivityId, LPCGUID pRelatedActivityId);
 };
diff --git a/src/vm/eventpipeeventsource.cpp b/src/vm/eventpipeeventsource.cpp
new file mode 100644 (file)
index 0000000..1a5cf2a
--- /dev/null
@@ -0,0 +1,118 @@
+// 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.
+
+#include "common.h"
+#include "eventpipeeventsource.h"
+#include "eventpipe.h"
+#include "eventpipeevent.h"
+#include "eventpipemetadatagenerator.h"
+#include "eventpipeprovider.h"
+#include "eventpipesession.h"
+
+#ifdef FEATURE_PERFTRACING
+
+const WCHAR* EventPipeEventSource::s_pProviderName = W("Microsoft-DotNETCore-EventPipe");
+const WCHAR* EventPipeEventSource::s_pProcessInfoEventName = W("ProcessInfo");
+
+EventPipeEventSource::EventPipeEventSource()
+{
+    CONTRACTL
+    {
+        THROWS;
+        GC_NOTRIGGER;
+        MODE_ANY;
+    }
+    CONTRACTL_END;
+
+    m_pProvider = EventPipe::CreateProvider(SL(s_pProviderName), NULL, NULL);
+
+    // Generate metadata.
+    const unsigned int numParams = 1;
+    EventPipeParameterDesc params[numParams];
+    params[0].Type = EventPipeParameterType::String;
+    params[0].Name = W("CommandLine");
+
+    size_t metadataLength = 0;
+    BYTE *pMetadata = EventPipeMetadataGenerator::GenerateEventMetadata(
+        1,      /* eventID */
+        s_pProcessInfoEventName,
+        0,      /* keywords */
+        0,      /* version */
+        EventPipeEventLevel::LogAlways,
+        params,
+        numParams,
+        metadataLength);
+
+    // Add the event.
+    m_pProcessInfoEvent = m_pProvider->AddEvent(
+        1,      /* eventID */
+        0,      /* keywords */
+        0,      /* eventVersion */
+        EventPipeEventLevel::LogAlways,
+        pMetadata,
+        (unsigned int)metadataLength);
+
+    // Delete the metadata after the event is created.
+    // The metadata blob will be copied into EventPipe-owned memory.
+    delete(pMetadata);
+}
+
+EventPipeEventSource::~EventPipeEventSource()
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_TRIGGERS;
+        MODE_ANY;
+    }
+    CONTRACTL_END;
+
+    // Delete the provider and associated events.
+    // This is called in the shutdown path which can't throw.
+    // Catch exceptions and ignore failures.
+    EX_TRY
+    {
+        EventPipe::DeleteProvider(m_pProvider);
+    }
+    EX_CATCH { }
+    EX_END_CATCH(SwallowAllExceptions);
+}
+
+void EventPipeEventSource::Enable(EventPipeSession *pSession)
+{
+    CONTRACTL
+    {
+        THROWS;
+        GC_TRIGGERS;
+        MODE_ANY;
+        PRECONDITION(pSession != NULL);
+    }
+    CONTRACTL_END;
+
+    EventPipeSessionProvider *pSessionProvider = new EventPipeSessionProvider(
+        s_pProviderName,
+        -1,
+        EventPipeEventLevel::LogAlways);
+    pSession->AddSessionProvider(pSessionProvider);
+}
+
+void EventPipeEventSource::SendProcessInfo(LPCWSTR pCommandLine)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        MODE_ANY;
+    }
+    CONTRACTL_END;
+
+    EventData data[1];
+    data[0].Ptr = (UINT64) pCommandLine;
+    data[0].Size = (unsigned int)(wcslen(pCommandLine) + 1) * 2;
+    data[0].Reserved = 0;
+
+    EventPipe::WriteEvent(*m_pProcessInfoEvent, data, 1);
+}
+
+#endif // FEATURE_PERFTRACING
diff --git a/src/vm/eventpipeeventsource.h b/src/vm/eventpipeeventsource.h
new file mode 100644 (file)
index 0000000..67adb43
--- /dev/null
@@ -0,0 +1,33 @@
+// 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.
+
+#ifndef __EVENTPIPE_EVENTSOURCE_H__
+#define __EVENTPIPE_EVENTSOURCE_H__
+
+#ifdef FEATURE_PERFTRACING
+
+class EventPipeProvider;
+class EventPipeEvent;
+class EventPipeSession;
+
+class EventPipeEventSource
+{
+private:
+    const static WCHAR* s_pProviderName;
+    EventPipeProvider *m_pProvider;
+
+    const static WCHAR* s_pProcessInfoEventName;
+    EventPipeEvent *m_pProcessInfoEvent;
+
+public:
+    EventPipeEventSource();
+    ~EventPipeEventSource();
+
+    void Enable(EventPipeSession *pSession);
+    void SendProcessInfo(LPCWSTR pCommandLine);
+};
+
+#endif // FEATURE_PERFTRACING
+
+#endif // __EVENTPIPE_EVENTSOURCE_H__
index 3346ee5..907a5dc 100644 (file)
@@ -51,13 +51,17 @@ EventPipeFile::EventPipeFile(
 
     m_samplingRateInNs = SampleProfiler::GetSamplingRate();
 
-    m_pSerializer = new FastSerializer(outputFilePath); // it creates the file stream and writes the header
+    // Create the file stream and write the header.
+    m_pSerializer = new FastSerializer(outputFilePath);
+
     m_serializationLock.Init(LOCK_TYPE_DEFAULT);
     m_pMetadataIds = new MapSHashWithRemove<EventPipeEvent*, unsigned int>();
 
-    m_metadataIdCounter = 0; // we start with 0, it's always gets incremented by generator so the first id will be 1, as specified in the docs
+    // Start and 0 - The value is always incremented prior to use, so the first ID will be 1.
+    m_metadataIdCounter = 0;
 
-    m_pSerializer->WriteObject(this); // this is the first object in the file
+    // Write the first object to the file.
+    m_pSerializer->WriteObject(this);
 }
 
 EventPipeFile::~EventPipeFile()
diff --git a/src/vm/eventpipemetadatagenerator.cpp b/src/vm/eventpipemetadatagenerator.cpp
new file mode 100644 (file)
index 0000000..3b17e41
--- /dev/null
@@ -0,0 +1,97 @@
+// 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.
+
+#include "common.h"
+#include "eventpipemetadatagenerator.h"
+#include "eventpipe.h"
+
+#ifdef FEATURE_PERFTRACING
+
+BYTE* EventPipeMetadataGenerator::GenerateEventMetadata(
+    unsigned int eventID,
+    LPCWSTR pEventName,
+    INT64 keywords,
+    unsigned int version,
+    EventPipeEventLevel level,
+    EventPipeParameterDesc *pParams,
+    unsigned int paramCount,
+    size_t &metadataLength)
+{
+    CONTRACTL
+    {
+        THROWS;
+        GC_NOTRIGGER;
+        MODE_ANY;
+        PRECONDITION(pEventName != NULL);
+        PRECONDITION(paramCount == 0 || pParams != NULL);
+    }
+    CONTRACTL_END;
+
+    // eventID          : 4 bytes
+    // eventName        : (eventName.Length + 1) * 2 bytes
+    // keywords         : 8 bytes
+    // eventVersion     : 4 bytes
+    // level            : 4 bytes
+    // parameterCount   : 4 bytes
+    size_t eventNameLength = wcslen(pEventName);
+    metadataLength = 24 + ((eventNameLength + 1) * sizeof(WCHAR));
+
+    // Each parameter has a 4 byte TypeCode + (parameterName.Length + 1) * 2 bytes.
+    for(unsigned int i=0; i<paramCount; i++)
+    {
+        _ASSERTE(pParams[i].Name != NULL);
+
+        metadataLength += (4 + ((wcslen(pParams[i].Name) + 1) * sizeof(WCHAR)));
+    }
+
+    // Allocate a metadata blob.
+    BYTE *pMetadata = new BYTE[metadataLength];
+    BYTE *pCurrent = pMetadata;
+
+    // Write the event ID.
+    *((unsigned int *)pCurrent) = eventID;
+    pCurrent += sizeof(unsigned int);
+
+    // Write the event name.
+    wcsncpy((WCHAR *)pCurrent, pEventName, eventNameLength);
+    pCurrent += eventNameLength * sizeof(WCHAR);
+    *((WCHAR *)pCurrent) = W('\0');
+    pCurrent += sizeof(WCHAR);
+
+    // Write the keywords.
+    *((INT64 *)pCurrent) = keywords;
+    pCurrent += sizeof(INT64);
+
+    // Write the version.
+    *((unsigned int *)pCurrent) = version;
+    pCurrent += sizeof(unsigned int);
+
+    // Write the level.
+    *((unsigned int *)pCurrent) = (unsigned int)level;
+    pCurrent += sizeof(unsigned int);
+
+    // Write the parameter count.
+    *((unsigned int *)pCurrent) = paramCount;
+    pCurrent += sizeof(unsigned int);
+
+    // Write the parameter descriptions.
+    for(unsigned int i=0; i<paramCount; i++)
+    {
+        EventPipeParameterDesc *pParam = &pParams[i];
+        *((unsigned int *)pCurrent) = (unsigned int)pParam->Type;
+        pCurrent += sizeof(unsigned int);
+
+        size_t parameterNameLength = wcslen(pParam->Name);
+        wcsncpy((WCHAR *)pCurrent, pParam->Name, parameterNameLength);
+        pCurrent += parameterNameLength * sizeof(WCHAR);
+        *((WCHAR *)pCurrent) = W('\0');
+        pCurrent += sizeof(WCHAR);
+    }
+
+    _ASSERTE(metadataLength == (pCurrent - pMetadata));
+
+    return pMetadata;
+}
+
+#endif // FEATURE_PERFTRACING
diff --git a/src/vm/eventpipemetadatagenerator.h b/src/vm/eventpipemetadatagenerator.h
new file mode 100644 (file)
index 0000000..2886fce
--- /dev/null
@@ -0,0 +1,63 @@
+// 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.
+
+#ifndef __EVENTPIPE_METADATAGENERATOR_H__
+#define __EVENTPIPE_METADATAGENERATOR_H__
+
+#ifdef FEATURE_PERFTRACING
+
+enum class EventPipeEventLevel;
+
+// Represents the type of an event parameter.
+// This enum is derived from the managed TypeCode type, though
+// not all of these values are available in TypeCode.
+// For example, Guid does not exist in TypeCode.
+enum class EventPipeParameterType
+{
+    Empty = 0,          // Null reference
+    Object = 1,         // Instance that isn't a value
+    DBNull = 2,         // Database null value
+    Boolean = 3,        // Boolean
+    Char = 4,           // Unicode character
+    SByte = 5,          // Signed 8-bit integer
+    Byte = 6,           // Unsigned 8-bit integer
+    Int16 = 7,          // Signed 16-bit integer
+    UInt16 = 8,         // Unsigned 16-bit integer
+    Int32 = 9,          // Signed 32-bit integer
+    UInt32 = 10,        // Unsigned 32-bit integer
+    Int64 = 11,         // Signed 64-bit integer
+    UInt64 = 12,        // Unsigned 64-bit integer
+    Single = 13,        // IEEE 32-bit float
+    Double = 14,        // IEEE 64-bit double
+    Decimal = 15,       // Decimal
+    DateTime = 16,      // DateTime
+    Guid = 17,          // Guid
+    String = 18,        // Unicode character string
+};
+
+// Contains the metadata associated with an EventPipe event parameter.
+struct EventPipeParameterDesc
+{
+    EventPipeParameterType Type;
+    LPCWSTR Name;
+};
+
+// Generates metadata for an event emitted by the EventPipe.
+class EventPipeMetadataGenerator
+{
+public:
+    static BYTE* GenerateEventMetadata(
+        unsigned int eventID,
+        LPCWSTR pEventName,
+        INT64 keywords,
+        unsigned int version,
+        EventPipeEventLevel level,
+        EventPipeParameterDesc *pParams,
+        unsigned int paramCount,
+        size_t &metadataLength);
+};
+
+#endif // FEATURE_PERFTRACING
+
+#endif // __EVENTPIPE_METADATAGENERATOR_H__
index 4ef9eb2..79969ea 100644 (file)
@@ -72,6 +72,11 @@ namespace Tracing.Tests.Common
                         return;
                     }
 
+                    if(data.ProviderName.Equals("Microsoft-DotNETCore-EventPipe"))
+                    {
+                        return;
+                    }
+
                     Assert.True($"m_nextTestVerificationIndex({m_nextTestVerificationIndex}) < m_tests.Count({m_tests.Count})", m_nextTestVerificationIndex < m_tests.Count);
                     try
                     {