@@ -14,13 +14,52 @@ namespace Microsoft.Diagnostics.Tools.Trace
1414{
1515 internal sealed class ListProfilesCommandHandler
1616 {
17+ private static long defaultKeyword = 0x1 | // GC
18+ 0x4 | // Loader
19+ 0x8 | // AssemblyLoader
20+ 0x10 | // JIT
21+ 0x8000 | // Exceptions
22+ 0x10000 | // Threading
23+ 0x20000 | // JittedMethodILToNativeMap
24+ 0x1000000000 ; // Contention
25+
26+ private static string dotnetCommonDescription = """
27+ Lightweight .NET runtime diagnostics designed to stay low overhead.
28+ Includes:
29+ GC
30+ AssemblyLoader
31+ Jit
32+ Exception
33+ Threading
34+ JittedMethodILToNativeMap
35+ Compilation
36+ Contention
37+ Equivalent to --providers "Microsoft-Windows-DotNETRuntime:0x100003801D:4".
38+ """ ;
39+
1740 public static int GetProfiles ( )
1841 {
1942 try
2043 {
44+ Console . Out . WriteLine ( "dotnet-trace collect profiles:" ) ;
45+ int profileNameWidth = ProfileNamesMaxWidth ( DotNETRuntimeProfiles ) ;
2146 foreach ( Profile profile in DotNETRuntimeProfiles )
2247 {
23- Console . Out . WriteLine ( $ "\t { profile . Name , - 16 } - { profile . Description } ") ;
48+ PrintProfile ( profile , profileNameWidth ) ;
49+ }
50+
51+ if ( OperatingSystem . IsLinux ( ) )
52+ {
53+ Console . Out . WriteLine ( "\n dotnet-trace collect-linux profiles:" ) ;
54+ profileNameWidth = Math . Max ( profileNameWidth , ProfileNamesMaxWidth ( LinuxPerfEventProfiles ) ) ;
55+ foreach ( Profile profile in DotNETRuntimeProfiles )
56+ {
57+ PrintProfile ( profile , profileNameWidth ) ;
58+ }
59+ foreach ( Profile profile in LinuxPerfEventProfiles )
60+ {
61+ PrintProfile ( profile , profileNameWidth ) ;
62+ }
2463 }
2564
2665 return 0 ;
@@ -44,12 +83,17 @@ public static Command ListProfilesCommand()
4483
4584 internal static IEnumerable < Profile > DotNETRuntimeProfiles { get ; } = new [ ] {
4685 new Profile (
47- "cpu-sampling" ,
86+ "dotnet-common" ,
87+ new EventPipeProvider [ ] {
88+ new ( "Microsoft-Windows-DotNETRuntime" , EventLevel . Informational , defaultKeyword )
89+ } ,
90+ dotnetCommonDescription ) ,
91+ new Profile (
92+ "dotnet-sampled-thread-time" ,
4893 new EventPipeProvider [ ] {
4994 new ( "Microsoft-DotNETCore-SampleProfiler" , EventLevel . Informational ) ,
50- new ( "Microsoft-Windows-DotNETRuntime" , EventLevel . Informational , ( long ) ClrTraceEventParser . Keywords . Default )
5195 } ,
52- "Useful for tracking CPU usage and general .NET runtime information. This is the default option if no profile or providers are specified ." ) ,
96+ "Samples .NET thread stacks (~100 Hz) to identify hotspots over time. Uses the runtime sample profiler with managed stacks ." ) ,
5397 new Profile (
5498 "gc-verbose" ,
5599 new EventPipeProvider [ ] {
@@ -104,6 +148,44 @@ public static Command ListProfilesCommand()
104148 "Captures ADO.NET and Entity Framework database commands" )
105149 } ;
106150
151+ internal static IEnumerable < Profile > LinuxPerfEventProfiles { get ; } = new [ ] {
152+ new Profile (
153+ "kernel-cpu" ,
154+ providers : Array . Empty < EventPipeProvider > ( ) ,
155+ description : "Kernel CPU sampling (perf-based), emitted as Universal.Events/cpu, for precise on-CPU attribution." ) ,
156+ new Profile (
157+ "kernel-cswitch" ,
158+ providers : Array . Empty < EventPipeProvider > ( ) ,
159+ description : "Kernel thread context switches, emitted as Universal.Events/cswitch, for on/off-CPU and scheduler analysis." )
160+ } ;
161+
162+ private static int ProfileNamesMaxWidth ( IEnumerable < Profile > profiles )
163+ {
164+ int maxWidth = 0 ;
165+ foreach ( Profile profile in profiles )
166+ {
167+ if ( profile . Name . Length > maxWidth )
168+ {
169+ maxWidth = profile . Name . Length ;
170+ }
171+ }
172+
173+ return maxWidth ;
174+ }
175+
176+ private static void PrintProfile ( Profile profile , int nameColumnWidth )
177+ {
178+ string [ ] descriptionLines = profile . Description . Replace ( "\r \n " , "\n " ) . Split ( '\n ' ) ;
179+
180+ Console . Out . WriteLine ( $ "\t { profile . Name . PadRight ( nameColumnWidth ) } - { descriptionLines [ 0 ] } ") ;
181+
182+ string continuationPrefix = $ "\t { new string ( ' ' , nameColumnWidth ) } ";
183+ for ( int i = 1 ; i < descriptionLines . Length ; i ++ )
184+ {
185+ Console . Out . WriteLine ( continuationPrefix + descriptionLines [ i ] ) ;
186+ }
187+ }
188+
107189 /// <summary>
108190 /// Keywords for DiagnosticSourceEventSource provider
109191 /// </summary>
0 commit comments