From 76c7fe9cf8aa6774a6b9fa5d1dd699262fae737e Mon Sep 17 00:00:00 2001 From: Brian Robbins Date: Mon, 5 Feb 2018 16:15:55 -0800 Subject: [PATCH] Remove FEATURE_ACTIVITYSAMPLING and associated code. (#16185) --- .../System/Diagnostics/Tracing/EventProvider.cs | 6 - .../System/Diagnostics/Tracing/EventSource.cs | 1207 -------------------- .../TraceLogging/TraceLoggingEventSource.cs | 4 - .../Diagnostics/Eventing/EventSource_CoreCLR.cs | 44 +- 4 files changed, 10 insertions(+), 1251 deletions(-) diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs index 64c2491..bd50f9c 100644 --- a/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs +++ b/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs @@ -259,12 +259,6 @@ namespace System.Diagnostics.Tracing m_anyKeywordMask = anyKeyword; m_allKeywordMask = allKeyword; - // ES_SESSION_INFO is a marker for additional places we #ifdeffed out to remove - // references to EnumerateTraceGuidsEx. This symbol is actually not used because - // today we use FEATURE_ACTIVITYSAMPLING to determine if this code is there or not. - // However we put it in the #if so that we don't lose the fact that this feature - // switch is at least partially independent of FEATURE_ACTIVITYSAMPLING - List> sessionsChanged = GetSessions(); foreach (var session in sessionsChanged) { diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs index f6d4899..d0d1fad 100644 --- a/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs +++ b/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs @@ -4,10 +4,6 @@ // This program uses code hyperlinks available as part of the HyperAddin Visual Studio plug-in. // It is available from http://www.codeplex.com/hyperAddin -#if PLATFORM_WINDOWS && !ES_BUILD_STANDALONE && !CORECLR && !ES_BUILD_PN -#define FEATURE_ACTIVITYSAMPLING -#endif // !ES_BUILD_STANDALONE - #if ES_BUILD_STANDALONE #define FEATURE_MANAGED_ETW_CHANNELS // #define FEATURE_ADVANCED_MANAGED_ETW_CHANNELS @@ -170,9 +166,6 @@ // using System; using System.Runtime.CompilerServices; -#if FEATURE_ACTIVITYSAMPLING -using System.Collections.Concurrent; -#endif using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; @@ -308,83 +301,7 @@ namespace System.Diagnostics.Tracing if (!IsEnabledCommon(m_eventSourceEnabled, m_level, m_matchAnyKeyword, level, keywords, channel)) return false; -#if !FEATURE_ACTIVITYSAMPLING - return true; - -#else // FEATURE_ACTIVITYSAMPLING - - return true; - -#if OPTIMIZE_IS_ENABLED - //================================================================================ - // 2013/03/06 - The code below is a possible optimization for IsEnabled(level, kwd) - // in case activity tracing/sampling is enabled. The added complexity of this - // code however weighs against having it "on" until we know it's really needed. - // For now we'll have this #ifdef-ed out in case we see evidence this is needed. - //================================================================================ - - // At this point we believe the event is enabled, however we now need to check - // if we filter because of activity - - // Optimization, all activity filters also register a delegate here, so if there - // is no delegate, we know there are no activity filters, which means that there - // is no additional filtering, which means that we can return true immediately. - if (s_activityDying == null) - return true; - - // if there's at least one legacy ETW listener we can't filter this - if (m_legacySessions != null && m_legacySessions.Count > 0) - return true; - - // if any event ID that triggers a new activity, or "transfers" activities - // is covered by 'keywords' we can't filter this - if (unchecked(((long)keywords & m_keywordTriggers)) != 0) - return true; - - // See if all listeners have activity filters that would block the event. - for (int perEventSourceSessionId = 0; perEventSourceSessionId < SessionMask.MAX; ++perEventSourceSessionId) - { - EtwSession etwSession = m_etwSessionIdMap[perEventSourceSessionId]; - if (etwSession == null) - continue; - - ActivityFilter activityFilter = etwSession.m_activityFilter; - if (activityFilter == null || - ActivityFilter.GetFilter(activityFilter, this) == null) - { - // No activity filter for ETW, if event is active for ETW, we can't filter. - for (int i = 0; i < m_eventData.Length; i++) - if (m_eventData[i].EnabledForETW) - return true; - } - else if (ActivityFilter.IsCurrentActivityActive(activityFilter)) - return true; - } - - // for regular event listeners - var curDispatcher = m_Dispatchers; - while (curDispatcher != null) - { - ActivityFilter activityFilter = curDispatcher.m_Listener.m_activityFilter; - if (activityFilter == null) - { - // See if any event is enabled. - for (int i = 0; i < curDispatcher.m_EventEnabled.Length; i++) - if (curDispatcher.m_EventEnabled[i]) - return true; - } - else if (ActivityFilter.IsCurrentActivityActive(activityFilter)) - return true; - curDispatcher = curDispatcher.m_Next; - } - - // Every listener has an activity filter that is blocking writing the event, - // thus the event is not enabled. - return false; -#endif // OPTIMIZE_IS_ENABLED - -#endif // FEATURE_ACTIVITYSAMPLING } /// @@ -1257,75 +1174,6 @@ namespace System.Diagnostics.Tracing #if FEATURE_MANAGED_ETW if (m_eventData[eventId].EnabledForETW) { - -#if FEATURE_ACTIVITYSAMPLING - // this code should be kept in sync with WriteEventVarargs(). - SessionMask etwSessions = SessionMask.All; - // only compute etwSessions if there are *any* ETW filters enabled... - if ((ulong)m_curLiveSessions != 0) - etwSessions = GetEtwSessionMask(eventId, relatedActivityId); - // OutputDebugString(string.Format("{0}.WriteEvent(id {1}) -> to sessions {2:x}", - // m_name, m_eventData[eventId].Name, (ulong) etwSessions)); - - if ((ulong)etwSessions != 0 || m_legacySessions != null && m_legacySessions.Count > 0) - { - if (!SelfDescribingEvents) - { - if (etwSessions.IsEqualOrSupersetOf(m_curLiveSessions)) - { - // OutputDebugString(string.Format(" (1) id {0}, kwd {1:x}", - // m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Keywords)); - // by default the Descriptor.Keyword will have the perEventSourceSessionId bit - // mask set to 0x0f so, when all ETW sessions want the event we don't need to - // synthesize a new one - if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data)) - ThrowEventSourceException(m_eventData[eventId].Name); - } - else - { - long origKwd = unchecked((long)((ulong)m_eventData[eventId].Descriptor.Keywords & ~(SessionMask.All.ToEventKeywords()))); - // OutputDebugString(string.Format(" (2) id {0}, kwd {1:x}", - // m_eventData[eventId].Name, etwSessions.ToEventKeywords() | (ulong) origKwd)); - // only some of the ETW sessions will receive this event. Synthesize a new - // Descriptor whose Keywords field will have the appropriate bits set. - // etwSessions might be 0, if there are legacy ETW listeners that want this event - var desc = new EventDescriptor( - m_eventData[eventId].Descriptor.EventId, - m_eventData[eventId].Descriptor.Version, - m_eventData[eventId].Descriptor.Channel, - m_eventData[eventId].Descriptor.Level, - m_eventData[eventId].Descriptor.Opcode, - m_eventData[eventId].Descriptor.Task, - unchecked((long)etwSessions.ToEventKeywords() | origKwd)); - - if (!m_provider.WriteEvent(ref desc, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data)) - ThrowEventSourceException(m_eventData[eventId].Name); - } - } - else - { - TraceLoggingEventTypes tlet = m_eventData[eventId].TraceLoggingEventTypes; - if (tlet == null) - { - tlet = new TraceLoggingEventTypes(m_eventData[eventId].Name, - EventTags.None, - m_eventData[eventId].Parameters); - Interlocked.CompareExchange(ref m_eventData[eventId].TraceLoggingEventTypes, tlet, null); - - } - long origKwd = unchecked((long)((ulong)m_eventData[eventId].Descriptor.Keywords & ~(SessionMask.All.ToEventKeywords()))); - // TODO: activity ID support - EventSourceOptions opt = new EventSourceOptions - { - Keywords = (EventKeywords)unchecked((long)etwSessions.ToEventKeywords() | origKwd), - Level = (EventLevel)m_eventData[eventId].Descriptor.Level, - Opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode - }; - - WriteMultiMerge(m_eventData[eventId].Name, ref opt, tlet, pActivityId, relatedActivityId, data); - } - } -#else if (!SelfDescribingEvents) { if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data)) @@ -1351,7 +1199,6 @@ namespace System.Diagnostics.Tracing WriteMultiMerge(m_eventData[eventId].Name, ref opt, tlet, pActivityId, relatedActivityId, data); } -#endif // FEATURE_ACTIVITYSAMPLING } #endif // FEATURE_MANAGED_ETW @@ -1455,30 +1302,6 @@ namespace System.Diagnostics.Tracing #endregion #region private -#if FEATURE_ACTIVITYSAMPLING - internal void WriteStringToListener(EventListener listener, string msg, SessionMask m) - { - Debug.Assert(listener == null || (uint)m == (uint)SessionMask.FromId(0)); - - if (m_eventSourceEnabled) - { - if (listener == null) - { - WriteEventString(0, unchecked((long)m.ToEventKeywords()), msg); - } - else - { - EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this); - eventCallbackArgs.EventId = 0; - eventCallbackArgs.Message = msg; - eventCallbackArgs.Payload = new ReadOnlyCollection(new List() { msg }); - eventCallbackArgs.PayloadNames = new ReadOnlyCollection(new List { "message" }); - eventCallbackArgs.EventName = "EventSourceMessage"; - listener.OnEventWritten(eventCallbackArgs); - } - } - } -#endif private unsafe void WriteEventRaw( string eventName, @@ -1543,10 +1366,6 @@ namespace System.Diagnostics.Tracing m_name = eventSourceName; m_guid = eventSourceGuid; -#if FEATURE_ACTIVITYSAMPLING - m_curLiveSessions = new SessionMask(0); - m_etwSessionIdMap = new EtwSession[SessionMask.MAX]; -#endif // FEATURE_ACTIVITYSAMPLING //Enable Implicit Activity tracker m_activityTracker = ActivityTracker.Instance; @@ -2024,67 +1843,6 @@ namespace System.Diagnostics.Tracing #if FEATURE_MANAGED_ETW if (m_eventData[eventId].EnabledForETW) { -#if FEATURE_ACTIVITYSAMPLING - // this code should be kept in sync with WriteEventWithRelatedActivityIdCore(). - SessionMask etwSessions = SessionMask.All; - // only compute etwSessions if there are *any* ETW filters enabled... - if ((ulong)m_curLiveSessions != 0) - etwSessions = GetEtwSessionMask(eventId, childActivityID); - - if ((ulong)etwSessions != 0 || m_legacySessions != null && m_legacySessions.Count > 0) - { - if (!SelfDescribingEvents) - { - if (etwSessions.IsEqualOrSupersetOf(m_curLiveSessions)) - { - // by default the Descriptor.Keyword will have the perEventSourceSessionId bit - // mask set to 0x0f so, when all ETW sessions want the event we don't need to - // synthesize a new one - if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args)) - ThrowEventSourceException(m_eventData[eventId].Name); - } - else - { - long origKwd = unchecked((long)((ulong)m_eventData[eventId].Descriptor.Keywords & ~(SessionMask.All.ToEventKeywords()))); - // only some of the ETW sessions will receive this event. Synthesize a new - // Descriptor whose Keywords field will have the appropriate bits set. - var desc = new EventDescriptor( - m_eventData[eventId].Descriptor.EventId, - m_eventData[eventId].Descriptor.Version, - m_eventData[eventId].Descriptor.Channel, - m_eventData[eventId].Descriptor.Level, - m_eventData[eventId].Descriptor.Opcode, - m_eventData[eventId].Descriptor.Task, - unchecked((long)etwSessions.ToEventKeywords() | origKwd)); - - if (!m_provider.WriteEvent(ref desc, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args)) - ThrowEventSourceException(m_eventData[eventId].Name); - } - } - else - { - TraceLoggingEventTypes tlet = m_eventData[eventId].TraceLoggingEventTypes; - if (tlet == null) - { - tlet = new TraceLoggingEventTypes(m_eventData[eventId].Name, - EventTags.None, - m_eventData[eventId].Parameters); - Interlocked.CompareExchange(ref m_eventData[eventId].TraceLoggingEventTypes, tlet, null); - - } - long origKwd = unchecked((long)((ulong)m_eventData[eventId].Descriptor.Keywords & ~(SessionMask.All.ToEventKeywords()))); - // TODO: activity ID support - EventSourceOptions opt = new EventSourceOptions - { - Keywords = (EventKeywords)unchecked((long)etwSessions.ToEventKeywords() | origKwd), - Level = (EventLevel)m_eventData[eventId].Descriptor.Level, - Opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode - }; - - WriteMultiMerge(m_eventData[eventId].Name, ref opt, tlet, pActivityId, childActivityID, args); - } - } -#else if (!SelfDescribingEvents) { if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args)) @@ -2111,7 +1869,6 @@ namespace System.Diagnostics.Tracing WriteMultiMerge(m_eventData[eventId].Name, ref opt, tlet, pActivityId, childActivityID, args); } -#endif // FEATURE_ACTIVITYSAMPLING } #endif // FEATURE_MANAGED_ETW if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener) @@ -2253,18 +2010,6 @@ namespace System.Diagnostics.Tracing Debug.Assert(dispatcher.m_EventEnabled != null); if (eventId == -1 || dispatcher.m_EventEnabled[eventId]) { -#if FEATURE_ACTIVITYSAMPLING - var activityFilter = dispatcher.m_Listener.m_activityFilter; - // order below is important as PassesActivityFilter will "flow" active activities - // even when the current EventSource doesn't have filtering enabled. This allows - // interesting activities to be updated so that sources that do sample can get - // accurate data - if (activityFilter == null || - ActivityFilter.PassesActivityFilter(activityFilter, childActivityID, - m_eventData[eventId].TriggersActivityTracking > 0, - this, eventId) || - !dispatcher.m_activityFilteringEnabled) -#endif // FEATURE_ACTIVITYSAMPLING { try { @@ -2379,62 +2124,6 @@ namespace System.Diagnostics.Tracing } } -#if FEATURE_ACTIVITYSAMPLING - unsafe private SessionMask GetEtwSessionMask(int eventId, Guid* childActivityID) - { - SessionMask etwSessions = new SessionMask(); - - for (int i = 0; i < SessionMask.MAX; ++i) - { - EtwSession etwSession = m_etwSessionIdMap[i]; - if (etwSession != null) - { - ActivityFilter activityFilter = etwSession.m_activityFilter; - // PassesActivityFilter() will flow "interesting" activities, so make sure - // to perform this test first, before ORing with ~m_activityFilteringForETWEnabled - // (note: the first test for !m_activityFilteringForETWEnabled[i] ensures we - // do not fire events indiscriminately, when no filters are specified, but only - // if, in addition, the session did not also enable ActivitySampling) - if (activityFilter == null && !m_activityFilteringForETWEnabled[i] || - activityFilter != null && - ActivityFilter.PassesActivityFilter(activityFilter, childActivityID, - m_eventData[eventId].TriggersActivityTracking > 0, this, eventId) || - !m_activityFilteringForETWEnabled[i]) - { - etwSessions[i] = true; - } - } - } - // flow "interesting" activities for all legacy sessions in which there's some - // level of activity tracing enabled (even other EventSources) - if (m_legacySessions != null && m_legacySessions.Count > 0 && - (EventOpcode)m_eventData[eventId].Descriptor.Opcode == EventOpcode.Send) - { - // only calculate InternalCurrentThreadActivityId once - Guid* pCurrentActivityId = null; - Guid currentActivityId; - foreach (var legacyEtwSession in m_legacySessions) - { - if (legacyEtwSession == null) - continue; - - ActivityFilter activityFilter = legacyEtwSession.m_activityFilter; - if (activityFilter != null) - { - if (pCurrentActivityId == null) - { - currentActivityId = InternalCurrentThreadActivityId; - pCurrentActivityId = ¤tActivityId; - } - ActivityFilter.FlowActivityIfNeeded(activityFilter, pCurrentActivityId, childActivityID); - } - } - } - - return etwSessions; - } -#endif // FEATURE_ACTIVITYSAMPLING - /// /// Returns true if 'eventNum' is enabled if you only consider the level and matchAnyKeyword filters. /// It is possible that eventSources turn off the event based on additional filtering criteria. @@ -2616,13 +2305,9 @@ namespace System.Diagnostics.Tracing public bool EnabledForETW; // is this event on for the OS ETW data dispatcher? public bool HasRelatedActivityID; // Set if the event method's first parameter is a Guid named 'relatedActivityId' -#if !FEATURE_ACTIVITYSAMPLING #pragma warning disable 0649 -#endif public byte TriggersActivityTracking; // count of listeners that marked this event as trigger for start of activity logging. -#if !FEATURE_ACTIVITYSAMPLING #pragma warning restore 0649 -#endif public string Name; // the name of the event public string Message; // If the event has a message associated with it, this is it. public ParameterInfo[] Parameters; // TODO can we remove? @@ -2790,43 +2475,6 @@ namespace System.Diagnostics.Tracing #endif } -#if FEATURE_ACTIVITYSAMPLING - if (bSessionEnable && commandArgs.perEventSourceSessionId != -1) - { - bool participateInSampling = false; - string activityFilters; - int sessionIdBit; - - ParseCommandArgs(commandArgs.Arguments, out participateInSampling, - out activityFilters, out sessionIdBit); - - if (commandArgs.listener == null && commandArgs.Arguments.Count > 0 && commandArgs.perEventSourceSessionId != sessionIdBit) - { - throw new ArgumentException(SR.Format(SR.EventSource_SessionIdError, - commandArgs.perEventSourceSessionId + SessionMask.SHIFT_SESSION_TO_KEYWORD, - sessionIdBit + SessionMask.SHIFT_SESSION_TO_KEYWORD)); - } - - if (commandArgs.listener == null) - { - UpdateEtwSession(commandArgs.perEventSourceSessionId, commandArgs.etwSessionId, true, activityFilters, participateInSampling); - } - else - { - ActivityFilter.UpdateFilter(ref commandArgs.listener.m_activityFilter, this, 0, activityFilters); - commandArgs.dispatcher.m_activityFilteringEnabled = participateInSampling; - } - } - else if (!bSessionEnable && commandArgs.listener == null) - { - // if we disable an ETW session, indicate that in a synthesized command argument - if (commandArgs.perEventSourceSessionId >= 0 && commandArgs.perEventSourceSessionId < SessionMask.MAX) - { - commandArgs.Arguments["EtwSessionKeyword"] = (commandArgs.perEventSourceSessionId + SessionMask.SHIFT_SESSION_TO_KEYWORD).ToString(CultureInfo.InvariantCulture); - } - } -#endif // FEATURE_ACTIVITYSAMPLING - // Turn on the enable bit before making the OnEventCommand callback This allows you to do useful // things like log messages, or test if keywords are enabled in the callback. if (commandArgs.enable) @@ -2840,47 +2488,11 @@ namespace System.Diagnostics.Tracing if (eventCommandCallback != null) eventCommandCallback(this, commandArgs); -#if FEATURE_ACTIVITYSAMPLING - if (commandArgs.listener == null && !bSessionEnable && commandArgs.perEventSourceSessionId != -1) - { - // if we disable an ETW session, complete disabling it - UpdateEtwSession(commandArgs.perEventSourceSessionId, commandArgs.etwSessionId, false, null, false); - } -#endif // FEATURE_ACTIVITYSAMPLING - if (!commandArgs.enable) { // If we are disabling, maybe we can turn on 'quick checks' to filter // quickly. These are all just optimizations (since later checks will still filter) -#if FEATURE_ACTIVITYSAMPLING - // Turn off (and forget) any information about Activity Tracing. - if (commandArgs.listener == null) - { - // reset all filtering information for activity-tracing-aware sessions - for (int i = 0; i < SessionMask.MAX; ++i) - { - EtwSession etwSession = m_etwSessionIdMap[i]; - if (etwSession != null) - ActivityFilter.DisableFilter(ref etwSession.m_activityFilter, this); - } - m_activityFilteringForETWEnabled = new SessionMask(0); - m_curLiveSessions = new SessionMask(0); - // reset activity-tracing-aware sessions - if (m_etwSessionIdMap != null) - for (int i = 0; i < SessionMask.MAX; ++i) - m_etwSessionIdMap[i] = null; - // reset legacy sessions - if (m_legacySessions != null) - m_legacySessions.Clear(); - } - else - { - ActivityFilter.DisableFilter(ref commandArgs.listener.m_activityFilter, this); - commandArgs.dispatcher.m_activityFilteringEnabled = false; - } -#endif // FEATURE_ACTIVITYSAMPLING - // There is a good chance EnabledForAnyListener are not as accurate as // they could be, go ahead and get a better estimate. for (int i = 0; i < m_eventData.Length; i++) @@ -2905,9 +2517,6 @@ namespace System.Diagnostics.Tracing m_eventSourceEnabled = false; } } -#if FEATURE_ACTIVITYSAMPLING - UpdateKwdTriggers(commandArgs.enable); -#endif // FEATURE_ACTIVITYSAMPLING } else { @@ -2930,14 +2539,6 @@ namespace System.Diagnostics.Tracing if (eventCommandCallback != null) eventCommandCallback(this, commandArgs); } - -#if FEATURE_ACTIVITYSAMPLING - if (m_completelyInited && (commandArgs.listener != null || shouldReport)) - { - SessionMask m = SessionMask.FromId(commandArgs.perEventSourceSessionId); - ReportActivitySamplingInfo(commandArgs.listener, m); - } -#endif // FEATURE_ACTIVITYSAMPLING } catch (Exception e) { @@ -2948,133 +2549,6 @@ namespace System.Diagnostics.Tracing } } -#if FEATURE_ACTIVITYSAMPLING - - internal void UpdateEtwSession( - int sessionIdBit, - int etwSessionId, - bool bEnable, - string activityFilters, - bool participateInSampling) - { - if (sessionIdBit < SessionMask.MAX) - { - // activity-tracing-aware etw session - if (bEnable) - { - var etwSession = EtwSession.GetEtwSession(etwSessionId, true); - ActivityFilter.UpdateFilter(ref etwSession.m_activityFilter, this, sessionIdBit, activityFilters); - m_etwSessionIdMap[sessionIdBit] = etwSession; - m_activityFilteringForETWEnabled[sessionIdBit] = participateInSampling; - } - else - { - var etwSession = EtwSession.GetEtwSession(etwSessionId); - m_etwSessionIdMap[sessionIdBit] = null; - m_activityFilteringForETWEnabled[sessionIdBit] = false; - if (etwSession != null) - { - ActivityFilter.DisableFilter(ref etwSession.m_activityFilter, this); - // the ETW session is going away; remove it from the global list - EtwSession.RemoveEtwSession(etwSession); - } - } - m_curLiveSessions[sessionIdBit] = bEnable; - } - else - { - // legacy etw session - if (bEnable) - { - if (m_legacySessions == null) - m_legacySessions = new List(8); - var etwSession = EtwSession.GetEtwSession(etwSessionId, true); - if (!m_legacySessions.Contains(etwSession)) - m_legacySessions.Add(etwSession); - } - else - { - var etwSession = EtwSession.GetEtwSession(etwSessionId); - if (etwSession != null) - { - if (m_legacySessions != null) - m_legacySessions.Remove(etwSession); - // the ETW session is going away; remove it from the global list - EtwSession.RemoveEtwSession(etwSession); - } - } - } - } - - internal static bool ParseCommandArgs( - IDictionary commandArguments, - out bool participateInSampling, - out string activityFilters, - out int sessionIdBit) - { - bool res = true; - participateInSampling = false; - string activityFilterString; - if (commandArguments.TryGetValue("ActivitySamplingStartEvent", out activityFilters)) - { - // if a start event is specified default the event source to participate in sampling - participateInSampling = true; - } - - if (commandArguments.TryGetValue("ActivitySampling", out activityFilterString)) - { - if (string.Compare(activityFilterString, "false", StringComparison.OrdinalIgnoreCase) == 0 || - activityFilterString == "0") - participateInSampling = false; - else - participateInSampling = true; - } - - string sSessionKwd; - int sessionKwd = -1; - if (!commandArguments.TryGetValue("EtwSessionKeyword", out sSessionKwd) || - !int.TryParse(sSessionKwd, out sessionKwd) || - sessionKwd < SessionMask.SHIFT_SESSION_TO_KEYWORD || - sessionKwd >= SessionMask.SHIFT_SESSION_TO_KEYWORD + SessionMask.MAX) - { - sessionIdBit = -1; - res = false; - } - else - { - sessionIdBit = sessionKwd - SessionMask.SHIFT_SESSION_TO_KEYWORD; - } - return res; - } - - internal void UpdateKwdTriggers(bool enable) - { - if (enable) - { - // recompute m_keywordTriggers - ulong gKeywords = unchecked((ulong)m_matchAnyKeyword); - if (gKeywords == 0) - gKeywords = 0xFFFFffffFFFFffff; - - m_keywordTriggers = 0; - for (int sessId = 0; sessId < SessionMask.MAX; ++sessId) - { - EtwSession etwSession = m_etwSessionIdMap[sessId]; - if (etwSession == null) - continue; - - ActivityFilter activityFilter = etwSession.m_activityFilter; - ActivityFilter.UpdateKwdTriggers(activityFilter, m_guid, this, unchecked((EventKeywords)gKeywords)); - } - } - else - { - m_keywordTriggers = 0; - } - } - -#endif // FEATURE_ACTIVITYSAMPLING - /// /// If 'value is 'true' then set the eventSource so that 'dispatcher' will receive event with the eventId /// of 'eventId. If value is 'false' disable the event for that dispatcher. If 'eventId' is out of @@ -4148,48 +3622,6 @@ namespace System.Diagnostics.Tracing } } -#if FEATURE_ACTIVITYSAMPLING - private void ReportActivitySamplingInfo(EventListener listener, SessionMask sessions) - { - Debug.Assert(listener == null || (uint)sessions == (uint)SessionMask.FromId(0)); - - for (int perEventSourceSessionId = 0; perEventSourceSessionId < SessionMask.MAX; ++perEventSourceSessionId) - { - if (!sessions[perEventSourceSessionId]) - continue; - - ActivityFilter af; - if (listener == null) - { - EtwSession etwSession = m_etwSessionIdMap[perEventSourceSessionId]; - Debug.Assert(etwSession != null); - af = etwSession.m_activityFilter; - } - else - { - af = listener.m_activityFilter; - } - - if (af == null) - continue; - - SessionMask m = new SessionMask(); - m[perEventSourceSessionId] = true; - - foreach (var t in af.GetFilterAsTuple(m_guid)) - { - WriteStringToListener(listener, string.Format(CultureInfo.InvariantCulture, "Session {0}: {1} = {2}", perEventSourceSessionId, t.Item1, t.Item2), m); - } - - bool participateInSampling = (listener == null) ? - m_activityFilteringForETWEnabled[perEventSourceSessionId] : - GetDispatcher(listener).m_activityFilteringEnabled; - WriteStringToListener(listener, string.Format(CultureInfo.InvariantCulture, "Session {0}: Activity Sampling support: {1}", - perEventSourceSessionId, participateInSampling ? "enabled" : "disabled"), m); - } - } -#endif // FEATURE_ACTIVITYSAMPLING - // private instance state private string m_name; // My friendly name (privided in ctor) internal int m_id; // A small integer that is unique to this instance. @@ -4231,16 +3663,6 @@ namespace System.Diagnostics.Tracing internal volatile ulong[] m_channelData; #endif -#if FEATURE_ACTIVITYSAMPLING - private SessionMask m_curLiveSessions; // the activity-tracing aware sessions' bits - private EtwSession[] m_etwSessionIdMap; // the activity-tracing aware sessions - private List m_legacySessions; // the legacy ETW sessions listening to this source - internal long m_keywordTriggers; // a bit is set if it corresponds to a keyword that's part of an enabled triggering event - internal SessionMask m_activityFilteringForETWEnabled; // does THIS EventSource have activity filtering turned on for each ETW session - static internal Action s_activityDying; // Fires when something calls SetCurrentThreadToActivity() - // Also used to mark that activity tracing is on for some case -#endif // FEATURE_ACTIVITYSAMPLING - // We use a single instance of ActivityTracker for all EventSources instances to allow correlation between multiple event providers. // We have m_activityTracker field simply because instance field is more efficient than static field fetch. ActivityTracker m_activityTracker; @@ -4772,9 +4194,6 @@ namespace System.Diagnostics.Tracing // Instance fields internal volatile EventListener m_Next; // These form a linked list in s_Listeners -#if FEATURE_ACTIVITYSAMPLING - internal ActivityFilter m_activityFilter; // If we are filtering by activity on this Listener, this keeps track of it. -#endif // FEATURE_ACTIVITYSAMPLING // static fields @@ -5360,629 +4779,6 @@ namespace System.Diagnostics.Tracing #region private classes -#if FEATURE_ACTIVITYSAMPLING - - /// - /// ActivityFilter is a helper structure that is used to keep track of run-time state - /// associated with activity filtering. It is 1-1 with EventListeners (logically - /// every listener has one of these, however we actually allocate them lazily), as well - /// as 1-to-1 with tracing-aware EtwSessions. - /// - /// This structure also keeps track of the sampling counts associated with 'trigger' - /// events. Because these trigger events are rare, and you typically only have one of - /// them, we store them here as a linked list. - /// - internal sealed class ActivityFilter : IDisposable - { - /// - /// Disable all activity filtering for the listener associated with 'filterList', - /// (in the session associated with it) that is triggered by any event in 'source'. - /// - public static void DisableFilter(ref ActivityFilter filterList, EventSource source) - { -#if !ES_BUILD_STANDALONE - Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); -#endif - - if (filterList == null) - return; - - ActivityFilter cur; - // Remove it from anywhere in the list (except the first element, which has to - // be treated specially) - ActivityFilter prev = filterList; - cur = prev.m_next; - while (cur != null) - { - if (cur.m_providerGuid == source.Guid) - { - // update TriggersActivityTracking bit - if (cur.m_eventId >= 0 && cur.m_eventId < source.m_eventData.Length) - --source.m_eventData[cur.m_eventId].TriggersActivityTracking; - - // Remove it from the linked list. - prev.m_next = cur.m_next; - // dispose of the removed node - cur.Dispose(); - // update cursor - cur = prev.m_next; - } - else - { - // update cursors - prev = cur; - cur = prev.m_next; - } - } - - // Sadly we have to treat the first element specially in linked list removal in C# - if (filterList.m_providerGuid == source.Guid) - { - // update TriggersActivityTracking bit - if (filterList.m_eventId >= 0 && filterList.m_eventId < source.m_eventData.Length) - --source.m_eventData[filterList.m_eventId].TriggersActivityTracking; - - // We are the first element in the list. - var first = filterList; - filterList = first.m_next; - // dispose of the removed node - first.Dispose(); - } - // the above might have removed the one ActivityFilter in the session that contains the - // cleanup delegate; re-create the delegate if needed - if (filterList != null) - { - EnsureActivityCleanupDelegate(filterList); - } - } - - /// - /// Currently this has "override" semantics. We first disable all filters - /// associated with 'source', and next we add new filters for each entry in the - /// string 'startEvents'. participateInSampling specifies whether non-startEvents - /// always trigger or only trigger when current activity is 'active'. - /// - public static void UpdateFilter( - ref ActivityFilter filterList, - EventSource source, - int perEventSourceSessionId, - string startEvents) - { -#if !ES_BUILD_STANDALONE - Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); -#endif - - // first remove all filters associated with 'source' - DisableFilter(ref filterList, source); - - if (!string.IsNullOrEmpty(startEvents)) - { - // ActivitySamplingStartEvents is a space-separated list of Event:Frequency pairs. - // The Event may be specified by name or by ID. Errors in parsing such a pair - // result in the error being reported to the listeners, and the pair being ignored. - // E.g. "CustomActivityStart:1000 12:10" specifies that for event CustomActivityStart - // we should initiate activity tracing once every 1000 events, *and* for event ID 12 - // we should initiate activity tracing once every 10 events. - string[] activityFilterStrings = startEvents.Split(' '); - - for (int i = 0; i < activityFilterStrings.Length; ++i) - { - string activityFilterString = activityFilterStrings[i]; - int sampleFreq = 1; - int eventId = -1; - int colonIdx = activityFilterString.IndexOf(':'); - if (colonIdx < 0) - { - source.ReportOutOfBandMessage("ERROR: Invalid ActivitySamplingStartEvent specification: " + - activityFilterString, false); - // ignore failure... - continue; - } - string sFreq = activityFilterString.Substring(colonIdx + 1); - if (!int.TryParse(sFreq, out sampleFreq)) - { - source.ReportOutOfBandMessage("ERROR: Invalid sampling frequency specification: " + sFreq, false); - continue; - } - activityFilterString = activityFilterString.Substring(0, colonIdx); - if (!int.TryParse(activityFilterString, out eventId)) - { - // reset eventId - eventId = -1; - // see if it's an event name - for (int j = 0; j < source.m_eventData.Length; j++) - { - EventSource.EventMetadata[] ed = source.m_eventData; - if (ed[j].Name != null && ed[j].Name.Length == activityFilterString.Length && - string.Compare(ed[j].Name, activityFilterString, StringComparison.OrdinalIgnoreCase) == 0) - { - eventId = ed[j].Descriptor.EventId; - break; - } - } - } - if (eventId < 0 || eventId >= source.m_eventData.Length) - { - source.ReportOutOfBandMessage("ERROR: Invalid eventId specification: " + activityFilterString, false); - continue; - } - EnableFilter(ref filterList, source, perEventSourceSessionId, eventId, sampleFreq); - } - } - } - - /// - /// Returns the first ActivityFilter from 'filterList' corresponding to 'source'. - /// - public static ActivityFilter GetFilter(ActivityFilter filterList, EventSource source) - { - for (var af = filterList; af != null; af = af.m_next) - { - if (af.m_providerGuid == source.Guid && af.m_samplingFreq != -1) - return af; - } - return null; - } - - /// - /// Returns a session mask representing all sessions in which the activity - /// associated with the current thread is allowed through the activity filter. - /// If 'triggeringEvent' is true the event MAY be a triggering event. Ideally - /// most of the time this is false as you can guarantee this event is NOT a - /// triggering event. If 'triggeringEvent' is true, then it checks the - /// 'EventSource' and 'eventID' of the event being logged to see if it is actually - /// a trigger. If so it activates the current activity. - /// - /// If 'childActivityID' is present, it will be added to the active set if the - /// current activity is active. - /// - unsafe public static bool PassesActivityFilter( - ActivityFilter filterList, - Guid* childActivityID, - bool triggeringEvent, - EventSource source, - int eventId) - { - Debug.Assert(filterList != null && filterList.m_activeActivities != null); - bool shouldBeLogged = false; - if (triggeringEvent) - { - for (ActivityFilter af = filterList; af != null; af = af.m_next) - { - if (eventId == af.m_eventId && source.Guid == af.m_providerGuid) - { - // Update the sampling count with wrap-around - int curSampleCount, newSampleCount; - do - { - curSampleCount = af.m_curSampleCount; - if (curSampleCount <= 1) - newSampleCount = af.m_samplingFreq; // Wrap around, counting down to 1 - else - newSampleCount = curSampleCount - 1; - } - while (Interlocked.CompareExchange(ref af.m_curSampleCount, newSampleCount, curSampleCount) != curSampleCount); - // If we hit zero, then start tracking the activity. - if (curSampleCount <= 1) - { - Guid currentActivityId = EventSource.InternalCurrentThreadActivityId; - Tuple startId; - // only add current activity if it's not already a root activity - if (!af.m_rootActiveActivities.TryGetValue(currentActivityId, out startId)) - { - // EventSource.OutputDebugString(string.Format(" PassesAF - Triggering(session {0}, evt {1})", af.m_perEventSourceSessionId, eventId)); - shouldBeLogged = true; - af.m_activeActivities[currentActivityId] = Environment.TickCount; - af.m_rootActiveActivities[currentActivityId] = Tuple.Create(source.Guid, eventId); - } - } - else - { - // a start event following a triggering start event - Guid currentActivityId = EventSource.InternalCurrentThreadActivityId; - Tuple startId; - // only remove current activity if we added it - if (af.m_rootActiveActivities.TryGetValue(currentActivityId, out startId) && - startId.Item1 == source.Guid && startId.Item2 == eventId) - { - // EventSource.OutputDebugString(string.Format("Activity dying: {0} -> StartEvent({1})", currentActivityId, eventId)); - // remove activity only from current logging scope (af) - int dummy; - af.m_activeActivities.TryRemove(currentActivityId, out dummy); - } - } - break; - } - } - } - - var activeActivities = GetActiveActivities(filterList); - if (activeActivities != null) - { - // if we hadn't already determined this should be logged, test further - if (!shouldBeLogged) - { - shouldBeLogged = !activeActivities.IsEmpty && - activeActivities.ContainsKey(EventSource.InternalCurrentThreadActivityId); - } - if (shouldBeLogged && childActivityID != null && - ((EventOpcode)source.m_eventData[eventId].Descriptor.Opcode == EventOpcode.Send)) - { - FlowActivityIfNeeded(filterList, null, childActivityID); - // EventSource.OutputDebugString(string.Format(" PassesAF - activity {0}", *childActivityID)); - } - } - // EventSource.OutputDebugString(string.Format(" PassesAF - shouldBeLogged(evt {0}) = {1:x}", eventId, shouldBeLogged)); - return shouldBeLogged; - } - - public static bool IsCurrentActivityActive(ActivityFilter filterList) - { - var activeActivities = GetActiveActivities(filterList); - if (activeActivities != null && - activeActivities.ContainsKey(EventSource.InternalCurrentThreadActivityId)) - return true; - - return false; - } - - /// - /// For the EventListener/EtwSession associated with 'filterList', add 'childActivityid' - /// to list of active activities IF 'currentActivityId' is also active. Passing in a null - /// value for 'currentActivityid' is an indication the caller has already verified - /// that the current activity is active. - /// - unsafe public static void FlowActivityIfNeeded(ActivityFilter filterList, Guid* currentActivityId, Guid* childActivityID) - { - Debug.Assert(childActivityID != null); - - var activeActivities = GetActiveActivities(filterList); - Debug.Assert(activeActivities != null); - - // take currentActivityId == null to mean we *know* the current activity is "active" - if (currentActivityId != null && !activeActivities.ContainsKey(*currentActivityId)) - return; - - if (activeActivities.Count > MaxActivityTrackCount) - { - TrimActiveActivityStore(activeActivities); - // make sure current activity is still in the set: - activeActivities[EventSource.InternalCurrentThreadActivityId] = Environment.TickCount; - } - // add child activity to list of activities - activeActivities[*childActivityID] = Environment.TickCount; - - } - - /// - /// - public static void UpdateKwdTriggers(ActivityFilter activityFilter, Guid sourceGuid, EventSource source, EventKeywords sessKeywords) - { - for (var af = activityFilter; af != null; af = af.m_next) - { - if ((sourceGuid == af.m_providerGuid) && - (source.m_eventData[af.m_eventId].TriggersActivityTracking > 0 || - ((EventOpcode)source.m_eventData[af.m_eventId].Descriptor.Opcode == EventOpcode.Send))) - { - // we could be more precise here, if we tracked 'anykeywords' per session - unchecked - { - source.m_keywordTriggers |= (source.m_eventData[af.m_eventId].Descriptor.Keywords & (long)sessKeywords); - } - } - } - } - - /// - /// For the EventSource specified by 'sourceGuid' and the EventListener/EtwSession - /// associated with 'this' ActivityFilter list, return configured sequence of - /// [eventId, sampleFreq] pairs that defines the sampling policy. - /// - public IEnumerable> GetFilterAsTuple(Guid sourceGuid) - { - for (ActivityFilter af = this; af != null; af = af.m_next) - { - if (af.m_providerGuid == sourceGuid) - yield return Tuple.Create(af.m_eventId, af.m_samplingFreq); - } - } - - /// - /// The cleanup being performed consists of removing the m_myActivityDelegate from - /// the static s_activityDying, therefore allowing the ActivityFilter to be reclaimed. - /// - public void Dispose() - { -#if !ES_BUILD_STANDALONE - Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); -#endif - // m_myActivityDelegate is still alive (held by the static EventSource.s_activityDying). - // Therefore we are ok to take a dependency on m_myActivityDelegate being valid even - // during the finalization of the ActivityFilter - if (m_myActivityDelegate != null) - { - EventSource.s_activityDying = (Action)Delegate.Remove(EventSource.s_activityDying, m_myActivityDelegate); - m_myActivityDelegate = null; - } - } - -#region private - - /// - /// Creates a new ActivityFilter that is triggered by 'eventId' from 'source' ever - /// 'samplingFreq' times the event fires. You can have several of these forming a - /// linked list. - /// - private ActivityFilter(EventSource source, int perEventSourceSessionId, int eventId, int samplingFreq, ActivityFilter existingFilter = null) - { - m_providerGuid = source.Guid; - m_perEventSourceSessionId = perEventSourceSessionId; - m_eventId = eventId; - m_samplingFreq = samplingFreq; - m_next = existingFilter; - - Debug.Assert(existingFilter == null || - (existingFilter.m_activeActivities == null) == (existingFilter.m_rootActiveActivities == null)); - - // if this is the first filter we add for this session, we need to create a new - // table of activities. m_activeActivities is common across EventSources in the same - // session - ConcurrentDictionary activeActivities = null; - if (existingFilter == null || - (activeActivities = GetActiveActivities(existingFilter)) == null) - { - m_activeActivities = new ConcurrentDictionary(); - m_rootActiveActivities = new ConcurrentDictionary>(); - - // Add a delegate to the 'SetCurrentThreadToActivity callback so that I remove 'dead' activities - m_myActivityDelegate = GetActivityDyingDelegate(this); - EventSource.s_activityDying = (Action)Delegate.Combine(EventSource.s_activityDying, m_myActivityDelegate); - } - else - { - m_activeActivities = activeActivities; - m_rootActiveActivities = existingFilter.m_rootActiveActivities; - } - - } - - /// - /// Ensure there's at least one ActivityFilter in the 'filterList' that contains an - /// activity-removing delegate for the listener/session associated with 'filterList'. - /// - private static void EnsureActivityCleanupDelegate(ActivityFilter filterList) - { - if (filterList == null) - return; - - for (ActivityFilter af = filterList; af != null; af = af.m_next) - { - if (af.m_myActivityDelegate != null) - return; - } - - // we didn't find a delegate - filterList.m_myActivityDelegate = GetActivityDyingDelegate(filterList); - EventSource.s_activityDying = (Action)Delegate.Combine(EventSource.s_activityDying, filterList.m_myActivityDelegate); - } - - /// - /// Builds the delegate to be called when an activity is dying. This is responsible - /// for performing whatever cleanup is needed for the ActivityFilter list passed in. - /// This gets "added" to EventSource.s_activityDying and ends up being called from - /// EventSource.SetCurrentThreadActivityId and ActivityFilter.PassesActivityFilter. - /// - /// The delegate to be called when an activity is dying - private static Action GetActivityDyingDelegate(ActivityFilter filterList) - { - return (Guid oldActivity) => - { - int dummy; - filterList.m_activeActivities.TryRemove(oldActivity, out dummy); - Tuple dummyTuple; - filterList.m_rootActiveActivities.TryRemove(oldActivity, out dummyTuple); - }; - } - - /// - /// Enables activity filtering for the listener associated with 'filterList', triggering on - /// the event 'eventID' from 'source' with a sampling frequency of 'samplingFreq' - /// - /// if 'eventID' is out of range (e.g. negative), it means we are not triggering (but we are - /// activitySampling if something else triggered). - /// - /// true if activity sampling is enabled the samplingFreq is non-zero - private static bool EnableFilter(ref ActivityFilter filterList, EventSource source, int perEventSourceSessionId, int eventId, int samplingFreq) - { -#if !ES_BUILD_STANDALONE - Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); -#endif - Debug.Assert(samplingFreq > 0); - Debug.Assert(eventId >= 0); - - filterList = new ActivityFilter(source, perEventSourceSessionId, eventId, samplingFreq, filterList); - - // Mark the 'quick Check' that indicates this is a trigger event. - // If eventId is out of range then this mark is not done which has the effect of ignoring - // the trigger. - if (0 <= eventId && eventId < source.m_eventData.Length) - ++source.m_eventData[eventId].TriggersActivityTracking; - - return true; - } - - /// - /// Normally this code never runs, it is here just to prevent run-away resource usage. - /// - private static void TrimActiveActivityStore(ConcurrentDictionary activities) - { - if (activities.Count > MaxActivityTrackCount) - { - // Remove half of the oldest activity ids. - var keyValues = activities.ToArray(); - var tickNow = Environment.TickCount; - - // Sort by age, taking into account wrap-around. As long as x and y are within - // 23 days of now then (0x7FFFFFFF & (tickNow - x.Value)) is the delta (even if - // TickCount wraps). I then sort by DESCENDING age. (that is oldest value first) - Array.Sort(keyValues, (x, y) => (0x7FFFFFFF & (tickNow - y.Value)) - (0x7FFFFFFF & (tickNow - x.Value))); - for (int i = 0; i < keyValues.Length / 2; i++) - { - int dummy; - activities.TryRemove(keyValues[i].Key, out dummy); - } - } - } - - private static ConcurrentDictionary GetActiveActivities( - ActivityFilter filterList) - { - for (ActivityFilter af = filterList; af != null; af = af.m_next) - { - if (af.m_activeActivities != null) - return af.m_activeActivities; - } - return null; - } - - // m_activeActivities always points to the sample dictionary for EVERY ActivityFilter - // in the m_next list. The 'int' value in the m_activities set is a timestamp - // (Environment.TickCount) of when the entry was put in the system and is used to - // remove 'old' entries that if the set gets too big. - ConcurrentDictionary m_activeActivities; - - // m_rootActiveActivities holds the "root" active activities, i.e. the activities - // that were marked as active because a Start event fired on them. We need to keep - // track of these to enable sampling in the scenario of an app's main thread that - // never explicitly sets distinct activity IDs as it executes. To handle these - // situations we manufacture a Guid from the thread's ID, and: - // (a) we consider the firing of a start event when the sampling counter reaches - // zero to mark the beginning of an interesting activity, and - // (b) we consider the very next firing of the same start event to mark the - // ending of that activity. - // We use a ConcurrentDictionary to avoid taking explicit locks. - // The key (a guid) represents the activity ID of the root active activity - // The value is made up of the Guid of the event provider and the eventId of - // the start event. - ConcurrentDictionary> m_rootActiveActivities; - Guid m_providerGuid; // We use the GUID rather than object identity because we don't want to keep the eventSource alive - int m_eventId; // triggering event - int m_samplingFreq; // Counter reset to this when it hits 0 - int m_curSampleCount; // We count down to 0 and then activate the activity. - int m_perEventSourceSessionId; // session ID bit for ETW, 0 for EventListeners - - const int MaxActivityTrackCount = 100000; // maximum number of tracked activities - - ActivityFilter m_next; // We create a linked list of these - Action m_myActivityDelegate; -#endregion - }; - - - /// - /// An EtwSession instance represents an activity-tracing-aware ETW session. Since these - /// are limited to 8 concurrent sessions per machine (currently) we're going to store - /// the active ones in a singly linked list. - /// - internal class EtwSession - { - public static EtwSession GetEtwSession(int etwSessionId, bool bCreateIfNeeded = false) - { - if (etwSessionId < 0) - return null; - - EtwSession etwSession; - foreach (var wrEtwSession in s_etwSessions) - { -#if ES_BUILD_STANDALONE - if ((etwSession = (EtwSession) wrEtwSession.Target) != null && etwSession.m_etwSessionId == etwSessionId) - return etwSession; -#else - if (wrEtwSession.TryGetTarget(out etwSession) && etwSession.m_etwSessionId == etwSessionId) - return etwSession; -#endif - } - - if (!bCreateIfNeeded) - return null; - -#if ES_BUILD_STANDALONE - if (s_etwSessions == null) - s_etwSessions = new List(); - - etwSession = new EtwSession(etwSessionId); - s_etwSessions.Add(new WeakReference(etwSession)); -#else - if (s_etwSessions == null) - s_etwSessions = new List>(); - - etwSession = new EtwSession(etwSessionId); - s_etwSessions.Add(new WeakReference(etwSession)); -#endif - - if (s_etwSessions.Count > s_thrSessionCount) - TrimGlobalList(); - - return etwSession; - - } - - public static void RemoveEtwSession(EtwSession etwSession) - { - Debug.Assert(etwSession != null); - if (s_etwSessions == null || etwSession == null) - return; - - s_etwSessions.RemoveAll((wrEtwSession) => - { - EtwSession session; -#if ES_BUILD_STANDALONE - return (session = (EtwSession) wrEtwSession.Target) != null && - (session.m_etwSessionId == etwSession.m_etwSessionId); -#else - return wrEtwSession.TryGetTarget(out session) && - (session.m_etwSessionId == etwSession.m_etwSessionId); -#endif - }); - - if (s_etwSessions.Count > s_thrSessionCount) - TrimGlobalList(); - } - - private static void TrimGlobalList() - { - if (s_etwSessions == null) - return; - - s_etwSessions.RemoveAll((wrEtwSession) => - { -#if ES_BUILD_STANDALONE - return wrEtwSession.Target == null; -#else - EtwSession session; - return !wrEtwSession.TryGetTarget(out session); -#endif - }); - } - - private EtwSession(int etwSessionId) - { - m_etwSessionId = etwSessionId; - } - - public readonly int m_etwSessionId; // ETW session ID (as retrieved by EventProvider) - public ActivityFilter m_activityFilter; // all filters enabled for this session - -#if ES_BUILD_STANDALONE - private static List s_etwSessions = new List(); -#else - private static List> s_etwSessions = new List>(); -#endif - private const int s_thrSessionCount = 16; - } - -#endif // FEATURE_ACTIVITYSAMPLING - // holds a bitfield representing a session mask /// /// A SessionMask represents a set of (at most MAX) sessions as a bit mask. The perEventSourceSessionId @@ -6096,9 +4892,6 @@ namespace System.Diagnostics.Tracing // Instance fields readonly internal EventListener m_Listener; // The dispatcher this entry is for internal bool[] m_EventEnabled; // For every event in a the eventSource, is it enabled? -#if FEATURE_ACTIVITYSAMPLING - internal bool m_activityFilteringEnabled; // does THIS EventSource have activity filtering turned on for this listener? -#endif // FEATURE_ACTIVITYSAMPLING // Only guaranteed to exist after a InsureInit() internal EventDispatcher m_Next; // These form a linked list in code:EventSource.m_Dispatchers diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs index bf29d71..393f49a 100644 --- a/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs +++ b/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs @@ -7,10 +7,6 @@ #if PLATFORM_WINDOWS #define FEATURE_MANAGED_ETW - -#if !ES_BUILD_STANDALONE -#define FEATURE_ACTIVITYSAMPLING -#endif #endif // PLATFORM_WINDOWS #if ES_BUILD_STANDALONE diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs index 98556a7..4233e46 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs @@ -33,46 +33,22 @@ namespace System.Diagnostics.Tracing { if (TplEtwProvider.Log != null) TplEtwProvider.Log.SetActivityId(activityId); -#if FEATURE_MANAGED_ETW -#if FEATURE_ACTIVITYSAMPLING - Guid newId = activityId; -#endif // FEATURE_ACTIVITYSAMPLING + // We ignore errors to keep with the convention that EventSources do not throw errors. // Note we can't access m_throwOnWrites because this is a static method. - -#if FEATURE_PERFTRACING && PLATFORM_WINDOWS +#if FEATURE_MANAGED_ETW +#if FEATURE_PERFTRACING // Set the activity id via EventPipe. EventPipeInternal.EventActivityIdControl( (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, ref activityId); - - // Set the activity id via ETW and fetch the previous id. - if (UnsafeNativeMethods.ManifestEtw.EventActivityIdControl( - UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID, - ref activityId) == 0) -#elif FEATURE_PERFTRACING - if (EventPipeInternal.EventActivityIdControl( - (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID, - ref activityId) == 0) -#elif PLATFORM_WINDOWS - if (UnsafeNativeMethods.ManifestEtw.EventActivityIdControl( - UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID, - ref activityId) == 0) -#endif // FEATURE_PERFTRACING && PLATFORM_WINDOWS - { -#if FEATURE_ACTIVITYSAMPLING - var activityDying = s_activityDying; - if (activityDying != null && newId != activityId) - { - if (activityId == Guid.Empty) - { - activityId = FallbackActivityId; - } - // OutputDebugString(string.Format("Activity dying: {0} -> {1}", activityId, newId)); - activityDying(activityId); // This is actually the OLD activity ID. - } -#endif // FEATURE_ACTIVITYSAMPLING - } +#endif // FEATURE_PERFTRACING +#if PLATFORM_WINDOWS + // Set the activity id via ETW. + UnsafeNativeMethods.ManifestEtw.EventActivityIdControl( + UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, + ref activityId); +#endif // PLATFORM_WINDOWS #endif // FEATURE_MANAGED_ETW } -- 2.7.4