Skip to content

#5962 Change to early return of OS instead of throwing #5963

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

Merged
merged 8 commits into from
Jun 30, 2025
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
@@ -1,6 +1,10 @@
# Microsoft.Extensions.Diagnostics.ResourceMonitoring

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.
Measures and reports processor and memory usage. To monitor system resources, this library:

- Utilizes control groups (cgroups) in Linux. Both cgroups v1 and v2 are supported.
- Utilized Job Objects in Windows.
- Mac OS is not supported.

## Install the package

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,21 @@ public static IServiceCollection AddResourceMonitoring(
return services.AddResourceMonitoringInternal(configure);
}

// can't easily test the exception throwing case
[ExcludeFromCodeCoverage]
private static IServiceCollection AddResourceMonitoringInternal(
this IServiceCollection services,
Action<IResourceMonitorBuilder> configure)
{
var builder = new ResourceMonitorBuilder(services);

_ = services.AddMetrics();

var builder = new ResourceMonitorBuilder(services);
#if NETFRAMEWORK
_ = builder.AddWindowsProvider();
#else
bool isSupportedOs = OperatingSystem.IsWindows() || OperatingSystem.IsLinux();
if (!isSupportedOs)
{
return services;
}

if (OperatingSystem.IsWindows())
{
_ = builder.AddWindowsProvider();
Expand All @@ -81,10 +83,6 @@ private static IServiceCollection AddResourceMonitoringInternal(
{
_ = builder.AddLinuxProvider();
}
else
{
throw new PlatformNotSupportedException();
}
#endif

configure.Invoke(builder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring.Test;

[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
public sealed class ResourceMonitoringExtensionsTests
{
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
[ConditionalFact]
public void Throw_Null_When_Registration_Ingredients_Null()
{
Expand All @@ -30,6 +30,7 @@ public void Throw_Null_When_Registration_Ingredients_Null()
Assert.Throws<ArgumentNullException>(() => services.AddResourceMonitoring((b) => b.ConfigureMonitor((Action<ResourceMonitoringOptions>)null!)));
}

[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
[ConditionalFact]
public void AddsResourceMonitoringService_ToServicesCollection()
{
Expand All @@ -50,6 +51,7 @@ public void AddsResourceMonitoringService_ToServicesCollection()
Assert.IsAssignableFrom<IResourceMonitor>(trackerService);
}

[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
[ConditionalFact]
public void AddsResourceMonitoringService_ToServicesCollection_NoArgs()
{
Expand All @@ -66,6 +68,7 @@ public void AddsResourceMonitoringService_ToServicesCollection_NoArgs()
Assert.IsAssignableFrom<IResourceMonitor>(trackerService);
}

[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
[ConditionalFact]
public void AddsResourceMonitoringService_AsHostedService()
{
Expand All @@ -87,6 +90,7 @@ public void AddsResourceMonitoringService_AsHostedService()
Assert.IsAssignableFrom<IResourceMonitor>(trackerService);
}

[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
[ConditionalFact]
public void ConfigureResourceUtilization_InitializeTrackerProperly()
{
Expand All @@ -113,6 +117,7 @@ public void ConfigureResourceUtilization_InitializeTrackerProperly()
Assert.NotNull(publisher);
}

[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
[ConditionalFact]
public void ConfigureMonitor_GivenOptionsDelegate_InitializeTrackerWithOptionsProperly()
{
Expand Down Expand Up @@ -141,6 +146,7 @@ public void ConfigureMonitor_GivenOptionsDelegate_InitializeTrackerWithOptionsPr
Assert.Equal(TimeSpan.FromSeconds(CalculationPeriodValue), options!.Value.PublishingWindow);
}

[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
[ConditionalFact]
public void ConfigureMonitor_GivenIConfigurationSection_InitializeTrackerWithOptionsProperly()
{
Expand Down Expand Up @@ -182,6 +188,7 @@ public void ConfigureMonitor_GivenIConfigurationSection_InitializeTrackerWithOpt
Assert.Equal(TimeSpan.FromSeconds(CalculationPeriod), options!.Value.PublishingWindow);
}

[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
[ConditionalFact]
public void Registering_Resource_Utilization_Adds_Only_One_Object_Of_Type_ResourceUtilizationService_To_DI_Container()
{
Expand All @@ -204,4 +211,46 @@ public void Registering_Resource_Utilization_Adds_Only_One_Object_Of_Type_Resour
Assert.IsAssignableFrom<ResourceMonitorService>(background);
Assert.Same(tracker as ResourceMonitorService, background as ResourceMonitorService);
}

[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.Windows, SkipReason = "For MacOs only.")]
[ConditionalFact]
public void AddResourceMonitoringInternal_WhenMacOs_ReturnsSameServiceCollection()
{
var services = new ServiceCollection();

// Act
IServiceCollection result = services.AddResourceMonitoring();

// Assert
Assert.Same(services, result);
Assert.DoesNotContain(services, s => s.ServiceType == typeof(ISnapshotProvider));
}

[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
[ConditionalFact]
public void AddResourceMonitoring_AddsISnapshotProvider()
{
var services = new ServiceCollection();

// Act
IServiceCollection result = services.AddResourceMonitoring();

// Assert
Assert.Same(services, result);
Assert.Contains(services, s => s.ServiceType == typeof(ISnapshotProvider));
}

[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Not supported on MacOs.")]
[ConditionalFact]
public void AddResourceMonitoringInternal_CallsConfigureDelegate()
{
var services = new ServiceCollection();
bool delegateCalled = false;

// Act
services.AddResourceMonitoring(_ => delegateCalled = true);

// Assert
Assert.True(delegateCalled);
}
}
2 changes: 1 addition & 1 deletion test/TestUtilities/XUnit/OSSkipConditionAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private static OperatingSystems GetCurrentOS()

throw new PlatformNotSupportedException();
#else
// RuntimeInformation API is only avaialble in .NET Framework 4.7.1+
// RuntimeInformation API is only available in .NET Framework 4.7.1+
// .NET Framework 4.7 and below can only run on Windows.
return OperatingSystems.Windows;
#endif
Expand Down
Loading