diff --git a/.github/labeler.yml b/.github/labeler.yml index 87db1be728..d783d78485 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -141,3 +141,6 @@ UI: uris: - src/HealthChecks.Uris/**/* + +hazelcast: + - src/HealthChecks.Hazelcast/**/* \ No newline at end of file diff --git a/.github/workflows/healthchecks_hazelcast_cd.yml b/.github/workflows/healthchecks_hazelcast_cd.yml new file mode 100644 index 0000000000..8ffe2d4275 --- /dev/null +++ b/.github/workflows/healthchecks_hazelcast_cd.yml @@ -0,0 +1,29 @@ +name: HealthChecks Hazelcast CD + +on: + push: + tags: + - release-hazelcast-* + - release-all-* + +jobs: + build: + env: + BUILD_CONFIG: Release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 6.0.x + 7.0.x + - name: Restore + run: dotnet restore ./src/HealthChecks.Hazelcast/HealthChecks.Hazelcast.csproj + - name: Build + run: dotnet build --no-restore ./src/HealthChecks.Hazelcast/HealthChecks.Hazelcast.csproj -c $BUILD_CONFIG + - name: Pack + run: dotnet pack --no-build ./src/HealthChecks.Hazelcast/HealthChecks.Hazelcast.csproj -c $BUILD_CONFIG -o ./artifacts + - name: Publish + run: dotnet nuget push ./artifacts/AspNetCore.HealthChecks.Hazelcast.*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/.github/workflows/healthchecks_hazelcast_ci.yml b/.github/workflows/healthchecks_hazelcast_ci.yml new file mode 100644 index 0000000000..103e4cb843 --- /dev/null +++ b/.github/workflows/healthchecks_hazelcast_ci.yml @@ -0,0 +1,65 @@ +name: HealthChecks Hazelcast CI + +on: + workflow_dispatch: + push: + branches: [ master ] + paths: + - src/HealthChecks.Hazelcast/** + - test/HealthChecks.Hazelcast.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_hazelcast_ci.yml + - Directory.Build.props + - Directory.Build.targets + tags-ignore: + - release-* + - preview-* + + pull_request: + branches: [ master ] + paths: + - src/HealthChecks.Hazelcast/** + - test/HealthChecks.Hazelcast.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_hazelcast_ci.yml + - Directory.Build.props + - Directory.Build.targets + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 6.0.x + 7.0.x + - name: Restore + run: | + dotnet restore ./src/HealthChecks.Hazelcast/HealthChecks.Hazelcast.csproj && + dotnet restore ./test/HealthChecks.Hazelcast.Tests/HealthChecks.Hazelcast.Tests.csproj + - name: Check formatting + run: | + dotnet format --no-restore --verify-no-changes --severity warn ./src/HealthChecks.Hazelcast/HealthChecks.Hazelcast.csproj || (echo "Run 'dotnet format' to fix issues" && exit 1) && + dotnet format --no-restore --verify-no-changes --severity warn ./test/HealthChecks.Hazelcast.Tests/HealthChecks.Hazelcast.Tests.csproj || (echo "Run 'dotnet format' to fix issues" && exit 1) + - name: Build + run: | + dotnet build --no-restore ./src/HealthChecks.Hazelcast/HealthChecks.Hazelcast.csproj && + dotnet build --no-restore ./test/HealthChecks.Hazelcast.Tests/HealthChecks.Hazelcast.Tests.csproj + - name: Test + run: > + dotnet test + ./test/HealthChecks.Hazelcast.Tests/HealthChecks.Hazelcast.Tests.csproj + --no-restore + --no-build + --collect "XPlat Code Coverage" + --results-directory .coverage + -- + DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover + - name: Upload Coverage + uses: codecov/codecov-action@v3 + with: + flags: Hazelcast + directory: .coverage diff --git a/AspNetCore.Diagnostics.HealthChecks.sln b/AspNetCore.Diagnostics.HealthChecks.sln index baf683de9b..65a961a49f 100644 --- a/AspNetCore.Diagnostics.HealthChecks.sln +++ b/AspNetCore.Diagnostics.HealthChecks.sln @@ -247,9 +247,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.AzureDigitalTw EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Aws.Sqs", "src\HealthChecks.Aws.Sqs\HealthChecks.Aws.Sqs.csproj", "{3E28B63C-814E-46C9-ADBF-7357997148F5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthChecks.AzureApplicationInsights", "src\HealthChecks.AzureApplicationInsights\HealthChecks.AzureApplicationInsights.csproj", "{97C43FFC-0A48-47C7-93EE-7382C2989AAE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.AzureApplicationInsights", "src\HealthChecks.AzureApplicationInsights\HealthChecks.AzureApplicationInsights.csproj", "{97C43FFC-0A48-47C7-93EE-7382C2989AAE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthChecks.AzureApplicationInsights.Tests", "test\HealthChecks.AzureApplicationInsights.Tests\HealthChecks.AzureApplicationInsights.Tests.csproj", "{78902D9E-CD1A-4FB7-B752-A3471A2DD457}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.AzureApplicationInsights.Tests", "test\HealthChecks.AzureApplicationInsights.Tests\HealthChecks.AzureApplicationInsights.Tests.csproj", "{78902D9E-CD1A-4FB7-B752-A3471A2DD457}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Aws.Sqs.Tests", "test\HealthChecks.Aws.Sqs.Tests\HealthChecks.Aws.Sqs.Tests.csproj", "{EFA76A2C-CA0E-42BC-8215-AEEB16414947}" EndProject @@ -283,11 +283,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.UI.Data.Tests" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Dapr", "src\HealthChecks.Dapr\HealthChecks.Dapr.csproj", "{716C2E59-6BB4-49A1-B685-9958B7EF0F3B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthChecks.Dapr.Tests", "test\HealthChecks.Dapr.Tests\HealthChecks.Dapr.Tests.csproj", "{1C2085FA-2D33-459B-945E-337323485E16}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Dapr.Tests", "test\HealthChecks.Dapr.Tests\HealthChecks.Dapr.Tests.csproj", "{1C2085FA-2D33-459B-945E-337323485E16}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthChecks.Azure.KeyVault.Secrets", "src\HealthChecks.Azure.KeyVault.Secrets\HealthChecks.Azure.KeyVault.Secrets.csproj", "{877E2C7C-F136-4DC7-882D-C1ADE6B5E3ED}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.KeyVault.Secrets", "src\HealthChecks.Azure.KeyVault.Secrets\HealthChecks.Azure.KeyVault.Secrets.csproj", "{877E2C7C-F136-4DC7-882D-C1ADE6B5E3ED}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthChecks.Azure.KeyVault.Secrets.Tests", "test\HealthChecks.Azure.KeyVault.Secrets.Tests\HealthChecks.Azure.KeyVault.Secrets.Tests.csproj", "{B664ADD4-7067-4CCE-BBAC-146A174A7F73}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.KeyVault.Secrets.Tests", "test\HealthChecks.Azure.KeyVault.Secrets.Tests\HealthChecks.Azure.KeyVault.Secrets.Tests.csproj", "{B664ADD4-7067-4CCE-BBAC-146A174A7F73}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Hazelcast", "src\HealthChecks.Hazelcast\HealthChecks.Hazelcast.csproj", "{4F89E1D6-B9A0-4C7A-B3BF-2948A613A489}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Hazelcast.Tests", "test\HealthChecks.Hazelcast.Tests\HealthChecks.Hazelcast.Tests.csproj", "{419BAB71-82A1-4931-B581-F01C306EBC3F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -719,18 +723,18 @@ Global {7052C706-4B1A-4167-A33A-DF3E9FBCFE6B}.Debug|Any CPU.Build.0 = Debug|Any CPU {7052C706-4B1A-4167-A33A-DF3E9FBCFE6B}.Release|Any CPU.ActiveCfg = Release|Any CPU {7052C706-4B1A-4167-A33A-DF3E9FBCFE6B}.Release|Any CPU.Build.0 = Release|Any CPU - {78902D9E-CD1A-4FB7-B752-A3471A2DD457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78902D9E-CD1A-4FB7-B752-A3471A2DD457}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78902D9E-CD1A-4FB7-B752-A3471A2DD457}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78902D9E-CD1A-4FB7-B752-A3471A2DD457}.Release|Any CPU.Build.0 = Release|Any CPU - {97C43FFC-0A48-47C7-93EE-7382C2989AAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {97C43FFC-0A48-47C7-93EE-7382C2989AAE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {97C43FFC-0A48-47C7-93EE-7382C2989AAE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {97C43FFC-0A48-47C7-93EE-7382C2989AAE}.Release|Any CPU.Build.0 = Release|Any CPU {3E28B63C-814E-46C9-ADBF-7357997148F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3E28B63C-814E-46C9-ADBF-7357997148F5}.Debug|Any CPU.Build.0 = Debug|Any CPU {3E28B63C-814E-46C9-ADBF-7357997148F5}.Release|Any CPU.ActiveCfg = Release|Any CPU {3E28B63C-814E-46C9-ADBF-7357997148F5}.Release|Any CPU.Build.0 = Release|Any CPU + {97C43FFC-0A48-47C7-93EE-7382C2989AAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97C43FFC-0A48-47C7-93EE-7382C2989AAE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97C43FFC-0A48-47C7-93EE-7382C2989AAE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97C43FFC-0A48-47C7-93EE-7382C2989AAE}.Release|Any CPU.Build.0 = Release|Any CPU + {78902D9E-CD1A-4FB7-B752-A3471A2DD457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78902D9E-CD1A-4FB7-B752-A3471A2DD457}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78902D9E-CD1A-4FB7-B752-A3471A2DD457}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78902D9E-CD1A-4FB7-B752-A3471A2DD457}.Release|Any CPU.Build.0 = Release|Any CPU {EFA76A2C-CA0E-42BC-8215-AEEB16414947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EFA76A2C-CA0E-42BC-8215-AEEB16414947}.Debug|Any CPU.Build.0 = Debug|Any CPU {EFA76A2C-CA0E-42BC-8215-AEEB16414947}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -807,6 +811,14 @@ Global {B664ADD4-7067-4CCE-BBAC-146A174A7F73}.Debug|Any CPU.Build.0 = Debug|Any CPU {B664ADD4-7067-4CCE-BBAC-146A174A7F73}.Release|Any CPU.ActiveCfg = Release|Any CPU {B664ADD4-7067-4CCE-BBAC-146A174A7F73}.Release|Any CPU.Build.0 = Release|Any CPU + {4F89E1D6-B9A0-4C7A-B3BF-2948A613A489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F89E1D6-B9A0-4C7A-B3BF-2948A613A489}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F89E1D6-B9A0-4C7A-B3BF-2948A613A489}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F89E1D6-B9A0-4C7A-B3BF-2948A613A489}.Release|Any CPU.Build.0 = Release|Any CPU + {419BAB71-82A1-4931-B581-F01C306EBC3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {419BAB71-82A1-4931-B581-F01C306EBC3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {419BAB71-82A1-4931-B581-F01C306EBC3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {419BAB71-82A1-4931-B581-F01C306EBC3F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -918,9 +930,9 @@ Global {FF492215-60BC-40C6-B118-D22DF9063547} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} {247EF2E5-F4B9-47D4-BB89-27860DF53D5F} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} {7052C706-4B1A-4167-A33A-DF3E9FBCFE6B} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} - {78902D9E-CD1A-4FB7-B752-A3471A2DD457} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} - {97C43FFC-0A48-47C7-93EE-7382C2989AAE} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} {3E28B63C-814E-46C9-ADBF-7357997148F5} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} + {97C43FFC-0A48-47C7-93EE-7382C2989AAE} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} + {78902D9E-CD1A-4FB7-B752-A3471A2DD457} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} {EFA76A2C-CA0E-42BC-8215-AEEB16414947} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} {AE41DB38-93BC-48A7-8841-163E5E13CE8D} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} {CB1A7B68-E24A-4729-9401-606F3A914586} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} @@ -940,6 +952,8 @@ Global {1C2085FA-2D33-459B-945E-337323485E16} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} {877E2C7C-F136-4DC7-882D-C1ADE6B5E3ED} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} {B664ADD4-7067-4CCE-BBAC-146A174A7F73} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} + {4F89E1D6-B9A0-4C7A-B3BF-2948A613A489} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} + {419BAB71-82A1-4931-B581-F01C306EBC3F} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2B8C62A1-11B6-469F-874C-A02443256568} diff --git a/README.md b/README.md index 19112a7243..94851a526e 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,7 @@ HealthChecks packages include health checks for: | Google Cloud Firestore | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.Gcp.CloudFirestore)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Gcp.CloudFirestore) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.Gcp.CloudFirestore)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Gcp.CloudFirestore) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/cloudfirestore)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/cloudfirestore) | Gremlin | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.Gremlin)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Gremlin) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.Gremlin)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Gremlin) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/gremlin)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/gremlin) | Hangfire | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.Hangfire)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Hangfire) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.Hangfire)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Hangfire) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/hangfire)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/hangfire) +| Hazelcast | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.Hazelcast)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Hazelcast) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.Hazelcast)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Hazelcast) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/hazelcast)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/hazelcast) | IbmMQ | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.IbmMQ)](https://www.nuget.org/packages/AspNetCore.HealthChecks.IbmMQ) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.IbmMQ)](https://www.nuget.org/packages/AspNetCore.HealthChecks.IbmMQ) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/ibmmq)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/ibmmq) | InfluxDB | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.InfluxDB)](https://www.nuget.org/packages/AspNetCore.HealthChecks.InfluxDB) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.InfluxDB)](https://www.nuget.org/packages/AspNetCore.HealthChecks.InfluxDB) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/influxdb)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/influxdb) | Kafka | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.Kafka)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Kafka) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.Kafka)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Kafka) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/kafka)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/kafka) @@ -141,6 +142,7 @@ Install-Package AspNetCore.HealthChecks.EventStore.gRPC Install-Package AspNetCore.HealthChecks.Gcp.CloudFirestore Install-Package AspNetCore.HealthChecks.Gremlin Install-Package AspNetCore.HealthChecks.Hangfire +Install-Package AspNetCore.HealthChecks.Hazelcast Install-Package AspNetCore.HealthChecks.IbmMQ Install-Package AspNetCore.HealthChecks.InfluxDB Install-Package AspNetCore.HealthChecks.Kafka diff --git a/build/versions.props b/build/versions.props index c6857f2661..4a01a2242e 100644 --- a/build/versions.props +++ b/build/versions.props @@ -24,6 +24,7 @@ 7.0.0 7.0.0 7.0.0 + 7.0.0 7.0.0 7.0.0 7.0.0 diff --git a/src/HealthChecks.Hazelcast/DependencyInjection/HazelcastHealthCheckBuilderExtensions.cs b/src/HealthChecks.Hazelcast/DependencyInjection/HazelcastHealthCheckBuilderExtensions.cs new file mode 100644 index 0000000000..5820c4c695 --- /dev/null +++ b/src/HealthChecks.Hazelcast/DependencyInjection/HazelcastHealthCheckBuilderExtensions.cs @@ -0,0 +1,68 @@ +using HealthChecks.Hazelcast; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Microsoft.Extensions.DependencyInjection; + +/// +/// Extension methods to configure . +/// +public static class HazelcastHealthCheckBuilderExtensions +{ + /// + /// Add a health check for Hazelcast. + /// + /// The . + /// Action to configure + /// The health check name. Optional. If null the type name 'hazelcast' will be used for the name. + /// + /// The that should be reported when the health check fails. Optional. If null then + /// the default status of will be reported. + /// + /// A list of tags that can be used to filter sets of health checks. Optional. + /// An optional representing the timeout of the check. + /// + public static IHealthChecksBuilder AddHazelcast( + this IHealthChecksBuilder builder, + Action setup, + string? name = default, + HealthStatus failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + var options = new HazelcastHealthCheckOptions(); + setup?.Invoke(options); + + return builder.AddHazelcast(options, name, failureStatus, tags, timeout); + } + + /// + /// Add a health check for Hazelcast. + /// + /// The . + /// Options for health check. + /// The health check name. Optional. If null the type name 'hazelcast' will be used for the name. + /// + /// The that should be reported when the health check fails. Optional. If null then + /// the default status of will be reported. + /// + /// A list of tags that can be used to filter sets of health checks. Optional. + /// An optional representing the timeout of the check. + /// + public static IHealthChecksBuilder AddHazelcast( + this IHealthChecksBuilder builder, + HazelcastHealthCheckOptions options, + string? name = default, + HealthStatus failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + Guard.ThrowIfNull(options); + + return builder.Add(new HealthCheckRegistration( + name ?? "hazelcast", + _ => new HazelcastHealthCheck(options), + failureStatus, + tags, + timeout)); + } +} diff --git a/src/HealthChecks.Hazelcast/HazelcastHealthCheck.cs b/src/HealthChecks.Hazelcast/HazelcastHealthCheck.cs new file mode 100644 index 0000000000..8495afa6a4 --- /dev/null +++ b/src/HealthChecks.Hazelcast/HazelcastHealthCheck.cs @@ -0,0 +1,50 @@ +using Hazelcast; +using Hazelcast.Networking; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace HealthChecks.Hazelcast; + +/// +/// A health check for Hazelcast services. +/// +public class HazelcastHealthCheck : IHealthCheck +{ + private readonly HazelcastHealthCheckOptions _options; + + public HazelcastHealthCheck(HazelcastHealthCheckOptions options) + { + _ = Guard.ThrowIfNull(options); + _ = Guard.ThrowIfNull(options.ConnectionHost, true); + + _options = options; + if (string.IsNullOrEmpty(_options.ClientName)) + { + _options.ClientName = $"HazelcastHealthcheck_{Environment.MachineName}"; + } + } + + /// + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + await using var client = await HazelcastClientFactory.StartNewClientAsync(options => + { + options.Networking.Addresses.Add(_options.ConnectionHost); + options.Networking.ReconnectMode = ReconnectMode.DoNotReconnect; + options.Networking.ConnectionTimeoutMilliseconds = (int)_options.ConnectionTimeout.TotalMilliseconds; + + options.ClusterName = _options.ClusterName; + options.ClientName = _options.ClientName; + }, cancellationToken).ConfigureAwait(false); + + return client.IsActive && client.IsConnected + ? HealthCheckResult.Healthy() + : new HealthCheckResult(context.Registration.FailureStatus, description: $"Hazelcast client connection failed: {client.State}"); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } +} diff --git a/src/HealthChecks.Hazelcast/HazelcastHealthCheckOptions.cs b/src/HealthChecks.Hazelcast/HazelcastHealthCheckOptions.cs new file mode 100644 index 0000000000..fa90ceff37 --- /dev/null +++ b/src/HealthChecks.Hazelcast/HazelcastHealthCheckOptions.cs @@ -0,0 +1,27 @@ +namespace HealthChecks.Hazelcast; + +/// +/// Options for . +/// +public class HazelcastHealthCheckOptions +{ + /// + /// Hazelcast connection host ({ip/DNS}:{port}) + /// + public string ConnectionHost { get; set; } = null!; + + /// + /// Hazelcast cluster name to connect + /// + public string ClusterName { get; set; } = "dev"; + + /// + /// Hazelcast connection client name (use to track the healthcheck connection to your Hazelcast) + /// + public string ClientName { get; set; } = null!; + + /// + /// Hazelcast client connection timeout + /// + public TimeSpan ConnectionTimeout { get; set; } = TimeSpan.FromMilliseconds(100); +} diff --git a/src/HealthChecks.Hazelcast/HealthChecks.Hazelcast.csproj b/src/HealthChecks.Hazelcast/HealthChecks.Hazelcast.csproj new file mode 100644 index 0000000000..63204c7066 --- /dev/null +++ b/src/HealthChecks.Hazelcast/HealthChecks.Hazelcast.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + $(PackageTags);Hazelcast + HealthChecks.Hazelcast is the health check package for Hazelcast. + $(HealthCheckHazelcast) + + + + + + + + diff --git a/test/HealthChecks.Hazelcast.Tests/DependencyInjection/RegistrationTests.cs b/test/HealthChecks.Hazelcast.Tests/DependencyInjection/RegistrationTests.cs new file mode 100644 index 0000000000..aa98fe774c --- /dev/null +++ b/test/HealthChecks.Hazelcast.Tests/DependencyInjection/RegistrationTests.cs @@ -0,0 +1,88 @@ +namespace HealthChecks.Hazelcast.Tests.DependencyInjection; + +public class hazelcast_registration_should +{ + [Fact] + public void add_health_check_when_properly_configured() + { + var services = new ServiceCollection() + .AddHealthChecks() + .AddHazelcast(new HazelcastHealthCheckOptions() + { + ConnectionHost = "127.0.0.1:5701" + }) + .Services; + + using var serviceProvider = services.BuildServiceProvider(); + var options = serviceProvider.GetRequiredService>(); + + var registration = options.Value.Registrations.First(); + var check = registration.Factory(serviceProvider); + + registration.Name.ShouldBe("hazelcast"); + check.ShouldBeOfType(); + } + + [Fact] + public void add_named_health_check_when_properly_configured() + { + var services = new ServiceCollection() + .AddHealthChecks() + .AddHazelcast(new HazelcastHealthCheckOptions() + { + ConnectionHost = "127.0.0.1:5701" + }, name: "my-hazelcast-1") + .Services; + + using var serviceProvider = services.BuildServiceProvider(); + var options = serviceProvider.GetRequiredService>(); + + var registration = options.Value.Registrations.First(); + var check = registration.Factory(serviceProvider); + + registration.Name.ShouldBe("my-hazelcast-1"); + check.ShouldBeOfType(); + } + + [Fact] + public void add_health_check_with_action_options_when_properly_configured() + { + var services = new ServiceCollection() + .AddHealthChecks() + .AddHazelcast(options => + { + options.ConnectionHost = "127.0.0.1:5701"; + options.ClusterName = "dev"; + options.ClientName = "my-client"; + options.ConnectionTimeout = TimeSpan.FromMilliseconds(500); + }) + .Services; + + using var serviceProvider = services.BuildServiceProvider(); + var options = serviceProvider.GetRequiredService>(); + + var registration = options.Value.Registrations.First(); + var check = registration.Factory(serviceProvider); + + registration.Name.ShouldBe("hazelcast"); + check.ShouldBeOfType(); + } + + [Fact] + public void throw_exception_when_not_properly_configured() + { + var services = new ServiceCollection() + .AddHealthChecks() + .AddHazelcast(new HazelcastHealthCheckOptions()) + .Services; + + using var serviceProvider = services.BuildServiceProvider(); + var options = serviceProvider.GetRequiredService>(); + + var registration = options.Value.Registrations.First(); + + var exception = Record.Exception(() => registration.Factory(serviceProvider)); + var anException = exception.ShouldBeOfType(); + anException.ParamName.ShouldBeEquivalentTo("options.ConnectionHost"); + } +} diff --git a/test/HealthChecks.Hazelcast.Tests/HealthChecks.Hazelcast.Tests.csproj b/test/HealthChecks.Hazelcast.Tests/HealthChecks.Hazelcast.Tests.csproj new file mode 100644 index 0000000000..2bf07acf2f --- /dev/null +++ b/test/HealthChecks.Hazelcast.Tests/HealthChecks.Hazelcast.Tests.csproj @@ -0,0 +1,13 @@ + + + + + net6.0;net7.0 + + + + + + + +