From: Sung Yoon Whang Date: Tue, 8 Oct 2019 02:16:20 +0000 (-0700) Subject: [dotnet-trace] Allow user to specify text version of event level (#540) X-Git-Tag: submit/tizen/20200402.013218~14^2^2~33 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=51c99d114cd9c2c9f9ef8e954be63bb0ebeabe0c;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git [dotnet-trace] Allow user to specify text version of event level (#540) * Allow user to specify text version of event level * Throw on unknown event level * add tests * docs change * more docs change * make case insensitive comparison --- diff --git a/documentation/design-docs/dotnet-tools.md b/documentation/design-docs/dotnet-tools.md index 557eaf7e0..5d100ae7b 100644 --- a/documentation/design-docs/dotnet-tools.md +++ b/documentation/design-docs/dotnet-tools.md @@ -291,7 +291,7 @@ COLLECT Provider format: KnownProviderName[:Keywords[:Level][:KeyValueArgs]] KnownProviderName - The provider's name Keywords - 8 character hex number bit mask - Level - A number in the range [0, 5] + Level - A number in the range [0, 5], or their corresponding text values (refer to https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.tracing.eventlevel?view=netframework-4.8). KeyValueArgs - A semicolon separated list of key=value KeyValueArgs format: '[key1=value1][;key2=value2]' @@ -303,12 +303,22 @@ COLLECT Examples: + + To perform a default `cpu-tracing` profiling: + > dotnet trace collect --process-id 1902 No profile or providers specified, defaulting to trace profile 'cpu-sampling' Recording trace 38MB 's' - stop tracing + + To collect just the GC keyword events from the .NET runtime at informational level: + + > dotnet trace collect --process-id 1902 --providers Microsoft-Windows-DotNETRuntime:0x1:Informational + + + CONVERT dotnet-trace convert [-h|--help] diff --git a/src/Tools/dotnet-trace/Extensions.cs b/src/Tools/dotnet-trace/Extensions.cs index fbaf43847..a1055eeeb 100644 --- a/src/Tools/dotnet-trace/Extensions.cs +++ b/src/Tools/dotnet-trace/Extensions.cs @@ -12,6 +12,8 @@ namespace Microsoft.Diagnostics.Tools.Trace { internal static class Extensions { + private static EventLevel defaultEventLevel = EventLevel.Verbose; + public static List ToProviders(string providers) { if (providers == null) @@ -20,6 +22,35 @@ namespace Microsoft.Diagnostics.Tools.Trace new List() : providers.Split(',').Select(ToProvider).ToList(); } + private static EventLevel GetEventLevel(string token) + { + if (Int32.TryParse(token, out int level) && level >= 0) + { + return level > (int)EventLevel.Verbose ? EventLevel.Verbose : (EventLevel)level; + } + + else + { + switch (token.ToLower()) + { + case "critical": + return EventLevel.Critical; + case "error": + return EventLevel.Error; + case "informational": + return EventLevel.Informational; + case "logalways": + return EventLevel.LogAlways; + case "verbose": + return EventLevel.Verbose; + case "warning": + return EventLevel.Warning; + default: + throw new ArgumentException($"Unknown EventLevel: {token}"); + } + } + } + private static Provider ToProvider(string provider) { if (string.IsNullOrWhiteSpace(provider)) @@ -44,10 +75,8 @@ namespace Microsoft.Diagnostics.Tools.Trace Convert.ToUInt64(tokens[1], 16) : ulong.MaxValue; // Level - uint level = tokens.Length > 2 && !string.IsNullOrWhiteSpace(tokens[2]) ? - Convert.ToUInt32(tokens[2]) : (uint)EventLevel.Verbose; - EventLevel eventLevel = level > (uint)EventLevel.Verbose ? - EventLevel.Verbose : (EventLevel)level; // TODO: Should we throw here? + EventLevel eventLevel = tokens.Length > 2 && !string.IsNullOrWhiteSpace(tokens[2]) ? + GetEventLevel(tokens[2]) : defaultEventLevel; // Event counters string filterData = tokens.Length > 3 ? tokens[3] : null; diff --git a/src/tests/dotnet-trace/ProviderParsing.cs b/src/tests/dotnet-trace/ProviderParsing.cs index 9b84140b5..8d1930d4b 100644 --- a/src/tests/dotnet-trace/ProviderParsing.cs +++ b/src/tests/dotnet-trace/ProviderParsing.cs @@ -178,5 +178,84 @@ namespace Microsoft.Diagnostics.Tools.Trace Assert.True(providerThree.EventLevel == System.Diagnostics.Tracing.EventLevel.Warning); Assert.True(providerThree.FilterData == "FilterAndPayloadSpecs=\"QuotedValue:-\r\nQuoted/Value:-A=B;C=D;\""); } + + [Theory] + [InlineData("ProviderOne:0x1:Verbose")] + [InlineData("ProviderOne:0x1:verbose")] + public void TextLevelProviderSpecVerbose_CorrectlyParse(string providerToParse) + { + List parsedProviders = Extensions.ToProviders(providerToParse); + Assert.True(parsedProviders.Count == 1); + Assert.True(parsedProviders[0].Name == "ProviderOne"); + Assert.True(parsedProviders[0].Keywords == 1); + Assert.True(parsedProviders[0].EventLevel == System.Diagnostics.Tracing.EventLevel.Verbose); + } + + [Theory] + [InlineData("ProviderOne:0x1:Informational")] + [InlineData("ProviderOne:0x1:INFORMATIONAL")] + public void TextLevelProviderSpecInformational_CorrectlyParse(string providerToParse) + { + List parsedProviders = Extensions.ToProviders(providerToParse); + Assert.True(parsedProviders.Count == 1); + Assert.True(parsedProviders[0].Name == "ProviderOne"); + Assert.True(parsedProviders[0].Keywords == 1); + Assert.True(parsedProviders[0].EventLevel == System.Diagnostics.Tracing.EventLevel.Informational); + } + + [Theory] + [InlineData("ProviderOne:0x1:LogAlways")] + [InlineData("ProviderOne:0x1:LogAlwayS")] + public void TextLevelProviderSpecLogAlways_CorrectlyParse(string providerToParse) + { + List parsedProviders = Extensions.ToProviders(providerToParse); + Assert.True(parsedProviders.Count == 1); + Assert.True(parsedProviders[0].Name == "ProviderOne"); + Assert.True(parsedProviders[0].Keywords == 1); + Assert.True(parsedProviders[0].EventLevel == System.Diagnostics.Tracing.EventLevel.LogAlways); + } + + [Theory] + [InlineData("ProviderOne:0x1:Error")] + [InlineData("ProviderOne:0x1:ERRor")] + public void TextLevelProviderSpecError_CorrectlyParse(string providerToParse) + { + List parsedProviders = Extensions.ToProviders(providerToParse); + Assert.True(parsedProviders.Count == 1); + Assert.True(parsedProviders[0].Name == "ProviderOne"); + Assert.True(parsedProviders[0].Keywords == 1); + Assert.True(parsedProviders[0].EventLevel == System.Diagnostics.Tracing.EventLevel.Error); + } + + [Theory] + [InlineData("ProviderOne:0x1:Critical")] + [InlineData("ProviderOne:0x1:CRITICAL")] + public void TextLevelProviderSpecCritical_CorrectlyParse(string providerToParse) + { + List parsedProviders = Extensions.ToProviders(providerToParse); + Assert.True(parsedProviders.Count == 1); + Assert.True(parsedProviders[0].Name == "ProviderOne"); + Assert.True(parsedProviders[0].Keywords == 1); + Assert.True(parsedProviders[0].EventLevel == System.Diagnostics.Tracing.EventLevel.Critical); + } + + [Theory] + [InlineData("ProviderOne:0x1:Warning")] + [InlineData("ProviderOne:0x1:warning")] + public void TextLevelProviderSpecWarning_CorrectlyParse(string providerToParse) + { + List parsedProviders = Extensions.ToProviders(providerToParse); + Assert.True(parsedProviders.Count == 1); + Assert.True(parsedProviders[0].Name == "ProviderOne"); + Assert.True(parsedProviders[0].Keywords == 1); + Assert.True(parsedProviders[0].EventLevel == System.Diagnostics.Tracing.EventLevel.Warning); + } + + [Theory] + [InlineData("ProviderOne:0x1:UnknownLevel")] + public void TextLevelProviderSpec_CorrectlyThrows(string providerToParse) + { + Assert.Throws(() => Extensions.ToProviders(providerToParse)); + } } } \ No newline at end of file