[-o|--output <trace-file-path>]
[--profile <profile_name>]
[--providers <list-of-comma-separated-providers>]
- [-f|--format <trace-file-format>]
+ [--format <trace-file-format>]
Collects a diagnostic trace from a currently running process
--buffersize <Size>
Sets the size of the in-memory circular buffer in megabytes. Default 256 MB.
- -f, --format
- The format of the output trace file. This defaults to "netperf" on Windows and "speedscope" on other OSes.
+ --format
+ The format of the output trace file. The default value is netperf.
Examples:
dotnet-trace convert [-h|--help]
[-o|--output <output_file_path>]
- [--to-speedscope]
+ --format <format>
<trace_file_path>
Converts traces to alternate formats for use with alternate trace analysis tools
The path where the converted file is written. If unspecified the file is written in the current directory
using the same base filename as the input file and the extension appropriate for the new format.
- --to-speedscope
- Indicates that the output file format should be speedscope JSON format used by https://www.speedscope.app/
- Currently this is the only supported format, but other options may be available in the future.
+ --format
+ Specifies the format to convert the netperf file to. Currently, the only valid input is 'speedscope'.
trace_file_path
- The path to the trace file that should be converted. The trace file can be in either a netperf or netperf.zip file.
+ The path to the trace file that should be converted. The trace file can be a netperf file. Defaults to 'trace.netperf'.
Examples:
- > dotnet-trace convert trace.netperf --to-speedscope
+ > dotnet-trace convert trace.netperf -f speedscope
Writing: ./trace.speedscope.json
Conversion complete
Console.Out.WriteLine();
Console.Out.WriteLine("Trace completed.");
- TraceFileFormatConverter.ConvertToFormat(format, output.FullName);
+ if (format != TraceFileFormat.Netperf)
+ TraceFileFormatConverter.ConvertToFormat(format, output.FullName);
await Task.FromResult(0);
return sessionId != 0 ? 0 : 1;
argument: new Argument<uint>(defaultValue: DefaultCircularBufferSizeInMB) { Name = "size" },
isHidden: false);
- private static string DefaultTraceName => "trace.netperf";
+ public static string DefaultTraceName => "trace.netperf";
private static Option OutputPathOption() =>
new Option(
--- /dev/null
+// 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.Tools.RuntimeClient;
+using System;
+using System.IO;
+using System.CommandLine;
+using System.CommandLine.Builder;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Microsoft.Diagnostics.Tools.Trace
+{
+ internal static class ConvertCommandHandler
+ {
+ public static int ConvertFile(IConsole console, FileInfo inputFilename, TraceFileFormat format, FileInfo output)
+ {
+ if (format == TraceFileFormat.Netperf)
+ throw new ArgumentException("Cannot convert to netperf format.");
+
+ if (!inputFilename.Exists)
+ throw new FileNotFoundException($"File '{inputFilename}' does not exist.");
+
+ if (output == null)
+ output = inputFilename;
+
+ TraceFileFormatConverter.ConvertToFormat(format, inputFilename.FullName, output.FullName);
+
+ return 0;
+ }
+
+ 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 netperf 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.FormatOption(),
+ OutputOption()
+ },
+ handler: System.CommandLine.Invocation.CommandHandler.Create<IConsole, FileInfo, TraceFileFormat, FileInfo>(ConvertFile),
+ isHidden: false
+ );
+
+ public 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
+ );
+ }
+}
argument: new Argument<int> { Name = "pid" },
isHidden: false);
- public static TraceFileFormat DefaultTraceFileFormat =>
- RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? TraceFileFormat.netperf : TraceFileFormat.speedscope;
+ public static TraceFileFormat DefaultTraceFileFormat => TraceFileFormat.Netperf;
public static Option FormatOption() =>
new Option(
- aliases: new[] { "-f", "--format" },
+ 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);
.AddCommand(CollectCommandHandler.CollectCommand())
.AddCommand(ListProcessesCommandHandler.ListProcessesCommand())
.AddCommand(ListProfilesCommandHandler.ListProfilesCommand())
+ .AddCommand(ConvertCommandHandler.ConvertCommand())
.UseDefaults()
.Build();
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections.Generic;
using System.IO;
using Microsoft.Diagnostics.Symbols;
using Microsoft.Diagnostics.Tracing;
namespace Microsoft.Diagnostics.Tools.Trace
{
- internal enum TraceFileFormat { netperf, speedscope };
+ internal enum TraceFileFormat { Netperf, Speedscope };
internal static class TraceFileFormatConverter
{
- public static void ConvertToFormat(TraceFileFormat format, string fileToConvert)
+ private static Dictionary<TraceFileFormat, string> TraceFileFormatExtensions = new Dictionary<TraceFileFormat, string>() {
+ { TraceFileFormat.Netperf, "netperf" },
+ { TraceFileFormat.Speedscope, "speedscope.json" }
+ };
+
+ public static void ConvertToFormat(TraceFileFormat format, string fileToConvert, string outputFilename = "")
{
+ if (string.IsNullOrWhiteSpace(outputFilename))
+ outputFilename = fileToConvert;
+
+ outputFilename = Path.ChangeExtension(outputFilename, TraceFileFormatExtensions[format]);
+ Console.Out.WriteLine($"Writing:\t{outputFilename}");
+
switch (format)
{
- case TraceFileFormat.netperf:
+ case TraceFileFormat.Netperf:
break;
- case TraceFileFormat.speedscope:
- Console.Out.WriteLine($"Converting to {format}...");
- ConvertToSpeedscope(fileToConvert);
+ case TraceFileFormat.Speedscope:
+ ConvertToSpeedscope(fileToConvert, outputFilename);
break;
default:
// Validation happened way before this, so we shoud never reach this...
- throw new Exception($"Invalid TraceFileFormat \"{format}\"");
+ throw new ArgumentException($"Invalid TraceFileFormat \"{format}\"");
}
+ Console.Out.WriteLine("Conversion complete");
}
- private static void ConvertToSpeedscope(string fileToConvert)
+ private static void ConvertToSpeedscope(string fileToConvert, string outputFilename)
{
- var symbolReader = new SymbolReader(System.IO.TextWriter.Null) { SymbolPath = SymbolPath.MicrosoftSymbolServerPath };
var etlxFilePath = TraceLog.CreateFromEventPipeDataFile(fileToConvert);
-
- var eventLog = new TraceLog(etlxFilePath);
-
- try
+ using (var symbolReader = new SymbolReader(System.IO.TextWriter.Null) { SymbolPath = SymbolPath.MicrosoftSymbolServerPath })
+ using (var eventLog = new TraceLog(etlxFilePath))
{
var stackSource = new MutableTraceEventStackSource(eventLog)
{
};
var computer = new SampleProfilerThreadTimeComputer(eventLog, symbolReader);
- computer.GenerateThreadTimeStacks(stackSource);
+ computer.GenerateThreadTimeStacks(stackSource);
- var speedScopeFilePath = Path.ChangeExtension(fileToConvert, "speedscope.json");
-
- SpeedScopeStackSourceWriter.WriteStackViewAsJson(stackSource, speedScopeFilePath);
+ SpeedScopeStackSourceWriter.WriteStackViewAsJson(stackSource, outputFilename);
}
- finally
- {
- eventLog.Dispose();
- if (File.Exists(etlxFilePath))
- {
- File.Delete(etlxFilePath);
- }
+ if (File.Exists(etlxFilePath))
+ {
+ File.Delete(etlxFilePath);
}
+
}
}
}