Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Add More Process Information to EventPipe Traces (#17080)
Browse files Browse the repository at this point in the history
  • Loading branch information
brianrob authored Mar 21, 2018
1 parent 166258a commit b82063e
Show file tree
Hide file tree
Showing 12 changed files with 417 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,6 @@ internal static class EventPipeInternal
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ unsafe int IEventProvider.EventWriteTransferWrapper(
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;
}
Expand Down
2 changes: 2 additions & 0 deletions src/vm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/vm/corhost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#endif // !FEATURE_PAL

#include "stringarraylist.h"
#include "eventpipe.h"

#ifdef FEATURE_COMINTEROP
#include "winrttypenameconverter.h"
Expand Down Expand Up @@ -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;
Expand Down
81 changes: 73 additions & 8 deletions src/vm/eventpipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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
{
Expand All @@ -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())
Expand Down Expand Up @@ -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;
}
}
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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());

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -447,7 +471,7 @@ EventPipeProvider* EventPipe::CreateProvider(const SString &providerName, EventP
CONTRACTL
{
THROWS;
GC_TRIGGERS;
GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
18 changes: 12 additions & 6 deletions src/vm/eventpipe.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class EventPipeFile;
class EventPipeJsonFile;
class EventPipeBuffer;
class EventPipeBufferManager;
class EventPipeEventSource;
class EventPipeProvider;
class MethodDesc;
class SampleProfilerEventInstance;
Expand All @@ -35,7 +36,7 @@ typedef void (*EventPipeCallback)(
struct EventData
{
public:
unsigned long Ptr;
UINT64 Ptr;
unsigned int Size;
unsigned int Reserved;
};
Expand All @@ -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;
Expand All @@ -57,7 +58,7 @@ class EventPipeEventPayload
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();
Expand Down Expand Up @@ -87,7 +88,7 @@ class EventPipeEventPayload
return m_size;
}

EventData** GetEventDataArray() const
EventData* GetEventDataArray() const
{
LIMITED_METHOD_CONTRACT;

Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -408,7 +414,7 @@ class EventPipeInternal
static void QCALLTYPE WriteEventData(
INT_PTR eventHandle,
UINT32 eventID,
EventData **pEventData,
EventData *pEventData,
UINT32 eventDataCount,
LPCGUID pActivityId, LPCGUID pRelatedActivityId);
};
Expand Down
Loading

0 comments on commit b82063e

Please sign in to comment.