Change provider defaults for dotnet-trace (#4512)
authorDavid Mason <davmason@microsoft.com>
Fri, 16 Feb 2024 19:17:14 +0000 (11:17 -0800)
committerGitHub <noreply@github.com>
Fri, 16 Feb 2024 19:17:14 +0000 (11:17 -0800)
src/Tools/dotnet-trace/Extensions.cs
src/tests/dotnet-trace/ProfileProviderMerging.cs
src/tests/dotnet-trace/ProviderParsing.cs

index 2eca2eeedbd57bdf3f378a8a0bbd5b4a8dfb01e9..d73cadcb7f48b8c0aa4e994e6ffa3ef0e4486912 100644 (file)
@@ -14,7 +14,9 @@ namespace Microsoft.Diagnostics.Tools.Trace
     {
         public static string CLREventProviderName = "Microsoft-Windows-DotNETRuntime";
 
-        private static EventLevel defaultEventLevel = EventLevel.Verbose;
+        private const EventLevel defaultEventLevel = EventLevel.Informational;
+        private const long defaultKeywords = 0;
+
         // Keep this in sync with runtime repo's clretwall.man
         private static Dictionary<string, long> CLREventKeywords = new(StringComparer.InvariantCultureIgnoreCase)
         {
@@ -55,15 +57,53 @@ namespace Microsoft.Diagnostics.Tools.Trace
             { "typediagnostic", 0x8000000000 },
         };
 
-        public static List<EventPipeProvider> ToProviders(string providers)
+        public static List<EventPipeProvider> ToProviders(string providersRawInput)
         {
-            if (providers == null)
+            if (providersRawInput == null)
+            {
+                throw new ArgumentNullException(nameof(providersRawInput));
+            }
+
+            if (string.IsNullOrWhiteSpace(providersRawInput))
             {
-                throw new ArgumentNullException(nameof(providers));
+                return new List<EventPipeProvider>();
             }
 
-            return string.IsNullOrWhiteSpace(providers) ?
-                new List<EventPipeProvider>() : providers.Split(',').Select(ToProvider).ToList();
+            IEnumerable<EventPipeProvider> providers = providersRawInput.Split(',').Select(ToProvider).ToList();
+
+            // Dedupe the entries
+            providers = providers.GroupBy(p => p.Name)
+                                 .Select(p => {
+                                     string providerName = p.Key;
+                                     EventLevel providerLevel = EventLevel.Critical;
+                                     long providerKeywords = 0;
+                                     IDictionary<string, string> providerFilterArgs = null;
+
+                                     foreach (EventPipeProvider currentProvider in p)
+                                     {
+                                         providerKeywords |= currentProvider.Keywords;
+
+                                         if ((currentProvider.EventLevel == EventLevel.LogAlways)
+                                             || (providerLevel != EventLevel.LogAlways && currentProvider.EventLevel > providerLevel))
+                                         {
+                                             providerLevel = currentProvider.EventLevel;
+                                         }
+
+                                         if (currentProvider.Arguments != null)
+                                         {
+                                             if (providerFilterArgs != null)
+                                             {
+                                                 throw new ArgumentException($"Provider \"{providerName}\" is declared multiple times with filter arguments.");
+                                             }
+
+                                             providerFilterArgs = currentProvider.Arguments;
+                                         }
+                                     }
+
+                                     return new EventPipeProvider(providerName, providerLevel, providerKeywords, providerFilterArgs);
+                                 });
+
+            return providers.ToList();
         }
 
         public static EventPipeProvider ToCLREventPipeProvider(string clreventslist, string clreventlevel)
@@ -151,7 +191,7 @@ namespace Microsoft.Diagnostics.Tools.Trace
 
             // Keywords
             long keywords = tokens.Length > 1 && !string.IsNullOrWhiteSpace(tokens[1]) ?
-                Convert.ToInt64(tokens[1], 16) : -1;
+                Convert.ToInt64(tokens[1], 16) : defaultKeywords;
 
             // Level
             EventLevel eventLevel = tokens.Length > 2 && !string.IsNullOrWhiteSpace(tokens[2]) ?
index c01860810932f7b8a7b991f4de4fb234cb412932..606fa24e50091a0d8e027d724bb5bf7b15396eee 100644 (file)
@@ -36,9 +36,9 @@ namespace Microsoft.Diagnostics.Tools.Trace
             EventPipeProvider enabledProvider = parsedProviders.SingleOrDefault(p => p.Name == "Microsoft-Windows-DotNETRuntime");
 
             // Assert that our specified provider overrides the version in the profile
-            Assert.True(enabledProvider.Keywords == (long)(-1));
-            Assert.True(enabledProvider.EventLevel == EventLevel.Verbose);
-            Assert.True(enabledBy[enabledProvider.Name] == "--providers");
+            Assert.Equal((long)(0), enabledProvider.Keywords);
+            Assert.Equal(EventLevel.Informational, enabledProvider.EventLevel);
+            Assert.Equal("--providers", enabledBy[enabledProvider.Name]);
         }
     }
 }
index c71167a3ee4d9cb8117bfdc6f02c11aed6c64a7d..bab3b6fb0de2d35213a4ba43ee1fbd246000cfbd 100644 (file)
@@ -71,18 +71,18 @@ namespace Microsoft.Diagnostics.Tools.Trace
         }
 
         [Theory]
-        [InlineData("VeryCoolProvider::5:FilterAndPayloadSpecs=\"QuotedValue\"")]
+        [InlineData("VeryCoolProvider::4:FilterAndPayloadSpecs=\"QuotedValue\"")]
         [InlineData("VeryCoolProvider:::FilterAndPayloadSpecs=\"QuotedValue\"")]
         public void ValidProviderEventLevel_CorrectlyParses(string providerToParse)
         {
             List<EventPipeProvider> parsedProviders = Extensions.ToProviders(providerToParse);
-            Assert.True(parsedProviders.Count == 1);
+            Assert.Equal(1, parsedProviders.Count);
             EventPipeProvider provider = parsedProviders.First();
-            Assert.True(provider.Name == "VeryCoolProvider");
-            Assert.True(provider.Keywords == (long)(-1));
-            Assert.True(provider.EventLevel == System.Diagnostics.Tracing.EventLevel.Verbose);
-            Assert.True(provider.Arguments.Count == 1);
-            Assert.True(provider.Arguments["FilterAndPayloadSpecs"] == "QuotedValue");
+            Assert.Equal("VeryCoolProvider", provider.Name);
+            Assert.Equal(0, provider.Keywords);
+            Assert.Equal(System.Diagnostics.Tracing.EventLevel.Informational, provider.EventLevel);
+            Assert.Equal(1, provider.Arguments.Count);
+            Assert.Equal("QuotedValue", provider.Arguments["FilterAndPayloadSpecs"]);
         }
 
         [Theory]
@@ -306,5 +306,36 @@ namespace Microsoft.Diagnostics.Tools.Trace
         {
             Assert.Throws<ArgumentException>(() => Extensions.ToProviders(providerToParse));
         }
+
+        [Theory]
+        [InlineData("DupeProvider,DupeProvider:0xF:LogAlways")]
+        public void DeDupeProviders_DefaultAndSpecified(string providersToParse)
+        {
+            List<EventPipeProvider> parsedProviders = Extensions.ToProviders(providersToParse);
+            Assert.Equal("DupeProvider", parsedProviders.First().Name);
+            Assert.Equal(1, parsedProviders.Count);
+            Assert.Equal(0xF, parsedProviders.First().Keywords);
+            Assert.Equal(System.Diagnostics.Tracing.EventLevel.LogAlways, parsedProviders.First().EventLevel);
+            Assert.Null(parsedProviders.First().Arguments);
+        }
+
+        [Theory]
+        [InlineData("DupeProvider:0xF0:Informational,DupeProvider:0xF:Verbose")]
+        public void DeDupeProviders_BothSpecified(string providersToParse)
+        {
+            List<EventPipeProvider> parsedProviders = Extensions.ToProviders(providersToParse);
+            Assert.Equal("DupeProvider", parsedProviders.First().Name);
+            Assert.Equal(1, parsedProviders.Count);
+            Assert.Equal(0xFF, parsedProviders.First().Keywords);
+            Assert.Equal(System.Diagnostics.Tracing.EventLevel.Verbose, parsedProviders.First().EventLevel);
+            Assert.Null(parsedProviders.First().Arguments);
+        }
+
+        [Theory]
+        [InlineData("DupeProvider:::key=value,DupeProvider:::key=value")]
+        public void DeDupeProviders_FilterDataThrows(string providersToParse)
+        {
+            Assert.Throws<ArgumentException>(() => Extensions.ToProviders(providersToParse));
+        }
     }
 }