diff --git a/eng/Versions.props b/eng/Versions.props
index 82fe464071..f5f5c89b2a 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -29,7 +29,7 @@
9.0.8
17.10.0-beta1.24272.1
- 3.1.23
+ 3.1.28
11.0.0-beta.25528.108
8.0.1
8.0.3
@@ -46,8 +46,8 @@
4.5.5
4.3.0
4.5.4
- 8.0.0
- 8.0.5
+ 9.0.8
+ 9.0.8
2.0.3
1.2.0-beta.556
10.0.26100.1
diff --git a/src/Tools/dotnet-trace/CommandLine/Commands/ReportCommand.cs b/src/Tools/dotnet-trace/CommandLine/Commands/ReportCommand.cs
index 7330cc1604..989778f17d 100644
--- a/src/Tools/dotnet-trace/CommandLine/Commands/ReportCommand.cs
+++ b/src/Tools/dotnet-trace/CommandLine/Commands/ReportCommand.cs
@@ -41,55 +41,43 @@ private static int TopNReport(string traceFile, int number, bool inclusive, bool
{
try
{
- string tempEtlxFilename = TraceLog.CreateFromEventPipeDataFile(traceFile);
int count = 0;
int index = 0;
List nodesToReport = new();
- using (SymbolReader symbolReader = new(System.IO.TextWriter.Null) { SymbolPath = SymbolPath.MicrosoftSymbolServerPath })
- using (TraceLog eventLog = new(tempEtlxFilename))
- {
- MutableTraceEventStackSource stackSource = new(eventLog)
- {
- OnlyManagedCodeStacks = true
- };
-
- SampleProfilerThreadTimeComputer computer = new(eventLog, symbolReader);
+ MutableTraceEventStackSource stackSource = ThreadTimeStackSourceHelper.GenerateStackSourceFromTrace(traceFile);
- computer.GenerateThreadTimeStacks(stackSource);
-
- FilterParams filterParams = new()
- {
- FoldRegExs = "CPU_TIME;UNMANAGED_CODE_TIME;{Thread (}",
- };
- FilterStackSource filterStack = new(filterParams, stackSource, ScalingPolicyKind.ScaleToData);
- CallTree callTree = new(ScalingPolicyKind.ScaleToData);
- callTree.StackSource = filterStack;
+ FilterParams filterParams = new()
+ {
+ FoldRegExs = "CPU_TIME;UNMANAGED_CODE_TIME;{Thread (}",
+ };
+ FilterStackSource filterStack = new(filterParams, stackSource, ScalingPolicyKind.ScaleToData);
+ CallTree callTree = new(ScalingPolicyKind.ScaleToData);
+ callTree.StackSource = filterStack;
- List callTreeNodes = null;
+ List callTreeNodes = null;
- if (!inclusive)
- {
- callTreeNodes = callTree.ByIDSortedExclusiveMetric();
- }
- else
- {
- callTreeNodes = callTree.ByIDSortedInclusiveMetric();
- }
+ if (!inclusive)
+ {
+ callTreeNodes = callTree.ByIDSortedExclusiveMetric();
+ }
+ else
+ {
+ callTreeNodes = callTree.ByIDSortedInclusiveMetric();
+ }
- int totalElements = callTreeNodes.Count;
- while (count < number && index < totalElements)
+ int totalElements = callTreeNodes.Count;
+ while (count < number && index < totalElements)
+ {
+ CallTreeNodeBase node = callTreeNodes[index];
+ index++;
+ if (!unwantedMethodNames.Any(node.Name.Contains))
{
- CallTreeNodeBase node = callTreeNodes[index];
- index++;
- if (!unwantedMethodNames.Any(node.Name.Contains))
- {
- nodesToReport.Add(node);
- count++;
- }
+ nodesToReport.Add(node);
+ count++;
}
-
- PrintReportHelper.TopNWriteToStdOut(nodesToReport, inclusive, verbose);
}
+
+ PrintReportHelper.TopNWriteToStdOut(nodesToReport, inclusive, verbose);
return 0;
}
catch (Exception ex)
diff --git a/src/Tools/dotnet-trace/ThreadTimeProviderType.cs b/src/Tools/dotnet-trace/ThreadTimeProviderType.cs
new file mode 100644
index 0000000000..b4ea524012
--- /dev/null
+++ b/src/Tools/dotnet-trace/ThreadTimeProviderType.cs
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using Microsoft.Diagnostics.Symbols;
+using Microsoft.Diagnostics.Tracing;
+using Microsoft.Diagnostics.Tracing.Etlx;
+using Microsoft.Diagnostics.Tracing.Stacks;
+
+namespace Microsoft.Diagnostics.Tools.Trace
+{
+ internal enum ThreadTimeProviderType
+ {
+ SampleProfiler,
+ UniversalEvents,
+ Unknown
+ }
+
+ internal static class ThreadTimeStackSourceHelper
+ {
+ public static MutableTraceEventStackSource GenerateStackSourceFromTrace(string traceFile, bool includeEventSourceEvents = false, bool continueOnError = false)
+ {
+ string etlxFilePath = TraceLog.CreateFromEventPipeDataFile(traceFile, null, new TraceLogOptions() { ContinueOnError = continueOnError });
+ using SymbolReader symbolReader = new(TextWriter.Null) { SymbolPath = SymbolPath.MicrosoftSymbolServerPath };
+ using TraceLog eventLog = new(etlxFilePath);
+ MutableTraceEventStackSource stackSource = new(eventLog);
+
+ ThreadTimeProviderType providerType = DetectProviderType(eventLog);
+ switch (providerType)
+ {
+ case ThreadTimeProviderType.SampleProfiler:
+ {
+ stackSource.OnlyManagedCodeStacks = true;
+ SampleProfilerThreadTimeComputer computer = new(eventLog, symbolReader)
+ {
+ IncludeEventSourceEvents = includeEventSourceEvents,
+ };
+ computer.GenerateThreadTimeStacks(stackSource);
+ break;
+ }
+ case ThreadTimeProviderType.UniversalEvents:
+ {
+ stackSource.OnlyManagedCodeStacks = false;
+#pragma warning disable 618
+ ThreadTimeStackComputer computer = new(eventLog, symbolReader)
+ {
+ IncludeEventSourceEvents = false,
+ };
+ computer.GenerateThreadTimeStacks(stackSource);
+#pragma warning restore 618
+ break;
+ }
+ case ThreadTimeProviderType.Unknown:
+ default:
+ throw new DiagnosticToolException("The trace does not contain SampleProfiler or Universal.Events data required for thread-time analysis.");
+ }
+
+ if (File.Exists(etlxFilePath))
+ {
+ File.Delete(etlxFilePath);
+ }
+
+ return stackSource;
+ }
+
+ private static ThreadTimeProviderType DetectProviderType(TraceLog eventLog)
+ {
+ foreach (TraceEvent evt in eventLog.Events)
+ {
+ if (string.Equals(evt.ProviderName, "Microsoft-DotNETCore-SampleProfiler", StringComparison.Ordinal))
+ {
+ return ThreadTimeProviderType.SampleProfiler;
+ }
+ if (string.Equals(evt.ProviderName, "Universal.Events", StringComparison.Ordinal))
+ {
+ return ThreadTimeProviderType.UniversalEvents;
+ }
+ }
+
+ return ThreadTimeProviderType.Unknown;
+ }
+ }
+}
diff --git a/src/Tools/dotnet-trace/TraceFileFormatConverter.cs b/src/Tools/dotnet-trace/TraceFileFormatConverter.cs
index a6e08ac74c..5b95145fa2 100644
--- a/src/Tools/dotnet-trace/TraceFileFormatConverter.cs
+++ b/src/Tools/dotnet-trace/TraceFileFormatConverter.cs
@@ -69,38 +69,20 @@ internal static void ConvertToFormat(TextWriter stdOut, TextWriter stdError, Tra
private static void Convert(TraceFileFormat format, string fileToConvert, string outputFilename, bool continueOnError = false)
{
- string etlxFilePath = TraceLog.CreateFromEventPipeDataFile(fileToConvert, null, new TraceLogOptions() { ContinueOnError = continueOnError });
- using (SymbolReader symbolReader = new(TextWriter.Null) { SymbolPath = SymbolPath.MicrosoftSymbolServerPath })
- using (TraceLog eventLog = new(etlxFilePath))
- {
- MutableTraceEventStackSource stackSource = new(eventLog)
- {
- OnlyManagedCodeStacks = true // EventPipe currently only has managed code stacks.
- };
-
- SampleProfilerThreadTimeComputer computer = new(eventLog, symbolReader)
- {
- IncludeEventSourceEvents = false // SpeedScope handles only CPU samples, events are not supported
- };
- computer.GenerateThreadTimeStacks(stackSource);
-
- switch (format)
- {
- case TraceFileFormat.Speedscope:
- SpeedScopeStackSourceWriter.WriteStackViewAsJson(stackSource, outputFilename);
- break;
- case TraceFileFormat.Chromium:
- ChromiumStackSourceWriter.WriteStackViewAsJson(stackSource, outputFilename, compress: false);
- break;
- default:
- // we should never get here
- throw new DiagnosticToolException($"Invalid TraceFileFormat \"{format}\"");
- }
- }
+ // Speedscope/Chromium outputs only understand CPU samples; exclude EventSource events.
+ MutableTraceEventStackSource stackSource = ThreadTimeStackSourceHelper.GenerateStackSourceFromTrace(fileToConvert, includeEventSourceEvents: false, continueOnError);
- if (File.Exists(etlxFilePath))
+ switch (format)
{
- File.Delete(etlxFilePath);
+ case TraceFileFormat.Speedscope:
+ SpeedScopeStackSourceWriter.WriteStackViewAsJson(stackSource, outputFilename);
+ break;
+ case TraceFileFormat.Chromium:
+ ChromiumStackSourceWriter.WriteStackViewAsJson(stackSource, outputFilename, compress: false);
+ break;
+ default:
+ // we should never get here
+ throw new DiagnosticToolException($"Invalid TraceFileFormat \"{format}\"");
}
}
}
diff --git a/src/Tools/dotnet-trace/dotnet-trace.csproj b/src/Tools/dotnet-trace/dotnet-trace.csproj
index 6b14eef616..9be52fb7f5 100644
--- a/src/Tools/dotnet-trace/dotnet-trace.csproj
+++ b/src/Tools/dotnet-trace/dotnet-trace.csproj
@@ -13,7 +13,7 @@
-
+