diff options
author | Sung Yoon Whang <suwhang@microsoft.com> | 2019-06-25 21:03:04 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-25 21:03:04 -0700 |
commit | 68f6fd0b3294894d2d39357eff895b5a6b11433f (patch) | |
tree | 649f807469a91127b07bd4c89a2e980ba93fc96f | |
parent | 5ad5f29d5e3009396c92047220255f36b33eddcf (diff) | |
download | coreclr-68f6fd0b3294894d2d39357eff895b5a6b11433f.tar.gz coreclr-68f6fd0b3294894d2d39357eff895b5a6b11433f.tar.bz2 coreclr-68f6fd0b3294894d2d39357eff895b5a6b11433f.zip |
Fix LTTng filtering for runtime providers (#25374)
* LTTng filtering
* Fix Windows build, make IsInitialized check faster
* Cleanup/change default to no keywords/level set
* Keep the default to be the current policy - enable everything
* more cleanup
* No need to check for initialization
* Fix Windows build
-rw-r--r-- | src/inc/clrconfigvalues.h | 12 | ||||
-rw-r--r-- | src/inc/eventtracebase.h | 263 | ||||
-rw-r--r-- | src/scripts/genEventing.py | 64 | ||||
-rw-r--r-- | src/vm/eventtrace.cpp | 4 |
4 files changed, 306 insertions, 37 deletions
diff --git a/src/inc/clrconfigvalues.h b/src/inc/clrconfigvalues.h index 4343ef4942..a97e53d4f8 100644 --- a/src/inc/clrconfigvalues.h +++ b/src/inc/clrconfigvalues.h @@ -249,11 +249,6 @@ CONFIG_DWORD_INFO(INTERNAL_SuppressLockViolationsOnReentryFromOS, W("SuppressLoc #endif // WIN64EXCEPTIONS /// -/// Diagnostics (unsuported general-purpose) -/// -RETAIL_CONFIG_DWORD_INFO(UNSUPORTED_LTTng, W("LTTng"), 1, "If COMPlus_LTTng is set to 0, this will prevent the LTTng library from being loaded at runtime") - -/// /// Exception Handling /// CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AssertOnFailFast, W("AssertOnFailFast"), "") @@ -726,6 +721,13 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeRundown, W("EventPipeRundown"), 1, "E RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeCircularMB, W("EventPipeCircularMB"), 1024, "The EventPipe circular buffer size in megabytes.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers"), 0, "Enable/disable capturing processor numbers in EventPipe event headers") +// +// LTTng +// +RETAIL_CONFIG_STRING_INFO(INTERNAL_LTTngConfig, W("LTTngConfig"), "Configuration for LTTng.") +RETAIL_CONFIG_DWORD_INFO(UNSUPORTED_LTTng, W("LTTng"), 1, "If COMPlus_LTTng is set to 0, this will prevent the LTTng library from being loaded at runtime") + + #ifdef FEATURE_GDBJIT /// /// GDBJIT diff --git a/src/inc/eventtracebase.h b/src/inc/eventtracebase.h index bda2262bc7..09c82fcb7b 100644 --- a/src/inc/eventtracebase.h +++ b/src/inc/eventtracebase.h @@ -103,12 +103,12 @@ enum EtwThreadFlags #define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) #define ETW_EVENT_ENABLED(Context, EventDescriptor) (EventPipeHelper::IsEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword) || \ - (XplatEventLogger::IsEventLoggingEnabled())) + (XplatEventLogger::IsKeywordEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword))) #define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::IsEnabled(Context, Level, Keyword) || \ - (XplatEventLogger::IsEventLoggingEnabled()) + (XplatEventLogger::IsKeywordEnabled(Context, Level, Keyword))) #define ETW_TRACING_ENABLED(Context, EventDescriptor) (EventEnabled##EventDescriptor()) #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::IsEnabled(Context, Level, Keyword) || \ - (XplatEventLogger::IsEventLoggingEnabled())) + (XplatEventLogger::IsKeywordEnabled(Context, Level, Keyword))) #define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) #else //defined(FEATURE_PERFTRACING) #define ETW_INLINE @@ -116,11 +116,11 @@ enum EtwThreadFlags #define ETWFireEvent(EventName) #define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) -#define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (XplatEventLogger::IsEventLoggingEnabled()) -#define ETW_EVENT_ENABLED(Context, EventDescriptor) (XplatEventLogger::IsEventLoggingEnabled()) -#define ETW_TRACING_ENABLED(Context, EventDescriptor) (EventEnabled##EventDescriptor()) -#define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (XplatEventLogger::IsEventLoggingEnabled()) -#define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) +#define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (XplatEventLogger::IsKeywordEnabled(Context, Level, Keyword)) +#define ETW_EVENT_ENABLED(Context, EventDescriptor) (XplatEventLogger::IsKeywordEnabled(Context, EventDescriptor.Level, EventDescriptor.KeywordsBitmask)) +#define ETW_TRACING_ENABLED(Context, EventDescriptor) (ETW_EVENT_ENABLED(Context, EventDescriptor) && EventEnabled##EventDescriptor()) +#define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (ETW_CATEGORY_ENABLED(Context, Level, Keyword)) +#define ETW_PROVIDER_ENABLED(ProviderSymbol) (XplatEventLogger::IsProviderEnabled(Context)) #endif // defined(FEATURE_PERFTRACING) #endif // !defined(FEATURE_PAL) @@ -237,23 +237,250 @@ extern UINT32 g_nClrInstanceId; #define DEF_LTTNG_KEYWORD_ENABLED 1 #include "clrproviders.h" #include "clrconfig.h" -#endif // defined(FEATURE_PAL) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +class XplatEventLoggerConfiguration +{ +public: + XplatEventLoggerConfiguration() = default; -#if defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT) + XplatEventLoggerConfiguration(XplatEventLoggerConfiguration const & other) = delete; + XplatEventLoggerConfiguration(XplatEventLoggerConfiguration && other) + { + _provider = std::move(other._provider); + _isValid = other._isValid; + _enabledKeywords = other._enabledKeywords; + _level = other._level; + } -#include "clrconfig.h" - class XplatEventLogger -{ + ~XplatEventLoggerConfiguration() + { + _provider = nullptr; + } + + void Initialize(LPWSTR configString) + { + Parse(configString); + } + + bool IsValid() const + { + return _isValid; + } + + LPCWSTR GetProviderName() const + { + return _provider; + } + + ULONGLONG GetEnabledKeywordsMask() const + { + return _enabledKeywords; + } + + UINT GetLevel() const + { + return _level; + } + +private: + struct ComponentSpan + { public: - inline static BOOL IsEventLoggingEnabled() + ComponentSpan(LPCWSTR start, LPCWSTR end) + : Start(start), End(end) + { + } + + LPCWSTR Start; + LPCWSTR End; + }; + + void Parse(LPWSTR configString) + { + if (configString == nullptr || *configString == L'\0') + { + _provider = W("*"); + _enabledKeywords = (ULONGLONG)(-1); + _level = TRACE_LEVEL_VERBOSE; + return; + } + + auto providerComponent = GetNextComponentString(configString); + _provider = ParseProviderName(providerComponent); + if (_provider == nullptr) + { + _isValid = false; + return; + } + + auto keywordsComponent = GetNextComponentString(providerComponent.End + 1); + _enabledKeywords = ParseEnabledKeywordsMask(keywordsComponent); + + auto levelComponent = GetNextComponentString(keywordsComponent.End + 1); + _level = ParseEnabledKeywordsMask(levelComponent); + _isValid = true; + } + + ComponentSpan GetNextComponentString(LPCWSTR start) const + { + static WCHAR ComponentDelimiter = W(':'); + + auto end = wcschr(start, ComponentDelimiter); + if (end == nullptr) + { + end = start + wcslen(start); + } + + return ComponentSpan(start, end); + } + + LPCWSTR ParseProviderName(ComponentSpan const & component) const + { + auto providerName = (WCHAR*)nullptr; + if ((component.End - component.Start) != 0) + { + auto const length = component.End - component.Start; + providerName = new WCHAR[length + 1]; + memset(providerName, '\0', (length + 1) * sizeof(WCHAR)); + wcsncpy(providerName, component.Start, length); + } + return providerName; + } + + ULONGLONG ParseEnabledKeywordsMask(ComponentSpan const & component) const + { + auto enabledKeywordsMask = (ULONGLONG)(-1); + if ((component.End - component.Start) != 0) + { + enabledKeywordsMask = _wcstoui64(component.Start, nullptr, 16); + } + return enabledKeywordsMask; + } + + UINT ParseLevel(ComponentSpan const & component) const + { + auto level = TRACE_LEVEL_VERBOSE; + if ((component.End - component.Start) != 0) + { + level = _wtoi(component.Start); + } + return level; + } + + LPCWSTR _provider; + ULONGLONG _enabledKeywords; + UINT _level; + bool _isValid; +}; + +class XplatEventLoggerController +{ +public: + + static void Initialize(XplatEventLoggerConfiguration const &config) + { + if (!config.IsValid()) + { + return; + } + + auto providerName = config.GetProviderName(); + auto enabledKeywordsMask = config.GetEnabledKeywordsMask(); + auto level = config.GetLevel(); + if (_wcsicmp(providerName, W("*")) == 0 && enabledKeywordsMask == (ULONGLONG)(-1) && level == TRACE_LEVEL_VERBOSE) + { + ActivateAllKeywordsOfAllProviders(); + } + else + { + auto provider = GetProvider(providerName); + if (provider == nullptr) + { + return; + } + provider->EnabledKeywordsBitmask = enabledKeywordsMask; + provider->Level = level; + provider->IsEnabled = true; + } + } + +private: + + static LTTNG_TRACE_CONTEXT * const GetProvider(LPCWSTR providerName) + { + auto length = wcslen(providerName); + for (auto provider : ALL_LTTNG_PROVIDERS_CONTEXT) + { + if (_wcsicmp(provider->Name, providerName) == 0) + { + return provider; + } + } + return nullptr; + } + + static void ActivateAllKeywordsOfAllProviders() + { + for (LTTNG_TRACE_CONTEXT * const provider : ALL_LTTNG_PROVIDERS_CONTEXT) + { + provider->EnabledKeywordsBitmask = (ULONGLONG)(-1); + provider->Level = TRACE_LEVEL_VERBOSE; + provider->IsEnabled = true; + } + } +}; + +class XplatEventLogger +{ +public: + + inline static BOOL IsEventLoggingEnabled() + { + static ConfigDWORD configEventLogging; + return configEventLogging.val(CLRConfig::EXTERNAL_EnableEventLog); + } + + inline static bool IsProviderEnabled(DOTNET_TRACE_CONTEXT providerCtx) + { + return providerCtx.LttngProvider->IsEnabled; + } + + inline static bool IsKeywordEnabled(DOTNET_TRACE_CONTEXT providerCtx, UCHAR level, ULONGLONG keyword) + { + if (!providerCtx.LttngProvider->IsEnabled) { - static ConfigDWORD configEventLogging; - return configEventLogging.val(CLRConfig::EXTERNAL_EnableEventLog); + return false; } + + if ((level <= providerCtx.LttngProvider->Level) || (providerCtx.LttngProvider->Level == 0)) + { + if ((keyword == 0) || ((keyword & providerCtx.LttngProvider->EnabledKeywordsBitmask) != 0)) + { + return true; + } + } + return false; + } + + static void InitializeLogger() + { + if (!IsEventLoggingEnabled()) + { + return; + } + + LPWSTR xplatEventConfig = NULL; + CLRConfig::GetConfigValue(CLRConfig::INTERNAL_LTTngConfig, &xplatEventConfig); + + auto configuration = XplatEventLoggerConfiguration(); + configuration.Initialize(xplatEventConfig); + + XplatEventLoggerController::Initialize(configuration); + } }; -#endif //defined(FEATURE_EVENT_TRACE) + +#endif // defined(FEATURE_PAL) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) #if defined(FEATURE_EVENT_TRACE) @@ -346,8 +573,8 @@ extern "C" { #endif //!DONOT_DEFINE_ETW_CALLBACK && !DACCESS_COMPILE #endif //!FEATURE_PAL - #include "clretwallmain.h" + #if defined(FEATURE_PERFTRACING) class EventPipeHelper { diff --git a/src/scripts/genEventing.py b/src/scripts/genEventing.py index bdc1d88096..539733d117 100644 --- a/src/scripts/genEventing.py +++ b/src/scripts/genEventing.py @@ -273,8 +273,12 @@ def generateClrallEvents(eventNodes,allTemplates): clrallEvents.append("inline BOOL EventEnabled") clrallEvents.append(eventName) clrallEvents.append("() {return ") - clrallEvents.append("EventPipeEventEnabled" + eventName + "() || ") - clrallEvents.append("(XplatEventLogger::IsEventLoggingEnabled() && EventXplatEnabled" + eventName + "());}\n\n") + clrallEvents.append("EventPipeEventEnabled" + eventName + "()") + + if os.name == 'posix': + clrallEvents.append("|| (XplatEventLogger::IsEventLoggingEnabled() && EventXplatEnabled" + eventName + "());}\n\n") + else: + clrallEvents.append(";}\n\n") #generate FireEtw functions fnptype = [] fnbody = [] @@ -550,6 +554,19 @@ typedef struct _EVENTPIPE_TRACE_CONTEXT #endif // EVENTPIPE_TRACE_CONTEXT_DEF """ + lttng_trace_context_typedef = """ +#if !defined(LTTNG_TRACE_CONTEXT_DEF) +#define LTTNG_TRACE_CONTEXT_DEF +typedef struct _LTTNG_TRACE_CONTEXT +{ + WCHAR const * Name; + UCHAR Level; + bool IsEnabled; + ULONGLONG EnabledKeywordsBitmask; +} LTTNG_TRACE_CONTEXT, *PLTTNG_TRACE_CONTEXT; +#endif // LTTNG_TRACE_CONTEXT_DEF +""" + dotnet_trace_context_typedef_windows = """ #if !defined(DOTNET_TRACE_CONTEXT_DEF) #define DOTNET_TRACE_CONTEXT_DEF @@ -567,6 +584,7 @@ typedef struct _DOTNET_TRACE_CONTEXT typedef struct _DOTNET_TRACE_CONTEXT { EVENTPIPE_TRACE_CONTEXT EventPipeProvider; + PLTTNG_TRACE_CONTEXT LttngProvider; } DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT; #endif // DOTNET_TRACE_CONTEXT_DEF """ @@ -582,13 +600,13 @@ EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNT """ trace_context_instdef_unix = """ -EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context }; +EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_LTTNG_Context }; -EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context }; +EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_LTTNG_Context }; -EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context }; +EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_LTTNG_Context }; -EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context }; +EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_LTTNG_Context }; """ # Write the main header for FireETW* functions @@ -601,13 +619,11 @@ EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNT #include "clreventpipewriteevents.h" """) - Clrallevents.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT # define DOTNET_TRACE_CONTEXT depending on the platform if is_windows: + Clrallevents.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT Clrallevents.write(dotnet_trace_context_typedef_windows) - else: - Clrallevents.write(dotnet_trace_context_typedef_unix) for providerNode in tree.getElementsByTagName('provider'): templateNodes = providerNode.getElementsByTagName('template') @@ -620,14 +636,13 @@ EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNT providerName = providerNode.getAttribute('name') providerSymbol = providerNode.getAttribute('symbol') - eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context" - Clrallevents.write('EXTERN_C __declspec(selectany) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') + if is_windows: + eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context" + Clrallevents.write('EXTERN_C __declspec(selectany) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') # define and initialize runtime providers' DOTNET_TRACE_CONTEXT depending on the platform if is_windows: Clrallevents.write(trace_context_instdef_windows) - else: - Clrallevents.write(trace_context_instdef_unix) if write_xplatheader: clrproviders = os.path.join(incDir, "clrproviders.h") @@ -639,13 +654,26 @@ EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNT ULONGLONG const Keyword; } EVENT_DESCRIPTOR; """) + + if not is_windows: + Clrproviders.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT + Clrproviders.write(lttng_trace_context_typedef) # define LTTNG_TRACE_CONTEXT + Clrproviders.write(dotnet_trace_context_typedef_unix) + allProviders = [] + nbProviders = 0 for providerNode in tree.getElementsByTagName('provider'): keywords = [] keywordsToMask = {} providerName = str(providerNode.getAttribute('name')) providerSymbol = str(providerNode.getAttribute('symbol')) + nbProviders += 1 nbKeywords = 0 + if not is_windows: + eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context" + Clrproviders.write('EXTERN_C __declspec(selectany) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') + lttngProviderCtxName = providerSymbol + "_LTTNG_Context" + Clrproviders.write('EXTERN_C __declspec(selectany) LTTNG_TRACE_CONTEXT ' + lttngProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') Clrproviders.write("// Keywords\n"); for keywordNode in providerNode.getElementsByTagName('keyword'): @@ -665,7 +693,15 @@ EXTERN_C __declspec(selectany) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNT level = convertToLevelId(levelName) Clrproviders.write("EXTERN_C __declspec(selectany) EVENT_DESCRIPTOR const " + symbolName + " = { " + str(level) + ", " + hex(getKeywordsMaskCombined(keywords, keywordsToMask)) + " };\n") - allProviders.append("&" + providerSymbol + "_Context") + allProviders.append("&" + providerSymbol + "_LTTNG_Context") + + # define and initialize runtime providers' DOTNET_TRACE_CONTEXT depending on the platform + if not is_windows: + Clrproviders.write('#define NB_PROVIDERS ' + str(nbProviders) + '\n') + Clrproviders.write('EXTERN_C __declspec(selectany) LTTNG_TRACE_CONTEXT * const ALL_LTTNG_PROVIDERS_CONTEXT[NB_PROVIDERS] = { ') + Clrproviders.write(', '.join(allProviders)) + Clrproviders.write(' };\n') + Clrproviders.write(trace_context_instdef_unix) clreventpipewriteevents = os.path.join(incDir, "clreventpipewriteevents.h") diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp index da3bc0db27..f97ef52249 100644 --- a/src/vm/eventtrace.cpp +++ b/src/vm/eventtrace.cpp @@ -4163,6 +4163,10 @@ void InitializeEventTracing() // Any classes that need some initialization to happen after we've registered the // providers can do so now ETW::TypeSystemLog::PostRegistrationInit(); + +#if defined(FEATURE_PAL) && defined (FEATURE_PERFTRACING) + XplatEventLogger::InitializeLogger(); +#endif // FEATURE_PAL && FEATURE_PERFTRACING } // Plumbing to funnel event pipe callbacks and ETW callbacks together into a single common |