1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 #ifndef __EVENTPIPE_H__
6 #define __EVENTPIPE_H__
8 #ifdef FEATURE_PERFTRACING
13 class EventPipeConfiguration;
15 class EventPipeEventInstance;
17 class EventPipeBufferManager;
18 class EventPipeEventSource;
19 class EventPipeProvider;
21 struct EventPipeProviderConfiguration;
22 class EventPipeSession;
24 enum class EventPipeSessionType;
26 // EVENT_FILTER_DESCRIPTOR (This type does not exist on non-Windows platforms.)
27 // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_filter_descriptor
28 // The structure supplements the event provider, level, and keyword data that
29 // determines which events are reported and traced. The structure gives the
30 // event provider greater control over the selection of events for reporting
32 // TODO: EventFilterDescriptor and EventData (defined below) are the same.
33 struct EventFilterDescriptor
35 // A pointer to the filter data.
38 // The size of the filter data, in bytes. The maximum size is 1024 bytes.
41 // The type of filter data. The type is application-defined. An event
42 // controller that knows about the provider and knows details about the
43 // provider's events can use the Type field to send the provider an
44 // arbitrary set of data for use as enhancements to the filtering of events.
48 // Define the event pipe callback to match the ETW callback signature.
49 typedef void (*EventPipeCallback)(
53 ULONGLONG MatchAnyKeywords,
54 ULONGLONG MatchAllKeywords,
55 EventFilterDescriptor *FilterData,
56 void *CallbackContext);
62 unsigned int Reserved;
65 class EventPipeEventPayload
69 EventData *m_pEventData;
70 unsigned int m_eventDataCount;
74 // If the data is stored only as an array of EventData objects, create a flat buffer and copy into it
78 // Build this payload with a flat buffer inside
79 EventPipeEventPayload(BYTE *pData, unsigned int length) :
81 m_pEventData(nullptr),
84 m_allocatedData(false)
86 LIMITED_METHOD_CONTRACT;
89 // Build this payload to contain an array of EventData objects
90 EventPipeEventPayload(EventData *pEventData, unsigned int eventDataCount);
92 // If a buffer was allocated internally, delete it
93 ~EventPipeEventPayload();
95 // Copy the data (whether flat or array of objects) into a flat buffer at pDst
96 // Assumes that pDst points to an appropriatly sized buffer
97 void CopyData(BYTE *pDst);
99 // Get the flat formatted data in this payload
100 // This method will allocate a buffer if it does not already contain flattened data
101 // This method will return NULL on OOM if a buffer needed to be allocated
104 // Return true is the data is stored in a flat buffer
105 bool IsFlattened() const
107 LIMITED_METHOD_CONTRACT;
108 return m_pData != NULL;
111 // The the size of buffer needed to contain the stored data
112 unsigned int GetSize() const
114 LIMITED_METHOD_CONTRACT;
118 EventData *GetEventDataArray() const
120 LIMITED_METHOD_CONTRACT;
128 const static unsigned int MAX_STACK_DEPTH = 100;
130 // Array of IP values from a stack crawl.
131 // Top of stack is at index 0.
132 UINT_PTR m_stackFrames[MAX_STACK_DEPTH];
135 // Parallel array of MethodDesc pointers.
136 // Used for debug-only stack printing.
137 MethodDesc *m_methods[MAX_STACK_DEPTH];
140 // The next available slot in StackFrames.
141 unsigned int m_nextAvailableFrame;
146 LIMITED_METHOD_CONTRACT;
150 void CopyTo(StackContents *pDest)
152 LIMITED_METHOD_CONTRACT;
153 _ASSERTE(pDest != NULL);
155 memcpy_s(pDest->m_stackFrames, MAX_STACK_DEPTH * sizeof(UINT_PTR), m_stackFrames, sizeof(UINT_PTR) * m_nextAvailableFrame);
157 memcpy_s(pDest->m_methods, MAX_STACK_DEPTH * sizeof(MethodDesc *), m_methods, sizeof(MethodDesc *) * m_nextAvailableFrame);
159 pDest->m_nextAvailableFrame = m_nextAvailableFrame;
164 LIMITED_METHOD_CONTRACT;
165 m_nextAvailableFrame = 0;
170 LIMITED_METHOD_CONTRACT;
171 return (m_nextAvailableFrame == 0);
174 unsigned int GetLength()
176 LIMITED_METHOD_CONTRACT;
177 return m_nextAvailableFrame;
180 UINT_PTR GetIP(unsigned int frameIndex)
182 LIMITED_METHOD_CONTRACT;
183 _ASSERTE(frameIndex < MAX_STACK_DEPTH);
185 if (frameIndex >= MAX_STACK_DEPTH)
190 return m_stackFrames[frameIndex];
194 MethodDesc *GetMethod(unsigned int frameIndex)
196 LIMITED_METHOD_CONTRACT;
197 _ASSERTE(frameIndex < MAX_STACK_DEPTH);
199 if (frameIndex >= MAX_STACK_DEPTH)
204 return m_methods[frameIndex];
208 void Append(UINT_PTR controlPC, MethodDesc *pMethod)
210 LIMITED_METHOD_CONTRACT;
212 if (m_nextAvailableFrame < MAX_STACK_DEPTH)
214 m_stackFrames[m_nextAvailableFrame] = controlPC;
216 m_methods[m_nextAvailableFrame] = pMethod;
218 m_nextAvailableFrame++;
222 BYTE *GetPointer() const
224 LIMITED_METHOD_CONTRACT;
225 return (BYTE *)m_stackFrames;
228 unsigned int GetSize() const
230 LIMITED_METHOD_CONTRACT;
231 return (m_nextAvailableFrame * sizeof(UINT_PTR));
235 typedef UINT64 EventPipeSessionID;
240 friend class EventPipeConfiguration;
241 friend class EventPipeFile;
242 friend class EventPipeProvider;
243 friend class EventPipeBufferManager;
244 friend class SampleProfiler;
247 // Initialize the event pipe.
248 static void Initialize();
250 // Shutdown the event pipe.
251 static void Shutdown();
253 // Enable tracing via the event pipe.
254 static EventPipeSessionID Enable(
255 LPCWSTR strOutputPath,
256 uint32_t circularBufferSizeInMB,
257 uint64_t profilerSamplingRateInNanoseconds,
258 const EventPipeProviderConfiguration *pProviders,
259 uint32_t numProviders,
260 EventPipeSessionType sessionType,
261 IpcStream *const pStream);
263 // Disable tracing via the event pipe.
264 static void Disable(EventPipeSessionID id);
266 // Get the session for the specified session ID.
267 static EventPipeSession *GetSession(EventPipeSessionID id);
269 // Specifies whether or not the event pipe is enabled.
270 static bool Enabled();
272 // Create a provider.
273 static EventPipeProvider *CreateProvider(const SString &providerName, EventPipeCallback pCallbackFunction = NULL, void *pCallbackData = NULL);
276 static EventPipeProvider *GetProvider(const SString &providerName);
278 // Delete a provider.
279 static void DeleteProvider(EventPipeProvider *pProvider);
281 // Write out an event from a flat buffer.
282 // Data is written as a serialized blob matching the ETW serialization conventions.
283 static void WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length, LPCGUID pActivityId = NULL, LPCGUID pRelatedActivityId = NULL);
285 // Write out an event from an EventData array.
286 // Data is written as a serialized blob matching the ETW serialization conventions.
287 static void WriteEvent(EventPipeEvent &event, EventData *pEventData, unsigned int eventDataCount, LPCGUID pActivityId = NULL, LPCGUID pRelatedActivityId = NULL);
289 // Write out a sample profile event.
290 static void WriteSampleProfileEvent(Thread *pSamplingThread, EventPipeEvent *pEvent, Thread *pTargetThread, StackContents &stackContents, BYTE *pData = NULL, unsigned int length = 0);
292 // Get the managed call stack for the current thread.
293 static bool WalkManagedStackForCurrentThread(StackContents &stackContents);
295 // Get the managed call stack for the specified thread.
296 static bool WalkManagedStackForThread(Thread *pThread, StackContents &stackContents);
298 // Save the command line for the current process.
299 static void SaveCommandLine(LPCWSTR pwzAssemblyPath, int argc, LPCWSTR *argv);
302 static EventPipeEventInstance *GetNextEvent();
305 // The counterpart to WriteEvent which after the payload is constructed
306 static void WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload &payload, LPCGUID pActivityId = NULL, LPCGUID pRelatedActivityId = NULL);
308 static void DisableInternal(EventPipeSessionID id);
310 // Enable the specified EventPipe session.
311 static EventPipeSessionID Enable(
312 LPCWSTR strOutputPath,
313 EventPipeSession *const pSession,
314 EventPipeSessionType sessionType,
315 IpcStream *const pStream);
317 static void CreateFlushTimerCallback();
319 static void DeleteFlushTimerCallback();
321 static void WINAPI FlushTimer(PVOID parameter, BOOLEAN timerFired);
323 // Callback function for the stack walker. For each frame walked, this callback is invoked.
324 static StackWalkAction StackWalkCallback(CrawlFrame *pCf, StackContents *pData);
326 // Get the configuration object.
327 // This is called directly by the EventPipeProvider constructor to register the new provider.
328 static EventPipeConfiguration *GetConfiguration()
330 LIMITED_METHOD_CONTRACT;
334 // Get the event pipe configuration lock.
335 static CrstStatic *GetLock()
337 LIMITED_METHOD_CONTRACT;
338 return &s_configCrst;
341 static CrstStatic s_configCrst;
342 static bool s_tracingInitialized;
343 static EventPipeConfiguration *s_pConfig;
344 static EventPipeSession *s_pSession;
345 static EventPipeBufferManager *s_pBufferManager;
346 static EventPipeFile *s_pFile;
347 static EventPipeEventSource *s_pEventSource;
348 static LPCWSTR s_pCommandLine;
349 static HANDLE s_fileSwitchTimerHandle;
350 static ULONGLONG s_lastFlushSwitchTime;
353 struct EventPipeProviderConfiguration
356 LPCWSTR m_pProviderName = nullptr;
357 UINT64 m_keywords = 0;
358 UINT32 m_loggingLevel = 0;
359 LPCWSTR m_pFilterData = nullptr;
362 EventPipeProviderConfiguration() = default;
364 EventPipeProviderConfiguration(LPCWSTR pProviderName, UINT64 keywords, UINT32 loggingLevel, LPCWSTR pFilterData) :
365 m_pProviderName(pProviderName),
366 m_keywords(keywords),
367 m_loggingLevel(loggingLevel),
368 m_pFilterData(pFilterData)
372 LPCWSTR GetProviderName() const
374 LIMITED_METHOD_CONTRACT;
375 return m_pProviderName;
378 UINT64 GetKeywords() const
380 LIMITED_METHOD_CONTRACT;
384 UINT32 GetLevel() const
386 LIMITED_METHOD_CONTRACT;
387 return m_loggingLevel;
390 LPCWSTR GetFilterData() const
392 LIMITED_METHOD_CONTRACT;
393 return m_pFilterData;
397 #endif // FEATURE_PERFTRACING
399 #endif // __EVENTPIPE_H__