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

Add More Process Information to EventPipe Traces #17080

Merged
merged 6 commits into from
Mar 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for adding this comment! 👍

// 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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why wait with this until Disable? imho the sooner we have this information, the better (I would move it to Enable).

I am not sure who is going to call ProcessName and when (after processing all events or maybe in the meantime?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am waiting until Disable in case the circular buffer wraps. This guarantees that this event doesn't get discarded.

With respect to TraceEvent - TraceLog already does a pass over the data before you can use it, which means that users won't notice that this isn't part of the header. That's actually the point of TraceLog - to allow you to fill data structures with information that is only available after you need it. Thus, TraceLog does a single pass and then the user of the TraceLog does a second pass.


// 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 @@ -1065,7 +1130,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