From ec11694beb11c38896a448a8c9774ac1f69e576a Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 12 Aug 2021 10:58:11 -0700 Subject: [PATCH 01/21] Add event to RuntimeEventSource for AppContext switches Fixes https://github.com/dotnet/runtime/issues/56142 --- .../src/System/AppContext.cs | 17 +++++++++++++++++ .../Diagnostics/Tracing/RuntimeEventSource.cs | 8 ++++++++ 2 files changed, 25 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index 35e45f472bb8b1..0d5410b38053c5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -135,6 +135,23 @@ public static void SetSwitch(string switchName, bool isEnabled) } } + internal static void LogSwitchValues(RuntimeEventSource ev) + { + if (s_switches is null) + { + return; + } + + lock (s_switches) + { + foreach (var (k, v) in s_switches) + { + // Convert bool to int because it's cheaper to log (no boxing) + ev.LogAppContextSwitch(k, v ? 0 : 1); + } + } + } + #if !CORERT internal static unsafe void Setup(char** pNames, char** pValues, int count) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs index 6d57c82ef6cc40..f1ff371180a015 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs @@ -50,6 +50,12 @@ public static void Initialize() // as you can't make a constructor partial. private RuntimeEventSource(int _) { } + [Event(2, Level = EventLevel.Informational)] + internal void LogAppContextSwitch(string switchName, int value) + { + base.WriteEvent(2, switchName, value); + } + protected override void OnEventCommand(EventCommandEventArgs command) { if (command.Command == EventCommand.Enable) @@ -87,6 +93,8 @@ protected override void OnEventCommand(EventCommandEventArgs command) _ilBytesJittedCounter ??= new PollingCounter("il-bytes-jitted", this, () => System.Runtime.JitInfo.GetCompiledILBytes()) { DisplayName = "IL Bytes Jitted", DisplayUnits = "B" }; _methodsJittedCounter ??= new PollingCounter("methods-jitted-count", this, () => System.Runtime.JitInfo.GetCompiledMethodCount()) { DisplayName = "Number of Methods Jitted" }; _jitTimeCounter ??= new IncrementingPollingCounter("time-in-jit", this, () => System.Runtime.JitInfo.GetCompilationTime().TotalMilliseconds) { DisplayName = "Time spent in JIT", DisplayUnits = "ms", DisplayRateTimeScale = new TimeSpan(0, 0, 1) }; + + AppContext.LogSwitchValues(this); } } From 5d9175f2cb510b16f2382214ae80c9b21aaae623 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 12 Aug 2021 13:23:34 -0700 Subject: [PATCH 02/21] Respond to PR comments --- .../src/System/AppContext.cs | 16 ++++++++++++++++ .../Diagnostics/Tracing/RuntimeEventSource.cs | 9 +++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index 0d5410b38053c5..caf78fe4a4d06e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -150,6 +150,22 @@ internal static void LogSwitchValues(RuntimeEventSource ev) ev.LogAppContextSwitch(k, v ? 0 : 1); } } + + if (s_dataStore is null) + { + return; + } + + lock (s_dataStore) + { + foreach (var (k, v) in s_dataStore) + { + if (v is bool b) + { + ev.LogAppContextSwitch(k, b ? 0 : 1); + } + } + } } #if !CORERT diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs index f1ff371180a015..6df1a2f0cd8393 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs @@ -50,10 +50,15 @@ public static void Initialize() // as you can't make a constructor partial. private RuntimeEventSource(int _) { } - [Event(2, Level = EventLevel.Informational)] + private enum EventId : int + { + AppContextSwitch = 1 + } + + [Event((int)EventId.AppContextSwitch, Level = EventLevel.Informational)] internal void LogAppContextSwitch(string switchName, int value) { - base.WriteEvent(2, switchName, value); + base.WriteEvent((int)EventId.AppContextSwitch, switchName, value); } protected override void OnEventCommand(EventCommandEventArgs command) From d4b0720907da027fa6b4dc8c85959cd0cec24995 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 11:55:10 -0700 Subject: [PATCH 03/21] Add preliminary tests --- .../src/System/AppContext.cs | 32 ++++--- .../tracing/eventcounter/runtimecounters.cs | 83 +++++++++++-------- 2 files changed, 61 insertions(+), 54 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index caf78fe4a4d06e..64531618c16a04 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -137,32 +137,28 @@ public static void SetSwitch(string switchName, bool isEnabled) internal static void LogSwitchValues(RuntimeEventSource ev) { - if (s_switches is null) + if (s_switches is not null) { - return; - } - - lock (s_switches) - { - foreach (var (k, v) in s_switches) + lock (s_switches) { - // Convert bool to int because it's cheaper to log (no boxing) - ev.LogAppContextSwitch(k, v ? 0 : 1); + foreach (var (k, v) in s_switches) + { + // Convert bool to int because it's cheaper to log (no boxing) + ev.LogAppContextSwitch(k, v ? 0 : 1); + } } } - if (s_dataStore is null) - { - return; - } - - lock (s_dataStore) + if (s_dataStore is not null) { - foreach (var (k, v) in s_dataStore) + lock (s_dataStore) { - if (v is bool b) + foreach (var (k, v) in s_dataStore) { - ev.LogAppContextSwitch(k, b ? 0 : 1); + if (v is bool b) + { + ev.LogAppContextSwitch(k, b ? 0 : 1); + } } } } diff --git a/src/tests/tracing/eventcounter/runtimecounters.cs b/src/tests/tracing/eventcounter/runtimecounters.cs index bdab454300ade0..522ad9719c6aa2 100644 --- a/src/tests/tracing/eventcounter/runtimecounters.cs +++ b/src/tests/tracing/eventcounter/runtimecounters.cs @@ -16,37 +16,36 @@ namespace RuntimeEventCounterTests { public class RuntimeCounterListener : EventListener { - public RuntimeCounterListener() - { - observedRuntimeCounters = new Dictionary() { - { "cpu-usage" , false }, - { "working-set", false }, - { "gc-heap-size", false }, - { "gen-0-gc-count", false }, - { "gen-1-gc-count", false }, - { "gen-2-gc-count", false }, - { "threadpool-thread-count", false }, - { "monitor-lock-contention-count", false }, - { "threadpool-queue-length", false }, - { "threadpool-completed-items-count", false }, - { "alloc-rate", false }, - { "active-timer-count", false }, - { "gc-fragmentation", false }, - { "gc-committed", false }, - { "exception-count", false }, - { "time-in-gc", false }, - { "gen-0-size", false }, - { "gen-1-size", false }, - { "gen-2-size", false }, - { "loh-size", false }, - { "poh-size", false }, - { "assembly-count", false }, - { "il-bytes-jitted", false }, - { "methods-jitted-count", false }, - { "time-in-jit", false } - }; - } - private Dictionary observedRuntimeCounters; + private Dictionary observedEvents = new Dictionary() { + { "cpu-usage" , false }, + { "working-set", false }, + { "gc-heap-size", false }, + { "gen-0-gc-count", false }, + { "gen-1-gc-count", false }, + { "gen-2-gc-count", false }, + { "threadpool-thread-count", false }, + { "monitor-lock-contention-count", false }, + { "threadpool-queue-length", false }, + { "threadpool-completed-items-count", false }, + { "alloc-rate", false }, + { "active-timer-count", false }, + { "gc-fragmentation", false }, + { "gc-committed", false }, + { "exception-count", false }, + { "time-in-gc", false }, + { "gen-0-size", false }, + { "gen-1-size", false }, + { "gen-2-size", false }, + { "loh-size", false }, + { "poh-size", false }, + { "assembly-count", false }, + { "il-bytes-jitted", false }, + { "methods-jitted-count", false }, + { "time-in-jit", false }, + // These are AppContext switches, not counters + { "appContextSwitch", false }, + { "appContextData", false } + }; protected override void OnEventSourceCreated(EventSource source) { @@ -60,7 +59,17 @@ protected override void OnEventSourceCreated(EventSource source) protected override void OnEventWritten(EventWrittenEventArgs eventData) { + // Check AppContext switches + if (eventData is { EventName: "LogAppContextSwitch", + Payload: { Count: 2 } } && + eventData.Payload[0] is string switchName && + observedEvents.ContainsKey(switchName)) + { + observedEvents[switchName] = true; + return; + } + // Check counters for (int i = 0; i < eventData.Payload.Count; i++) { IDictionary eventPayload = eventData.Payload[i] as IDictionary; @@ -69,7 +78,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) foreach (KeyValuePair payload in eventPayload) { if (payload.Key.Equals("Name")) - observedRuntimeCounters[payload.Value.ToString()] = true; + observedEvents[payload.Value.ToString()] = true; } } } @@ -77,11 +86,10 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) public bool Verify() { - foreach (string counterName in observedRuntimeCounters.Keys) + foreach (string counterName in observedEvents.Keys) { - if (!observedRuntimeCounters[counterName]) + if (!observedEvents[counterName]) { - Console.WriteLine($"Did not see {counterName}"); return false; } else @@ -97,10 +105,13 @@ public partial class TestRuntimeEventCounter { public static int Main(string[] args) { + AppContext.SetSwitch("appContextSwitch", true); + AppDomain.CurrentDomain.SetData("appContextData", true); + // Create an EventListener. using (RuntimeCounterListener myListener = new RuntimeCounterListener()) { - Thread.Sleep(3000); + Thread.Sleep(3000); if (myListener.Verify()) { Console.WriteLine("Test passed"); From 66810d6bf00eab40832444970ac7f7cd4091f32b Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 12:00:52 -0700 Subject: [PATCH 04/21] Respond to PR comments --- .../System.Private.CoreLib/src/System/AppContext.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index 64531618c16a04..49caac2fc9ab2a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -135,6 +135,7 @@ public static void SetSwitch(string switchName, bool isEnabled) } } +#if NETCOREAPP internal static void LogSwitchValues(RuntimeEventSource ev) { if (s_switches is not null) @@ -155,14 +156,15 @@ internal static void LogSwitchValues(RuntimeEventSource ev) { foreach (var (k, v) in s_dataStore) { - if (v is bool b) + if (bool.TryParse(v, out bool isEnabled)) { - ev.LogAppContextSwitch(k, b ? 0 : 1); + ev.LogAppContextSwitch(k, isEnabled ? 0 : 1); } } } } } +#endif #if !CORERT internal static unsafe void Setup(char** pNames, char** pValues, int count) From c08ac472a3b70145ec55b286bd179f1d703cd287 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 12:22:21 -0700 Subject: [PATCH 05/21] Add keyword --- .../System.Private.CoreLib/src/System/AppContext.cs | 2 -- .../src/System/Diagnostics/Tracing/RuntimeEventSource.cs | 7 ++++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index 49caac2fc9ab2a..88337a60c9e5fb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -135,7 +135,6 @@ public static void SetSwitch(string switchName, bool isEnabled) } } -#if NETCOREAPP internal static void LogSwitchValues(RuntimeEventSource ev) { if (s_switches is not null) @@ -164,7 +163,6 @@ internal static void LogSwitchValues(RuntimeEventSource ev) } } } -#endif #if !CORERT internal static unsafe void Setup(char** pNames, char** pValues, int count) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs index 6df1a2f0cd8393..3b3ac30c10aa9a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs @@ -14,6 +14,11 @@ internal sealed partial class RuntimeEventSource : EventSource { internal const string EventSourceName = "System.Runtime"; + public static class Keywords + { + public const EventKeywords AppContext = (EventKeywords)0x1; + } + private static RuntimeEventSource? s_RuntimeEventSource; private PollingCounter? _gcHeapSizeCounter; private IncrementingPollingCounter? _gen0GCCounter; @@ -55,7 +60,7 @@ private enum EventId : int AppContextSwitch = 1 } - [Event((int)EventId.AppContextSwitch, Level = EventLevel.Informational)] + [Event((int)EventId.AppContextSwitch, Level = EventLevel.Informational, Keywords = Keywords.AppContext)] internal void LogAppContextSwitch(string switchName, int value) { base.WriteEvent((int)EventId.AppContextSwitch, switchName, value); From 837a5ffabeff254c830dd66a04cc9168ee168c79 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 13:49:33 -0700 Subject: [PATCH 06/21] Fix tests --- .../src/System/AppContext.cs | 2 +- .../tracing/eventcounter/runtimecounters.cs | 25 +++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index 88337a60c9e5fb..d4438e8c14e0ff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -155,7 +155,7 @@ internal static void LogSwitchValues(RuntimeEventSource ev) { foreach (var (k, v) in s_dataStore) { - if (bool.TryParse(v, out bool isEnabled)) + if (v is string s && bool.TryParse(s, out bool isEnabled)) { ev.LogAppContextSwitch(k, isEnabled ? 0 : 1); } diff --git a/src/tests/tracing/eventcounter/runtimecounters.cs b/src/tests/tracing/eventcounter/runtimecounters.cs index 522ad9719c6aa2..3a379f37054dcb 100644 --- a/src/tests/tracing/eventcounter/runtimecounters.cs +++ b/src/tests/tracing/eventcounter/runtimecounters.cs @@ -16,7 +16,7 @@ namespace RuntimeEventCounterTests { public class RuntimeCounterListener : EventListener { - private Dictionary observedEvents = new Dictionary() { + private readonly Dictionary observedEvents = new Dictionary() { { "cpu-usage" , false }, { "working-set", false }, { "gc-heap-size", false }, @@ -44,7 +44,12 @@ public class RuntimeCounterListener : EventListener { "time-in-jit", false }, // These are AppContext switches, not counters { "appContextSwitch", false }, - { "appContextData", false } + { "appContextBoolAsStringData", false }, + }; + + private static readonly string[] s_unexpectedEvents = new[] { + "appContextBoolData", + "appContextStringData", }; protected override void OnEventSourceCreated(EventSource source) @@ -62,8 +67,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) // Check AppContext switches if (eventData is { EventName: "LogAppContextSwitch", Payload: { Count: 2 } } && - eventData.Payload[0] is string switchName && - observedEvents.ContainsKey(switchName)) + eventData.Payload[0] is string switchName) { observedEvents[switchName] = true; return; @@ -97,6 +101,15 @@ public bool Verify() Console.WriteLine($"Saw {counterName}"); } } + + foreach (var key in s_unexpectedEvents) + { + if (observedEvents.ContainsKey(key)) + { + Console.WriteLine($"Should not have seen appContextStringData"); + return false; + } + } return true; } } @@ -106,7 +119,9 @@ public partial class TestRuntimeEventCounter public static int Main(string[] args) { AppContext.SetSwitch("appContextSwitch", true); - AppDomain.CurrentDomain.SetData("appContextData", true); + AppDomain.CurrentDomain.SetData("appContextBoolData", true); + AppDomain.CurrentDomain.SetData("appContextBoolAsStringData", "true"); + AppDomain.CurrentDomain.SetData("appContextStringData", "myString"); // Create an EventListener. using (RuntimeCounterListener myListener = new RuntimeCounterListener()) From 80922f20e4f1b1679995e99a64bf15206c4a60ca Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 14:57:07 -0700 Subject: [PATCH 07/21] Remove AppContext EventSource support on browser --- .../src/System/AppContext.AnyOS.cs | 29 +++++++++++++++++++ .../src/System/AppContext.cs | 29 ------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index c8b5fcba415f5e..4fd808db210bcc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -30,5 +30,34 @@ private static string GetBaseDirectoryCore() return directory; } + + internal static void LogSwitchValues(RuntimeEventSource ev) + { + if (s_switches is not null) + { + lock (s_switches) + { + foreach (var (k, v) in s_switches) + { + // Convert bool to int because it's cheaper to log (no boxing) + ev.LogAppContextSwitch(k, v ? 0 : 1); + } + } + } + + if (s_dataStore is not null) + { + lock (s_dataStore) + { + foreach (var (k, v) in s_dataStore) + { + if (v is string s && bool.TryParse(s, out bool isEnabled)) + { + ev.LogAppContextSwitch(k, isEnabled ? 0 : 1); + } + } + } + } + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index d4438e8c14e0ff..35e45f472bb8b1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -135,35 +135,6 @@ public static void SetSwitch(string switchName, bool isEnabled) } } - internal static void LogSwitchValues(RuntimeEventSource ev) - { - if (s_switches is not null) - { - lock (s_switches) - { - foreach (var (k, v) in s_switches) - { - // Convert bool to int because it's cheaper to log (no boxing) - ev.LogAppContextSwitch(k, v ? 0 : 1); - } - } - } - - if (s_dataStore is not null) - { - lock (s_dataStore) - { - foreach (var (k, v) in s_dataStore) - { - if (v is string s && bool.TryParse(s, out bool isEnabled)) - { - ev.LogAppContextSwitch(k, isEnabled ? 0 : 1); - } - } - } - } - } - #if !CORERT internal static unsafe void Setup(char** pNames, char** pValues, int count) { From 8d73bb6a1d17a58b6e8f4ee9a1180e9cb6fe0f41 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 15:30:58 -0700 Subject: [PATCH 08/21] forgot using --- .../System.Private.CoreLib/src/System/AppContext.AnyOS.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index 4fd808db210bcc..e82be8033b2234 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Tracing; using System.IO; using System.Reflection; From b371a78dab98abfdf7bdbc52ed718ab038a38323 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Mon, 16 Aug 2021 11:09:57 -0700 Subject: [PATCH 09/21] Fix error reporting, add comments --- src/tests/tracing/eventcounter/runtimecounters.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tests/tracing/eventcounter/runtimecounters.cs b/src/tests/tracing/eventcounter/runtimecounters.cs index 3a379f37054dcb..dda6ba4b740769 100644 --- a/src/tests/tracing/eventcounter/runtimecounters.cs +++ b/src/tests/tracing/eventcounter/runtimecounters.cs @@ -106,7 +106,7 @@ public bool Verify() { if (observedEvents.ContainsKey(key)) { - Console.WriteLine($"Should not have seen appContextStringData"); + Console.WriteLine($"Should not have seen {key}"); return false; } } @@ -119,9 +119,9 @@ public partial class TestRuntimeEventCounter public static int Main(string[] args) { AppContext.SetSwitch("appContextSwitch", true); - AppDomain.CurrentDomain.SetData("appContextBoolData", true); + AppDomain.CurrentDomain.SetData("appContextBoolData", true); // Not loggeed, bool key AppDomain.CurrentDomain.SetData("appContextBoolAsStringData", "true"); - AppDomain.CurrentDomain.SetData("appContextStringData", "myString"); + AppDomain.CurrentDomain.SetData("appContextStringData", "myString"); // Not logged, string does not parse as bool // Create an EventListener. using (RuntimeCounterListener myListener = new RuntimeCounterListener()) From 7a262226911122ac5012e775071d78522d749125 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Tue, 17 Aug 2021 11:09:38 -0700 Subject: [PATCH 10/21] Respond to PR comments --- .../src/System/AppContext.AnyOS.cs | 15 +++++++++++---- src/tests/tracing/eventcounter/runtimecounters.cs | 3 ++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index e82be8033b2234..579d232debd0b1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -41,7 +41,7 @@ internal static void LogSwitchValues(RuntimeEventSource ev) foreach (var (k, v) in s_switches) { // Convert bool to int because it's cheaper to log (no boxing) - ev.LogAppContextSwitch(k, v ? 0 : 1); + ev.LogAppContextSwitch(k, v ? 1 : 0); } } } @@ -50,11 +50,18 @@ internal static void LogSwitchValues(RuntimeEventSource ev) { lock (s_dataStore) { - foreach (var (k, v) in s_dataStore) + if (s_switches is not null) { - if (v is string s && bool.TryParse(s, out bool isEnabled)) + lock (s_switches) { - ev.LogAppContextSwitch(k, isEnabled ? 0 : 1); + foreach (var (k, v) in s_dataStore) + { + if (v is string s && bool.TryParse(s, out bool isEnabled) && + !s_switches.ContainsKey(s)) + { + ev.LogAppContextSwitch(k, isEnabled ? 1 : 0); + } + } } } } diff --git a/src/tests/tracing/eventcounter/runtimecounters.cs b/src/tests/tracing/eventcounter/runtimecounters.cs index dda6ba4b740769..ec1b2e13af3be4 100644 --- a/src/tests/tracing/eventcounter/runtimecounters.cs +++ b/src/tests/tracing/eventcounter/runtimecounters.cs @@ -69,7 +69,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) Payload: { Count: 2 } } && eventData.Payload[0] is string switchName) { - observedEvents[switchName] = true; + observedEvents[switchName] = ((int)eventData.Payload[1]) == 1; return; } @@ -122,6 +122,7 @@ public static int Main(string[] args) AppDomain.CurrentDomain.SetData("appContextBoolData", true); // Not loggeed, bool key AppDomain.CurrentDomain.SetData("appContextBoolAsStringData", "true"); AppDomain.CurrentDomain.SetData("appContextStringData", "myString"); // Not logged, string does not parse as bool + AppDomain.CurrentDomain.SetData("appContextSwitch", false); // should not override the SetSwitch above // Create an EventListener. using (RuntimeCounterListener myListener = new RuntimeCounterListener()) From c848a1f3d3ba818521e2518b3f847eb642f7528a Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Tue, 17 Aug 2021 14:02:22 -0700 Subject: [PATCH 11/21] Refactor tests --- .../tracing/eventcounter/runtimecounters.cs | 101 +++++------- .../NativeRuntimeEventSourceTest.cs | 114 ++++++++++++++ .../RuntimeEventSourceTest.cs | 149 ++++++++---------- .../nativeruntimeeventsource.csproj | 21 +++ .../runtimeeventsource.csproj | 7 - 5 files changed, 237 insertions(+), 155 deletions(-) create mode 100644 src/tests/tracing/runtimeeventsource/NativeRuntimeEventSourceTest.cs create mode 100644 src/tests/tracing/runtimeeventsource/nativeruntimeeventsource.csproj diff --git a/src/tests/tracing/eventcounter/runtimecounters.cs b/src/tests/tracing/eventcounter/runtimecounters.cs index ec1b2e13af3be4..e6623649736d1b 100644 --- a/src/tests/tracing/eventcounter/runtimecounters.cs +++ b/src/tests/tracing/eventcounter/runtimecounters.cs @@ -16,41 +16,37 @@ namespace RuntimeEventCounterTests { public class RuntimeCounterListener : EventListener { - private readonly Dictionary observedEvents = new Dictionary() { - { "cpu-usage" , false }, - { "working-set", false }, - { "gc-heap-size", false }, - { "gen-0-gc-count", false }, - { "gen-1-gc-count", false }, - { "gen-2-gc-count", false }, - { "threadpool-thread-count", false }, - { "monitor-lock-contention-count", false }, - { "threadpool-queue-length", false }, - { "threadpool-completed-items-count", false }, - { "alloc-rate", false }, - { "active-timer-count", false }, - { "gc-fragmentation", false }, - { "gc-committed", false }, - { "exception-count", false }, - { "time-in-gc", false }, - { "gen-0-size", false }, - { "gen-1-size", false }, - { "gen-2-size", false }, - { "loh-size", false }, - { "poh-size", false }, - { "assembly-count", false }, - { "il-bytes-jitted", false }, - { "methods-jitted-count", false }, - { "time-in-jit", false }, - // These are AppContext switches, not counters - { "appContextSwitch", false }, - { "appContextBoolAsStringData", false }, - }; - - private static readonly string[] s_unexpectedEvents = new[] { - "appContextBoolData", - "appContextStringData", - }; + public RuntimeCounterListener() + { + observedRuntimeCounters = new Dictionary() { + { "cpu-usage" , false }, + { "working-set", false }, + { "gc-heap-size", false }, + { "gen-0-gc-count", false }, + { "gen-1-gc-count", false }, + { "gen-2-gc-count", false }, + { "threadpool-thread-count", false }, + { "monitor-lock-contention-count", false }, + { "threadpool-queue-length", false }, + { "threadpool-completed-items-count", false }, + { "alloc-rate", false }, + { "active-timer-count", false }, + { "gc-fragmentation", false }, + { "gc-committed", false }, + { "exception-count", false }, + { "time-in-gc", false }, + { "gen-0-size", false }, + { "gen-1-size", false }, + { "gen-2-size", false }, + { "loh-size", false }, + { "poh-size", false }, + { "assembly-count", false }, + { "il-bytes-jitted", false }, + { "methods-jitted-count", false }, + { "time-in-jit", false } + }; + } + private Dictionary observedRuntimeCounters; protected override void OnEventSourceCreated(EventSource source) { @@ -58,22 +54,15 @@ protected override void OnEventSourceCreated(EventSource source) { Dictionary refreshInterval = new Dictionary(); refreshInterval.Add("EventCounterIntervalSec", "1"); - EnableEvents(source, EventLevel.Informational, (EventKeywords)(-1), refreshInterval); + EnableEvents(source, EventLevel.Informational, + (EventKeywords)(-1 & (~1 /* RuntimeEventSource.Keywords.AppContext */)), + refreshInterval); } } protected override void OnEventWritten(EventWrittenEventArgs eventData) { - // Check AppContext switches - if (eventData is { EventName: "LogAppContextSwitch", - Payload: { Count: 2 } } && - eventData.Payload[0] is string switchName) - { - observedEvents[switchName] = ((int)eventData.Payload[1]) == 1; - return; - } - // Check counters for (int i = 0; i < eventData.Payload.Count; i++) { IDictionary eventPayload = eventData.Payload[i] as IDictionary; @@ -82,7 +71,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) foreach (KeyValuePair payload in eventPayload) { if (payload.Key.Equals("Name")) - observedEvents[payload.Value.ToString()] = true; + observedRuntimeCounters[payload.Value.ToString()] = true; } } } @@ -90,10 +79,11 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) public bool Verify() { - foreach (string counterName in observedEvents.Keys) + foreach (string counterName in observedRuntimeCounters.Keys) { - if (!observedEvents[counterName]) + if (!observedRuntimeCounters[counterName]) { + Console.WriteLine($"Did not see {counterName}"); return false; } else @@ -101,15 +91,6 @@ public bool Verify() Console.WriteLine($"Saw {counterName}"); } } - - foreach (var key in s_unexpectedEvents) - { - if (observedEvents.ContainsKey(key)) - { - Console.WriteLine($"Should not have seen {key}"); - return false; - } - } return true; } } @@ -118,12 +99,6 @@ public partial class TestRuntimeEventCounter { public static int Main(string[] args) { - AppContext.SetSwitch("appContextSwitch", true); - AppDomain.CurrentDomain.SetData("appContextBoolData", true); // Not loggeed, bool key - AppDomain.CurrentDomain.SetData("appContextBoolAsStringData", "true"); - AppDomain.CurrentDomain.SetData("appContextStringData", "myString"); // Not logged, string does not parse as bool - AppDomain.CurrentDomain.SetData("appContextSwitch", false); // should not override the SetSwitch above - // Create an EventListener. using (RuntimeCounterListener myListener = new RuntimeCounterListener()) { diff --git a/src/tests/tracing/runtimeeventsource/NativeRuntimeEventSourceTest.cs b/src/tests/tracing/runtimeeventsource/NativeRuntimeEventSourceTest.cs new file mode 100644 index 00000000000000..43306a803ffbfc --- /dev/null +++ b/src/tests/tracing/runtimeeventsource/NativeRuntimeEventSourceTest.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.IO; +using System.Diagnostics.Tracing; +using System.Runtime.CompilerServices; +using System.Threading; +using Tracing.Tests.Common; + +namespace Tracing.Tests +{ + public sealed class NativeRuntimeEventSourceTest + { + static int Main(string[] args) + { + SimpleEventListener.EnableKeywords = (EventKeywords)0; + using (SimpleEventListener noEventsListener = new SimpleEventListener("NoEvents")) + { + // Create an EventListener. + SimpleEventListener.EnableKeywords = (EventKeywords)0x4c14fccbd; + using (SimpleEventListener listener = new SimpleEventListener("Simple")) + { + // Trigger the allocator task. + System.Threading.Tasks.Task.Run(new Action(Allocator)); + + // Wait for events. + Thread.Sleep(1000); + + // Generate some GC events. + GC.Collect(2, GCCollectionMode.Forced); + + // Wait for more events. + Thread.Sleep(1000); + + // Ensure that we've seen some events. + Assert.True("listener.EventCount > 0", listener.EventCount > 0); + } + + // Generate some more GC events. + GC.Collect(2, GCCollectionMode.Forced); + + // Ensure that we've seen no events. + Assert.True("noEventsListener.EventCount == 0", noEventsListener.EventCount == 0); + } + + return 100; + } + + private static void Allocator() + { + while (true) + { + for(int i=0; i<1000; i++) + GC.KeepAlive(new object()); + + Thread.Sleep(10); + } + } + } + + internal sealed class SimpleEventListener : EventListener + { + private string m_name; + + // Keep track of the set of keywords to be enabled. + public static EventKeywords EnableKeywords + { + get; + set; + } + + public SimpleEventListener(string name) + { + m_name = name; + } + + public int EventCount { get; private set; } = 0; + + protected override void OnEventSourceCreated(EventSource eventSource) + { + if (eventSource.Name.Equals("Microsoft-Windows-DotNETRuntime")) + { + if (EnableKeywords != 0) + { + // Enable events. + EnableEvents(eventSource, EventLevel.Verbose, EnableKeywords); + } + else + { + // Enable the provider, but not any keywords, so we should get no events as long as no rundown occurs. + EnableEvents(eventSource, EventLevel.Critical, EnableKeywords); + } + } + } + + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + Console.WriteLine($"[{m_name}] ThreadID = {eventData.OSThreadId} ID = {eventData.EventId} Name = {eventData.EventName}"); + Console.WriteLine($"TimeStamp: {eventData.TimeStamp.ToLocalTime()}"); + Console.WriteLine($"LocalTime: {DateTime.Now}"); + Console.WriteLine($"Difference: {DateTime.UtcNow - eventData.TimeStamp}"); + Assert.True("eventData.TimeStamp <= DateTime.UtcNow", eventData.TimeStamp <= DateTime.UtcNow); + for (int i = 0; i < eventData.Payload.Count; i++) + { + string payloadString = eventData.Payload[i] != null ? eventData.Payload[i].ToString() : string.Empty; + Console.WriteLine($"\tName = \"{eventData.PayloadNames[i]}\" Value = \"{payloadString}\""); + } + Console.WriteLine("\n"); + + EventCount++; + } + } +} diff --git a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs index 4474176d360da5..3855596866544a 100644 --- a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs +++ b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs @@ -1,114 +1,93 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.IO; +#if USE_MDT_EVENTSOURCE +using Microsoft.Diagnostics.Tracing; +#else using System.Diagnostics.Tracing; -using System.Runtime.CompilerServices; +#endif +using System; +using System.Collections.Generic; using System.Threading; -using Tracing.Tests.Common; +using System.Threading.Tasks; +using System.Diagnostics; -namespace Tracing.Tests +AppContext.SetSwitch("appContextSwitch", true); +AppDomain.CurrentDomain.SetData("appContextBoolData", true); // Not loggeed, bool key +AppDomain.CurrentDomain.SetData("appContextBoolAsStringData", "true"); +AppDomain.CurrentDomain.SetData("appContextStringData", "myString"); // Not logged, string does not parse as bool +AppDomain.CurrentDomain.SetData("appContextSwitch", false); // should not override the SetSwitch above + +// Create an EventListener. +using (var myListener = new RuntimeEventListener()) { - public sealed class RuntimeEventSourceTest + await Task.Delay(10); + if (myListener.Verify()) { - static int Main(string[] args) - { - SimpleEventListener.EnableKeywords = (EventKeywords)0; - using (SimpleEventListener noEventsListener = new SimpleEventListener("NoEvents")) - { - // Create an EventListener. - SimpleEventListener.EnableKeywords = (EventKeywords)0x4c14fccbd; - using (SimpleEventListener listener = new SimpleEventListener("Simple")) - { - // Trigger the allocator task. - System.Threading.Tasks.Task.Run(new Action(Allocator)); - - // Wait for events. - Thread.Sleep(1000); - - // Generate some GC events. - GC.Collect(2, GCCollectionMode.Forced); - - // Wait for more events. - Thread.Sleep(1000); - - // Ensure that we've seen some events. - Assert.True("listener.EventCount > 0", listener.EventCount > 0); - } - - // Generate some more GC events. - GC.Collect(2, GCCollectionMode.Forced); + Console.WriteLine("Test passed"); + return 100; + } + else + { + Console.WriteLine($"Test Failed - did not see one or more of the expected runtime counters."); + return 1; + } +} - // Ensure that we've seen no events. - Assert.True("noEventsListener.EventCount == 0", noEventsListener.EventCount == 0); - } +public class RuntimeEventListener : EventListener +{ + private readonly Dictionary observedEvents = new Dictionary() { + { "appContextSwitch", false }, + { "appContextBoolAsStringData", false }, + }; - return 100; - } + private static readonly string[] s_unexpectedEvents = new[] { + "appContextBoolData", + "appContextStringData", + }; - private static void Allocator() + protected override void OnEventSourceCreated(EventSource source) + { + if (source.Name.Equals("System.Runtime")) { - while (true) - { - for(int i=0; i<1000; i++) - GC.KeepAlive(new object()); - - Thread.Sleep(10); - } + EnableEvents(source, EventLevel.Informational, (EventKeywords)1 /* RuntimeEventSource.Keywords.AppContext */); } } - internal sealed class SimpleEventListener : EventListener + protected override void OnEventWritten(EventWrittenEventArgs eventData) { - private string m_name; - - // Keep track of the set of keywords to be enabled. - public static EventKeywords EnableKeywords - { - get; - set; - } - - public SimpleEventListener(string name) + // Check AppContext switches + if (eventData is { EventName: "LogAppContextSwitch", + Payload: { Count: 2 } } && + eventData.Payload[0] is string switchName) { - m_name = name; + observedEvents[switchName] = ((int)eventData.Payload[1]) == 1; + return; } + } - public int EventCount { get; private set; } = 0; - - protected override void OnEventSourceCreated(EventSource eventSource) + public bool Verify() + { + foreach (string counterName in observedEvents.Keys) { - if (eventSource.Name.Equals("Microsoft-Windows-DotNETRuntime")) + if (!observedEvents[counterName]) { - if (EnableKeywords != 0) - { - // Enable events. - EnableEvents(eventSource, EventLevel.Verbose, EnableKeywords); - } - else - { - // Enable the provider, but not any keywords, so we should get no events as long as no rundown occurs. - EnableEvents(eventSource, EventLevel.Critical, EnableKeywords); - } + return false; + } + else + { + Console.WriteLine($"Saw {counterName}"); } } - protected override void OnEventWritten(EventWrittenEventArgs eventData) + foreach (var key in s_unexpectedEvents) { - Console.WriteLine($"[{m_name}] ThreadID = {eventData.OSThreadId} ID = {eventData.EventId} Name = {eventData.EventName}"); - Console.WriteLine($"TimeStamp: {eventData.TimeStamp.ToLocalTime()}"); - Console.WriteLine($"LocalTime: {DateTime.Now}"); - Console.WriteLine($"Difference: {DateTime.UtcNow - eventData.TimeStamp}"); - Assert.True("eventData.TimeStamp <= DateTime.UtcNow", eventData.TimeStamp <= DateTime.UtcNow); - for (int i = 0; i < eventData.Payload.Count; i++) + if (observedEvents.ContainsKey(key)) { - string payloadString = eventData.Payload[i] != null ? eventData.Payload[i].ToString() : string.Empty; - Console.WriteLine($"\tName = \"{eventData.PayloadNames[i]}\" Value = \"{payloadString}\""); + Console.WriteLine($"Should not have seen {key}"); + return false; } - Console.WriteLine("\n"); - - EventCount++; } + return true; } -} +} \ No newline at end of file diff --git a/src/tests/tracing/runtimeeventsource/nativeruntimeeventsource.csproj b/src/tests/tracing/runtimeeventsource/nativeruntimeeventsource.csproj new file mode 100644 index 00000000000000..70336054f35e5c --- /dev/null +++ b/src/tests/tracing/runtimeeventsource/nativeruntimeeventsource.csproj @@ -0,0 +1,21 @@ + + + Exe + BuildAndRun + true + 0 + true + + true + + true + + + + + + diff --git a/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj b/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj index 70336054f35e5c..4cc6b4cc592c0d 100644 --- a/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj +++ b/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj @@ -4,15 +4,8 @@ BuildAndRun true 0 - true true - - true From a599f925dc579f236254aa1c719d774b7c40dc76 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Tue, 17 Aug 2021 14:49:09 -0700 Subject: [PATCH 12/21] Fix case where s_switches is null --- .../src/System/AppContext.AnyOS.cs | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index 579d232debd0b1..9b4facd489747d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.IO; @@ -50,17 +51,27 @@ internal static void LogSwitchValues(RuntimeEventSource ev) { lock (s_dataStore) { + var dataStore = s_dataStore; if (s_switches is not null) { lock (s_switches) { - foreach (var (k, v) in s_dataStore) + LogDataStore(s_switches); + } + } + else + { + LogDataStore(null); + } + + void LogDataStore(Dictionary? switches) + { + foreach (var (k, v) in dataStore) + { + if (v is string s && bool.TryParse(s, out bool isEnabled) && + switches?.ContainsKey(s) != true) { - if (v is string s && bool.TryParse(s, out bool isEnabled) && - !s_switches.ContainsKey(s)) - { - ev.LogAppContextSwitch(k, isEnabled ? 1 : 0); - } + ev.LogAppContextSwitch(k, isEnabled ? 1 : 0); } } } From 98337ff7533d4a1a23cf570c01172f8699c4fd7b Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Tue, 17 Aug 2021 18:08:26 -0700 Subject: [PATCH 13/21] Fix bug --- .../System.Private.CoreLib/src/System/AppContext.AnyOS.cs | 7 ++++--- .../tracing/runtimeeventsource/RuntimeEventSourceTest.cs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index 9b4facd489747d..1e44e1404ffcc7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.IO; @@ -51,7 +52,6 @@ internal static void LogSwitchValues(RuntimeEventSource ev) { lock (s_dataStore) { - var dataStore = s_dataStore; if (s_switches is not null) { lock (s_switches) @@ -66,10 +66,11 @@ internal static void LogSwitchValues(RuntimeEventSource ev) void LogDataStore(Dictionary? switches) { - foreach (var (k, v) in dataStore) + Debug.Assert(s_dataStore is not null); + foreach (var (k, v) in s_dataStore) { if (v is string s && bool.TryParse(s, out bool isEnabled) && - switches?.ContainsKey(s) != true) + switches?.ContainsKey(k) != true) { ev.LogAppContextSwitch(k, isEnabled ? 1 : 0); } diff --git a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs index 3855596866544a..f9dc06c548854a 100644 --- a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs +++ b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs @@ -16,7 +16,7 @@ AppDomain.CurrentDomain.SetData("appContextBoolData", true); // Not loggeed, bool key AppDomain.CurrentDomain.SetData("appContextBoolAsStringData", "true"); AppDomain.CurrentDomain.SetData("appContextStringData", "myString"); // Not logged, string does not parse as bool -AppDomain.CurrentDomain.SetData("appContextSwitch", false); // should not override the SetSwitch above +AppDomain.CurrentDomain.SetData("appContextSwitch", "false"); // should not override the SetSwitch above // Create an EventListener. using (var myListener = new RuntimeEventListener()) From 216caef156909d4fb972f526c529f3102e6c92f8 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Wed, 18 Aug 2021 00:08:02 -0700 Subject: [PATCH 14/21] Print more info for test failure --- .../tracing/runtimeeventsource/RuntimeEventSourceTest.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs index f9dc06c548854a..585a8cf6d6ffca 100644 --- a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs +++ b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs @@ -68,15 +68,16 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) public bool Verify() { - foreach (string counterName in observedEvents.Keys) + foreach (var (k, v) in observedEvents) { - if (!observedEvents[counterName]) + if (!v) { + Console.WriteLine($"Could not find key {k}") return false; } else { - Console.WriteLine($"Saw {counterName}"); + Console.WriteLine($"Saw {k}"); } } From e15d564d1678f504c526a376dcc03752bc611d86 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Wed, 18 Aug 2021 00:46:26 -0700 Subject: [PATCH 15/21] Typo --- src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs index 585a8cf6d6ffca..3ca46b2a713902 100644 --- a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs +++ b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs @@ -72,7 +72,7 @@ public bool Verify() { if (!v) { - Console.WriteLine($"Could not find key {k}") + Console.WriteLine($"Could not find key {k}"); return false; } else From d305926f99a2f75eb62e6b58ead73f2187e6d730 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Wed, 18 Aug 2021 10:41:10 -0700 Subject: [PATCH 16/21] Fix lab failure --- .../RuntimeEventSourceTest.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs index 3ca46b2a713902..9a513ccf600319 100644 --- a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs +++ b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs @@ -36,9 +36,11 @@ public class RuntimeEventListener : EventListener { - private readonly Dictionary observedEvents = new Dictionary() { - { "appContextSwitch", false }, - { "appContextBoolAsStringData", false }, + private readonly Dictionary _observedEvents = new Dictionary(); + + private static readonly string[] s_expectedEvents = new[] { + "appContextSwitch", + "appContextBoolAsStringData", }; private static readonly string[] s_unexpectedEvents = new[] { @@ -58,32 +60,32 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) { // Check AppContext switches if (eventData is { EventName: "LogAppContextSwitch", - Payload: { Count: 2 } } && - eventData.Payload[0] is string switchName) + Payload: { Count: 2 } }) { - observedEvents[switchName] = ((int)eventData.Payload[1]) == 1; + var switchName = (string)eventData.Payload[0]; + _observedEvents[switchName] = ((int)eventData.Payload[1]) == 1; return; } } public bool Verify() { - foreach (var (k, v) in observedEvents) + foreach (var key in s_expectedEvents) { - if (!v) + if (!_observedEvents[key]) { - Console.WriteLine($"Could not find key {k}"); + Console.WriteLine($"Could not find key {key}"); return false; } else { - Console.WriteLine($"Saw {k}"); + Console.WriteLine($"Saw {key}"); } } foreach (var key in s_unexpectedEvents) { - if (observedEvents.ContainsKey(key)) + if (_observedEvents.ContainsKey(key)) { Console.WriteLine($"Should not have seen {key}"); return false; From d62f0c714d10d4898acba2793062bcf7bf87a5d5 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Wed, 18 Aug 2021 13:51:01 -0700 Subject: [PATCH 17/21] Respond to PR comments --- .../runtimeeventsource/RuntimeEventSourceTest.cs | 15 ++++++++++----- .../runtimeeventsource/runtimeeventsource.csproj | 1 + 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs index 9a513ccf600319..3a4b4bd38667e9 100644 --- a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs +++ b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs @@ -21,7 +21,6 @@ // Create an EventListener. using (var myListener = new RuntimeEventListener()) { - await Task.Delay(10); if (myListener.Verify()) { Console.WriteLine("Test passed"); @@ -30,17 +29,23 @@ else { Console.WriteLine($"Test Failed - did not see one or more of the expected runtime counters."); + Console.WriteLine("Observed events: "); + foreach (var (k, v) in myListener.ObservedEvents) + { + Console.WriteLine("Event: " + k + " " + v); + } return 1; } } public class RuntimeEventListener : EventListener { - private readonly Dictionary _observedEvents = new Dictionary(); + internal readonly Dictionary ObservedEvents = new Dictionary(); private static readonly string[] s_expectedEvents = new[] { "appContextSwitch", "appContextBoolAsStringData", + "RuntimeHostConfigSwitch", // Set in the project file }; private static readonly string[] s_unexpectedEvents = new[] { @@ -63,7 +68,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) Payload: { Count: 2 } }) { var switchName = (string)eventData.Payload[0]; - _observedEvents[switchName] = ((int)eventData.Payload[1]) == 1; + ObservedEvents[switchName] = ((int)eventData.Payload[1]) == 1; return; } } @@ -72,7 +77,7 @@ public bool Verify() { foreach (var key in s_expectedEvents) { - if (!_observedEvents[key]) + if (!ObservedEvents[key]) { Console.WriteLine($"Could not find key {key}"); return false; @@ -85,7 +90,7 @@ public bool Verify() foreach (var key in s_unexpectedEvents) { - if (_observedEvents.ContainsKey(key)) + if (ObservedEvents.ContainsKey(key)) { Console.WriteLine($"Should not have seen {key}"); return false; diff --git a/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj b/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj index 4cc6b4cc592c0d..0a79cdfa7a8227 100644 --- a/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj +++ b/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj @@ -10,5 +10,6 @@ + From 7975d52e90d98de205fb894bf4cc7b5e212d0f8e Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 19 Aug 2021 10:29:27 -0700 Subject: [PATCH 18/21] Respond to PR comments --- .../src/System/AppContext.AnyOS.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index 1e44e1404ffcc7..89a2c31e7b4f9a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -40,10 +40,10 @@ internal static void LogSwitchValues(RuntimeEventSource ev) { lock (s_switches) { - foreach (var (k, v) in s_switches) + foreach (KeyValuePair kvp in s_switches) { // Convert bool to int because it's cheaper to log (no boxing) - ev.LogAppContextSwitch(k, v ? 1 : 0); + ev.LogAppContextSwitch(kvp.Key, kvp.Value ? 1 : 0); } } } @@ -67,12 +67,13 @@ internal static void LogSwitchValues(RuntimeEventSource ev) void LogDataStore(Dictionary? switches) { Debug.Assert(s_dataStore is not null); - foreach (var (k, v) in s_dataStore) + foreach (KeyValuePair kvp in s_dataStore) { - if (v is string s && bool.TryParse(s, out bool isEnabled) && - switches?.ContainsKey(k) != true) + if (kvp.Value is string s && + bool.TryParse(s, out bool isEnabled) && + switches?.ContainsKey(kvp.Key) != true) { - ev.LogAppContextSwitch(k, isEnabled ? 1 : 0); + ev.LogAppContextSwitch(kvp.Key, isEnabled ? 1 : 0); } } } From 5906df36f98fe0416bbf437ba0f3afb63ee17c0b Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 19 Aug 2021 10:40:18 -0700 Subject: [PATCH 19/21] Typo --- .../System.Private.CoreLib/src/System/AppContext.AnyOS.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index 89a2c31e7b4f9a..d23f8148588f96 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -67,7 +67,7 @@ internal static void LogSwitchValues(RuntimeEventSource ev) void LogDataStore(Dictionary? switches) { Debug.Assert(s_dataStore is not null); - foreach (KeyValuePair kvp in s_dataStore) + foreach (KeyValuePair kvp in s_dataStore) { if (kvp.Value is string s && bool.TryParse(s, out bool isEnabled) && From e8f6c5c56fe72b84e156ccd0b3d62351e42948c6 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 19 Aug 2021 14:19:26 -0700 Subject: [PATCH 20/21] Respond to PR comments --- .../System.Private.CoreLib/src/System/AppContext.AnyOS.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index d23f8148588f96..94760aa0ef991c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -56,15 +56,15 @@ internal static void LogSwitchValues(RuntimeEventSource ev) { lock (s_switches) { - LogDataStore(s_switches); + LogDataStore(ev, s_switches); } } else { - LogDataStore(null); + LogDataStore(ev, null); } - void LogDataStore(Dictionary? switches) + static void LogDataStore(RuntimeEventSource ev, Dictionary? switches) { Debug.Assert(s_dataStore is not null); foreach (KeyValuePair kvp in s_dataStore) From 18f0504e7ff158b5960c2121ddedef33a9e88b6d Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Sat, 21 Aug 2021 20:37:48 -0700 Subject: [PATCH 21/21] Skip RuntimeEventSource tests on wasm and android (#57890) * Skip RuntimeEventSource tests on wasm and android * Skip tests without using issues.targets * Disable test for mono (cherry picked from commit 454ac571fe489ab818c7727f11eee71d521c4366) --- src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj b/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj index 0a79cdfa7a8227..79075307131d43 100644 --- a/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj +++ b/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj @@ -6,6 +6,7 @@ 0 true + true