Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ namespace Microsoft.Extensions.Diagnostics.HealthChecks;
/// </summary>
internal sealed partial class ResourceUtilizationHealthCheck : IHealthCheck, IDisposable
{
#if !NETFRAMEWORK
private const double Hundred = 100.0;
#endif
private readonly double _multiplier;
private readonly MeterListener? _meterListener;
private readonly ResourceUtilizationHealthCheckOptions _options;
Expand Down Expand Up @@ -82,12 +85,14 @@ public static Task<HealthCheckResult> EvaluateHealthStatusAsync(double cpuUsedPe
}
#pragma warning restore EA0014 // The async method doesn't support cancellation

#if !NETFRAMEWORK
/// <summary>
/// Initializes a new instance of the <see cref="ResourceUtilizationHealthCheck"/> class.
/// </summary>
/// <param name="options">The options.</param>
/// <param name="dataTracker">The datatracker.</param>
public ResourceUtilizationHealthCheck(IOptions<ResourceUtilizationHealthCheckOptions> options, IResourceMonitor dataTracker)
/// <param name="rmOptions">The Resource Monitoring options.</param>
public ResourceUtilizationHealthCheck(IOptions<ResourceUtilizationHealthCheckOptions> options, IResourceMonitor dataTracker, IOptions<ResourceMonitoringOptions> rmOptions)
{
_options = Throw.IfMemberNull(options, options.Value);
if (!_options.UseObservableResourceMonitoringInstruments)
Expand All @@ -96,25 +101,44 @@ public ResourceUtilizationHealthCheck(IOptions<ResourceUtilizationHealthCheckOpt
return;
}

#if NETFRAMEWORK
_multiplier = 1;
#else
// Due to a bug on Windows https://github.com/dotnet/extensions/issues/5472,
// the CPU utilization comes in the range [0, 100].
if (OperatingSystem.IsWindows())
// On Windows there was a bug https://github.com/dotnet/extensions/issues/5472,
// so the CPU utilization might come in the range [0, 100], which means we don't need to multiply it by 100.
var rmOptionsValue = Throw.IfMemberNull(rmOptions, rmOptions.Value);
if (OperatingSystem.IsWindows() && !rmOptionsValue.UseZeroToOneRangeForMetrics)
{
_multiplier = 1;
}

// On Linux, the CPU utilization comes in the correct range [0, 1], which we will be converting to percentage.
// On Linux, the CPU utilization always comes in the correct range [0, 1], which we need to convert to percentage.
else
{
#pragma warning disable S109 // Magic numbers should not be used
_multiplier = 100;
#pragma warning restore S109 // Magic numbers should not be used
_multiplier = Hundred;
}

_meterListener = new()
{
InstrumentPublished = OnInstrumentPublished
};

_meterListener.SetMeasurementEventCallback<double>(OnMeasurementRecorded);
_meterListener.Start();
}
#else
/// <summary>
/// Initializes a new instance of the <see cref="ResourceUtilizationHealthCheck"/> class.
/// </summary>
/// <param name="options">The options.</param>
/// <param name="dataTracker">The datatracker.</param>
public ResourceUtilizationHealthCheck(IOptions<ResourceUtilizationHealthCheckOptions> options, IResourceMonitor dataTracker)
{
_options = Throw.IfMemberNull(options, options.Value);
if (!_options.UseObservableResourceMonitoringInstruments)
{
ObsoleteConstructor(dataTracker);
return;
}
#endif

_multiplier = 1;
_meterListener = new()
{
InstrumentPublished = OnInstrumentPublished
Expand All @@ -123,6 +147,7 @@ public ResourceUtilizationHealthCheck(IOptions<ResourceUtilizationHealthCheckOpt
_meterListener.SetMeasurementEventCallback<double>(OnMeasurementRecorded);
_meterListener.Start();
}
#endif

/// <summary>
/// Runs the health check.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,10 @@ public async Task TestCpuAndMemoryChecks_WithMetrics(
};

var options = Microsoft.Extensions.Options.Options.Create(checkOptions);
using var healthCheck = new ResourceUtilizationHealthCheck(options, dataTracker.Object);
using var healthCheck = new ResourceUtilizationHealthCheck(
options,
dataTracker.Object,
Microsoft.Extensions.Options.Options.Create(new ResourceMonitoringOptions()));

// Act
fakeClock.Advance(TimeSpan.FromMilliseconds(1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ public void AddResourceHealthCheck_RegistersInternalResourceMonitoring()

IResourceMonitor? resourceMonitor = serviceProvider.GetService<IResourceMonitor>();
Assert.NotNull(resourceMonitor);

// check Resource Monitoring Options:
var resourceMonitoringOptions = serviceProvider.GetRequiredService<IOptions<ResourceMonitoringOptions>>().Value;
Assert.NotNull(resourceMonitoringOptions);
}

[ConditionalFact]
Expand Down Expand Up @@ -522,7 +526,16 @@ public async Task TestCpuAndMemoryChecks_WithMetrics(
};

var options = Microsoft.Extensions.Options.Options.Create(checkOptions);
using var healthCheck = new ResourceUtilizationHealthCheck(options, dataTracker.Object);
#if !NETFRAMEWORK
using var healthCheck = new ResourceUtilizationHealthCheck(
options,
dataTracker.Object,
Microsoft.Extensions.Options.Options.Create(new ResourceMonitoringOptions()));
#else
using var healthCheck = new ResourceUtilizationHealthCheck(
options,
dataTracker.Object);
#endif

// Act
fakeClock.Advance(TimeSpan.FromMilliseconds(1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,16 @@ public async Task TestCpuAndMemoryChecks(HealthStatus expected, double utilizati
};

var options = Microsoft.Extensions.Options.Options.Create(checkOptions);
using var healthCheck = new ResourceUtilizationHealthCheck(options, dataTracker.Object);
#if !NETFRAMEWORK
using var healthCheck = new ResourceUtilizationHealthCheck(
options,
dataTracker.Object,
Microsoft.Extensions.Options.Options.Create(new ResourceMonitoringOptions()));
#else
using var healthCheck = new ResourceUtilizationHealthCheck(
options,
dataTracker.Object);
#endif
var healthCheckResult = await healthCheck.CheckHealthAsync(checkContext);
Assert.Equal(expected, healthCheckResult.Status);
Assert.NotEmpty(healthCheckResult.Data);
Expand All @@ -43,9 +52,22 @@ public async Task TestCpuAndMemoryChecks(HealthStatus expected, double utilizati
}
}

#if !NETFRAMEWORK
[Fact]
public void TestNullChecks()
{
Assert.Throws<ArgumentException>(() => new ResourceUtilizationHealthCheck(Mock.Of<IOptions<ResourceUtilizationHealthCheckOptions>>(), null!));
Assert.Throws<ArgumentException>(() => new ResourceUtilizationHealthCheck(
Mock.Of<IOptions<ResourceUtilizationHealthCheckOptions>>(),
null!,
Mock.Of<IOptions<ResourceMonitoringOptions>>()));
}
#else
[Fact]
public void TestNullChecks()
{
Assert.Throws<ArgumentException>(() => new ResourceUtilizationHealthCheck(
Mock.Of<IOptions<ResourceUtilizationHealthCheckOptions>>(),
null!));
}
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public void Throw_Null_When_Registration_Ingredients_Null()
}

[ConditionalFact]
public void AddResourceUtilization_AddsResourceMonitoringService_ToServicesCollection()
public void AddsResourceMonitoringService_ToServicesCollection()
{
using var provider = new ServiceCollection()
.AddLogging()
Expand All @@ -51,7 +51,7 @@ public void AddResourceUtilization_AddsResourceMonitoringService_ToServicesColle
}

[ConditionalFact]
public void AddResourceUtilization_AddsResourceMonitoringService_ToServicesCollection_NoArgs()
public void AddsResourceMonitoringService_ToServicesCollection_NoArgs()
{
using var provider = new ServiceCollection()
.AddLogging()
Expand All @@ -67,7 +67,7 @@ public void AddResourceUtilization_AddsResourceMonitoringService_ToServicesColle
}

[ConditionalFact]
public void AddResourceUtilization_AddsResourceMonitoringService_AsHostedService()
public void AddsResourceMonitoringService_AsHostedService()
{
using var provider = new ServiceCollection()
.AddLogging()
Expand Down Expand Up @@ -114,7 +114,7 @@ public void ConfigureResourceUtilization_InitializeTrackerProperly()
}

[ConditionalFact]
public void ConfigureTracker_GivenOptionsDelegate_InitializeTrackerWithOptionsProperly()
public void ConfigureMonitor_GivenOptionsDelegate_InitializeTrackerWithOptionsProperly()
{
const int SamplingWindowValue = 3;
const int CalculationPeriodValue = 2;
Expand Down Expand Up @@ -142,7 +142,7 @@ public void ConfigureTracker_GivenOptionsDelegate_InitializeTrackerWithOptionsPr
}

[ConditionalFact]
public void ConfigureTracker_GivenIConfigurationSection_InitializeTrackerWithOptionsProperly()
public void ConfigureMonitor_GivenIConfigurationSection_InitializeTrackerWithOptionsProperly()
{
const int SamplingWindowValue = 3;
const int CalculationPeriod = 2;
Expand Down