{
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)
{
{ "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)
// 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]) ?
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]);
}
}
}
}
[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]
{
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));
+ }
}
}