Skip to content

Commit 771157c

Browse files
authored
Merge pull request #25 from StuFrankish/project-organisation
Implemented configuration options
2 parents 7e7d5ad + 073760a commit 771157c

File tree

6 files changed

+109
-8
lines changed

6 files changed

+109
-8
lines changed

HealthChecks.UnitTests/TestSuite.cs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using HealthChecks.Uptime;
2+
using HealthChecks.Uptime.Options;
23
using Microsoft.Extensions.Diagnostics.HealthChecks;
34

45
namespace HealthChecks.UnitTests;
@@ -10,13 +11,14 @@ public class TestSuite
1011
{
1112
private readonly DateTime _fixedStartupTime = new(2023, 1, 1);
1213
private readonly StartupTimeHealthCheck _healthCheckWithFixedTime;
14+
private readonly UptimeHealthCheckOptions _healthCheckOptions = new();
1315

1416
/// <summary>
1517
/// Initializes a new instance of the <see cref="TestSuite"/> class.
1618
/// </summary>
1719
public TestSuite()
1820
{
19-
_healthCheckWithFixedTime = new StartupTimeHealthCheck(_fixedStartupTime);
21+
_healthCheckWithFixedTime = new StartupTimeHealthCheck(_fixedStartupTime, _healthCheckOptions);
2022
}
2123

2224
/// <summary>
@@ -30,7 +32,7 @@ public TestSuite()
3032
public async Task CheckHealthAsync_Should_ReturnHealthy(int hoursOffset)
3133
{
3234
// Arrange
33-
var healthCheck = hoursOffset == 0 ? _healthCheckWithFixedTime : new StartupTimeHealthCheck(DateTime.Now.AddHours(hoursOffset));
35+
var healthCheck = hoursOffset == 0 ? _healthCheckWithFixedTime : new StartupTimeHealthCheck(DateTime.Now.AddHours(hoursOffset), _healthCheckOptions);
3436

3537
// Act
3638
var result = await healthCheck.CheckHealthAsync(new HealthCheckContext());
@@ -57,4 +59,35 @@ public async Task CheckHealthAsync_Should_ReturnHealthy_WithCustomStartupTime()
5759
Assert.True(data.ContainsKey("Uptime"));
5860
Assert.Equal(_fixedStartupTime.ToString("o"), data["Startup Time"].ToString());
5961
}
62+
/// <summary>
63+
/// Tests the CheckHealthAsync method to ensure it returns a degraded status when DegradedThresholdInSeconds is set.
64+
/// </summary>
65+
/// <param name="hoursOffset">The number of hours offset from the startup time.</param>
66+
/// <returns>A task representing the asynchronous operation.</returns>
67+
[Theory]
68+
[InlineData(0)] // At startup
69+
[InlineData(-1)] // After 1 hour of uptime
70+
public async Task CheckHealthAsync_Should_ReturnDegraded_WhenDegradedThresholdInSecondsIsSet(int hoursOffset)
71+
{
72+
// Arrange
73+
var degradedThresholdInSeconds = 3600; // Set the degraded threshold to 1 hour
74+
_healthCheckOptions.DegradedThresholdInSeconds = degradedThresholdInSeconds;
75+
76+
var healthCheck = new StartupTimeHealthCheck(DateTime.Now.AddHours(hoursOffset), _healthCheckOptions);
77+
78+
// Act
79+
var result = await healthCheck.CheckHealthAsync(new HealthCheckContext());
80+
81+
// Assert
82+
if (hoursOffset == 0)
83+
{
84+
Assert.Equal(HealthStatus.Degraded, result.Status);
85+
Assert.Contains("Application is experiencing degraded service.", result.Description);
86+
}
87+
else
88+
{
89+
Assert.Equal(HealthStatus.Healthy, result.Status);
90+
Assert.Contains("Application has been running without issues.", result.Description);
91+
}
92+
}
6093
}

HealthChecks.Uptime/Constants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ internal sealed class Language
1212
public const string Data_Uptime = "Uptime";
1313
public const string Data_StartupTime = "Startup Time";
1414
public const string Data_HealthyDescription = "Application has been running without issues.";
15+
public const string Data_DegradedDescription = "Application is experiencing degraded service.";
1516
}
1617
}

HealthChecks.Uptime/Extensions/ServiceCollectionExtension.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.Extensions.DependencyInjection;
1+
using HealthChecks.Uptime.Options;
2+
using Microsoft.Extensions.DependencyInjection;
23

34
namespace HealthChecks.Uptime;
45

@@ -11,7 +12,24 @@ public static class ServiceCollectionExtension
1112
/// <returns>The <see cref="IHealthChecksBuilder"/> with the Uptime health check added.</returns>
1213
public static IHealthChecksBuilder AddUptimeHealthCheck(this IHealthChecksBuilder builder)
1314
{
14-
builder.Services.AddSingleton(implementationInstance: new StartupTimeHealthCheck(DateTime.Now));
15+
builder.Services.AddSingleton(implementationInstance: new StartupTimeHealthCheck(DateTime.Now, options: null));
16+
builder.AddCheck<StartupTimeHealthCheck>(name: Constants.Configuration.DefaultCheckName);
17+
18+
return builder;
19+
}
20+
21+
/// <summary>
22+
/// Adds the Uptime health check to the <see cref="IHealthChecksBuilder"/> with the specified options.
23+
/// </summary>
24+
/// <param name="builder">The <see cref="IHealthChecksBuilder"/> to add the health check to.</param>
25+
/// <param name="options">The options for the Uptime health check.</param>
26+
/// <returns>The <see cref="IHealthChecksBuilder"/> with the Uptime health check added.</returns>
27+
public static IHealthChecksBuilder AddUptimeHealthCheck(this IHealthChecksBuilder builder, Action<UptimeHealthCheckOptions>? options)
28+
{
29+
UptimeHealthCheckOptions healthCheckOptions = new();
30+
options?.Invoke(healthCheckOptions);
31+
32+
builder.Services.AddSingleton(implementationInstance: new StartupTimeHealthCheck(DateTime.Now, options: healthCheckOptions));
1533
builder.AddCheck<StartupTimeHealthCheck>(name: Constants.Configuration.DefaultCheckName);
1634

1735
return builder;

HealthChecks.Uptime/HealthCheck/StartupTimeHealthCheck.cs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
using Microsoft.Extensions.Diagnostics.HealthChecks;
1+
using HealthChecks.Uptime.Options;
2+
using Microsoft.Extensions.Diagnostics.HealthChecks;
23

34
namespace HealthChecks.Uptime;
45

56
/// <summary>
67
/// Initializes a new instance of the <see cref="StartupTimeHealthCheck"/> class.
78
/// </summary>
89
/// <param name="startupTime">The startup time of the application.</param>
9-
public sealed class StartupTimeHealthCheck(DateTime startupTime) : IHealthCheck
10+
public sealed class StartupTimeHealthCheck(DateTime startupTime, UptimeHealthCheckOptions? options) : IHealthCheck
1011
{
1112
private readonly DateTime _startupTime = startupTime;
13+
private readonly UptimeHealthCheckOptions _options = options ?? new();
1214

1315
/// <summary>
1416
/// Checks the health of the application's startup time.
@@ -21,10 +23,51 @@ public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, Canc
2123
var uptime = DateTime.Now - _startupTime;
2224
var data = new Dictionary<string, object>
2325
{
26+
// Formats the startup time as a string using the "o" format specifier (ISO 8601 format)
2427
{ Constants.Language.Data_StartupTime, _startupTime.ToString(format: "o") },
28+
29+
// Include the uptime as a string
2530
{ Constants.Language.Data_Uptime, uptime.ToString() }
2631
};
2732

28-
return Task.FromResult(HealthCheckResult.Healthy(description: Constants.Language.Data_HealthyDescription, data));
33+
// Shortcut for when the degraded threshold is not set or is less than 0
34+
if (
35+
_options.DegradedThresholdInSeconds is null ||
36+
_options.DegradedThresholdInSeconds.HasValue && _options.DegradedThresholdInSeconds.Value < 0
37+
)
38+
{
39+
// Create a new HealthCheckResult object with the specified parameters
40+
var shortResult = new HealthCheckResult(
41+
status: HealthStatus.Healthy,
42+
description: Constants.Language.Data_HealthyDescription,
43+
data: data
44+
);
45+
46+
return Task.FromResult(shortResult);
47+
}
48+
49+
// Normal operation
50+
HealthStatus status;
51+
string description;
52+
53+
if (uptime.TotalSeconds < _options.DegradedThresholdInSeconds)
54+
{
55+
status = HealthStatus.Degraded;
56+
description = Constants.Language.Data_DegradedDescription;
57+
}
58+
else
59+
{
60+
status = HealthStatus.Healthy;
61+
description = Constants.Language.Data_HealthyDescription;
62+
}
63+
64+
// Create a new HealthCheckResult object with the specified parameters
65+
var result = new HealthCheckResult(
66+
status: status,
67+
description: description,
68+
data: data
69+
);
70+
71+
return Task.FromResult(result);
2972
}
3073
}

HealthChecks.Uptime/HealthChecks.Uptime.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<OutputType>Library</OutputType>
99
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
1010
<Title>Uptime HealthCheck</Title>
11-
<Version>2.0.4</Version>
11+
<Version>2.0.5</Version>
1212
<Authors>Stu Frankish</Authors>
1313
<Company>Stu Frankish</Company>
1414
<Description>Application uptime Healthcheck extension.</Description>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace HealthChecks.Uptime.Options;
2+
3+
public sealed class UptimeHealthCheckOptions
4+
{
5+
public int? DegradedThresholdInSeconds { get; set; }
6+
}

0 commit comments

Comments
 (0)