using Microsoft.Diagnostics.NETCore.Client; using Microsoft.Diagnostics.Tracing; using Microsoft.Diagnostics.Tracing.Etlx; using Microsoft.Diagnostics.Tracing.EventPipe; using Microsoft.Diagnostics.Tracing.Parsers; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.Tracing; using System.Text; using TraceKeywords = Microsoft.Diagnostics.Tracing.Parsers.ClrTraceEventParser.Keywords; public class RuntimeGCEventsPrinter { static ImmutableHashSet blacklist; static ImmutableHashSet stacklist; static RuntimeGCEventsPrinter() { blacklist = ImmutableHashSet.Create( "Method/ILToNativeMap", "GC/BulkMovedObjectRanges", "GC/BulkSurvivingObjectRanges", "GC/FinalizeObject", "Type/BulkType", "GC/SetGCHandle", "GC/DestoryGCHandle", "TypeLoad/Start", "Method/R2RGetEntryPointStart", "Method/MethodDetails", "Method/MemoryAllocatedForJitCode", "Method/JittingStarted", "GC/BulkRootStaticVar", "GC/BulkNode", "GC/BulkEdge", "GC/BulkRootEdge", "ThreadPoolWorkerThread/Wait", "ILStub/StubGenerated" ); stacklist = ImmutableHashSet.Create( "{TEST_ITEM}" ); log.logEndpointForCategory( "Method/MemoryAllocatedForJitCode", log.Endpoints.File ); log.logEndpointForCategory( "TypeLoad/Stop", log.Endpoints.File ); log.logEndpointForCategory( "GC/BulkRootStaticVar", log.Endpoints.File ); log.logEndpointForCategory( "GC/BulkNode", log.Endpoints.File ); log.logEndpointForCategory( "GC/BulkRootStaticVar", log.Endpoints.File ); } public static string MethodInfo( TraceEvent te, string prefix = "Method" ) { return $"{te.PayloadStringByName($"{prefix}Namespace")}.{te.PayloadStringByName($"{prefix}Name")}{te.PayloadStringByName($"{prefix}Signature")}"; } public static Action LogCategoryFunc( string catIn ) { return ( TraceEvent te ) => { var cat = catIn; if( blacklist.Contains( te.EventName )) return; { var methodBeingCompiledNamespace = te.PayloadStringByName("MethodBeingCompiledNamespace") ?? ""; if( ( methodBeingCompiledNamespace.StartsWith( "Microsoft" ) || methodBeingCompiledNamespace.StartsWith( "System" ) ) ) return; } { var methodNamespace = te.PayloadStringByName("MethodNamespace") ?? ""; if( ( methodNamespace.StartsWith( "Microsoft" ) || methodNamespace.StartsWith( "System" ) ) ) return; } { var ns = te.PayloadStringByName("TypeName") ?? ""; if( ( ns.StartsWith( "Microsoft" ) || ns.StartsWith( "System" ) ) ) return; } { var ns = te.PayloadStringByName("TypeLoad/Stop") ?? ""; if( ns.StartsWith( "Godot" ) ) return; } { var payloadIndex = te.PayloadIndex( "count" ); if( payloadIndex > 0 ) { var count = (int)te.PayloadValue( payloadIndex ); if( count > 16 ) return; } } // // // if( !te.EventName.StartsWith( "EventID") ) { var logDetails = ""; // Custom event displays if( te.EventName == "Method/LoadVerbose" ) { log.info( $"{te.PayloadStringByName("OptimizationTier")} {MethodInfo(te)}", cat: te.EventName ); return; //logDetails = "| Details: "; } else if( te.EventName.StartsWith( "Method/Inlining" ) ) { log.info( $"Inlining {te.PayloadStringByName("FailReason")} {te.PayloadStringByName("OptimizationTier")} {MethodInfo(te, "MethodBeingCompiled")}", cat: te.EventName ); return; //logDetails = "| Details: "; } else if( te.EventName == "TypeLoad/Stop" ) { var typeName = te.PayloadStringByName("TypeName"); if( typeName.StartsWith( "Godot." ) ) return; log.info( $"{typeName} Level: {te.PayloadStringByName("LoadLevel")}", cat: te.EventName ); return; //logDetails = "| Details: "; } else if( te.EventName.StartsWith( "Method/R2RGetEntryPoint" ) ) { log.info( $"{MethodInfo(te)} Entry: {te.PayloadStringByName("EntryPoint")}", cat: te.EventName ); return; //logDetails = "| Details: "; } //76 CHARACTERS // 0 ) { Encoding enc = new UnicodeEncoding(false, false, true); var eventDataUtf16 = enc.GetString( eventData ); log.debug( $"> {eventDataUtf16}" ); } */ } else { /* var payloadNames = te.PayloadNames; var channel = te.Channel; var formattedMsg = te.FormattedMessage; var keywords = te.Keywords; var source = te.Source; var dump = te.Dump(); var dynMemberNames = te.GetDynamicMemberNames(); var dataStart = te.DataStart; */ var eventData = te.EventData(); //var eventDataStr = eventData.ToString(); Encoding enc = new UnicodeEncoding(false, false, true); var eventDataUtf16 = enc.GetString( eventData ); //var safeEventData = eventDataUtf16.Replace( (char)0, '\n' ); var arrEventData = eventDataUtf16.Split( (char)0 ); var joinedEventData = string.Join( " | ", arrEventData ); //log.info( $"{te.FormattedMessage}", cat: catIn ); log.info( $"{joinedEventData}", cat: catIn ); } }; } public static void PrintRuntimeGCEvents( int processId ) { var providers = new List() { new EventPipeProvider("Microsoft-Windows-DotNETRuntime", EventLevel.Verbose, (long)( TraceKeywords.GC | TraceKeywords.Contention | TraceKeywords.Debugger | TraceKeywords.Exception | TraceKeywords.GCAllObjectAllocation | TraceKeywords.GCSampledObjectAllocationHigh | TraceKeywords.GCSampledObjectAllocationLow | TraceKeywords.Security | TraceKeywords.Threading | TraceKeywords.Type | TraceKeywords.TypeDiagnostic | TraceKeywords.WaitHandle | TraceKeywords.All ) ) }; var client = new DiagnosticsClient( processId ); using( EventPipeSession session = client.StartEventPipeSession( providers, false ) ) { var source = new EventPipeEventSource( session.EventStream ); source.Clr.All += LogCategoryFunc( "clr" ); source.Kernel.All += LogCategoryFunc( "kernel" ); // Doesnt seem to be too interesting. //source.Dynamic.All += LogCategoryFunc( "dynamic" ); try { source.Process(); } catch( Exception e ) { Console.WriteLine( "Error encountered while processing events" ); Console.WriteLine( e.ToString() ); } } } }