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.
7 #include "eventpipeconfiguration.h"
8 #include "eventpipeeventinstance.h"
9 #include "eventpipeprovider.h"
11 #ifdef FEATURE_PERFTRACING
13 // {5291C09C-2660-4D6A-83A3-C383FD020DEC}
14 const GUID EventPipeConfiguration::s_configurationProviderID =
15 { 0x5291c09c, 0x2660, 0x4d6a, { 0x83, 0xa3, 0xc3, 0x83, 0xfd, 0x2, 0xd, 0xec } };
17 EventPipeConfiguration::EventPipeConfiguration()
22 m_rundownEnabled = false;
23 m_circularBufferSizeInBytes = 1024 * 1024 * 1000; // Default to 1000MB.
24 m_pEnabledProviderList = NULL;
25 m_pProviderList = new SList<SListElem<EventPipeProvider*>>();
28 EventPipeConfiguration::~EventPipeConfiguration()
38 if(m_pEnabledProviderList != NULL)
40 delete(m_pEnabledProviderList);
41 m_pEnabledProviderList = NULL;
44 if(m_pProviderList != NULL)
46 delete(m_pProviderList);
47 m_pProviderList = NULL;
51 void EventPipeConfiguration::Initialize()
61 // Create the configuration provider.
62 m_pConfigProvider = EventPipe::CreateProvider(s_configurationProviderID);
64 // Create the metadata event.
65 m_pMetadataEvent = m_pConfigProvider->AddEvent(
69 EventPipeEventLevel::LogAlways,
70 false); /* needStack */
73 bool EventPipeConfiguration::RegisterProvider(EventPipeProvider &provider)
83 // Take the lock before manipulating the provider list.
84 CrstHolder _crst(EventPipe::GetLock());
86 // See if we've already registered this provider.
87 EventPipeProvider *pExistingProvider = GetProviderNoLock(provider.GetProviderID());
88 if(pExistingProvider != NULL)
93 // The provider has not been registered, so register it.
94 m_pProviderList->InsertTail(new SListElem<EventPipeProvider*>(&provider));
96 // Set the provider configuration and enable it if we know anything about the provider before it is registered.
97 if(m_pEnabledProviderList != NULL)
99 EventPipeEnabledProvider *pEnabledProvider = m_pEnabledProviderList->GetEnabledProvider(&provider);
100 if(pEnabledProvider != NULL)
102 provider.SetConfiguration(
103 true /* providerEnabled */,
104 pEnabledProvider->GetKeywords(),
105 pEnabledProvider->GetLevel());
112 bool EventPipeConfiguration::UnregisterProvider(EventPipeProvider &provider)
122 // Take the lock before manipulating the provider list.
123 CrstHolder _crst(EventPipe::GetLock());
125 // Find the provider.
126 SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
129 if(pElem->GetValue() == &provider)
134 pElem = m_pProviderList->GetNext(pElem);
137 // If we found the provider, remove it.
140 if(m_pProviderList->FindAndRemove(pElem) != NULL)
149 EventPipeProvider* EventPipeConfiguration::GetProvider(const GUID &providerID)
159 // Take the lock before touching the provider list to ensure no one tries to
161 CrstHolder _crst(EventPipe::GetLock());
163 return GetProviderNoLock(providerID);
166 EventPipeProvider* EventPipeConfiguration::GetProviderNoLock(const GUID &providerID)
173 PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
177 SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
180 EventPipeProvider *pProvider = pElem->GetValue();
181 if(pProvider->GetProviderID() == providerID)
186 pElem = m_pProviderList->GetNext(pElem);
192 size_t EventPipeConfiguration::GetCircularBufferSize() const
194 LIMITED_METHOD_CONTRACT;
196 return m_circularBufferSizeInBytes;
199 void EventPipeConfiguration::SetCircularBufferSize(size_t circularBufferSize)
201 LIMITED_METHOD_CONTRACT;
205 m_circularBufferSizeInBytes = circularBufferSize;
209 void EventPipeConfiguration::Enable(
210 unsigned int circularBufferSizeInMB,
211 EventPipeProviderConfiguration *pProviders,
219 // Lock must be held by EventPipe::Enable.
220 PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
224 m_circularBufferSizeInBytes = circularBufferSizeInMB * 1024 * 1024;
225 m_pEnabledProviderList = new EventPipeEnabledProviderList(pProviders, static_cast<unsigned int>(numProviders));
228 SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
231 EventPipeProvider *pProvider = pElem->GetValue();
233 // Enable the provider if it has been configured.
234 EventPipeEnabledProvider *pEnabledProvider = m_pEnabledProviderList->GetEnabledProvider(pProvider);
235 if(pEnabledProvider != NULL)
237 pProvider->SetConfiguration(
238 true /* providerEnabled */,
239 pEnabledProvider->GetKeywords(),
240 pEnabledProvider->GetLevel());
243 pElem = m_pProviderList->GetNext(pElem);
248 void EventPipeConfiguration::Disable()
255 // Lock must be held by EventPipe::Disable.
256 PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
260 SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
263 EventPipeProvider *pProvider = pElem->GetValue();
264 pProvider->SetConfiguration(false /* providerEnabled */, 0 /* keywords */, EventPipeEventLevel::Critical /* level */);
266 pElem = m_pProviderList->GetNext(pElem);
270 m_rundownEnabled = false;
272 // Free the enabled providers list.
273 if(m_pEnabledProviderList != NULL)
275 delete(m_pEnabledProviderList);
276 m_pEnabledProviderList = NULL;
280 bool EventPipeConfiguration::Enabled() const
282 LIMITED_METHOD_CONTRACT;
286 bool EventPipeConfiguration::RundownEnabled() const
288 LIMITED_METHOD_CONTRACT;
289 return m_rundownEnabled;
292 void EventPipeConfiguration::EnableRundown()
299 // Lock must be held by EventPipe::Disable.
300 PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
304 // Build the rundown configuration.
305 _ASSERTE(m_pEnabledProviderList == NULL);
306 const unsigned int numRundownProviders = 2;
307 EventPipeProviderConfiguration rundownProviders[numRundownProviders];
308 rundownProviders[0] = EventPipeProviderConfiguration(W("e13c0d23-ccbc-4e12-931b-d9cc2eee27e4"), 0x80020138, static_cast<unsigned int>(EventPipeEventLevel::Verbose)); // Public provider.
309 rundownProviders[1] = EventPipeProviderConfiguration(W("a669021c-c450-4609-a035-5af59af4df18"), 0x80020138, static_cast<unsigned int>(EventPipeEventLevel::Verbose)); // Rundown provider.
312 m_rundownEnabled = true;
314 // Enable tracing. The circular buffer size doesn't matter because we're going to write all events synchronously during rundown.
315 Enable(1 /* circularBufferSizeInMB */, rundownProviders, numRundownProviders);
318 EventPipeEventInstance* EventPipeConfiguration::BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance)
328 // The payload of the event should contain:
329 // - GUID ProviderID.
330 // - unsigned int EventID.
331 // - unsigned int EventVersion.
332 // - Optional event description payload.
334 // Calculate the size of the event.
335 EventPipeEvent &sourceEvent = *sourceInstance.GetEvent();
336 const GUID &providerID = sourceEvent.GetProvider()->GetProviderID();
337 unsigned int eventID = sourceEvent.GetEventID();
338 unsigned int eventVersion = sourceEvent.GetEventVersion();
339 BYTE *pPayloadData = sourceEvent.GetMetadata();
340 unsigned int payloadLength = sourceEvent.GetMetadataLength();
341 unsigned int instancePayloadSize = sizeof(providerID) + sizeof(eventID) + sizeof(eventVersion) + sizeof(payloadLength) + payloadLength;
343 // Allocate the payload.
344 BYTE *pInstancePayload = new BYTE[instancePayloadSize];
346 // Fill the buffer with the payload.
347 BYTE *currentPtr = pInstancePayload;
349 // Write the provider ID.
350 memcpy(currentPtr, (BYTE*)&providerID, sizeof(providerID));
351 currentPtr += sizeof(providerID);
353 // Write the event ID.
354 memcpy(currentPtr, &eventID, sizeof(eventID));
355 currentPtr += sizeof(eventID);
357 // Write the event version.
358 memcpy(currentPtr, &eventVersion, sizeof(eventVersion));
359 currentPtr += sizeof(eventVersion);
361 // Write the size of the metadata.
362 memcpy(currentPtr, &payloadLength, sizeof(payloadLength));
363 currentPtr += sizeof(payloadLength);
365 // Write the incoming payload data.
366 memcpy(currentPtr, pPayloadData, payloadLength);
368 // Construct the event instance.
369 EventPipeEventInstance *pInstance = new EventPipeEventInstance(
371 GetCurrentThreadId(),
374 NULL /* pActivityId */,
375 NULL /* pRelatedActivityId */);
377 // Set the timestamp to match the source event, because the metadata event
378 // will be emitted right before the source event.
379 pInstance->SetTimeStamp(sourceInstance.GetTimeStamp());
384 void EventPipeConfiguration::DeleteDeferredProviders()
391 // Lock must be held by EventPipe::Disable.
392 PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
397 SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
400 EventPipeProvider *pProvider = pElem->GetValue();
401 if(pProvider->GetDeleteDeferred())
403 // The act of deleting the provider unregisters it and removes it from the list.
407 pElem = m_pProviderList->GetNext(pElem);
411 EventPipeEnabledProviderList::EventPipeEnabledProviderList(
412 EventPipeProviderConfiguration *pConfigs,
413 unsigned int numConfigs)
424 m_pCatchAllProvider = NULL;
427 // Test COMPLUS variable to enable tracing at start-up.
428 // If tracing is enabled at start-up create the catch-all provider and always return it.
429 if((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PerformanceTracing) & 1) == 1)
431 m_pCatchAllProvider = new EventPipeEnabledProvider();
432 m_pCatchAllProvider->Set(NULL, 0xFFFFFFFFFFFFFFFF, EventPipeEventLevel::Verbose);
436 m_pCatchAllProvider = NULL;
437 m_numProviders = numConfigs;
438 if(m_numProviders == 0)
443 m_pProviders = new EventPipeEnabledProvider[m_numProviders];
444 for(int i=0; i<m_numProviders; i++)
447 pConfigs[i].GetProviderName(),
448 pConfigs[i].GetKeywords(),
449 (EventPipeEventLevel)pConfigs[i].GetLevel());
453 EventPipeEnabledProviderList::~EventPipeEnabledProviderList()
463 if(m_pProviders != NULL)
465 delete[] m_pProviders;
468 if(m_pCatchAllProvider != NULL)
470 delete(m_pCatchAllProvider);
471 m_pCatchAllProvider = NULL;
475 EventPipeEnabledProvider* EventPipeEnabledProviderList::GetEnabledProvider(
476 EventPipeProvider *pProvider)
486 // If tracing was enabled on start-up, all events should be on (this is a diagnostic config).
487 if(m_pCatchAllProvider != NULL)
489 return m_pCatchAllProvider;
492 if(m_pProviders == NULL)
497 // TEMPORARY: Convert the provider GUID to a string.
498 const unsigned int guidSize = 39;
499 WCHAR wszProviderID[guidSize];
500 if(!StringFromGUID2(pProvider->GetProviderID(), wszProviderID, guidSize))
502 wszProviderID[0] = '\0';
506 SString providerNameStr(&wszProviderID[1], guidSize-3);
507 LPCWSTR providerName = providerNameStr.GetUnicode();
509 EventPipeEnabledProvider *pEnabledProvider = NULL;
510 for(int i=0; i<m_numProviders; i++)
512 EventPipeEnabledProvider *pCandidate = &m_pProviders[i];
513 if(pCandidate != NULL)
515 if(wcscmp(providerName, pCandidate->GetProviderName()) == 0)
517 pEnabledProvider = pCandidate;
523 return pEnabledProvider;
526 EventPipeEnabledProvider::EventPipeEnabledProvider()
528 LIMITED_METHOD_CONTRACT;
529 m_pProviderName = NULL;
533 EventPipeEnabledProvider::~EventPipeEnabledProvider()
543 if(m_pProviderName != NULL)
545 delete[] m_pProviderName;
546 m_pProviderName = NULL;
550 void EventPipeEnabledProvider::Set(LPCWSTR providerName, UINT64 keywords, EventPipeEventLevel loggingLevel)
560 if(m_pProviderName != NULL)
562 delete(m_pProviderName);
563 m_pProviderName = NULL;
566 if(providerName != NULL)
568 unsigned int bufSize = wcslen(providerName) + 1;
569 m_pProviderName = new WCHAR[bufSize];
570 wcscpy_s(m_pProviderName, bufSize, providerName);
572 m_keywords = keywords;
573 m_loggingLevel = loggingLevel;
576 LPCWSTR EventPipeEnabledProvider::GetProviderName() const
578 LIMITED_METHOD_CONTRACT;
579 return m_pProviderName;
582 UINT64 EventPipeEnabledProvider::GetKeywords() const
584 LIMITED_METHOD_CONTRACT;
588 EventPipeEventLevel EventPipeEnabledProvider::GetLevel() const
590 LIMITED_METHOD_CONTRACT;
591 return m_loggingLevel;
594 #endif // FEATURE_PERFTRACING