From e0a1602e42482779f0d64cbcd5200506d5776293 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 12 Aug 2021 10:58:11 -0700 Subject: [PATCH 01/20] 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 35e45f472bb8b..0d5410b38053c 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 6d57c82ef6cc4..f1ff371180a01 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 c6503d3e2ec1bbbfdf96ef8eb6defdbf067ed171 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 12 Aug 2021 13:23:34 -0700 Subject: [PATCH 02/20] 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 0d5410b38053c..caf78fe4a4d06 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 f1ff371180a01..6df1a2f0cd839 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 c52f044dee59236d2fefd198d4fa7671aa3a67b8 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 11:55:10 -0700 Subject: [PATCH 03/20] 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 caf78fe4a4d06..64531618c16a0 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 bdab454300ade..522ad9719c6aa 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 8002ac9e3933f49936b8720adbbde86f2cd54eea Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 12:00:52 -0700 Subject: [PATCH 04/20] 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 64531618c16a0..49caac2fc9ab2 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 451ee4bce6678f7dcacb8e2afe70e3261d5ee89a Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 12:22:21 -0700 Subject: [PATCH 05/20] 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 49caac2fc9ab2..88337a60c9e5f 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 6df1a2f0cd839..3b3ac30c10aa9 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 6dd83dc29a4a97a3346d997bc94464cefc4874eb Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 13:49:33 -0700 Subject: [PATCH 06/20] 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 88337a60c9e5f..d4438e8c14e0f 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 522ad9719c6aa..3a379f37054dc 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 bc59e0082f338eaef27670cdab3d0d19c6dd9908 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 14:57:07 -0700 Subject: [PATCH 07/20] 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 c8b5fcba415f5..4fd808db210bc 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 d4438e8c14e0f..35e45f472bb8b 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 737492bd9a90f051c29efdfe3478e7bdfd82c4de Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 13 Aug 2021 15:30:58 -0700 Subject: [PATCH 08/20] 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 4fd808db210bc..e82be8033b223 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 4facebfbd2e982a6d5cd2bb9ef63ab9fd20867bf Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Mon, 16 Aug 2021 11:09:57 -0700 Subject: [PATCH 09/20] 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 3a379f37054dc..dda6ba4b74076 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 b0235f8ab4ab33f9acef1340af9f22b1e28ea6ee Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Tue, 17 Aug 2021 11:09:38 -0700 Subject: [PATCH 10/20] 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 e82be8033b223..579d232debd0b 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 dda6ba4b74076..ec1b2e13af3be 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 58a87f598b04e8c5a7c0b837b600b16de59a9622 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Tue, 17 Aug 2021 14:02:22 -0700 Subject: [PATCH 11/20] 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 ec1b2e13af3be..e6623649736d1 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 0000000000000..43306a803ffbf --- /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 4474176d360da..3855596866544 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 0000000000000..70336054f35e5 --- /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 70336054f35e5..4cc6b4cc592c0 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 5d4060c391bf53474b5a0425a2f1ef1cc57b1241 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Tue, 17 Aug 2021 14:49:09 -0700 Subject: [PATCH 12/20] 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 579d232debd0b..9b4facd489747 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 1044a0f1cd7936c50312adead081e0c4993425ae Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Tue, 17 Aug 2021 18:08:26 -0700 Subject: [PATCH 13/20] 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 9b4facd489747..1e44e1404ffcc 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 3855596866544..f9dc06c548854 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 f3526898de7f5150b3e56632a0d451ff20b44f08 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Wed, 18 Aug 2021 00:08:02 -0700 Subject: [PATCH 14/20] 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 f9dc06c548854..585a8cf6d6ffc 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 6a62a27b8919a097295bfe42d664d0d7e0a889d4 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Wed, 18 Aug 2021 00:46:26 -0700 Subject: [PATCH 15/20] 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 585a8cf6d6ffc..3ca46b2a71390 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 fad8256afe97c4db7c7903518ddb4332b03380d0 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Wed, 18 Aug 2021 10:41:10 -0700 Subject: [PATCH 16/20] 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 3ca46b2a71390..9a513ccf60031 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 8989c1bfbdacb04b83c0ebecbb69c952e8bb36a2 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Wed, 18 Aug 2021 13:51:01 -0700 Subject: [PATCH 17/20] 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 9a513ccf60031..3a4b4bd38667e 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 4cc6b4cc592c0..0a79cdfa7a822 100644 --- a/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj +++ b/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj @@ -10,5 +10,6 @@ + From 01288ae8bf8a1f28d668ddfe5d2deb25fb8eaebc Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 19 Aug 2021 10:29:27 -0700 Subject: [PATCH 18/20] 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 1e44e1404ffcc..89a2c31e7b4f9 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 0da16778178609acca2aca15fabf74b35751e73a Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 19 Aug 2021 10:40:18 -0700 Subject: [PATCH 19/20] 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 89a2c31e7b4f9..d23f8148588f9 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 740a7508632c9e37613800b37f653bc26c1b2c5d Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 19 Aug 2021 14:19:26 -0700 Subject: [PATCH 20/20] 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 d23f8148588f9..94760aa0ef991 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)