summaryrefslogtreecommitdiff
path: root/src/vm/eventpipeeventinstance.cpp
diff options
context:
space:
mode:
authorBrian Robbins <brianrob@microsoft.com>2017-05-06 12:36:08 -0700
committerVance Morrison <vancem@microsoft.com>2017-05-06 12:36:08 -0700
commit72ac46450bec8ea88ed023d9c1faf5a04556c834 (patch)
tree59085824f4268257d041ed9870f038216cd8ed45 /src/vm/eventpipeeventinstance.cpp
parent3ababc21ab334a2e37c6ba4115c946ea26a6f2fb (diff)
downloadcoreclr-72ac46450bec8ea88ed023d9c1faf5a04556c834.tar.gz
coreclr-72ac46450bec8ea88ed023d9c1faf5a04556c834.tar.bz2
coreclr-72ac46450bec8ea88ed023d9c1faf5a04556c834.zip
Log Events to EventPipe on Linux (#11433)
* Implement the EventPipe object model for providers and events. * Plumb Runtime Events into EventPipe (#11145) Plumb runtime ETW events into the EventPipe. * Fix bug where all events except for SampleProfiler events were never enabled. * Plumb EventPipeEventInstance through the EventPipe. * Implement EventPipeFile and FastSerializer. * Write event contents to the EventPipeFile. * Only build EventPipe on Linux. * Conditionally add a sentinel value marking event end. * Send SampleProfiler events to the EventPipeFile. * Fix provider ID printing to JSON file. * Write the start date/time, timestamp, and clock frequency into the trace file. * Support unloading of EventPipeProviders. * Handle failure cases when we can't walk the stack or are shutting down. * Fix a bug where we pass a null src pointer to memcpy.
Diffstat (limited to 'src/vm/eventpipeeventinstance.cpp')
-rw-r--r--src/vm/eventpipeeventinstance.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/vm/eventpipeeventinstance.cpp b/src/vm/eventpipeeventinstance.cpp
new file mode 100644
index 0000000000..2bf500be70
--- /dev/null
+++ b/src/vm/eventpipeeventinstance.cpp
@@ -0,0 +1,157 @@
+// 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 "eventpipeeventinstance.h"
+#include "eventpipejsonfile.h"
+#include "fastserializer.h"
+#include "sampleprofiler.h"
+
+#ifdef FEATURE_PERFTRACING
+
+EventPipeEventInstance::EventPipeEventInstance(
+ EventPipeEvent &event,
+ DWORD threadID,
+ BYTE *pData,
+ unsigned int length)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ m_pEvent = &event;
+ m_threadID = threadID;
+ m_pData = pData;
+ m_dataLength = length;
+ QueryPerformanceCounter(&m_timeStamp);
+
+ if(event.NeedStack())
+ {
+ EventPipe::WalkManagedStackForCurrentThread(m_stackContents);
+ }
+}
+
+StackContents* EventPipeEventInstance::GetStack()
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return &m_stackContents;
+}
+
+EventPipeEvent* EventPipeEventInstance::GetEvent() const
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return m_pEvent;
+}
+
+BYTE* EventPipeEventInstance::GetData() const
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return m_pData;
+}
+
+unsigned int EventPipeEventInstance::GetLength() const
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return m_dataLength;
+}
+
+void EventPipeEventInstance::FastSerialize(FastSerializer *pSerializer, StreamLabel metadataLabel)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifdef _DEBUG
+ // Useful for diagnosing serialization bugs.
+ const unsigned int value = 0xDEADBEEF;
+ pSerializer->WriteBuffer((BYTE*)&value, sizeof(value));
+#endif
+
+ // Calculate the size of the total payload so that it can be written to the file.
+ unsigned int payloadLength =
+ sizeof(metadataLabel) +
+ sizeof(m_threadID) + // Thread ID
+ sizeof(m_timeStamp) + // TimeStamp
+ m_dataLength + // Event payload data length
+ m_stackContents.GetSize(); // Stack payload size
+
+ // Write the size of the event to the file.
+ pSerializer->WriteBuffer((BYTE*)&payloadLength, sizeof(payloadLength));
+
+ // Write the metadata label.
+ pSerializer->WriteBuffer((BYTE*)&metadataLabel, sizeof(metadataLabel));
+
+ // Write the thread ID.
+ pSerializer->WriteBuffer((BYTE*)&m_threadID, sizeof(m_threadID));
+
+ // Write the timestamp.
+ pSerializer->WriteBuffer((BYTE*)&m_timeStamp, sizeof(m_timeStamp));
+
+ // Write the event data payload.
+ if(m_dataLength > 0)
+ {
+ pSerializer->WriteBuffer(m_pData, m_dataLength);
+ }
+
+ // Write the stack if present.
+ if(m_stackContents.GetSize() > 0)
+ {
+ pSerializer->WriteBuffer(m_stackContents.GetPointer(), m_stackContents.GetSize());
+ }
+}
+
+void EventPipeEventInstance::SerializeToJsonFile(EventPipeJsonFile *pFile)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ if(pFile == NULL)
+ {
+ return;
+ }
+
+ EX_TRY
+ {
+ const unsigned int guidSize = 39;
+ WCHAR wszProviderID[guidSize];
+ if(!StringFromGUID2(m_pEvent->GetProvider()->GetProviderID(), wszProviderID, guidSize))
+ {
+ wszProviderID[0] = '\0';
+ }
+
+ // Strip off the {}.
+ StackScratchBuffer scratch;
+ SString guidStr(&wszProviderID[1], guidSize-3);
+
+ SString message;
+ message.Printf("Provider=%s/EventID=%d/Version=%d", guidStr.GetANSI(scratch), m_pEvent->GetEventID(), m_pEvent->GetEventVersion());
+ pFile->WriteEvent(m_timeStamp, m_threadID, message, m_stackContents);
+ }
+ EX_CATCH{} EX_END_CATCH(SwallowAllExceptions);
+}
+
+SampleProfilerEventInstance::SampleProfilerEventInstance(Thread *pThread)
+ :EventPipeEventInstance(*SampleProfiler::s_pThreadTimeEvent, pThread->GetOSThreadId(), NULL, 0)
+{
+ LIMITED_METHOD_CONTRACT;
+}
+
+#endif // FEATURE_PERFTRACING