-
Notifications
You must be signed in to change notification settings - Fork 394
Expand file tree
/
Copy pathReportCommand.cs
More file actions
146 lines (128 loc) · 5.27 KB
/
ReportCommand.cs
File metadata and controls
146 lines (128 loc) · 5.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// 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.Collections.Generic;
using System.CommandLine;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Diagnostics.Tracing.StackSources;
using Microsoft.Diagnostics.Symbols;
using Microsoft.Diagnostics.Tools.Trace.CommandLine;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Etlx;
using Microsoft.Diagnostics.Tracing.Stacks;
using Microsoft.Internal.Common;
namespace Microsoft.Diagnostics.Tools.Trace
{
internal static class ReportCommandHandler
{
private static List<string> unwantedMethodNames = new() { "ROOT", "Process" };
//Create an extension function to help
public static List<CallTreeNodeBase> ByIDSortedInclusiveMetric(this CallTree callTree)
{
List<CallTreeNodeBase> ret = new(callTree.ByID);
ret.Sort((x, y) => Math.Abs(y.InclusiveMetric).CompareTo(Math.Abs(x.InclusiveMetric)));
return ret;
}
private static Task<int> Report()
{
Console.Error.WriteLine("Error: subcommand was not provided. Available subcommands:");
Console.Error.WriteLine(" topN: Finds the top N methods on the callstack the longest.");
return Task.FromResult(-1);
}
private static int TopNReport(string traceFile, int number, bool inclusive, bool verbose)
{
try
{
int count = 0;
int index = 0;
List<CallTreeNodeBase> nodesToReport = new();
MutableTraceEventStackSource stackSource = ThreadTimeStackSourceHelper.GenerateStackSourceFromTrace(traceFile);
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<CallTreeNodeBase> callTreeNodes = null;
if (!inclusive)
{
callTreeNodes = callTree.ByIDSortedExclusiveMetric();
}
else
{
callTreeNodes = callTree.ByIDSortedInclusiveMetric();
}
int totalElements = callTreeNodes.Count;
while (count < number && index < totalElements)
{
CallTreeNodeBase node = callTreeNodes[index];
index++;
if (!unwantedMethodNames.Any(node.Name.Contains))
{
nodesToReport.Add(node);
count++;
}
}
PrintReportHelper.TopNWriteToStdOut(nodesToReport, inclusive, verbose);
return 0;
}
catch (Exception ex)
{
Console.Error.WriteLine($"[ERROR] {ex}");
return 1;
}
}
public static Command ReportCommand()
{
Command topNCommand = new(
name: "topN",
description: "Finds the top N methods that have been on the callstack the longest.")
{
TopNOption,
InclusiveOption,
VerboseOption,
};
topNCommand.SetAction((parseResult, ct) => Task.FromResult(TopNReport(
traceFile: parseResult.GetValue(FileNameArgument),
number: parseResult.GetValue(TopNOption),
inclusive: parseResult.GetValue(InclusiveOption),
verbose: parseResult.GetValue(VerboseOption)
)));
Command reportCommand = new(
name: "report",
description: "Generates a report into stdout from a previously generated trace.")
{
FileNameArgument,
topNCommand
};
reportCommand.SetAction((parseResult, ct) => Report());
return reportCommand;
}
private static readonly Argument<string> FileNameArgument =
new("trace_filename")
{
Description = "The file path for the trace being analyzed.",
Arity = new ArgumentArity(1, 1)
};
private static readonly Option<int> TopNOption =
new("--number", "-n")
{
Description = "Gives the top N methods on the callstack.",
DefaultValueFactory = _ => 5
};
private static readonly Option<bool> InclusiveOption =
new("--inclusive")
{
Description = "Output the top N methods based on inclusive time. If not specified, exclusive time is used by default."
};
private static readonly Option<bool> VerboseOption =
new("--verbose", "-v")
{
Description = "Output the parameters of each method in full. If not specified, parameters will be truncated."
};
}
}