Skip to content

Commit 4a959a6

Browse files
author
Danila Polevshchikov
committed
Internal resource state monitoring
1 parent 94d6b5d commit 4a959a6

10 files changed

Lines changed: 197 additions & 0 deletions

Greentube.Monitoring.sln

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greentube.Monitoring.Apache
4040
EndProject
4141
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greentube.Monitoring.IntegrationTests", "test\Greentube.Monitoring.IntegrationTests\Greentube.Monitoring.IntegrationTests.csproj", "{B9FAE3D9-FB45-479B-ADAE-5A81B0EED0A8}"
4242
EndProject
43+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greentube.Monitoring.InternalResource", "src\Greentube.Monitoring.InternalResource\Greentube.Monitoring.InternalResource.csproj", "{6C953298-9D57-49A7-8123-C110A99EADA6}"
44+
EndProject
4345
Global
4446
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4547
Coverage|Any CPU = Coverage|Any CPU
@@ -125,6 +127,12 @@ Global
125127
{B9FAE3D9-FB45-479B-ADAE-5A81B0EED0A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
126128
{B9FAE3D9-FB45-479B-ADAE-5A81B0EED0A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
127129
{B9FAE3D9-FB45-479B-ADAE-5A81B0EED0A8}.Release|Any CPU.Build.0 = Release|Any CPU
130+
{6C953298-9D57-49A7-8123-C110A99EADA6}.Coverage|Any CPU.ActiveCfg = Debug|Any CPU
131+
{6C953298-9D57-49A7-8123-C110A99EADA6}.Coverage|Any CPU.Build.0 = Debug|Any CPU
132+
{6C953298-9D57-49A7-8123-C110A99EADA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
133+
{6C953298-9D57-49A7-8123-C110A99EADA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
134+
{6C953298-9D57-49A7-8123-C110A99EADA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
135+
{6C953298-9D57-49A7-8123-C110A99EADA6}.Release|Any CPU.Build.0 = Release|Any CPU
128136
EndGlobalSection
129137
GlobalSection(SolutionProperties) = preSolution
130138
HideSolutionNode = FALSE
@@ -143,6 +151,7 @@ Global
143151
{D5DEE9C7-0A0A-4789-BD75-F78F5037C69A} = {843C8ED0-4792-40E0-8903-A3E5FF74A0A3}
144152
{DA5A72B9-EEED-4CFF-97A4-C5FE6BC90FB6} = {AE749C50-94C1-445C-B13F-E9D19372CBDB}
145153
{B9FAE3D9-FB45-479B-ADAE-5A81B0EED0A8} = {AE749C50-94C1-445C-B13F-E9D19372CBDB}
154+
{6C953298-9D57-49A7-8123-C110A99EADA6} = {843C8ED0-4792-40E0-8903-A3E5FF74A0A3}
146155
EndGlobalSection
147156
GlobalSection(ExtensibilityGlobals) = postSolution
148157
SolutionGuid = {BC80F7F7-4B53-4822-BFCB-50AC6E0EE384}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.2" />
9+
</ItemGroup>
10+
11+
<ItemGroup>
12+
<ProjectReference Include="..\Greentube.Monitoring\Greentube.Monitoring.csproj" />
13+
</ItemGroup>
14+
15+
</Project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace Greentube.Monitoring.InternalResource
2+
{
3+
/// <summary>
4+
/// Represents internal resource state
5+
/// </summary>
6+
public interface IInternalResourceMonitored
7+
{
8+
/// <summary>
9+
/// Gets a value indicating whether this resource is up.
10+
/// </summary>
11+
/// <value>
12+
/// <c>true</c> if this instance is up; otherwise, <c>false</c>.
13+
/// </value>
14+
bool IsUp { get; }
15+
}
16+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
4+
namespace Greentube.Monitoring.InternalResource
5+
{
6+
public sealed class InternalResourceHealthCheckStrategy : IHealthCheckStrategy
7+
{
8+
private readonly IInternalResourceMonitored _internalResourceMonitored;
9+
10+
public InternalResourceHealthCheckStrategy(IInternalResourceMonitored internalResourceMonitored)
11+
{
12+
_internalResourceMonitored = internalResourceMonitored;
13+
}
14+
15+
public Task<bool> Check(CancellationToken token)
16+
{
17+
return Task.FromResult(_internalResourceMonitored.IsUp);
18+
}
19+
}
20+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using Microsoft.Extensions.Logging;
2+
3+
namespace Greentube.Monitoring.InternalResource
4+
{
5+
/// <summary>
6+
/// Internal resource monitor
7+
///<seealso cref="ResourceMonitor" />
8+
/// </summary>
9+
public sealed class InternalResourceMonitor : ResourceMonitor
10+
{
11+
public InternalResourceMonitor(
12+
string resourceName,
13+
InternalResourceHealthCheckStrategy verificationStrategy,
14+
IResourceMonitorConfiguration configuration,
15+
ILogger<ResourceMonitor> logger,
16+
bool isCritical = false)
17+
: base(resourceName, verificationStrategy, configuration, logger, isCritical)
18+
{
19+
}
20+
}
21+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Logging;
3+
4+
namespace Greentube.Monitoring.InternalResource
5+
{
6+
public static class InternalResourceMonitoringExtensions
7+
{
8+
/// <summary>
9+
/// Adds the internal resource monitor.
10+
/// </summary>
11+
/// <param name="options">The options.</param>
12+
/// <param name="internalResource">Instance of internal resource that has state</param>
13+
/// <param name="resourceName">Name of the resource. Defaults to: Uri.AbsoluteUri.</param>
14+
/// <param name="isCritical">if set to <c>true</c> [is critical].</param>
15+
/// <param name="configOverride">The configuration override.</param>
16+
public static void AddInternalResourceMonitor(
17+
this MonitoringOptions options,
18+
IInternalResourceMonitored internalResource,
19+
string resourceName,
20+
bool isCritical = false,
21+
IResourceMonitorConfiguration configOverride = null)
22+
{
23+
options.AddResourceMonitor((conf, provider) =>
24+
{
25+
var logger = provider.GetRequiredService<ILogger<InternalResourceMonitor>>();
26+
return new InternalResourceMonitor(
27+
resourceName,
28+
new InternalResourceHealthCheckStrategy(internalResource),
29+
configOverride ?? conf,
30+
logger, isCritical
31+
);
32+
});
33+
}
34+
}
35+
}

test/Greentube.Monitoring.IntegrationTests/Greentube.Monitoring.IntegrationTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
</ItemGroup>
2020

2121
<ItemGroup>
22+
<ProjectReference Include="..\..\src\Greentube.Monitoring.AkkaCluster\Greentube.Monitoring.InternalResource.csproj" />
2223
<ProjectReference Include="..\..\src\Greentube.Monitoring.AspNetCore\Greentube.Monitoring.AspNetCore.csproj" />
2324
<ProjectReference Include="..\..\src\Greentube.Monitoring\Greentube.Monitoring.csproj" />
2425
</ItemGroup>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System;
2+
using System.Net.Http;
3+
using System.Threading.Tasks;
4+
using Microsoft.AspNetCore.Hosting;
5+
using Microsoft.AspNetCore.TestHost;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Newtonsoft.Json;
8+
using Xunit;
9+
10+
namespace Greentube.Monitoring.IntegrationTests
11+
{
12+
public class InternalResourceMonitorTests
13+
{
14+
private readonly TestServer _server;
15+
16+
public InternalResourceMonitorTests()
17+
{
18+
var webHostBuilder = new WebHostBuilder();
19+
_server = new TestServer(webHostBuilder.UseStartup<TestStartup>());
20+
}
21+
22+
[Fact]
23+
public async Task InternalStateIsMonitored()
24+
{
25+
var client = _server.CreateClient();
26+
27+
// check if node is up
28+
var healthCheckResponse = await GetHealth(client);
29+
Assert.True(healthCheckResponse.Up);
30+
31+
// set internalState to down
32+
await client.GetAsync("/?SetToDown");
33+
34+
await Task.Delay(TimeSpan.FromMilliseconds(500));
35+
// check if node is down
36+
healthCheckResponse = await GetHealth(client);
37+
Assert.False(healthCheckResponse.Up);
38+
}
39+
40+
private static async Task<HealthCheckResponse> GetHealth(HttpClient client)
41+
{
42+
var httpResponseMessage = await client.GetAsync("/health?Detailed");
43+
var content = await httpResponseMessage.Content.ReadAsStringAsync();
44+
var healthCheckResponse =
45+
JsonConvert.DeserializeObject<HealthCheckResponse>(content);
46+
return healthCheckResponse;
47+
}
48+
49+
private class HealthCheckResponse
50+
{
51+
public bool Up { get; set; }
52+
}
53+
}
54+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using Greentube.Monitoring.InternalResource;
5+
6+
namespace Greentube.Monitoring.IntegrationTests
7+
{
8+
class SimpleInternalResource: IInternalResourceMonitored
9+
{
10+
public bool IsUp { get; set; } = false;
11+
}
12+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,40 @@
11
using System;
22
using System.Reflection;
33
using Greentube.Monitoring.DependencyInjection;
4+
using Greentube.Monitoring.InternalResource;
45
using Microsoft.AspNetCore.Builder;
56
using Microsoft.AspNetCore.Hosting;
67
using Microsoft.Extensions.DependencyInjection;
78

9+
810
namespace Greentube.Monitoring.IntegrationTests
911
{
1012
public sealed class TestStartup
1113
{
14+
private SimpleInternalResource _testInternalResource;
1215
public IServiceProvider ConfigureServices(IServiceCollection services)
1316
{
17+
_testInternalResource = new SimpleInternalResource { IsUp = true };
1418
services.AddMonitoring(Assembly.GetEntryAssembly(), options =>
1519
{
1620
options.AddShutdownMonitor(configOverride:new ResourceMonitorConfiguration(true, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(100)));
21+
options.AddInternalResourceMonitor(_testInternalResource, "simple resource", configOverride: new ResourceMonitorConfiguration(true, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(100)), isCritical: true);
1722
});
1823
return services.BuildServiceProvider();
1924
}
2025

2126
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
2227
{
2328
app.UseMonitoringEndpoint(options => options.Path = "/health");
29+
30+
app.Run(async context =>
31+
{
32+
if (context.Request.Query.ContainsKey("SetToUp"))
33+
{ _testInternalResource.IsUp = true;}
34+
35+
if (context.Request.Query.ContainsKey("SetToDown"))
36+
{ _testInternalResource.IsUp = false; }
37+
});
2438
}
2539
}
2640
}

0 commit comments

Comments
 (0)