Skip to content

Commit d89b747

Browse files
committed
Register services in health check builder
Signed-off-by: Victor Chang <vicchang@nvidia.com>
1 parent e89ebec commit d89b747

File tree

8 files changed

+174
-22
lines changed

8 files changed

+174
-22
lines changed

src/Monai.Deploy.Storage.sln

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,4 @@
11
Microsoft Visual Studio Solution File, Format Version 12.00
2-
<!--
3-
~ Copyright 2022 MONAI Consortium
4-
~
5-
~ Licensed under the Apache License, Version 2.0 (the "License");
6-
~ you may not use this file except in compliance with the License.
7-
~ You may obtain a copy of the License at
8-
~
9-
~ http://www.apache.org/licenses/LICENSE-2.0
10-
~
11-
~ Unless required by applicable law or agreed to in writing, software
12-
~ distributed under the License is distributed on an "AS IS" BASIS,
13-
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14-
~ See the License for the specific language governing permissions and
15-
~ limitations under the License.
16-
-->
17-
182
# Visual Studio Version 17
193
VisualStudioVersion = 17.1.32210.238
204
MinimumVisualStudioVersion = 10.0.40219.1
@@ -39,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Monai.Deploy.Storage.MinIO"
3923
EndProject
4024
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Monai.Deploy.Storage.MinIO.Tests", "Plugins\MinIO\Tests\Monai.Deploy.Storage.MinIO.Tests.csproj", "{FCB3FCA4-2BB6-4921-9715-CDECF343C6E2}"
4125
EndProject
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApi", "TestApi\TestApi.csproj", "{54D63D29-6949-40B4-84D8-9253291649E3}"
27+
EndProject
4228
Global
4329
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4430
Debug|Any CPU = Debug|Any CPU
@@ -73,6 +59,10 @@ Global
7359
{FCB3FCA4-2BB6-4921-9715-CDECF343C6E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
7460
{FCB3FCA4-2BB6-4921-9715-CDECF343C6E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
7561
{FCB3FCA4-2BB6-4921-9715-CDECF343C6E2}.Release|Any CPU.Build.0 = Release|Any CPU
62+
{54D63D29-6949-40B4-84D8-9253291649E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
63+
{54D63D29-6949-40B4-84D8-9253291649E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
64+
{54D63D29-6949-40B4-84D8-9253291649E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
65+
{54D63D29-6949-40B4-84D8-9253291649E3}.Release|Any CPU.Build.0 = Release|Any CPU
7666
EndGlobalSection
7767
GlobalSection(SolutionProperties) = preSolution
7868
HideSolutionNode = FALSE

src/Plugins/MinIO/HealthCheckBuilder.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* limitations under the License.
1515
*/
1616

17-
using System;
1817
using Microsoft.Extensions.DependencyInjection;
1918
using Microsoft.Extensions.Diagnostics.HealthChecks;
2019
using Microsoft.Extensions.Logging;
@@ -33,13 +32,12 @@ public override IHealthChecksBuilder Configure(
3332
IEnumerable<string>? tags = null,
3433
TimeSpan? timeout = null)
3534
{
36-
3735
builder.Add(new HealthCheckRegistration(
3836
ConfigurationKeys.StorageServiceName,
3937
serviceProvider =>
4038
{
41-
var minioClientFactory = serviceProvider.GetRequiredService<IMinIoClientFactory>();
4239
var logger = serviceProvider.GetRequiredService<ILogger<MinIoHealthCheck>>();
40+
var minioClientFactory = serviceProvider.GetRequiredService<IMinIoClientFactory>();
4341
return new MinIoHealthCheck(minioClientFactory, logger);
4442
},
4543
failureStatus,

src/Storage/IHealthChecksBuilderExtensions.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,32 @@ public static class IHealthChecksBuilderExtensions
2929
/// Configures health check for the MONAI Deploy Storage Service.
3030
/// </summary>
3131
/// <param name="builder">Instance of <see cref="IHealthChecksBuilder"/>.</param>
32+
/// <param name="serviceCollection">Instance of <see cref="IServiceCollection"/>.</param>
3233
/// <param name="serviceProvider">Instance of <see cref="IServiceProvider"/>.</param>
3334
/// <param name="fullyQualifiedTypeName">Fully qualified type name of the service to use.</param>
3435
/// <returns>Instance of <see cref="IHealthChecksBuilder"/>.</returns>
3536
/// <exception cref="ConfigurationException"></exception>
3637
public static IHealthChecksBuilder AddMonaiDeployStorageHealthCheck(
3738
this IHealthChecksBuilder builder,
39+
IServiceCollection serviceCollection,
3840
string fullyQualifiedTypeName,
3941
HealthStatus? failureStatus = null,
4042
IEnumerable<string>? tags = null,
4143
TimeSpan? timeout = null)
42-
=> AddMonaiDeployStorageHealthCheck(builder, fullyQualifiedTypeName, new FileSystem(), failureStatus, tags, timeout);
44+
=> AddMonaiDeployStorageHealthCheck(builder, serviceCollection, fullyQualifiedTypeName, new FileSystem(), failureStatus, tags, timeout);
4345

4446
/// <summary>
4547
/// Configures health check for the MONAI Deploy Storage Service.
4648
/// </summary>
4749
/// <param name="builder">Instance of <see cref="IHealthChecksBuilder"/>.</param>
50+
/// <param name="serviceCollection">Instance of <see cref="IServiceCollection"/>.</param>
4851
/// <param name="fullyQualifiedTypeName">Fully qualified type name of the service to use.</param>
4952
/// <param name="fileSystem">Instance of <see cref="IFileSystem"/>.</param>
5053
/// <returns>Instance of <see cref="IHealthChecksBuilder"/>.</returns>
5154
/// <exception cref="ConfigurationException"></exception>
5255
public static IHealthChecksBuilder AddMonaiDeployStorageHealthCheck(
5356
this IHealthChecksBuilder builder,
57+
IServiceCollection serviceCollection,
5458
string fullyQualifiedTypeName,
5559
IFileSystem fileSystem,
5660
HealthStatus? failureStatus = null,
@@ -68,18 +72,25 @@ public static IHealthChecksBuilder AddMonaiDeployStorageHealthCheck(
6872
AppDomain.CurrentDomain.AssemblyResolve += resolveEventHandler;
6973

7074
var storageServiceAssembly = IServiceCollectionExtensions.LoadAssemblyFromDisk(IServiceCollectionExtensions.GetAssemblyName(fullyQualifiedTypeName), fileSystem);
71-
var serviceRegistrationType = storageServiceAssembly.GetTypes().FirstOrDefault(p => p.IsSubclassOf(typeof(HealthCheckRegistrationBase)));
75+
var healthCheckBase = storageServiceAssembly.GetTypes().FirstOrDefault(p => p.IsSubclassOf(typeof(HealthCheckRegistrationBase)));
7276

73-
if (serviceRegistrationType is null || Activator.CreateInstance(serviceRegistrationType, fullyQualifiedTypeName) is not HealthCheckRegistrationBase healthCheckBuilder)
77+
if (healthCheckBase is null || Activator.CreateInstance(healthCheckBase, fullyQualifiedTypeName) is not HealthCheckRegistrationBase healthCheckBuilder)
7478
{
7579
throw new ConfigurationException($"Service registrar cannot be found for the configured plug-in '{fullyQualifiedTypeName}'.");
7680
}
81+
var serviceRegistrationType = storageServiceAssembly.GetTypes().FirstOrDefault(p => p.IsSubclassOf(typeof(ServiceRegistrationBase)));
7782

83+
if (serviceRegistrationType is null || Activator.CreateInstance(serviceRegistrationType, fullyQualifiedTypeName) is not ServiceRegistrationBase serviceRegistrar)
84+
{
85+
throw new ConfigurationException($"Service registrar cannot be found for the configured plug-in '{fullyQualifiedTypeName}'.");
86+
}
7887
if (!IServiceCollectionExtensions.IsSupportedType(fullyQualifiedTypeName, storageServiceAssembly))
7988
{
8089
throw new ConfigurationException($"The configured type '{fullyQualifiedTypeName}' does not implement the {typeof(IStorageService).Name} interface.");
8190
}
8291

92+
serviceRegistrar.Configure(serviceCollection);
93+
8394
healthCheckBuilder.Configure(builder, failureStatus, tags, timeout);
8495

8596
AppDomain.CurrentDomain.AssemblyResolve -= resolveEventHandler;

src/TestApi/Program.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using System.IO.Abstractions;
2+
using Monai.Deploy.Storage;
3+
using Monai.Deploy.Storage.Configuration;
4+
5+
internal class Program
6+
{
7+
private static void Main(string[] args)
8+
{
9+
var builder = WebApplication.CreateBuilder(args);
10+
11+
builder.Services.AddOptions<StorageServiceConfiguration>()
12+
.Bind(builder.Configuration.GetSection("storage"));
13+
builder.Services.AddMonaiDeployStorageService("Monai.Deploy.Storage.MinIO.MinIoStorageService, Monai.Deploy.Storage.MinIO");
14+
15+
builder.Services.AddHealthChecks()
16+
.AddMonaiDeployStorageHealthCheck(builder.Services, "Monai.Deploy.Storage.MinIO.MinIoStorageService, Monai.Deploy.Storage.MinIO");
17+
18+
builder.Services.AddSingleton<IFileSystem, FileSystem>();
19+
20+
// Add services to the container.
21+
22+
var app = builder.Build();
23+
24+
// Configure the HTTP request pipeline.
25+
26+
var summaries = new[]
27+
{
28+
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
29+
};
30+
app.UseRouting();
31+
app.UseEndpoints(endpoints =>
32+
{
33+
endpoints.MapHealthChecks("/health");
34+
});
35+
app.Use(async (context, func) =>
36+
{
37+
try
38+
{
39+
await func();
40+
}
41+
catch (Exception e)
42+
{
43+
context.Response.Clear();
44+
45+
// Preserve the status code that would have been written by the server automatically when a BadHttpRequestException is thrown.
46+
if (e is BadHttpRequestException badHttpRequestException)
47+
{
48+
context.Response.StatusCode = badHttpRequestException.StatusCode;
49+
}
50+
else
51+
{
52+
context.Response.StatusCode = 500;
53+
}
54+
// log, write custom response and so on...
55+
}
56+
});
57+
58+
app.Run();
59+
}
60+
}
61+
62+
internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
63+
{
64+
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
65+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"$schema": "https://json.schemastore.org/launchsettings.json",
3+
"iisSettings": {
4+
"windowsAuthentication": false,
5+
"anonymousAuthentication": true,
6+
"iisExpress": {
7+
"applicationUrl": "http://localhost:10845",
8+
"sslPort": 0
9+
}
10+
},
11+
"profiles": {
12+
"TestApi": {
13+
"commandName": "Project",
14+
"dotnetRunMessages": true,
15+
"launchBrowser": true,
16+
"launchUrl": "weatherforecast",
17+
"applicationUrl": "http://localhost:5045",
18+
"environmentVariables": {
19+
"ASPNETCORE_ENVIRONMENT": "Development"
20+
}
21+
},
22+
"IIS Express": {
23+
"commandName": "IISExpress",
24+
"launchBrowser": true,
25+
"launchUrl": "weatherforecast",
26+
"environmentVariables": {
27+
"ASPNETCORE_ENVIRONMENT": "Development"
28+
}
29+
}
30+
}
31+
}

src/TestApi/TestApi.csproj

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<IncludePackageReferencesDuringMarkupCompilation>true</IncludePackageReferencesDuringMarkupCompilation>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\Plugins\MinIO\Monai.Deploy.Storage.MinIO.csproj" />
12+
<ProjectReference Include="..\Storage\Monai.Deploy.Storage.csproj" />
13+
</ItemGroup>
14+
15+
<Target Name="CopyPluginsBuild" AfterTargets="Build">
16+
<ItemGroup>
17+
<PluginDlls Include="$(OutDir)Monai.Deploy.Storage.MinIO.dll;$(OutDir)Minio.dll" />
18+
</ItemGroup>
19+
<Copy SourceFiles="@(PluginDlls)" DestinationFolder="$(OutDir)\plug-ins\" SkipUnchangedFiles="true" />
20+
<Message Text="Files copied successfully to $(OutDir)\plug-ins\." Importance="high" />
21+
</Target>
22+
23+
</Project>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
}
8+
}

src/TestApi/appsettings.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"storage": {
9+
"bufferRootPath": "./temp",
10+
"tempStorageRootPath": "/incoming",
11+
"bucketName": "monaideploy",
12+
"storageRootPath": "/payloads",
13+
"temporaryBucketName": "monaideploy",
14+
"serviceAssemblyName": "Monai.Deploy.Storage.MinIO.MinIoStorageService, Monai.Deploy.Storage.MinIO",
15+
"settings": {
16+
"endpoint": "localhost:9000",
17+
"accessKey": "admin",
18+
"accessToken": "password",
19+
"securedConnection": false,
20+
"region": "local",
21+
"executableLocation": "/bin/mc",
22+
"serviceName": "MinIO"
23+
}
24+
},
25+
"AllowedHosts": "*"
26+
}

0 commit comments

Comments
 (0)