From: Juan Hoyos Date: Tue, 17 Nov 2020 03:10:21 +0000 (-0800) Subject: Remove dotnet-analyze (#1728) X-Git-Tag: submit/tizen/20210909.063632~17^2~324 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d387e47dd5395360dd12dabe43c6a9400fd6a7d1;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git Remove dotnet-analyze (#1728) --- diff --git a/src/Tools/dotnet-analyze/AnalysisSession.cs b/src/Tools/dotnet-analyze/AnalysisSession.cs deleted file mode 100644 index 243e28709..000000000 --- a/src/Tools/dotnet-analyze/AnalysisSession.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.Diagnostics.Tracing.Etlx; - -namespace Microsoft.Diagnostics.Tools.Analyze -{ - public class AnalysisSession - { - public MemoryDump Dump { get; } - public TraceLog Trace { get; } - - public AnalysisSession(MemoryDump dump, TraceLog trace) - { - Dump = dump; - Trace = trace; - } - } -} diff --git a/src/Tools/dotnet-analyze/AsyncHangAnalyzer.cs b/src/Tools/dotnet-analyze/AsyncHangAnalyzer.cs deleted file mode 100644 index 381dd7ba2..000000000 --- a/src/Tools/dotnet-analyze/AsyncHangAnalyzer.cs +++ /dev/null @@ -1,131 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; -using Microsoft.Diagnostics.Runtime; - -namespace Microsoft.Diagnostics.Tools.Analyze -{ - internal class AsyncHangAnalyzer - { - private const string AsyncStateMachineBoxTypeName = "System.Runtime.CompilerServices.AsyncTaskMethodBuilder+AsyncStateMachineBox<"; - private const string DebugFinalizableBoxTypeName = "System.Runtime.CompilerServices.AsyncTaskMethodBuilder+DebugFinalizableAsyncStateMachineBox<"; - - internal const int TASK_STATE_STARTED = 0x10000; //bin: 0000 0000 0000 0001 0000 0000 0000 0000 - internal const int TASK_STATE_DELEGATE_INVOKED = 0x20000; //bin: 0000 0000 0000 0010 0000 0000 0000 0000 - internal const int TASK_STATE_DISPOSED = 0x40000; //bin: 0000 0000 0000 0100 0000 0000 0000 0000 - internal const int TASK_STATE_EXCEPTIONOBSERVEDBYPARENT = 0x80000; //bin: 0000 0000 0000 1000 0000 0000 0000 0000 - internal const int TASK_STATE_CANCELLATIONACKNOWLEDGED = 0x100000; //bin: 0000 0000 0001 0000 0000 0000 0000 0000 - internal const int TASK_STATE_FAULTED = 0x200000; //bin: 0000 0000 0010 0000 0000 0000 0000 0000 - internal const int TASK_STATE_CANCELED = 0x400000; //bin: 0000 0000 0100 0000 0000 0000 0000 0000 - internal const int TASK_STATE_WAITING_ON_CHILDREN = 0x800000; //bin: 0000 0000 1000 0000 0000 0000 0000 0000 - internal const int TASK_STATE_RAN_TO_COMPLETION = 0x1000000; //bin: 0000 0001 0000 0000 0000 0000 0000 0000 - internal const int TASK_STATE_WAITINGFORACTIVATION = 0x2000000; //bin: 0000 0010 0000 0000 0000 0000 0000 0000 - internal const int TASK_STATE_COMPLETION_RESERVED = 0x4000000; //bin: 0000 0100 0000 0000 0000 0000 0000 0000 - internal const int TASK_STATE_THREAD_WAS_ABORTED = 0x8000000; //bin: 0000 1000 0000 0000 0000 0000 0000 0000 - internal const int TASK_STATE_WAIT_COMPLETION_NOTIFICATION = 0x10000000; //bin: 0001 0000 0000 0000 0000 0000 0000 0000 - internal const int TASK_STATE_EXECUTIONCONTEXT_IS_NULL = 0x20000000; //bin: 0010 0000 0000 0000 0000 0000 0000 0000 - internal const int TASK_STATE_TASKSCHEDULED_WAS_FIRED = 0x40000000; //bin: 0100 0000 0000 0000 0000 0000 0000 0000 - - public static void Run(IConsole console, ClrRuntime runtime) - { - // Collect all state machines - foreach (var obj in runtime.Heap.EnumerateObjects()) - { - // Skip non-matching types - if (!obj.Type.Name.StartsWith(AsyncStateMachineBoxTypeName) && !obj.Type.Name.StartsWith(DebugFinalizableBoxTypeName)) - { - continue; - } - - // Get the status of the task - var taskState = obj.GetField("m_stateFlags"); - var taskStatus = ToTaskStatus(taskState); - - if(taskStatus == TaskStatus.Canceled || taskStatus == TaskStatus.Faulted || taskStatus == TaskStatus.RanToCompletion) - { - continue; - } - - // Get the state machine field - var field = obj.Type.GetFieldByName("StateMachine"); - - // Get address and method table - if (field.ElementType == ClrElementType.Struct) - { - var stateMachine = obj.GetValueClassField("StateMachine"); - - // Exclude Microsoft/System state machines - if (stateMachine.Type.Name.StartsWith("System") || stateMachine.Type.Name.StartsWith("Microsoft")) - { - continue; - } - - console.WriteLine($"StateMachine: {stateMachine.Type.Name} struct 0x{stateMachine.Type.MethodTable:X}"); - foreach (var stateMachineField in stateMachine.Type.Fields) - { - console.WriteLine($" {stateMachineField.Name}: {stateMachineField.GetDisplayValue(stateMachine)}"); - } - } - else - { - var stateMachine = obj.GetObjectField("StateMachine"); - - // Exclude Microsoft/System state machines - if (stateMachine.Type.Name.StartsWith("System") || stateMachine.Type.Name.StartsWith("Microsoft")) - { - continue; - } - - console.WriteLine($"StateMachine: {stateMachine.Type.Name} class 0x{stateMachine.Type.MethodTable:X}"); - foreach (var stateMachineField in stateMachine.Type.Fields) - { - console.WriteLine($" {stateMachineField.Name}: {stateMachineField.GetDisplayValue(stateMachine)}"); - } - } - } - } - - private static TaskStatus ToTaskStatus(int stateFlags) - { - TaskStatus rval; - - if ((stateFlags & TASK_STATE_FAULTED) != 0) - { - rval = TaskStatus.Faulted; - } - else if ((stateFlags & TASK_STATE_CANCELED) != 0) - { - rval = TaskStatus.Canceled; - } - else if ((stateFlags & TASK_STATE_RAN_TO_COMPLETION) != 0) - { - rval = TaskStatus.RanToCompletion; - } - else if ((stateFlags & TASK_STATE_WAITING_ON_CHILDREN) != 0) - { - rval = TaskStatus.WaitingForChildrenToComplete; - } - else if ((stateFlags & TASK_STATE_DELEGATE_INVOKED) != 0) - { - rval = TaskStatus.Running; - } - else if ((stateFlags & TASK_STATE_STARTED) != 0) - { - rval = TaskStatus.WaitingToRun; - } - else if ((stateFlags & TASK_STATE_WAITINGFORACTIVATION) != 0) - { - rval = TaskStatus.WaitingForActivation; - } - else - { - rval = TaskStatus.Created; - } - - return rval; - } - } -} diff --git a/src/Tools/dotnet-analyze/ClrMdExtensions.cs b/src/Tools/dotnet-analyze/ClrMdExtensions.cs deleted file mode 100644 index 3458e289f..000000000 --- a/src/Tools/dotnet-analyze/ClrMdExtensions.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.Diagnostics.Runtime; - -namespace Microsoft.Diagnostics.Tools.Analyze -{ - internal static class ClrMdExtensions - { - public static bool IsDerivedFrom(this ClrType self, string typeName) - { - while (self != null) - { - if (string.Equals(self.Name, typeName)) - { - return true; - } - self = self.BaseType; - } - - return false; - } - - public static string GetDisplayValue(this ClrInstanceField self, ClrValueClass clrObject) - { - if (self.IsObjectReference) - { - var obj = clrObject.GetObjectField(self.Name); - if (obj.IsNull) - { - return "null"; - } - return $"0x{obj.Address:X} [{obj.Type.Name}:0x{obj.Type.MethodTable:X}]"; - } - else if(self.HasSimpleValue) - { - return $"{self.GetValue(clrObject.Address)} [{self.Type.Name}]"; - } - else if(self.IsValueClass) - { - var vt = clrObject.GetValueClassField(self.Name); - return $"0x{vt.Address:X} [struct {vt.Type.Name}:0x{vt.Type.MethodTable:X}]"; - } - else - { - return ""; - } - } - - public static string GetDisplayValue(this ClrInstanceField self, ClrObject clrObject) - { - if (self.IsObjectReference) - { - var obj = clrObject.GetObjectField(self.Name); - if (obj.IsNull) - { - return "null"; - } - return $"0x{obj.Address:X} [{obj.Type.Name}:0x{obj.Type.MethodTable:X}]"; - } - else if(self.HasSimpleValue) - { - return self.GetValue(clrObject.Address).ToString(); - } - else if(self.IsValueClass) - { - var vt = clrObject.GetValueClassField(self.Name); - return $"0x{vt.Address:X} [struct {vt.Type.Name}:0x{vt.Type.MethodTable:X}]"; - } - else - { - return ""; - } - } - } -} diff --git a/src/Tools/dotnet-analyze/CommandProcessor.cs b/src/Tools/dotnet-analyze/CommandProcessor.cs deleted file mode 100644 index d4324f87b..000000000 --- a/src/Tools/dotnet-analyze/CommandProcessor.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; -using Microsoft.Diagnostics.Tools.Analyze.Commands; - -namespace Microsoft.Diagnostics.Tools.Analyze -{ - public class CommandProcessor - { - private readonly IList _commands; - private readonly IDictionary _commandNames; - - public CommandProcessor() - { - _commands = GetCommands(); - _commandNames = BuildCommandNamesIndex(_commands); - } - - public async Task RunAsync(IConsole console, AnalysisSession session, CancellationToken cancellationToken = default) - { - await console.Out.WriteLineAsync("Ready to process analysis commands. Type 'help' to list available commands or 'help [command]' to get detailed help on a command."); - await console.Out.WriteLineAsync("Type 'quit' or 'exit' to exit the analysis session."); - while (!cancellationToken.IsCancellationRequested) - { - await console.Out.WriteAsync("> "); - var line = await console.In.ReadLineAsync(); - cancellationToken.ThrowIfCancellationRequested(); - - // Naive arg parsing - var args = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - if (string.Equals(args[0], "quit", StringComparison.OrdinalIgnoreCase) || string.Equals(args[0], "q", StringComparison.OrdinalIgnoreCase) || string.Equals(args[0], "exit", StringComparison.OrdinalIgnoreCase)) - { - return; - } - if (string.Equals(args[0], "help", StringComparison.OrdinalIgnoreCase)) - { - await ShowHelpAsync(console, args.AsMemory().Slice(1)); - } - else if (_commandNames.TryGetValue(args[0], out var command)) - { - await command.RunAsync(console, args.Skip(1).ToArray(), session); - } - else - { - console.Error.WriteLine($"Unknown command: {args[0]}"); - } - } - } - - private async Task ShowHelpAsync(IConsole console, ReadOnlyMemory args) - { - if (args.Length == 0) - { - foreach (var command in _commands) - { - var line = $"* {command.Names[0]} - {command.Description}"; - if (command.Names.Count > 1) - { - line += $" (aliases: {string.Join(", ", command.Names.Skip(1))})"; - } - console.WriteLine(line); - } - } - else - { - if (_commandNames.TryGetValue(args.Span[0], out var command)) - { - await command.WriteHelpAsync(console); - } - else - { - console.WriteLine($"Unknown command: {args.Span[0]}"); - } - } - } - - private IDictionary BuildCommandNamesIndex(IEnumerable commands) - { - var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach (var command in commands) - { - foreach (var name in command.Names) - { - dict[name] = command; - } - } - return dict; - } - - private static List GetCommands() - { - return typeof(Program).Assembly - .GetExportedTypes() - .Where(t => !t.IsAbstract && typeof(IAnalysisCommand).IsAssignableFrom(t)) - .Select(t => (IAnalysisCommand)Activator.CreateInstance(t)) - .ToList(); - } - } -} diff --git a/src/Tools/dotnet-analyze/Commands/DumpCommandBase.cs b/src/Tools/dotnet-analyze/Commands/DumpCommandBase.cs deleted file mode 100644 index 7f03d8274..000000000 --- a/src/Tools/dotnet-analyze/Commands/DumpCommandBase.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; - -namespace Microsoft.Diagnostics.Tools.Analyze.Commands -{ - public abstract class DumpCommandBase : IAnalysisCommand - { - public abstract IReadOnlyList Names { get; } - public abstract string Description { get; } - - public async Task RunAsync(IConsole console, string[] args, AnalysisSession session) - { - if (session.Dump == null) - { - await console.Error.WriteLineAsync("This command requires a memory dump!"); - } - else - { - await RunAsyncCoreAsync(console, args, session, session.Dump); - } - } - - public abstract Task WriteHelpAsync(IConsole console); - protected abstract Task RunAsyncCoreAsync(IConsole console, string[] args, AnalysisSession session, MemoryDump dump); - } -} diff --git a/src/Tools/dotnet-analyze/Commands/DumpHeapCommand.cs b/src/Tools/dotnet-analyze/Commands/DumpHeapCommand.cs deleted file mode 100644 index 31ae92df7..000000000 --- a/src/Tools/dotnet-analyze/Commands/DumpHeapCommand.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; - -namespace Microsoft.Diagnostics.Tools.Analyze.Commands -{ - public class DumpHeapCommand : DumpCommandBase - { - public override IReadOnlyList Names { get; } = new[] { "DumpHeap" }; - - public override string Description => "Dumps objects from the .NET Heap"; - - protected override Task RunAsyncCoreAsync(IConsole console, string[] args, AnalysisSession session, MemoryDump dump) - { - var stats = dump.ComputeHeapStatistics().OrderBy(s => s.TotalSize); - console.WriteLine(" MT Count TotalSize Class Name"); - foreach (var heapStats in stats) - { - console.WriteLine($"{heapStats.Type.MethodTable:X16} {heapStats.Count.ToString().PadLeft(8)} {heapStats.TotalSize.ToString().PadLeft(12)} {heapStats.Type.Name}"); - } - - return Task.CompletedTask; - } - - public override Task WriteHelpAsync(IConsole console) - { - console.WriteLine("TODO"); - return Task.CompletedTask; - } - } -} diff --git a/src/Tools/dotnet-analyze/Commands/DumpStackCommand.cs b/src/Tools/dotnet-analyze/Commands/DumpStackCommand.cs deleted file mode 100644 index fad0b3dc3..000000000 --- a/src/Tools/dotnet-analyze/Commands/DumpStackCommand.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; -using Microsoft.Diagnostics.Runtime; - -namespace Microsoft.Diagnostics.Tools.Analyze.Commands -{ - public class DumpStackCommand : DumpCommandBase - { - public override IReadOnlyList Names { get; } = new [] { "dumpstack" }; - - public override string Description => "Dumps the managed stack trace for the current thread."; - - protected override async Task RunAsyncCoreAsync(IConsole console, string[] args, AnalysisSession session, MemoryDump dump) - { - foreach(var frame in dump.ActiveThread.EnumerateStackTrace()) - { - var methodInfo = frame.Method == null ? "" : GenerateMethodInfo(frame.Method); - await console.Out.WriteLineAsync($"{frame.StackPointer:x16} {frame.InstructionPointer:x16} {methodInfo}"); - } - } - - private string GenerateMethodInfo(ClrMethod method) - { - return $"{method.Type.Name}.{method.Name}"; - } - - public override Task WriteHelpAsync(IConsole console) - { - console.WriteLine("TODO"); - return Task.CompletedTask; - } - } -} diff --git a/src/Tools/dotnet-analyze/Commands/EventStackCommand.cs b/src/Tools/dotnet-analyze/Commands/EventStackCommand.cs deleted file mode 100644 index ff097f970..000000000 --- a/src/Tools/dotnet-analyze/Commands/EventStackCommand.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; -using Microsoft.Diagnostics.Tracing.Etlx; - -namespace Microsoft.Diagnostics.Tools.Analyze.Commands -{ - public class EventStackCommand : TraceCommandBase - { - public override IReadOnlyList Names => new[] { "eventstack" }; - - public override string Description => "Dumps the stack trace associated with an event, if there is one."; - - protected override Task RunAsyncCore(IConsole console, string[] args, AnalysisSession session, TraceLog trace) - { - if (args.Length < 1) - { - console.Error.WriteLine("Usage: eventstack "); - return Task.CompletedTask; - } - - if (!int.TryParse(args[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var eventIndex)) - { - console.Error.WriteLine("Usage: eventstack "); - return Task.CompletedTask; - } - - var evt = trace.Events.ElementAt(eventIndex); - var stack = evt.CallStack(); - if (stack != null) - { - WriteStack(stack, console); - } - else - { - console.Error.WriteLine($"Unable to find any call stacks for event {eventIndex:X4}!"); - } - - return Task.CompletedTask; - } - - private void WriteStack(TraceCallStack stack, IConsole console) - { - while (stack != null) - { - console.WriteLine($" at {stack.CodeAddress.ModuleName}!{stack.CodeAddress.FullMethodName} + 0x{stack.CodeAddress.ILOffset:X4}"); - stack = stack.Caller; - } - } - - public override Task WriteHelpAsync(IConsole console) - { - console.WriteLine("TODO"); - return Task.CompletedTask; - } - } -} diff --git a/src/Tools/dotnet-analyze/Commands/IAnalysisCommand.cs b/src/Tools/dotnet-analyze/Commands/IAnalysisCommand.cs deleted file mode 100644 index 8aec791f3..000000000 --- a/src/Tools/dotnet-analyze/Commands/IAnalysisCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; - -namespace Microsoft.Diagnostics.Tools.Analyze.Commands -{ - public interface IAnalysisCommand - { - IReadOnlyList Names { get; } - string Description { get; } - - Task RunAsync(IConsole console, string[] args, AnalysisSession session); - Task WriteHelpAsync(IConsole console); - } -} diff --git a/src/Tools/dotnet-analyze/Commands/InfoCommand.cs b/src/Tools/dotnet-analyze/Commands/InfoCommand.cs deleted file mode 100644 index 00a162645..000000000 --- a/src/Tools/dotnet-analyze/Commands/InfoCommand.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; - -namespace Microsoft.Diagnostics.Tools.Analyze.Commands -{ - public class InfoCommand : IAnalysisCommand - { - public IReadOnlyList Names { get; } = new List() { "info" }; - public string Description => "Displays information about the current analysis session"; - - public Task RunAsync(IConsole console, string[] args, AnalysisSession session) - { - if(session.Dump != null) - { - console.WriteLine("Memory Dump:"); - console.WriteLine($" CLR Version: {session.Dump.Runtime.ClrInfo.Version}"); - console.WriteLine($" CLR Flavor: {session.Dump.Runtime.ClrInfo.Flavor}"); - } - else - { - console.WriteLine("No Memory Dump Loaded."); - } - - if(session.Trace != null) - { - console.WriteLine("Trace:"); - console.WriteLine($" OS: {session.Trace.OSName} {session.Trace.OSVersion}"); - } - else - { - console.WriteLine("No Trace Loaded."); - } - return Task.CompletedTask; - } - - public Task WriteHelpAsync(IConsole console) - { - console.WriteLine("TODO"); - return Task.CompletedTask; - } - } -} diff --git a/src/Tools/dotnet-analyze/Commands/LogsCommand.cs b/src/Tools/dotnet-analyze/Commands/LogsCommand.cs deleted file mode 100644 index 38ec88cfc..000000000 --- a/src/Tools/dotnet-analyze/Commands/LogsCommand.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; -using Microsoft.Diagnostics.Tracing; -using Microsoft.Diagnostics.Tracing.Etlx; -using Microsoft.Diagnostics.Tracing.Parsers; - -namespace Microsoft.Diagnostics.Tools.Analyze.Commands -{ - public class LogsCommand : TraceCommandBase - { - public override IReadOnlyList Names => new[] { "logs" }; - - public override string Description => "Dumps Microsoft.Extensions.Logging logs."; - - protected override Task RunAsyncCore(IConsole console, string[] args, AnalysisSession session, TraceLog trace) - { - var prefix = string.Empty; - if(args.Length > 0) { - prefix = args[0]; - } - console.WriteLine("Scanning log events..."); - var events = trace.Events - .Where(t => - string.Equals(t.ProviderName, "Microsoft-Extensions-Logging") && - string.Equals(t.EventName, "MessageJson") && - ((string)t.PayloadByName("LoggerName")).StartsWith(prefix)) - .Select(e => e.Clone()) - .ToList(); - console.WriteLine("Logs:"); - foreach (var evt in events) - { - var log = LogMessage.Load(evt); - console.WriteLine($"* ({((int)evt.EventIndex).ToString("X4")}) [{log.Timestamp:O}] [{log.Level}] {log.LoggerName}({log.EventId}): {log.Message}"); - foreach(var (key, value) in log.Arguments) - { - console.WriteLine($" {key} = {value}"); - } - } - - return Task.CompletedTask; - } - - public override Task WriteHelpAsync(IConsole console) - { - console.WriteLine("TODO"); - return Task.CompletedTask; - } - } -} diff --git a/src/Tools/dotnet-analyze/Commands/RequestsCommand.cs b/src/Tools/dotnet-analyze/Commands/RequestsCommand.cs deleted file mode 100644 index 36af2a003..000000000 --- a/src/Tools/dotnet-analyze/Commands/RequestsCommand.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; -using Microsoft.Diagnostics.Tracing; -using Microsoft.Diagnostics.Tracing.Etlx; -using Microsoft.Diagnostics.Tracing.Parsers; - -namespace Microsoft.Diagnostics.Tools.Analyze.Commands -{ - public class RequestsCommand : TraceCommandBase - { - public override IReadOnlyList Names => new[] { "requests" }; - - public override string Description => "Lists all ASP.NET Core HTTP requests contained in the attached trace (if there is one)."; - - protected override Task RunAsyncCore(IConsole console, string[] args, AnalysisSession session, TraceLog trace) - { - console.WriteLine("Scanning request events..."); - var requests = trace.Events - .Where(t => string.Equals(t.ProviderName, "Microsoft-AspNetCore-Hosting") && string.Equals(t.EventName, "RequestStart/Start")) - .Select(e => e.Clone()) - .ToList(); - console.WriteLine("HTTP requests:"); - foreach (var request in requests) - { - console.WriteLine($"* ({((int)request.EventIndex).ToString("X4")}) [{request.TimeStamp:O}] {request.PayloadString(0)} {request.PayloadString(1)}"); - } - - return Task.CompletedTask; - } - - public override Task WriteHelpAsync(IConsole console) - { - console.WriteLine("TODO"); - return Task.CompletedTask; - } - } -} diff --git a/src/Tools/dotnet-analyze/Commands/ThreadsCommand.cs b/src/Tools/dotnet-analyze/Commands/ThreadsCommand.cs deleted file mode 100644 index 5aa642865..000000000 --- a/src/Tools/dotnet-analyze/Commands/ThreadsCommand.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; - -namespace Microsoft.Diagnostics.Tools.Analyze.Commands -{ - public class ThreadsCommand : DumpCommandBase - { - public override IReadOnlyList Names { get; } = new List() { "threads", "~"}; - - public override string Description => "Lists threads in the current dump."; - - protected override async Task RunAsyncCoreAsync(IConsole console, string[] args, AnalysisSession session, MemoryDump dump) - { - foreach(var thread in dump.Runtime.Threads) - { - var isActive = dump.ActiveThreadId == thread.ManagedThreadId ? "." : " "; - await console.Out.WriteLineAsync($"{isActive}{thread.ManagedThreadId.ToString().PadLeft(2)} Id: {Utils.FormatAddress(thread.OSThreadId)} Teb: {Utils.FormatAddress(thread.Teb)}"); - } - } - - public override Task WriteHelpAsync(IConsole console) - { - console.WriteLine("TODO"); - return Task.CompletedTask; - } - } -} diff --git a/src/Tools/dotnet-analyze/Commands/TraceCommandBase.cs b/src/Tools/dotnet-analyze/Commands/TraceCommandBase.cs deleted file mode 100644 index 9729550c2..000000000 --- a/src/Tools/dotnet-analyze/Commands/TraceCommandBase.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; -using Microsoft.Diagnostics.Tracing.Etlx; - -namespace Microsoft.Diagnostics.Tools.Analyze.Commands -{ - public abstract class TraceCommandBase : IAnalysisCommand - { - public abstract IReadOnlyList Names { get; } - public abstract string Description { get; } - - public async Task RunAsync(IConsole console, string[] args, AnalysisSession session) - { - if (session.Trace == null) - { - await console.Error.WriteLineAsync("This command requires an event trace!"); - } - else - { - await RunAsyncCore(console, args, session, session.Trace); - } - } - - public abstract Task WriteHelpAsync(IConsole console); - protected abstract Task RunAsyncCore(IConsole console, string[] args, AnalysisSession session, TraceLog trace); - } -} diff --git a/src/Tools/dotnet-analyze/LogMessage.cs b/src/Tools/dotnet-analyze/LogMessage.cs deleted file mode 100644 index 09050666f..000000000 --- a/src/Tools/dotnet-analyze/LogMessage.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using Microsoft.Diagnostics.Tracing; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; - -namespace Microsoft.Diagnostics.Tools.Analyze -{ - internal class LogMessage - { - public DateTime Timestamp { get; } - public string LoggerName { get; } - public LogLevel Level { get; } - public EventId EventId { get; } - public IDictionary Arguments { get; } - public string Message { get; } - - public LogMessage(DateTime timestamp, string loggerName, EventId eventId, LogLevel level, IDictionary arguments, string message) - { - Timestamp = timestamp; - LoggerName = loggerName; - EventId = eventId; - Level = level; - Arguments = arguments; - Message = message; - } - - internal static LogMessage Load(TraceEvent request) - { - var (arguments, message) = LoadArguments((string)request.PayloadByName("ArgumentsJson")); - var eventIdStr = (string)request.PayloadByName("EventId"); - EventId eventId = default; - if (int.TryParse(eventIdStr, out var id)) - { - eventId = new EventId(id); - } - else - { - eventId = new EventId(0, eventIdStr); - } - - return new LogMessage( - request.TimeStamp, - loggerName: (string)request.PayloadByName("LoggerName"), - eventId: eventId, - level: (LogLevel)(int)request.PayloadByName("Level"), - arguments: arguments, - message: message); - } - - private static (IDictionary, string) LoadArguments(string json) - { - var jobj = JObject.Parse(json); - var arguments = new Dictionary(); - var format = ""; - foreach (var prop in jobj.Properties()) - { - if (prop.Name.Equals("{OriginalFormat}")) - { - format = prop.Value.ToString(); - } - else - { - arguments.Add(prop.Name, prop.Value.ToString()); - } - } - - var message = FormatMessage(format, arguments); - return (arguments, message); - } - - private static string FormatMessage(string format, Dictionary arguments) - { - foreach (var (key, value) in arguments) - { - format = format.Replace($"{{{key}}}", value); - } - return format; - } - } -} diff --git a/src/Tools/dotnet-analyze/MemoryDump.cs b/src/Tools/dotnet-analyze/MemoryDump.cs deleted file mode 100644 index 17dccd669..000000000 --- a/src/Tools/dotnet-analyze/MemoryDump.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.Diagnostics.Runtime; - -namespace Microsoft.Diagnostics.Tools.Analyze -{ - public class MemoryDump : IDisposable - { - public DataTarget Target { get; } - public ClrRuntime Runtime { get; } - public int ActiveThreadId { get; set; } - public ClrThread ActiveThread => GetThread(ActiveThreadId); - - public MemoryDump(DataTarget target, ClrRuntime runtime) - { - Target = target; - Runtime = runtime; - - var firstThread = runtime.Threads.FirstOrDefault(); - if (firstThread != null) - { - ActiveThreadId = firstThread.ManagedThreadId; - } - } - - public ClrThread GetThread(int id) - { - return Runtime.Threads.FirstOrDefault(t => t.ManagedThreadId == id); - } - - public IList ComputeHeapStatistics() - { - // Compute heap information - var stats = new Dictionary(); - foreach (var obj in Runtime.Heap.EnumerateObjects()) - { - var type = obj.Type.Name; - if (!stats.TryGetValue(type, out var heapStats)) - { - heapStats = new TypeHeapStats(obj.Type); - stats[type] = heapStats; - } - - heapStats.AddObject(obj.Size); - } - - return stats.Values.ToList(); - } - - public void Dispose() - { - Target.Dispose(); - } - } -} diff --git a/src/Tools/dotnet-analyze/Program.cs b/src/Tools/dotnet-analyze/Program.cs deleted file mode 100644 index 8415fa200..000000000 --- a/src/Tools/dotnet-analyze/Program.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using McMaster.Extensions.CommandLineUtils; -using Microsoft.Diagnostics.Runtime; -using Microsoft.Diagnostics.Tracing.Etlx; -using Microsoft.Internal.Utilities; - -namespace Microsoft.Diagnostics.Tools.Analyze -{ - [Command(Name = "dotnet-analyze", Description = "Inspect a crash dump using interactive commands")] - internal class Program - { - [Argument(0, "", Description = "The path to the diagnostic files to analyze.")] - public IList Files { get; set; } - - public async Task OnExecuteAsync(IConsole console, CommandLineApplication app) - { - var cleanupFiles = new List(); - - MemoryDump dump = null; - TraceLog trace = null; - - if (Files == null || Files.Count == 0) - { - console.Error.WriteLine("No files were provided!"); - return 1; - } - - try - { - foreach (var file in Files) - { - if (file.EndsWith(".nettrace")) - { - console.WriteLine($"Loading trace: {file} ..."); - var etlx = TraceLog.CreateFromEventPipeDataFile(file); - console.WriteLine($"Convert trace to: {etlx}."); - cleanupFiles.Add(etlx); - trace = TraceLog.OpenOrConvert(etlx); - } - else - { - console.WriteLine($"Loading crash dump: {file} ..."); - var target = DataTarget.LoadCrashDump(file); - // Assume there's only one - if (target.ClrVersions.Count > 1) - { - console.Error.WriteLine("Multiple CLR versions are present!"); - return 1; - } - - var runtime = target.ClrVersions[0].CreateRuntime(); - dump = new MemoryDump(target, runtime); - } - } - - if (dump == null && trace == null) - { - console.Error.WriteLine("A dump or trace could not be loaded from the provided files"); - return 1; - } - var session = new AnalysisSession(dump, trace); - await (new CommandProcessor()).RunAsync(console, session, console.GetCtrlCToken()); - return 0; - } - finally - { - dump?.Dispose(); - trace?.Dispose(); - - foreach (var file in cleanupFiles) - { - if (File.Exists(file)) - { - File.Delete(file); - } - } - } - } - - private static int Main(string[] args) - { - DebugUtil.WaitForDebuggerIfRequested(ref args); - - try - { - return CommandLineApplication.Execute(args); - } - catch (OperationCanceledException) - { - return 0; - } - } - } -} diff --git a/src/Tools/dotnet-analyze/TypeHeapStats.cs b/src/Tools/dotnet-analyze/TypeHeapStats.cs deleted file mode 100644 index 87f5d4a9d..000000000 --- a/src/Tools/dotnet-analyze/TypeHeapStats.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.Diagnostics.Runtime; - -namespace Microsoft.Diagnostics.Tools.Analyze -{ - public class TypeHeapStats - { - public ClrType Type { get; } - public long Count { get; private set; } - public ulong TotalSize { get; private set; } - - public TypeHeapStats(ClrType type) - { - Type = type; - } - - public void AddObject(ulong size) - { - Count++; - TotalSize += size; - } - } -} diff --git a/src/Tools/dotnet-analyze/Utils.cs b/src/Tools/dotnet-analyze/Utils.cs deleted file mode 100644 index e1dd29583..000000000 --- a/src/Tools/dotnet-analyze/Utils.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Microsoft.Diagnostics.Tools.Analyze -{ - internal static class Utils - { - internal static string FormatAddress(uint addr) - { - var hi = (short)(addr >> 16); - var lo = (short)addr; - return $"{hi:x4}`{lo:x4}"; - } - - internal static string FormatAddress(ulong addr) - { - var hi = (int)(addr >> 32); - var lo = (int)addr; - return $"{hi:x8}`{lo:x8}"; - } - } -} diff --git a/src/Tools/dotnet-analyze/dotnet-analyze.csproj b/src/Tools/dotnet-analyze/dotnet-analyze.csproj deleted file mode 100644 index 0b48075d5..000000000 --- a/src/Tools/dotnet-analyze/dotnet-analyze.csproj +++ /dev/null @@ -1,36 +0,0 @@ - - - Exe - netcoreapp2.1 - 2.1.0 - - win-x64;win-x86;osx-x64 - - 1.0.0 - 1.0.0 - dotnet-analyze - Microsoft.Diagnostics.Tools.Analyze - Diagnostic analyze tool - Diagnostic - $(Description) - - $(OutputPath) - - - - - - - - - - - - - - - - diff --git a/src/Tools/dotnet-analyze/runtimeconfig.template.json b/src/Tools/dotnet-analyze/runtimeconfig.template.json deleted file mode 100644 index f022b7ffc..000000000 --- a/src/Tools/dotnet-analyze/runtimeconfig.template.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "rollForwardOnNoCandidateFx": 2 -} \ No newline at end of file