зеркало из https://github.com/dotnet/diagnostics.git
Upgrade to latest System.CommandLine version (#668)
Upgrade to latest System.CommandLine version Use collection initializers
This commit is contained in:
Родитель
7df57cc8b9
Коммит
125ea40662
|
@ -63,6 +63,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracee", "src\tests\Tracee\
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventPipe.UnitTests", "src\tests\eventpipe\EventPipe.UnitTests.csproj", "{CED9ABBA-861E-4C0A-9359-22351208EF27}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{298AE119-6625-4604-BDE5-0765DC34C856}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
src\Tools\Common\CommandExtensions.cs = src\Tools\Common\CommandExtensions.cs
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Commands", "Commands", "{C457CBCD-3A8D-4402-9A2B-693A0390D3F9}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
src\Tools\Common\Commands\ProcessStatus.cs = src\Tools\Common\Commands\ProcessStatus.cs
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Checked|Any CPU = Checked|Any CPU
|
||||
|
@ -1090,6 +1100,8 @@ Global
|
|||
{6F4DD2F8-1C7B-4A87-B7E5-1BEE9F5AC128} = {03479E19-3F18-49A6-910A-F5041E27E7C0}
|
||||
{C79D6069-2C18-48CB-846E-71F7168C2F7D} = {03479E19-3F18-49A6-910A-F5041E27E7C0}
|
||||
{CED9ABBA-861E-4C0A-9359-22351208EF27} = {03479E19-3F18-49A6-910A-F5041E27E7C0}
|
||||
{298AE119-6625-4604-BDE5-0765DC34C856} = {B62728C8-1267-4043-B46F-5537BBAEC692}
|
||||
{C457CBCD-3A8D-4402-9A2B-693A0390D3F9} = {298AE119-6625-4604-BDE5-0765DC34C856}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {46465737-C938-44FC-BE1A-4CE139EBB5E0}
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
<MicrosoftDiagnosticsRuntimeVersion>1.1.46104</MicrosoftDiagnosticsRuntimeVersion>
|
||||
<MicrosoftDiaSymReaderNativePackageVersion>1.7.0</MicrosoftDiaSymReaderNativePackageVersion>
|
||||
<MicrosoftDiagnosticsTracingTraceEventVersion>2.0.44</MicrosoftDiagnosticsTracingTraceEventVersion>
|
||||
<SystemCommandLineExperimentalVersion>0.2.0-alpha.19254.1</SystemCommandLineExperimentalVersion>
|
||||
<SystemCommandLineRenderingVersion>0.2.0-alpha.19254.1</SystemCommandLineRenderingVersion>
|
||||
<SystemCommandLineExperimentalVersion>0.3.0-alpha.19602.1</SystemCommandLineExperimentalVersion>
|
||||
<SystemCommandLineRenderingVersion>0.3.0-alpha.19602.1</SystemCommandLineRenderingVersion>
|
||||
<SystemMemoryVersion>4.5.3</SystemMemoryVersion>
|
||||
<XUnitVersion>2.4.1</XUnitVersion>
|
||||
<XUnitAbstractionsVersion>2.0.3</XUnitAbstractionsVersion>
|
||||
|
|
|
@ -118,32 +118,32 @@ namespace Microsoft.Diagnostics.Repl
|
|||
{
|
||||
command = new Command(commandAttribute.Name, commandAttribute.Help);
|
||||
var properties = new List<(PropertyInfo, Option)>();
|
||||
PropertyInfo argument = null;
|
||||
var arguments = new List<(PropertyInfo, Argument)>();
|
||||
|
||||
foreach (PropertyInfo property in type.GetProperties().Where(p => p.CanWrite))
|
||||
{
|
||||
var argumentAttribute = (ArgumentAttribute)property.GetCustomAttributes(typeof(ArgumentAttribute), inherit: false).SingleOrDefault();
|
||||
if (argumentAttribute != null)
|
||||
{
|
||||
if (argument != null) {
|
||||
throw new ArgumentException($"More than one ArgumentAttribute in command class: {type.Name}");
|
||||
}
|
||||
IArgumentArity arity = property.PropertyType.IsArray ? ArgumentArity.ZeroOrMore : ArgumentArity.ZeroOrOne;
|
||||
|
||||
command.Argument = new Argument {
|
||||
var argument = new Argument {
|
||||
Name = argumentAttribute.Name ?? property.Name.ToLowerInvariant(),
|
||||
Description = argumentAttribute.Help,
|
||||
ArgumentType = property.PropertyType,
|
||||
Arity = arity
|
||||
};
|
||||
argument = property;
|
||||
command.AddArgument(argument);
|
||||
arguments.Add((property, argument));
|
||||
}
|
||||
else
|
||||
{
|
||||
var optionAttribute = (OptionAttribute)property.GetCustomAttributes(typeof(OptionAttribute), inherit: false).SingleOrDefault();
|
||||
if (optionAttribute != null)
|
||||
{
|
||||
var option = new Option(optionAttribute.Name ?? BuildAlias(property.Name), optionAttribute.Help, new Argument { ArgumentType = property.PropertyType });
|
||||
var option = new Option(optionAttribute.Name ?? BuildAlias(property.Name), optionAttribute.Help) {
|
||||
Argument = new Argument { ArgumentType = property.PropertyType }
|
||||
};
|
||||
command.AddOption(option);
|
||||
properties.Add((property, option));
|
||||
|
||||
|
@ -160,7 +160,7 @@ namespace Microsoft.Diagnostics.Repl
|
|||
}
|
||||
}
|
||||
|
||||
var handler = new Handler(this, commandAttribute.AliasExpansion, argument, properties, type);
|
||||
var handler = new Handler(this, commandAttribute.AliasExpansion, arguments, properties, type);
|
||||
_commandHandlers.Add(command.Name, handler);
|
||||
command.Handler = handler;
|
||||
|
||||
|
@ -201,18 +201,18 @@ namespace Microsoft.Diagnostics.Repl
|
|||
{
|
||||
private readonly CommandProcessor _commandProcessor;
|
||||
private readonly string _aliasExpansion;
|
||||
private readonly PropertyInfo _argument;
|
||||
private readonly IEnumerable<(PropertyInfo Property, Argument Argument)> _arguments;
|
||||
private readonly IEnumerable<(PropertyInfo Property, Option Option)> _properties;
|
||||
|
||||
private readonly ConstructorInfo _constructor;
|
||||
private readonly MethodInfo _methodInfo;
|
||||
private readonly MethodInfo _methodInfoHelp;
|
||||
|
||||
public Handler(CommandProcessor commandProcessor, string aliasExpansion, PropertyInfo argument, IEnumerable<(PropertyInfo, Option)> properties, Type type)
|
||||
public Handler(CommandProcessor commandProcessor, string aliasExpansion, IEnumerable<(PropertyInfo, Argument)> arguments, IEnumerable<(PropertyInfo, Option)> properties, Type type)
|
||||
{
|
||||
_commandProcessor = commandProcessor;
|
||||
_aliasExpansion = aliasExpansion;
|
||||
_argument = argument;
|
||||
_arguments = arguments;
|
||||
_properties = properties;
|
||||
|
||||
_constructor = type.GetConstructors().SingleOrDefault((info) => info.GetParameters().Length == 0) ??
|
||||
|
@ -303,19 +303,19 @@ namespace Microsoft.Diagnostics.Repl
|
|||
property.Property.SetValue(instance, value);
|
||||
}
|
||||
|
||||
if (context != null && _argument != null)
|
||||
if (context != null)
|
||||
{
|
||||
object value = null;
|
||||
ArgumentResult result = context.ParseResult.CommandResult.ArgumentResult;
|
||||
switch (result)
|
||||
IEnumerable<ArgumentResult> argumentResults = context.ParseResult.CommandResult.Children.OfType<ArgumentResult>();
|
||||
|
||||
foreach ((PropertyInfo Property, Argument Argument) argument in _arguments)
|
||||
{
|
||||
case SuccessfulArgumentResult successful:
|
||||
value = successful.Value;
|
||||
break;
|
||||
case FailedArgumentResult failed:
|
||||
throw new InvalidOperationException(failed.ErrorMessage);
|
||||
ArgumentResult argumentResult = argumentResults.Where((result) => result.Argument == argument.Argument).SingleOrDefault();
|
||||
if (argumentResult != null)
|
||||
{
|
||||
object value = argumentResult.GetValueOrDefault();
|
||||
argument.Property.SetValue(instance, value);
|
||||
}
|
||||
}
|
||||
_argument.SetValue(instance, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// 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.CommandLine;
|
||||
using System.CommandLine.Invocation;
|
||||
|
||||
namespace Microsoft.Tools.Common
|
||||
{
|
||||
public static class CommandExtenions
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows the command handler to be included in the collection initializer.
|
||||
/// </summary>
|
||||
public static void Add(this Command command, ICommandHandler handler)
|
||||
{
|
||||
command.Handler = handler;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +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.Runtime.Serialization;
|
||||
|
||||
namespace Microsoft.Internal.Utilities
|
||||
{
|
||||
public class CommandLineException : Exception
|
||||
{
|
||||
public CommandLineException()
|
||||
{
|
||||
}
|
||||
|
||||
public CommandLineException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public CommandLineException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected CommandLineException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,18 +2,24 @@
|
|||
// 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.NETCore.Client;
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.Diagnostics;
|
||||
using System.CommandLine.Invocation;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Microsoft.Diagnostics.NETCore.Client;
|
||||
using Process = System.Diagnostics.Process;
|
||||
|
||||
namespace Microsoft.Internal.Common.Commands
|
||||
{
|
||||
public class ProcessStatusCommandHandler
|
||||
{
|
||||
public static Command ProcessStatusCommand(string description) =>
|
||||
new Command(name: "ps", description)
|
||||
{
|
||||
Handler = CommandHandler.Create<IConsole>(PrintProcessStatus)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Print the current list of available .NET core processes for diagnosis and their statuses
|
||||
/// </summary>
|
||||
|
|
|
@ -1,45 +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;
|
||||
using System.Threading.Tasks;
|
||||
using McMaster.Extensions.CommandLineUtils;
|
||||
|
||||
namespace Microsoft.Internal.Utilities
|
||||
{
|
||||
public static class ConsoleCancellationExtensions
|
||||
{
|
||||
public static CancellationToken GetCtrlCToken(this IConsole console)
|
||||
{
|
||||
var cts = new CancellationTokenSource();
|
||||
console.CancelKeyPress += (sender, args) =>
|
||||
{
|
||||
if (cts.IsCancellationRequested)
|
||||
{
|
||||
// Terminate forcibly, the user pressed Ctrl-C a second time
|
||||
args.Cancel = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't terminate, just trip the token
|
||||
args.Cancel = true;
|
||||
cts.Cancel();
|
||||
}
|
||||
};
|
||||
return cts.Token;
|
||||
}
|
||||
|
||||
public static Task WaitForCtrlCAsync(this IConsole console)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
console.CancelKeyPress += (sender, args) =>
|
||||
{
|
||||
// Don't terminate, just trip the task
|
||||
args.Cancel = true;
|
||||
tcs.TrySetResult(null);
|
||||
};
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +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.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Internal.Utilities
|
||||
{
|
||||
internal static class DebugUtil
|
||||
{
|
||||
[Conditional("DEBUG")]
|
||||
public static void WaitForDebuggerIfRequested(ref string[] args)
|
||||
{
|
||||
if (args.Any(a => a == "--debug"))
|
||||
{
|
||||
args = args.Where(a => a != "--debug").ToArray();
|
||||
Console.WriteLine($"Ready for debugger to attach. Process ID: {Process.GetCurrentProcess().Id}.");
|
||||
Console.WriteLine("Press ENTER to continue.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,11 @@
|
|||
// 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.NETCore.Client;
|
||||
using Microsoft.Internal.Common.Commands;
|
||||
using Microsoft.Tools.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.Binding;
|
||||
using System.CommandLine.Builder;
|
||||
|
@ -10,9 +14,6 @@ using System.CommandLine.Invocation;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Diagnostics.NETCore.Client;
|
||||
using Microsoft.Internal.Common.Commands;
|
||||
|
||||
namespace Microsoft.Diagnostics.Tools.Counters
|
||||
{
|
||||
|
@ -24,67 +25,72 @@ namespace Microsoft.Diagnostics.Tools.Counters
|
|||
|
||||
private static Command MonitorCommand() =>
|
||||
new Command(
|
||||
"monitor",
|
||||
"Start monitoring a .NET application",
|
||||
new Option[] { ProcessIdOption(), RefreshIntervalOption() },
|
||||
argument: CounterList(),
|
||||
handler: CommandHandler.Create<CancellationToken, List<string>, IConsole, int, int>(new CounterMonitor().Monitor));
|
||||
name: "monitor",
|
||||
description: "Start monitoring a .NET application")
|
||||
{
|
||||
// Handler
|
||||
CommandHandler.Create<CancellationToken, List<string>, IConsole, int, int>(new CounterMonitor().Monitor),
|
||||
// Arguments and Options
|
||||
CounterList(), ProcessIdOption(), RefreshIntervalOption()
|
||||
};
|
||||
|
||||
private static Command CollectCommand() =>
|
||||
new Command(
|
||||
"collect",
|
||||
"Monitor counters in a .NET application and export the result into a file",
|
||||
new Option[] { ProcessIdOption(), RefreshIntervalOption(), ExportFormatOption(), ExportFileNameOption() },
|
||||
argument: CounterList(),
|
||||
handler: HandlerDescriptor.FromDelegate((ExportDelegate)new CounterMonitor().Collect).GetCommandHandler());
|
||||
name: "collect",
|
||||
description: "Monitor counters in a .NET application and export the result into a file")
|
||||
{
|
||||
// Handler
|
||||
HandlerDescriptor.FromDelegate((ExportDelegate)new CounterMonitor().Collect).GetCommandHandler(),
|
||||
// Arguments and Options
|
||||
CounterList(), ProcessIdOption(), RefreshIntervalOption(), ExportFormatOption(), ExportFileNameOption()
|
||||
};
|
||||
|
||||
private static Option ProcessIdOption() =>
|
||||
new Option(
|
||||
new[] { "-p", "--process-id" },
|
||||
"The ID of the process that will be monitored.",
|
||||
new Argument<int> { Name = "pid" });
|
||||
aliases: new[] { "-p", "--process-id" },
|
||||
description: "The process id that will be monitored.")
|
||||
{
|
||||
Argument = new Argument<int>(name: "pid")
|
||||
};
|
||||
|
||||
private static Option RefreshIntervalOption() =>
|
||||
new Option(
|
||||
new[] { "--refresh-interval" },
|
||||
"The number of seconds to delay between updating the displayed counters.",
|
||||
new Argument<int>(defaultValue: 1) { Name = "refresh-interval" });
|
||||
alias: "--refresh-interval",
|
||||
description: "The number of seconds to delay between updating the displayed counters.")
|
||||
{
|
||||
Argument = new Argument<int>(name: "refresh-interval", defaultValue: 1)
|
||||
};
|
||||
|
||||
private static Option ExportFormatOption() =>
|
||||
private static Option ExportFormatOption() =>
|
||||
new Option(
|
||||
new[] { "--format" },
|
||||
"The format of exported counter data.",
|
||||
new Argument<CountersExportFormat>(defaultValue: CountersExportFormat.csv) { Name = "format" });
|
||||
alias: "--format",
|
||||
description: "The format of exported counter data.")
|
||||
{
|
||||
Argument = new Argument<CountersExportFormat>(name: "format", defaultValue: CountersExportFormat.csv)
|
||||
};
|
||||
|
||||
private static Option ExportFileNameOption() =>
|
||||
private static Option ExportFileNameOption() =>
|
||||
new Option(
|
||||
new[] { "-o", "--output" },
|
||||
"The output file name.",
|
||||
new Argument<string>(defaultValue: "counter") { Name = "output" });
|
||||
aliases: new[] { "-o", "--output" },
|
||||
description: "The output file name.")
|
||||
{
|
||||
Argument = new Argument<string>(name: "output", defaultValue: "counter")
|
||||
};
|
||||
|
||||
private static Argument CounterList() =>
|
||||
new Argument<List<string>> {
|
||||
Name = "counter_list",
|
||||
Description = @"A space separated list of counters. Counters can be specified provider_name[:counter_name].
|
||||
If the provider_name is used without a qualifying counter_name then all counters will be shown. To discover
|
||||
provider and counter names, use the list command.
|
||||
.",
|
||||
new Argument<List<string>>(name: "counter_list", defaultValue: new List<string>())
|
||||
{
|
||||
Description = @"A space separated list of counters. Counters can be specified provider_name[:counter_name]. If the provider_name is used without a qualifying counter_name then all counters will be shown. To discover provider and counter names, use the list command.",
|
||||
Arity = ArgumentArity.ZeroOrMore
|
||||
};
|
||||
|
||||
private static Command ListCommand() =>
|
||||
new Command(
|
||||
"list",
|
||||
"Display a list of counter names and descriptions, grouped by provider.",
|
||||
new Option[] { },
|
||||
handler: CommandHandler.Create<IConsole>(List));
|
||||
|
||||
private static Command ProcessStatusCommand() =>
|
||||
new Command(
|
||||
"ps",
|
||||
"Display a list of dotnet processes that can be monitored.",
|
||||
new Option[] { },
|
||||
handler: CommandHandler.Create<IConsole>(ProcessStatusCommandHandler.PrintProcessStatus));
|
||||
name: "list",
|
||||
description: "Display a list of counter names and descriptions, grouped by provider.")
|
||||
{
|
||||
Handler = CommandHandler.Create<IConsole>(List)
|
||||
};
|
||||
|
||||
public static int List(IConsole console)
|
||||
{
|
||||
|
@ -111,7 +117,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
|
|||
.AddCommand(MonitorCommand())
|
||||
.AddCommand(CollectCommand())
|
||||
.AddCommand(ListCommand())
|
||||
.AddCommand(ProcessStatusCommand())
|
||||
.AddCommand(ProcessStatusCommandHandler.ProcessStatusCommand("Lists the dotnet processes that can be monitored"))
|
||||
.UseDefaults()
|
||||
.Build();
|
||||
return parser.InvokeAsync(args);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)..\dotnet-trace\Extensions.cs" Link="Extensions.cs" />
|
||||
<Compile Include="..\Common\CommandExtensions.cs" Link="CommandExtensions.cs" />
|
||||
<Compile Include="..\Common\Commands\ProcessStatus.cs" Link="ProcessStatus.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -76,7 +76,8 @@ namespace Microsoft.Diagnostics.Tools.Dump
|
|||
// Run the commands from the dotnet-dump command line
|
||||
if (command != null)
|
||||
{
|
||||
foreach (string cmd in command) {
|
||||
foreach (string cmd in command)
|
||||
{
|
||||
await _commandProcessor.Parse(cmd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
|
|||
{
|
||||
try {
|
||||
string arguments = null;
|
||||
if (Arguments.Length > 0) {
|
||||
if (Arguments != null && Arguments.Length > 0) {
|
||||
arguments = string.Concat(Arguments.Select((arg) => arg + " "));
|
||||
}
|
||||
SOSHost.ExecuteCommand(AliasExpansion, arguments);
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
// 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.NETCore.Client;
|
||||
using Microsoft.Internal.Common.Commands;
|
||||
using Microsoft.Tools.Common;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.Builder;
|
||||
using System.CommandLine.Invocation;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Diagnostics.NETCore.Client;
|
||||
using Microsoft.Internal.Common.Commands;
|
||||
|
||||
namespace Microsoft.Diagnostics.Tools.Dump
|
||||
{
|
||||
|
@ -19,7 +20,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
|
|||
var parser = new CommandLineBuilder()
|
||||
.AddCommand(CollectCommand())
|
||||
.AddCommand(AnalyzeCommand())
|
||||
.AddCommand(ProcessStatusCommand())
|
||||
.AddCommand(ProcessStatusCommandHandler.ProcessStatusCommand("Lists the dotnet processes that dumps can be collected"))
|
||||
.UseDefaults()
|
||||
.Build();
|
||||
|
||||
|
@ -27,67 +28,74 @@ namespace Microsoft.Diagnostics.Tools.Dump
|
|||
}
|
||||
|
||||
private static Command CollectCommand() =>
|
||||
new Command(
|
||||
"collect",
|
||||
"Capture dumps from a process",
|
||||
new Option[] { ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), TypeOption() },
|
||||
handler: CommandHandler.Create<IConsole, int, string, bool, Dumper.DumpTypeOption>(new Dumper().Collect));
|
||||
new Command( name: "collect", description: "Capture dumps from a process")
|
||||
{
|
||||
// Handler
|
||||
CommandHandler.Create<IConsole, int, string, bool, Dumper.DumpTypeOption>(new Dumper().Collect),
|
||||
// Options
|
||||
ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), TypeOption()
|
||||
};
|
||||
|
||||
private static Option ProcessIdOption() =>
|
||||
new Option(
|
||||
new[] { "-p", "--process-id" },
|
||||
"The process to collect a memory dump from.",
|
||||
new Argument<int> { Name = "pid" });
|
||||
aliases: new[] { "-p", "--process-id" },
|
||||
description: "The process id to collect a memory dump.")
|
||||
{
|
||||
Argument = new Argument<int>(name: "pid")
|
||||
};
|
||||
|
||||
private static Option OutputOption() =>
|
||||
new Option(
|
||||
new[] { "-o", "--output" },
|
||||
@"The path where collected dumps should be written. Defaults to '.\dump_YYYYMMDD_HHMMSS.dmp' on Windows and
|
||||
'./core_YYYYMMDD_HHMMSS' on Linux where YYYYMMDD is Year/Month/Day and HHMMSS is Hour/Minute/Second. Otherwise, it is the full
|
||||
path and file name of the dump.",
|
||||
new Argument<string>() { Name = "output_dump_path" });
|
||||
new Option(
|
||||
aliases: new[] { "-o", "--output" },
|
||||
description: @"The path where collected dumps should be written. Defaults to '.\dump_YYYYMMDD_HHMMSS.dmp' on Windows and './core_YYYYMMDD_HHMMSS'
|
||||
on Linux where YYYYMMDD is Year/Month/Day and HHMMSS is Hour/Minute/Second. Otherwise, it is the full path and file name of the dump.")
|
||||
{
|
||||
Argument = new Argument<string>(name: "output_dump_path")
|
||||
};
|
||||
|
||||
private static Option DiagnosticLoggingOption() =>
|
||||
new Option(
|
||||
new[] { "--diag" },
|
||||
"Enable dump collection diagnostic logging.",
|
||||
new Argument<bool> { Name = "diag" });
|
||||
alias: "--diag",
|
||||
description: "Enable dump collection diagnostic logging.")
|
||||
{
|
||||
Argument = new Argument<bool>(name: "diag")
|
||||
};
|
||||
|
||||
private static Option TypeOption() =>
|
||||
new Option(
|
||||
"--type",
|
||||
@"The dump type determines the kinds of information that are collected from the process. There are two types:
|
||||
|
||||
heap - A large and relatively comprehensive dump containing module lists, thread lists, all stacks,
|
||||
exception information, handle information, and all memory except for mapped images.
|
||||
mini - A small dump containing module lists, thread lists, exception information and all stacks.
|
||||
|
||||
If not specified 'heap' is the default.",
|
||||
new Argument<Dumper.DumpTypeOption>(Dumper.DumpTypeOption.Heap) { Name = "dump_type" });
|
||||
alias: "--type",
|
||||
description: @"The dump type determines the kinds of information that are collected from the process. There are two types: heap - A large and
|
||||
relatively comprehensive dump containing module lists, thread lists, all stacks, exception information, handle information, and all memory except for mapped
|
||||
images. mini - A small dump containing module lists, thread lists, exception information and all stacks. If not specified 'heap' is the default.")
|
||||
{
|
||||
Argument = new Argument<Dumper.DumpTypeOption>(name: "dump_type", defaultValue: Dumper.DumpTypeOption.Heap)
|
||||
};
|
||||
|
||||
private static Command AnalyzeCommand() =>
|
||||
new Command(
|
||||
"analyze",
|
||||
"Starts an interactive shell with debugging commands to explore a dump",
|
||||
new Option[] { RunCommand() }, argument: DumpPath(),
|
||||
handler: CommandHandler.Create<FileInfo, string[]>(new Analyzer().Analyze));
|
||||
name: "analyze",
|
||||
description: "Starts an interactive shell with debugging commands to explore a dump")
|
||||
{
|
||||
// Handler
|
||||
CommandHandler.Create<FileInfo, string[]>(new Analyzer().Analyze),
|
||||
// Arguments and Options
|
||||
DumpPath(),
|
||||
RunCommand()
|
||||
};
|
||||
|
||||
private static Argument DumpPath() =>
|
||||
new Argument<FileInfo> {
|
||||
Name = "dump_path",
|
||||
Description = "Name of the dump file to analyze." }.ExistingOnly();
|
||||
new Argument<FileInfo>(
|
||||
name: "dump_path")
|
||||
{
|
||||
Description = "Name of the dump file to analyze."
|
||||
}.ExistingOnly();
|
||||
|
||||
private static Option RunCommand() =>
|
||||
new Option(
|
||||
new[] { "-c", "--command" },
|
||||
"Run the command on start.",
|
||||
new Argument<string[]>() { Name = "command", Arity = ArgumentArity.ZeroOrMore });
|
||||
|
||||
private static Command ProcessStatusCommand() =>
|
||||
new Command(
|
||||
"ps",
|
||||
"Display a list of dotnet processes to create dump from",
|
||||
new Option[] { },
|
||||
handler: CommandHandler.Create<IConsole>(ProcessStatusCommandHandler.PrintProcessStatus));
|
||||
aliases: new[] { "-c", "--command" },
|
||||
description: "Run the command on start.")
|
||||
{
|
||||
Argument = new Argument<string[]>(name: "command", defaultValue: new string[0]) { Arity = ArgumentArity.ZeroOrMore }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Common\CommandExtensions.cs" Link="CommandExtensions.cs" />
|
||||
<Compile Include="..\Common\Commands\ProcessStatus.cs" Link="ProcessStatus.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -2,14 +2,11 @@
|
|||
// 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.Tools.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.Binding;
|
||||
using System.CommandLine.Rendering;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -100,42 +97,45 @@ namespace Microsoft.Diagnostics.Tools.GCDump
|
|||
public static Command CollectCommand() =>
|
||||
new Command(
|
||||
name: "collect",
|
||||
description: "Collects a diagnostic trace from a currently running process",
|
||||
symbols: new Option[] {
|
||||
ProcessIdOption(),
|
||||
OutputPathOption(),
|
||||
VerboseOption(),
|
||||
TimeoutOption()
|
||||
},
|
||||
handler: HandlerDescriptor.FromDelegate((CollectDelegate)Collect).GetCommandHandler());
|
||||
description: "Collects a diagnostic trace from a currently running process")
|
||||
{
|
||||
// Handler
|
||||
HandlerDescriptor.FromDelegate((CollectDelegate)Collect).GetCommandHandler(),
|
||||
// Options
|
||||
ProcessIdOption(), OutputPathOption(), VerboseOption(), TimeoutOption()
|
||||
};
|
||||
|
||||
public static Option ProcessIdOption() =>
|
||||
new Option(
|
||||
aliases: new[] { "-p", "--process-id" },
|
||||
description: "The process to collect the trace from",
|
||||
argument: new Argument<int>(defaultValue: 0) { Name = "pid" },
|
||||
isHidden: false);
|
||||
description: "The process id to collect the trace.")
|
||||
{
|
||||
Argument = new Argument<int>(name: "pid", defaultValue: 0),
|
||||
};
|
||||
|
||||
private static Option OutputPathOption() =>
|
||||
new Option(
|
||||
aliases: new[] { "-o", "--output" },
|
||||
description: $@"The path where collected gcdumps should be written. Defaults to '.\YYYYMMDD_HHMMSS_<pid>.gcdump' where YYYYMMDD is Year/Month/Day and HHMMSS is Hour/Minute/Second. Otherwise, it is the full path and file name of the dump.",
|
||||
argument: new Argument<string>(defaultValue: "") { Name = "gcdump-file-path" },
|
||||
isHidden: false);
|
||||
description: $@"The path where collected gcdumps should be written. Defaults to '.\YYYYMMDD_HHMMSS_<pid>.gcdump' where YYYYMMDD is Year/Month/Day and HHMMSS is Hour/Minute/Second. Otherwise, it is the full path and file name of the dump.")
|
||||
{
|
||||
Argument = new Argument<string>(name: "gcdump-file-path", defaultValue: "")
|
||||
};
|
||||
|
||||
private static Option VerboseOption() =>
|
||||
new Option(
|
||||
aliases: new[] { "-v", "--verbose" },
|
||||
description: $"Output the log while collecting the gcdump",
|
||||
argument: new Argument<bool>(defaultValue: false) { Name = "verbose" },
|
||||
isHidden: false);
|
||||
description: $"Output the log while collecting the gcdump.")
|
||||
{
|
||||
Argument = new Argument<bool>(name: "verbose", defaultValue: false)
|
||||
};
|
||||
|
||||
private static int DefaultTimeout = 30;
|
||||
private static Option TimeoutOption() =>
|
||||
new Option(
|
||||
aliases: new[] { "-t", "--timeout" },
|
||||
description: $"Give up on collecting the gcdump if it takes longer than this many seconds. The default value is {DefaultTimeout}s",
|
||||
argument: new Argument<int>(defaultValue: DefaultTimeout) { Name = "timeout" },
|
||||
isHidden: false);
|
||||
description: $"Give up on collecting the gcdump if it takes longer than this many seconds. The default value is {DefaultTimeout}s.")
|
||||
{
|
||||
Argument = new Argument<int>(name: "timeout", defaultValue: DefaultTimeout)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +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.Internal.Common.Commands;
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Diagnostics.Tools.GCDump
|
||||
{
|
||||
internal static class ListProcessesCommandHandler
|
||||
{
|
||||
public static async Task<int> GetActivePorts(IConsole console)
|
||||
{
|
||||
ProcessStatusCommandHandler.PrintProcessStatus(console);
|
||||
await Task.FromResult(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static Command ProcessStatusCommand() =>
|
||||
new Command(
|
||||
name: "ps",
|
||||
description: "Lists dotnet processes that can be attached to.",
|
||||
handler: System.CommandLine.Invocation.CommandHandler.Create<IConsole>(GetActivePorts),
|
||||
isHidden: false);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
// 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.Internal.Common.Commands;
|
||||
using System.CommandLine.Builder;
|
||||
using System.CommandLine.Invocation;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -14,7 +15,7 @@ namespace Microsoft.Diagnostics.Tools.GCDump
|
|||
{
|
||||
var parser = new CommandLineBuilder()
|
||||
.AddCommand(CollectCommandHandler.CollectCommand())
|
||||
.AddCommand(ListProcessesCommandHandler.ProcessStatusCommand())
|
||||
.AddCommand(ProcessStatusCommandHandler.ProcessStatusCommand("Lists the dotnet processes that gcdumps can be collected"))
|
||||
.UseDefaults()
|
||||
.Build();
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Common\CommandExtensions.cs" Link="CommandExtensions.cs" />
|
||||
<Compile Include="..\Common\Commands\ProcessStatus.cs" Link="ProcessStatus.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
// 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.Tools.Common;
|
||||
using SOS;
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.Builder;
|
||||
using System.CommandLine.Invocation;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -28,22 +27,30 @@ namespace Microsoft.Diagnostics.Tools.SOS
|
|||
|
||||
private static Command InstallCommand() =>
|
||||
new Command(
|
||||
"install",
|
||||
"Installs SOS and configures LLDB to load it on startup.",
|
||||
new Option[] { ArchitectureOption() },
|
||||
handler: CommandHandler.Create<IConsole, Architecture?>((console, architecture) => InvokeAsync(console, architecture, install: true)));
|
||||
name: "install",
|
||||
description: "Installs SOS and configures LLDB to load it on startup.")
|
||||
{
|
||||
// Handler
|
||||
CommandHandler.Create<IConsole, Architecture?>((console, architecture) => InvokeAsync(console, architecture, install: true)),
|
||||
// Options
|
||||
ArchitectureOption()
|
||||
};
|
||||
|
||||
private static Option ArchitectureOption() =>
|
||||
new Option(
|
||||
new[] { "--architecture" },
|
||||
"The process to collect a memory dump from.",
|
||||
new Argument<Architecture>() { Name = "architecture" });
|
||||
alias: "--architecture",
|
||||
description: "The processor architecture to install.")
|
||||
{
|
||||
Argument = new Argument<Architecture>(name: "architecture")
|
||||
};
|
||||
|
||||
private static Command UninstallCommand() =>
|
||||
new Command(
|
||||
"uninstall",
|
||||
"Uninstalls SOS and reverts any configuration changes to LLDB.",
|
||||
handler: CommandHandler.Create<IConsole>((console) => InvokeAsync(console, architecture: null, install: false)));
|
||||
name: "uninstall",
|
||||
description: "Uninstalls SOS and reverts any configuration changes to LLDB.")
|
||||
{
|
||||
Handler = CommandHandler.Create<IConsole>((console) => InvokeAsync(console, architecture: null, install: false))
|
||||
};
|
||||
|
||||
private static Task<int> InvokeAsync(IConsole console, Architecture? architecture, bool install)
|
||||
{
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
<PackageReleaseNotes>$(Description)</PackageReleaseNotes>
|
||||
<SOSPackagePathPrefix>tools/$(TargetFramework)/any</SOSPackagePathPrefix>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Common\CommandExtensions.cs" Link="CommandExtensions.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\SOS\SOS.InstallHelper\SOS.InstallHelper.csproj" />
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Diagnostics.NETCore.Client;
|
||||
using Microsoft.Tools.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
|
@ -261,55 +262,63 @@ namespace Microsoft.Diagnostics.Tools.Trace
|
|||
public static Command CollectCommand() =>
|
||||
new Command(
|
||||
name: "collect",
|
||||
description: "Collects a diagnostic trace from a currently running process",
|
||||
symbols: new Option[] {
|
||||
CommonOptions.ProcessIdOption(),
|
||||
CircularBufferOption(),
|
||||
OutputPathOption(),
|
||||
ProvidersOption(),
|
||||
ProfileOption(),
|
||||
CommonOptions.FormatOption(),
|
||||
DurationOption()
|
||||
},
|
||||
handler: HandlerDescriptor.FromDelegate((CollectDelegate)Collect).GetCommandHandler());
|
||||
description: "Collects a diagnostic trace from a currently running process")
|
||||
{
|
||||
// Handler
|
||||
HandlerDescriptor.FromDelegate((CollectDelegate)Collect).GetCommandHandler(),
|
||||
// Options
|
||||
CommonOptions.ProcessIdOption(),
|
||||
CircularBufferOption(),
|
||||
OutputPathOption(),
|
||||
ProvidersOption(),
|
||||
ProfileOption(),
|
||||
CommonOptions.FormatOption(),
|
||||
DurationOption()
|
||||
};
|
||||
|
||||
private static uint DefaultCircularBufferSizeInMB => 256;
|
||||
|
||||
private static Option CircularBufferOption() =>
|
||||
new Option(
|
||||
alias: "--buffersize",
|
||||
description: $"Sets the size of the in-memory circular buffer in megabytes. Default {DefaultCircularBufferSizeInMB} MB.",
|
||||
argument: new Argument<uint>(defaultValue: DefaultCircularBufferSizeInMB) { Name = "size" },
|
||||
isHidden: false);
|
||||
description: $"Sets the size of the in-memory circular buffer in megabytes. Default {DefaultCircularBufferSizeInMB} MB.")
|
||||
{
|
||||
Argument = new Argument<uint>(name: "size", defaultValue: DefaultCircularBufferSizeInMB)
|
||||
};
|
||||
|
||||
public static string DefaultTraceName => "trace.nettrace";
|
||||
|
||||
private static Option OutputPathOption() =>
|
||||
new Option(
|
||||
aliases: new[] { "-o", "--output" },
|
||||
description: $"The output path for the collected trace data. If not specified it defaults to '{DefaultTraceName}'",
|
||||
argument: new Argument<FileInfo>(defaultValue: new FileInfo(DefaultTraceName)) { Name = "trace-file-path" },
|
||||
isHidden: false);
|
||||
description: $"The output path for the collected trace data. If not specified it defaults to '{DefaultTraceName}'.")
|
||||
{
|
||||
Argument = new Argument<FileInfo>(name: "trace-file-path", defaultValue: new FileInfo(DefaultTraceName))
|
||||
};
|
||||
|
||||
private static Option ProvidersOption() =>
|
||||
new Option(
|
||||
alias: "--providers",
|
||||
description: @"A list of EventPipe providers to be enabled. This is in the form 'Provider[,Provider]', where Provider is in the form: 'KnownProviderName[:Flags[:Level][:KeyValueArgs]]', and KeyValueArgs is in the form: '[key1=value1][;key2=value2]'. These providers are in addition to any providers implied by the --profile argument. If there is any discrepancy for a particular provider, the configuration here takes precedence over the implicit configuration from the profile.",
|
||||
argument: new Argument<string>(defaultValue: "") { Name = "list-of-comma-separated-providers" }, // TODO: Can we specify an actual type?
|
||||
isHidden: false);
|
||||
description: @"A list of EventPipe providers to be enabled. This is in the form 'Provider[,Provider]', where Provider is in the form: 'KnownProviderName[:Flags[:Level][:KeyValueArgs]]', and KeyValueArgs is in the form: '[key1=value1][;key2=value2]'. These providers are in addition to any providers implied by the --profile argument. If there is any discrepancy for a particular provider, the configuration here takes precedence over the implicit configuration from the profile.")
|
||||
{
|
||||
Argument = new Argument<string>(name: "list-of-comma-separated-providers", defaultValue: "") // TODO: Can we specify an actual type?
|
||||
};
|
||||
|
||||
private static Option ProfileOption() =>
|
||||
new Option(
|
||||
alias: "--profile",
|
||||
description: @"A named pre-defined set of provider configurations that allows common tracing scenarios to be specified succinctly.",
|
||||
argument: new Argument<string>(defaultValue: "") { Name = "profile-name" },
|
||||
isHidden: false);
|
||||
description: @"A named pre-defined set of provider configurations that allows common tracing scenarios to be specified succinctly.")
|
||||
{
|
||||
Argument = new Argument<string>(name: "profile-name", defaultValue: "")
|
||||
};
|
||||
|
||||
private static Option DurationOption() =>
|
||||
new Option(
|
||||
alias: "--duration",
|
||||
description: @"When specified, will trace for the given timespan and then automatically stop the trace. Provided in the form of dd:hh:mm:ss.",
|
||||
argument: new Argument<TimeSpan>(defaultValue: default(TimeSpan)) { Name = "duration-timespan" },
|
||||
isHidden: true);
|
||||
description: @"When specified, will trace for the given timespan and then automatically stop the trace. Provided in the form of dd:hh:mm:ss.")
|
||||
{
|
||||
Argument = new Argument<TimeSpan>(name: "duration-timespan", defaultValue: default),
|
||||
IsHidden = true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,14 +2,11 @@
|
|||
// 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.NETCore.Client;
|
||||
using Microsoft.Tools.Common;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.Builder;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Diagnostics.Tools.Trace
|
||||
{
|
||||
|
@ -45,25 +42,28 @@ namespace Microsoft.Diagnostics.Tools.Trace
|
|||
public static Command ConvertCommand() =>
|
||||
new Command(
|
||||
name: "convert",
|
||||
description: "Converts traces to alternate formats for use with alternate trace analysis tools. Can only convert from the nettrace format.",
|
||||
argument: (new Argument<FileInfo>(defaultValue: new FileInfo(CollectCommandHandler.DefaultTraceName)) {
|
||||
Name = "input-filename",
|
||||
Description = $"Input trace file to be converted. Defaults to '{CollectCommandHandler.DefaultTraceName}'."
|
||||
}).ExistingOnly(),
|
||||
symbols: new Option[] {
|
||||
CommonOptions.ConvertFormatOption(),
|
||||
OutputOption()
|
||||
},
|
||||
handler: System.CommandLine.Invocation.CommandHandler.Create<IConsole, FileInfo, TraceFileFormat, FileInfo>(ConvertFile),
|
||||
isHidden: false
|
||||
);
|
||||
description: "Converts traces to alternate formats for use with alternate trace analysis tools. Can only convert from the nettrace format")
|
||||
{
|
||||
// Handler
|
||||
System.CommandLine.Invocation.CommandHandler.Create<IConsole, FileInfo, TraceFileFormat, FileInfo>(ConvertFile),
|
||||
// Arguments and Options
|
||||
InputFileArgument(),
|
||||
CommonOptions.ConvertFormatOption(),
|
||||
OutputOption(),
|
||||
};
|
||||
|
||||
public static Option OutputOption() =>
|
||||
private static Argument InputFileArgument() =>
|
||||
new Argument<FileInfo>(name: "input-filename", defaultValue: new FileInfo(CollectCommandHandler.DefaultTraceName))
|
||||
{
|
||||
Description = $"Input trace file to be converted. Defaults to '{CollectCommandHandler.DefaultTraceName}'."
|
||||
}.ExistingOnly();
|
||||
|
||||
private static Option OutputOption() =>
|
||||
new Option(
|
||||
aliases: new [] { "-o", "--output" },
|
||||
description: "Output filename. Extension of target format will be added.",
|
||||
argument: new Argument<FileInfo>() { Name = "output-filename" },
|
||||
isHidden: false
|
||||
);
|
||||
aliases: new[] { "-o", "--output" },
|
||||
description: "Output filename. Extension of target format will be added.")
|
||||
{
|
||||
Argument = new Argument<FileInfo>(name: "output-filename")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +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.Internal.Common.Commands;
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Diagnostics.Tools.Trace
|
||||
{
|
||||
internal static class ListProcessesCommandHandler
|
||||
{
|
||||
public static async Task<int> GetActivePorts(IConsole console)
|
||||
{
|
||||
ProcessStatusCommandHandler.PrintProcessStatus(console);
|
||||
await Task.FromResult(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static Command ListProcessesCommand() =>
|
||||
new Command(
|
||||
name: "ps",
|
||||
description: "Lists dotnet processes that can be attached to.",
|
||||
handler: System.CommandLine.Invocation.CommandHandler.Create<IConsole>(GetActivePorts),
|
||||
isHidden: false);
|
||||
}
|
||||
}
|
|
@ -35,9 +35,10 @@ namespace Microsoft.Diagnostics.Tools.Trace
|
|||
public static Command ListProfilesCommand() =>
|
||||
new Command(
|
||||
name: "list-profiles",
|
||||
description: "Lists pre-built tracing profiles with a description of what providers and filters are in each profile.",
|
||||
handler: CommandHandler.Create<IConsole>(GetProfiles),
|
||||
isHidden: false);
|
||||
description: "Lists pre-built tracing profiles with a description of what providers and filters are in each profile")
|
||||
{
|
||||
Handler = CommandHandler.Create<IConsole>(GetProfiles),
|
||||
};
|
||||
|
||||
internal static IEnumerable<Profile> DotNETRuntimeProfiles { get; } = new[] {
|
||||
new Profile(
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.CommandLine;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Diagnostics.Tools.Trace
|
||||
{
|
||||
|
@ -13,24 +11,27 @@ namespace Microsoft.Diagnostics.Tools.Trace
|
|||
public static Option ProcessIdOption() =>
|
||||
new Option(
|
||||
aliases: new[] { "-p", "--process-id" },
|
||||
description: "The process to collect the trace from",
|
||||
argument: new Argument<int> { Name = "pid" },
|
||||
isHidden: false);
|
||||
description: "The process id to collect the trace.")
|
||||
{
|
||||
Argument = new Argument<int>(name: "pid")
|
||||
};
|
||||
|
||||
public static TraceFileFormat DefaultTraceFileFormat => TraceFileFormat.NetTrace;
|
||||
|
||||
public static Option FormatOption() =>
|
||||
new Option(
|
||||
aliases: new[] { "--format" },
|
||||
description: $"Sets the output format for the trace file. Default is {DefaultTraceFileFormat}",
|
||||
argument: new Argument<TraceFileFormat>(defaultValue: DefaultTraceFileFormat) { Name = "trace-file-format" },
|
||||
isHidden: false);
|
||||
alias: "--format",
|
||||
description: $"Sets the output format for the trace file. Default is {DefaultTraceFileFormat}.")
|
||||
{
|
||||
Argument = new Argument<TraceFileFormat>(name: "trace-file-format", defaultValue: DefaultTraceFileFormat)
|
||||
};
|
||||
|
||||
public static Option ConvertFormatOption() =>
|
||||
new Option(
|
||||
aliases: new[] { "--format" },
|
||||
description: $"Sets the output format for the trace file conversion.",
|
||||
argument: new Argument<TraceFileFormat> { Name = "trace-file-format" },
|
||||
isHidden: false);
|
||||
alias: "--format",
|
||||
description: $"Sets the output format for the trace file conversion.")
|
||||
{
|
||||
Argument = new Argument<TraceFileFormat>(name: "trace-file-format")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// 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.Internal.Common.Commands;
|
||||
using System.CommandLine.Builder;
|
||||
using System.CommandLine.Invocation;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -14,7 +15,7 @@ namespace Microsoft.Diagnostics.Tools.Trace
|
|||
{
|
||||
var parser = new CommandLineBuilder()
|
||||
.AddCommand(CollectCommandHandler.CollectCommand())
|
||||
.AddCommand(ListProcessesCommandHandler.ListProcessesCommand())
|
||||
.AddCommand(ProcessStatusCommandHandler.ProcessStatusCommand("Lists the dotnet processes that traces can be collected"))
|
||||
.AddCommand(ListProfilesCommandHandler.ListProfilesCommand())
|
||||
.AddCommand(ConvertCommandHandler.ConvertCommand())
|
||||
.UseDefaults()
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Common\CommandExtensions.cs" Link="CommandExtensions.cs" />
|
||||
<Compile Include="..\Common\Commands\ProcessStatus.cs" Link="ProcessStatus.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче