diff options
author | Brian Robbins <brianrob@microsoft.com> | 2017-05-06 12:36:08 -0700 |
---|---|---|
committer | Vance Morrison <vancem@microsoft.com> | 2017-05-06 12:36:08 -0700 |
commit | 72ac46450bec8ea88ed023d9c1faf5a04556c834 (patch) | |
tree | 59085824f4268257d041ed9870f038216cd8ed45 /src/vm/eventpipeeventinstance.cpp | |
parent | 3ababc21ab334a2e37c6ba4115c946ea26a6f2fb (diff) | |
download | coreclr-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.cpp | 157 |
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 |