-
Notifications
You must be signed in to change notification settings - Fork 383
[dotnet-trace] Add collect-linux verb #5570
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
536cd50
49a875b
b4787fc
c921869
e1c15c7
b4112b5
e5f3975
677e54e
31186a8
44593bb
b190d73
9f1ef6d
c8e53ea
590a203
8e2453f
573d769
1b3b583
e6d9de9
676efa9
d90d1be
096f325
1f75125
55bc84a
4c1a361
208086f
40c5905
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
// 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.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using System.Linq; | ||
using Microsoft.Diagnostics.Tests.Common; | ||
using Microsoft.Diagnostics.Tools.Trace; | ||
using Xunit; | ||
|
||
namespace Microsoft.Diagnostics.Tools.Trace | ||
{ | ||
public class CollectLinuxCommandFunctionalTests | ||
{ | ||
private static CollectLinuxCommandHandler.CollectLinuxArgs TestArgs( | ||
CancellationToken ct = default, | ||
string[] providers = null, | ||
string clrEventLevel = "", | ||
string clrEvents = "", | ||
string[] perfEvents = null, | ||
string[] profiles = null, | ||
FileInfo output = null, | ||
TimeSpan duration = default, | ||
string name = "", | ||
int processId = -1) | ||
{ | ||
return new CollectLinuxCommandHandler.CollectLinuxArgs(ct, | ||
providers ?? Array.Empty<string>(), | ||
clrEventLevel, | ||
clrEvents, | ||
perfEvents ?? Array.Empty<string>(), | ||
profiles ?? Array.Empty<string>(), | ||
output ?? new FileInfo(CommonOptions.DefaultTraceName), | ||
duration, | ||
name, | ||
processId); | ||
} | ||
|
||
[Theory] | ||
[MemberData(nameof(BasicCases))] | ||
public void CollectLinuxCommandProviderConfigurationConsolidation(object testArgs, string[] expectedLines) | ||
{ | ||
MockConsole console = new(200, 30); | ||
RunAsync((CollectLinuxCommandHandler.CollectLinuxArgs)testArgs, console); | ||
console.AssertSanitizedLinesEqual(null, expectedLines); | ||
} | ||
|
||
private static string[] RunAsync(CollectLinuxCommandHandler.CollectLinuxArgs args, MockConsole console) | ||
{ | ||
var handler = new CollectLinuxCommandHandler(); | ||
handler.Console = console; | ||
handler.RecordTraceInvoker = (cmd, len, cb) => 0; | ||
int exit = handler.CollectLinux(args); | ||
if (exit != 0) | ||
{ | ||
throw new InvalidOperationException($"Collect exited with return code {exit}."); | ||
} | ||
return console.Lines; | ||
} | ||
|
||
public static IEnumerable<object[]> BasicCases() | ||
{ | ||
yield return new object[] { | ||
TestArgs(), | ||
new string[] { | ||
"No providers, profiles, ClrEvents, or PerfEvents were specified, defaulting to trace profiles 'dotnet-common' + 'cpu-sampling'.", | ||
"", | ||
ProviderHeader, | ||
FormatProvider("Microsoft-Windows-DotNETRuntime","000000100003801D","Informational",4,"--profile"), | ||
"", | ||
LinuxHeader, | ||
LinuxProfile("cpu-sampling"), | ||
"" | ||
} | ||
|
||
}; | ||
yield return new object[] { | ||
TestArgs(providers: new[]{"Foo:0x1:4"}), | ||
new string[] { | ||
"", ProviderHeader, | ||
FormatProvider("Foo","0000000000000001","Informational",4,"--providers"), | ||
"", | ||
LinuxHeader, | ||
"" | ||
} | ||
}; | ||
yield return new object[] { | ||
TestArgs(providers: new[]{"Foo:0x1:4","Bar:0x2:4"}), | ||
new string[] { | ||
"", ProviderHeader, | ||
FormatProvider("Foo","0000000000000001","Informational",4,"--providers"), | ||
FormatProvider("Bar","0000000000000002","Informational",4,"--providers"), | ||
"", | ||
LinuxHeader, | ||
"" | ||
} | ||
}; | ||
yield return new object[] { | ||
TestArgs(profiles: new[]{"cpu-sampling"}), | ||
new string[] { | ||
"No .NET providers were configured.", | ||
"", | ||
LinuxHeader, | ||
LinuxProfile("cpu-sampling"), | ||
"" | ||
} | ||
}; | ||
yield return new object[] { | ||
TestArgs(providers: new[]{"Foo:0x1:4"}, profiles: new[]{"cpu-sampling"}), | ||
new string[] { | ||
"", ProviderHeader, | ||
FormatProvider("Foo","0000000000000001","Informational",4,"--providers"), | ||
"", | ||
LinuxHeader, | ||
LinuxProfile("cpu-sampling"), | ||
"" | ||
} | ||
}; | ||
yield return new object[] { | ||
TestArgs(clrEvents: "gc", profiles: new[]{"cpu-sampling"}), | ||
new string[] { | ||
"", ProviderHeader, | ||
FormatProvider("Microsoft-Windows-DotNETRuntime","0000000000000001","Informational",4,"--clrevents"), | ||
"", | ||
LinuxHeader, | ||
LinuxProfile("cpu-sampling"), | ||
"" | ||
} | ||
}; | ||
yield return new object[] { | ||
TestArgs(providers: new[]{"Microsoft-Windows-DotNETRuntime:0x1:4"}, profiles: new[]{"cpu-sampling"}), | ||
new string[] { | ||
"", ProviderHeader, | ||
FormatProvider("Microsoft-Windows-DotNETRuntime","0000000000000001","Informational",4,"--providers"), | ||
"", | ||
LinuxHeader, | ||
LinuxProfile("cpu-sampling"), | ||
"" | ||
} | ||
}; | ||
yield return new object[] { | ||
TestArgs(providers: new[]{"Microsoft-Windows-DotNETRuntime:0x1:4"}, clrEvents: "gc"), | ||
new string[] { | ||
"Warning: The CLR provider was already specified through --providers or --profile. Ignoring --clrevents.", | ||
"", ProviderHeader, | ||
FormatProvider("Microsoft-Windows-DotNETRuntime","0000000000000001","Informational",4,"--providers"), | ||
"", | ||
LinuxHeader, | ||
"" | ||
} | ||
}; | ||
yield return new object[] { | ||
TestArgs(clrEvents: "gc+jit"), | ||
new string[] { | ||
"", ProviderHeader, | ||
FormatProvider("Microsoft-Windows-DotNETRuntime","0000000000000011","Informational",4,"--clrevents"), | ||
"", | ||
LinuxHeader, | ||
"" | ||
} | ||
}; | ||
yield return new object[] { | ||
TestArgs(clrEvents: "gc+jit", clrEventLevel: "5"), | ||
new string[] { | ||
"", ProviderHeader, | ||
FormatProvider("Microsoft-Windows-DotNETRuntime","0000000000000011","Verbose",5,"--clrevents"), | ||
"", | ||
LinuxHeader, | ||
"" | ||
} | ||
}; | ||
yield return new object[] { | ||
TestArgs(perfEvents: new[]{"sched:sched_switch"}), | ||
new string[] { | ||
"No .NET providers were configured.", | ||
"", | ||
LinuxHeader, | ||
LinuxPerfEvent("sched:sched_switch"), | ||
"" | ||
} | ||
}; | ||
mdh1418 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
private const string ProviderHeader = "Provider Name Keywords Level Enabled By"; | ||
private static string LinuxHeader => $"{"Linux Events",-80}Enabled By"; | ||
private static string LinuxProfile(string name) => $"{name,-80}--profile"; | ||
private static string LinuxPerfEvent(string spec) => $"{spec,-80}--perf-events"; | ||
private static string FormatProvider(string name, string keywordsHex, string levelName, int levelValue, string enabledBy) | ||
{ | ||
string display = string.Format("{0, -40}", name) + | ||
string.Format("0x{0, -18}", keywordsHex) + | ||
string.Format("{0, -8}", $"{levelName}({levelValue})"); | ||
return string.Format("{0, -80}", display) + enabledBy; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If testing caused multiple instances of CollectLinuxCommandHandler to run in parallel, would we want those instances to be sharing any of these static fields? I'm guessing we'd want all these fields to be instanced too.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to non-static. From some learning, I'm seeing that parallelization occurs at the test class level, so it doesn't seem like the theory members would run in parallel.