diff --git a/Greentube.Monitoring.sln b/Greentube.Monitoring.sln
index 16c0dd9..c373645 100644
--- a/Greentube.Monitoring.sln
+++ b/Greentube.Monitoring.sln
@@ -40,6 +40,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greentube.Monitoring.Apache
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greentube.Monitoring.IntegrationTests", "test\Greentube.Monitoring.IntegrationTests\Greentube.Monitoring.IntegrationTests.csproj", "{B9FAE3D9-FB45-479B-ADAE-5A81B0EED0A8}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greentube.Monitoring.InternalResource", "src\Greentube.Monitoring.InternalResource\Greentube.Monitoring.InternalResource.csproj", "{6C953298-9D57-49A7-8123-C110A99EADA6}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Coverage|Any CPU = Coverage|Any CPU
@@ -125,6 +127,12 @@ Global
{B9FAE3D9-FB45-479B-ADAE-5A81B0EED0A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9FAE3D9-FB45-479B-ADAE-5A81B0EED0A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9FAE3D9-FB45-479B-ADAE-5A81B0EED0A8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6C953298-9D57-49A7-8123-C110A99EADA6}.Coverage|Any CPU.ActiveCfg = Debug|Any CPU
+ {6C953298-9D57-49A7-8123-C110A99EADA6}.Coverage|Any CPU.Build.0 = Debug|Any CPU
+ {6C953298-9D57-49A7-8123-C110A99EADA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6C953298-9D57-49A7-8123-C110A99EADA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6C953298-9D57-49A7-8123-C110A99EADA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6C953298-9D57-49A7-8123-C110A99EADA6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -143,6 +151,7 @@ Global
{D5DEE9C7-0A0A-4789-BD75-F78F5037C69A} = {843C8ED0-4792-40E0-8903-A3E5FF74A0A3}
{DA5A72B9-EEED-4CFF-97A4-C5FE6BC90FB6} = {AE749C50-94C1-445C-B13F-E9D19372CBDB}
{B9FAE3D9-FB45-479B-ADAE-5A81B0EED0A8} = {AE749C50-94C1-445C-B13F-E9D19372CBDB}
+ {6C953298-9D57-49A7-8123-C110A99EADA6} = {843C8ED0-4792-40E0-8903-A3E5FF74A0A3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BC80F7F7-4B53-4822-BFCB-50AC6E0EE384}
diff --git a/src/Greentube.Monitoring.InternalResource/Greentube.Monitoring.InternalResource.csproj b/src/Greentube.Monitoring.InternalResource/Greentube.Monitoring.InternalResource.csproj
new file mode 100644
index 0000000..2bbdcbb
--- /dev/null
+++ b/src/Greentube.Monitoring.InternalResource/Greentube.Monitoring.InternalResource.csproj
@@ -0,0 +1,15 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Greentube.Monitoring.InternalResource/IInternalResourceMonitored.cs b/src/Greentube.Monitoring.InternalResource/IInternalResourceMonitored.cs
new file mode 100644
index 0000000..2e9edc7
--- /dev/null
+++ b/src/Greentube.Monitoring.InternalResource/IInternalResourceMonitored.cs
@@ -0,0 +1,16 @@
+namespace Greentube.Monitoring.InternalResource
+{
+ ///
+ /// Represents internal resource state
+ ///
+ public interface IInternalResourceMonitored
+ {
+ ///
+ /// Gets a value indicating whether this resource is up.
+ ///
+ ///
+ /// true if this instance is up; otherwise, false.
+ ///
+ bool IsUp { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Greentube.Monitoring.InternalResource/InternalResourceHealthCheckStrategy.cs b/src/Greentube.Monitoring.InternalResource/InternalResourceHealthCheckStrategy.cs
new file mode 100644
index 0000000..114635f
--- /dev/null
+++ b/src/Greentube.Monitoring.InternalResource/InternalResourceHealthCheckStrategy.cs
@@ -0,0 +1,20 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Greentube.Monitoring.InternalResource
+{
+ public sealed class InternalResourceHealthCheckStrategy : IHealthCheckStrategy
+ {
+ private readonly IInternalResourceMonitored _internalResourceMonitored;
+
+ public InternalResourceHealthCheckStrategy(IInternalResourceMonitored internalResourceMonitored)
+ {
+ _internalResourceMonitored = internalResourceMonitored;
+ }
+
+ public Task Check(CancellationToken token)
+ {
+ return Task.FromResult(_internalResourceMonitored.IsUp);
+ }
+ }
+}
diff --git a/src/Greentube.Monitoring.InternalResource/InternalResourceMonitor.cs b/src/Greentube.Monitoring.InternalResource/InternalResourceMonitor.cs
new file mode 100644
index 0000000..31fd575
--- /dev/null
+++ b/src/Greentube.Monitoring.InternalResource/InternalResourceMonitor.cs
@@ -0,0 +1,21 @@
+using Microsoft.Extensions.Logging;
+
+namespace Greentube.Monitoring.InternalResource
+{
+ ///
+ /// Internal resource monitor
+ ///
+ ///
+ public sealed class InternalResourceMonitor : ResourceMonitor
+ {
+ public InternalResourceMonitor(
+ string resourceName,
+ InternalResourceHealthCheckStrategy verificationStrategy,
+ IResourceMonitorConfiguration configuration,
+ ILogger logger,
+ bool isCritical = false)
+ : base(resourceName, verificationStrategy, configuration, logger, isCritical)
+ {
+ }
+ }
+}
diff --git a/src/Greentube.Monitoring.InternalResource/InternalResourceMonitorExtensions.cs b/src/Greentube.Monitoring.InternalResource/InternalResourceMonitorExtensions.cs
new file mode 100644
index 0000000..e9720ee
--- /dev/null
+++ b/src/Greentube.Monitoring.InternalResource/InternalResourceMonitorExtensions.cs
@@ -0,0 +1,35 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+
+namespace Greentube.Monitoring.InternalResource
+{
+ public static class InternalResourceMonitoringExtensions
+ {
+ ///
+ /// Adds the internal resource monitor.
+ ///
+ /// The options.
+ /// Instance of internal resource that has state
+ /// Name of the resource. Defaults to: Uri.AbsoluteUri.
+ /// if set to true [is critical].
+ /// The configuration override.
+ public static void AddInternalResourceMonitor(
+ this MonitoringOptions options,
+ IInternalResourceMonitored internalResource,
+ string resourceName,
+ bool isCritical = false,
+ IResourceMonitorConfiguration configOverride = null)
+ {
+ options.AddResourceMonitor((conf, provider) =>
+ {
+ var logger = provider.GetRequiredService>();
+ return new InternalResourceMonitor(
+ resourceName,
+ new InternalResourceHealthCheckStrategy(internalResource),
+ configOverride ?? conf,
+ logger, isCritical
+ );
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Greentube.Monitoring.IntegrationTests/Greentube.Monitoring.IntegrationTests.csproj b/test/Greentube.Monitoring.IntegrationTests/Greentube.Monitoring.IntegrationTests.csproj
index cf708ea..76cf21e 100644
--- a/test/Greentube.Monitoring.IntegrationTests/Greentube.Monitoring.IntegrationTests.csproj
+++ b/test/Greentube.Monitoring.IntegrationTests/Greentube.Monitoring.IntegrationTests.csproj
@@ -19,6 +19,7 @@
+
diff --git a/test/Greentube.Monitoring.IntegrationTests/InternalResourceMonitorTests.cs b/test/Greentube.Monitoring.IntegrationTests/InternalResourceMonitorTests.cs
new file mode 100644
index 0000000..3af63f9
--- /dev/null
+++ b/test/Greentube.Monitoring.IntegrationTests/InternalResourceMonitorTests.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.TestHost;
+using Microsoft.Extensions.DependencyInjection;
+using Newtonsoft.Json;
+using Xunit;
+
+namespace Greentube.Monitoring.IntegrationTests
+{
+ public class InternalResourceMonitorTests
+ {
+ private readonly TestServer _server;
+
+ public InternalResourceMonitorTests()
+ {
+ var webHostBuilder = new WebHostBuilder();
+ _server = new TestServer(webHostBuilder.UseStartup());
+ }
+
+ [Fact]
+ public async Task InternalStateIsMonitored()
+ {
+ var client = _server.CreateClient();
+
+ // check if node is up
+ var healthCheckResponse = await GetHealth(client);
+ Assert.True(healthCheckResponse.Up);
+
+ // set internalState to down
+ await client.GetAsync("/?SetToDown");
+
+ await Task.Delay(TimeSpan.FromMilliseconds(500));
+ // check if node is down
+ healthCheckResponse = await GetHealth(client);
+ Assert.False(healthCheckResponse.Up);
+
+ // set internalState to down
+ await client.GetAsync("/?SetToUp");
+
+ await Task.Delay(TimeSpan.FromMilliseconds(500));
+ // check if node is up again
+ healthCheckResponse = await GetHealth(client);
+ Assert.True(healthCheckResponse.Up);
+ }
+
+ private static async Task GetHealth(HttpClient client)
+ {
+ var httpResponseMessage = await client.GetAsync("/health?Detailed");
+ var content = await httpResponseMessage.Content.ReadAsStringAsync();
+ var healthCheckResponse =
+ JsonConvert.DeserializeObject(content);
+ return healthCheckResponse;
+ }
+
+ private class HealthCheckResponse
+ {
+ public bool Up { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Greentube.Monitoring.IntegrationTests/SimpleInternalResource.cs b/test/Greentube.Monitoring.IntegrationTests/SimpleInternalResource.cs
new file mode 100644
index 0000000..730b83b
--- /dev/null
+++ b/test/Greentube.Monitoring.IntegrationTests/SimpleInternalResource.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Greentube.Monitoring.InternalResource;
+
+namespace Greentube.Monitoring.IntegrationTests
+{
+ class SimpleInternalResource: IInternalResourceMonitored
+ {
+ public bool IsUp { get; set; } = false;
+ }
+}
diff --git a/test/Greentube.Monitoring.IntegrationTests/TestStartup.cs b/test/Greentube.Monitoring.IntegrationTests/TestStartup.cs
index c69156a..1ec90a3 100644
--- a/test/Greentube.Monitoring.IntegrationTests/TestStartup.cs
+++ b/test/Greentube.Monitoring.IntegrationTests/TestStartup.cs
@@ -1,19 +1,24 @@
using System;
using System.Reflection;
using Greentube.Monitoring.DependencyInjection;
+using Greentube.Monitoring.InternalResource;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
+
namespace Greentube.Monitoring.IntegrationTests
{
public sealed class TestStartup
{
+ private SimpleInternalResource _testInternalResource;
public IServiceProvider ConfigureServices(IServiceCollection services)
{
+ _testInternalResource = new SimpleInternalResource { IsUp = true };
services.AddMonitoring(Assembly.GetEntryAssembly(), options =>
{
options.AddShutdownMonitor(configOverride:new ResourceMonitorConfiguration(true, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(100)));
+ options.AddInternalResourceMonitor(_testInternalResource, "simple resource", configOverride: new ResourceMonitorConfiguration(true, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(100)), isCritical: true);
});
return services.BuildServiceProvider();
}
@@ -21,6 +26,15 @@ public IServiceProvider ConfigureServices(IServiceCollection services)
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMonitoringEndpoint(options => options.Path = "/health");
+
+ app.Run(async context =>
+ {
+ if (context.Request.Query.ContainsKey("SetToUp"))
+ { _testInternalResource.IsUp = true;}
+
+ if (context.Request.Query.ContainsKey("SetToDown"))
+ { _testInternalResource.IsUp = false; }
+ });
}
}
}