Skip to content

Commit

Permalink
Fix CPU share calculation (#5324)
Browse files Browse the repository at this point in the history
  • Loading branch information
evgenyfedorov2 authored Aug 4, 2024
2 parents 601ec1e + 85ab682 commit ff546f3
Show file tree
Hide file tree
Showing 89 changed files with 892 additions and 77 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ bld/
*.VisualState.xml
TestResult.xml

# VERIFY
*.received.*

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
Expand Down
5 changes: 3 additions & 2 deletions eng/packages/TestOnly.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
<PackageVersion Include="autofixture" Version="4.17.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.13.5" />
<PackageVersion Include="FluentAssertions" Version="6.11.0" />
<PackageVersion Include="Grpc.AspNetCore" Version="2.57.0" />
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.3" />
<PackageVersion Include="Moq.AutoMock" Version="3.1.0" />
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="Polly.Testing" Version="8.4.1" />
<PackageVersion Include="StrongNamer" Version="0.2.5" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="$(SystemConfigurationConfigurationManagerVersion)" />
<PackageVersion Include="Xunit.Combinatorial" Version="1.5.25" />
<PackageVersion Include="Verify.Xunit" Version="20.4.0" />
<PackageVersion Include="Xunit.Combinatorial" Version="1.6.24" />
<PackageVersion Include="xunit.extensibility.execution" Version="2.4.2" />
<PackageVersion Include="Grpc.AspNetCore" Version="2.57.0" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ public long GetMemoryUsageInBytesFromSlices(string pattern)
{
memoryUsageInBytesTotal = 0;
Throw.InvalidOperationException(
$"We tried to read '{memoryUsageInBytesFile}', and we expected to get a positive number but instead it was: '{containerMemoryUsage}'.");
$"We tried to read '{memoryUsageInBytesFile}', and we expected to get a positive number but instead it was: '{memoryUsageFile}'.");
}

memoryUsageInBytesTotal += containerMemoryUsage;
Expand Down Expand Up @@ -533,6 +533,9 @@ private static bool TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, out float

private static bool TryGetCgroupRequestCpu(IFileSystem fileSystem, out float cpuUnits)
{
const long CpuPodWeightPossibleMax = 10_000;
const long CpuPodWeightPossibleMin = 1;

if (!fileSystem.Exists(_cpuPodWeight))
{
cpuUnits = 0;
Expand All @@ -545,26 +548,33 @@ private static bool TryGetCgroupRequestCpu(IFileSystem fileSystem, out float cpu

if (cpuPodWeightBuffer.IsEmpty || (cpuPodWeightBuffer.Length == 2 && cpuPodWeightBuffer[0] == '-' && cpuPodWeightBuffer[1] == '1'))
{
Throw.InvalidOperationException($"Could not parse '{_cpuPodWeight}' content. Expected to find CPU weight but got '{new string(cpuPodWeightBuffer)}' instead.");
Throw.InvalidOperationException(
$"Could not parse '{_cpuPodWeight}' content. Expected to find CPU weight but got '{new string(cpuPodWeightBuffer)}' instead.");
}

_ = GetNextNumber(cpuPodWeightBuffer, out long cpuPodWeight);

if (cpuPodWeight == -1)
{
Throw.InvalidOperationException($"Could not parse '{_cpuPodWeight}'. Expected to get an integer but got: '{cpuPodWeight}'.");
Throw.InvalidOperationException(
$"Could not parse '{_cpuPodWeight}' content. Expected to get an integer but got: '{cpuPodWeightBuffer}'.");
}

// Calculate CPU pod request in millicores based on the weight, using the formula:
// y = (1 + ((x - 2) * 9999) / 262142), where y is the CPU weight and x is the CPU share (cgroup v1)
// https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2254-cgroup-v2#phase-1-convert-from-cgroups-v1-settings-to-v2
long cpuPodShare = ((cpuPodWeight * 262142) + 19997) / 9999;
if (cpuPodShare == -1)
if (cpuPodWeight < CpuPodWeightPossibleMin || cpuPodWeight > CpuPodWeightPossibleMax)
{
Throw.InvalidOperationException($"Could not calculate CPU share from CPU weight '{cpuPodShare}'");
Throw.ArgumentOutOfRangeException("CPU weight",
$"Expected to find CPU weight in range [{CpuPodWeightPossibleMin}-{CpuPodWeightPossibleMax}] in '{_cpuPodWeight}', but got '{cpuPodWeight}' instead.");
}

cpuUnits = cpuPodShare;
// The formula to calculate CPU pod weight (measured in millicores) from CPU share:
// y = (1 + ((x - 2) * 9999) / 262142),
// where y is the CPU pod weight (e.g. cpuPodWeight) and x is the CPU share of cgroup v1 (e.g. cpuUnits).
// https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2254-cgroup-v2#phase-1-convert-from-cgroups-v1-settings-to-v2
// We invert the formula to calculate CPU share from CPU pod weight:
#pragma warning disable S109 // Magic numbers should not be used - using the formula, forgive.
cpuUnits = ((cpuPodWeight - 1) * 262142 / 9999) + 2;
#pragma warning restore S109 // Magic numbers should not be used

return true;
}

Expand All @@ -580,7 +590,7 @@ private long GetMemoryUsageInBytesPod()
if (memoryUsage == -1)
{
Throw.InvalidOperationException(
$"We tried to read '{_memoryUsageInBytes}', and we expected to get a positive number but instead it was: '{memoryUsage}'.");
$"We tried to read '{_memoryUsageInBytes}', and we expected to get a positive number but instead it was: '{memoryUsageFile}'.");
}

return memoryUsage;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Microsoft.Extensions.Diagnostics.ResourceMonitoring

Measures and reports processor and memory usage. This library utilizes control groups (cgroups) including cgroups v2 in Linux to monitor system resources.
Measures and reports processor and memory usage. This library utilizes control groups (cgroups) in Linux to monitor system resources. Both cgroups v1 and v2 are supported.

## Install the package

Expand Down
1 change: 1 addition & 0 deletions test/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<PackageReference Include="Moq.AutoMock" />
<PackageReference Include="Moq" />
<PackageReference Include="StrongNamer" Condition="'$(SignArtifacts)' == 'true' " />
<PackageReference Include="Verify.Xunit" />
<PackageReference Include="Xunit.Combinatorial" />

<Content Include="$(MSBuildThisFileDirectory)\..\eng\xunit.runner.json" CopyToOutputDirectory="PreserveNewest" Visible="false" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpuset.cpus.effective'. Expected comma-separated list of integers, with dashes ("-") based ranges ("0", "2-6,12") but got '@'.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.<GetHostCpuCount>g__ThrowException|23_0(ReadOnlySpan`1 content)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetHostCpuCount()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass15_0.<Fallsback_To_Cpuset_When_Quota_And_Period_Are_Minus_One_>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/memory.max' content. Expected to find available memory in bytes but got 'Suspicious12312312' instead.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetAvailableMemoryInBytes()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass6_0.<Throws_When_AvailableMemoryInBytes_Doesnt_Contain_Just_A_Number>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/memory.max' content. Expected to find available memory in bytes but got 'string12312' instead.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetAvailableMemoryInBytes()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass6_0.<Throws_When_AvailableMemoryInBytes_Doesnt_Contain_Just_A_Number>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/memory.max' content. Expected to find available memory in bytes but got 'string@' instead.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetAvailableMemoryInBytes()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass6_0.<Throws_When_AvailableMemoryInBytes_Doesnt_Contain_Just_A_Number>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.max'. Expected to get an integer but got: ' eeeee 12'.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.max'. Expected to get an integer but got: ''.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.max'. Expected an integer but got: '-18 18'.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.max'. Expected an integer but got: '- d''.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.max'. Expected an integer but got: '- d/:'.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.max'. Expected to get an integer but got: ' '.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
Type: InvalidOperationException,
Message:
Could not parse '/sys/fs/cgroup/cpu.max'. Expected to get an integer but got: '




'.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.max'. Expected to get an integer but got: ' d/:'.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.max'. Expected to get an integer but got: 'd2d2d e3'.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.max'. Expected to get an integer but got: 'd d3'.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.max'. Expected an integer but got: 'dd1d 18'.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupLimitedCpus()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass16_0.<Throws_When_Cgroup_Cpu_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
Type: InvalidOperationException,
Message: Could not parse '/sys/fs/cgroup/cpu.weight' content. Expected to find CPU weight but got '-1' instead.,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.InvalidOperationException(String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCgroupRequestCpu(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupRequestCpu()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass22_0.<Throws_When_Cgroup_Cpu_Weight_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
Type: ArgumentOutOfRangeException,
Message: Expected to find CPU weight in range [1-10000] in '/sys/fs/cgroup/cpu.weight', but got '0' instead. (Parameter 'CPU weight'),
ParamName: CPU weight,
StackTrace:
at Microsoft.Shared.Diagnostics.Throw.ArgumentOutOfRangeException(String paramName, String message)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.TryGetCgroupRequestCpu(IFileSystem fileSystem, Single& cpuUnits)
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.LinuxUtilizationParserCgroupV2.GetCgroupRequestCpu()
at Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test.LinuxUtilizationParserCgroupV2Tests.<>c__DisplayClass22_0.<Throws_When_Cgroup_Cpu_Weight_Files_Contain_Invalid_Data>b__0()
at Xunit.Record.Exception(Func`1 testCode)
}
Loading

0 comments on commit ff546f3

Please sign in to comment.