Skip to content

Commit

Permalink
Add ClickHouse HealthCheck support
Browse files Browse the repository at this point in the history
  • Loading branch information
smbecker committed Nov 11, 2024
1 parent 0017092 commit b7411b3
Show file tree
Hide file tree
Showing 19 changed files with 727 additions and 4 deletions.
5 changes: 4 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ FTP_PORT=21
FTP_USER=bob
FTP_PASS=12345
RAVENDB_PORT=9030
SOLR_PORT=8983
SOLR_PORT=8983
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=Password12!
CLICKHOUSE_PORT=8123
2 changes: 2 additions & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ flags:
carryforward: true
AzureStorage:
carryforward: true
ClickHouse:
carryforward: true
Consul:
carryforward: true
CosmosDb:
Expand Down
3 changes: 3 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ aws:
azure:
- src/HealthChecks.Azure*/**/*

clickhouse:
- src/HealthChecks.ClickHouse/**/*

consul:
- src/HealthChecks.Consul/**/*

Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/healthchecks_clickhouse_cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: HealthChecks ClickHouse DB CD

on:
push:
tags:
- release-clickhouse-*
- release-all-*

jobs:
build:
uses: ./.github/workflows/reusable_cd_workflow.yml
secrets: inherit
with:
BUILD_CONFIG: Release
PROJECT_PATH: ./src/HealthChecks.ClickHouse/HealthChecks.ClickHouse.csproj
PACKAGE_NAME: AspNetCore.HealthChecks.ClickHouse
17 changes: 17 additions & 0 deletions .github/workflows/healthchecks_clickhouse_cd_preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: HealthChecks ClickHouse DB Preview CD

on:
push:
tags:
- preview-clickhouse-*
- preview-all-*

jobs:
build:
uses: ./.github/workflows/reusable_cd_preview_workflow.yml
secrets: inherit
with:
BUILD_CONFIG: Release
VERSION_SUFFIX_PREFIX: rc1
PROJECT_PATH: ./src/HealthChecks.ClickHouse/HealthChecks.ClickHouse.csproj
PACKAGE_NAME: AspNetCore.HealthChecks.ClickHouse
76 changes: 76 additions & 0 deletions .github/workflows/healthchecks_clickhouse_ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: HealthChecks ClickHouse DB CI

on:
workflow_dispatch:
push:
branches: [ master ]
paths:
- src/HealthChecks.ClickHouse/**
- test/HealthChecks.ClickHouse.Tests/**
- test/_SHARED/**
- .github/workflows/healthchecks_clickhouse_ci.yml
- Directory.Build.props
- Directory.Build.targets
tags-ignore:
- release-*
- preview-*

pull_request:
branches: [ master ]
paths:
- src/HealthChecks.ClickHouse/**
- test/HealthChecks.ClickHouse.Tests/**
- test/_SHARED/**
- .github/workflows/healthchecks_clickhouse_ci.yml
- Directory.Build.props
- Directory.Build.targets

jobs:
build:
runs-on: ubuntu-latest
services:
clickhouse:
image: clickhouse/clickhouse-server:24-alpine
ports:
- 8123:8123
env:
CLICKHOUSE_DB: default
CLICKHOUSE_USER: default
CLICKHOUSE_PASSWORD: "Password12!"
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: "1"
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
7.0.x
8.0.x
- name: Restore
run: |
dotnet restore ./src/HealthChecks.ClickHouse/HealthChecks.ClickHouse.csproj &&
dotnet restore ./test/HealthChecks.ClickHouse.Tests/HealthChecks.ClickHouse.Tests.csproj
- name: Check formatting
run: |
dotnet format --no-restore --verify-no-changes --severity warn ./src/HealthChecks.ClickHouse/HealthChecks.ClickHouse.csproj || (echo "Run 'dotnet format' to fix issues" && exit 1) &&
dotnet format --no-restore --verify-no-changes --severity warn ./test/HealthChecks.ClickHouse.Tests/HealthChecks.ClickHouse.Tests.csproj || (echo "Run 'dotnet format' to fix issues" && exit 1)
- name: Build
run: |
dotnet build --no-restore ./src/HealthChecks.ClickHouse/HealthChecks.ClickHouse.csproj &&
dotnet build --no-restore ./test/HealthChecks.ClickHouse.Tests/HealthChecks.ClickHouse.Tests.csproj
- name: Test
run: >
dotnet test
./test/HealthChecks.ClickHouse.Tests/HealthChecks.ClickHouse.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: ClickHouse
directory: .coverage
14 changes: 14 additions & 0 deletions AspNetCore.Diagnostics.HealthChecks.sln
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Milvus", "src\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Milvus.Tests", "test\HealthChecks.Milvus.Tests\HealthChecks.Milvus.Tests.csproj", "{D49CF52C-9D21-4D98-8A15-A2B259E9C003}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthChecks.ClickHouse", "src\HealthChecks.ClickHouse\HealthChecks.ClickHouse.csproj", "{96E2B0A3-02BD-456B-8888-4D96DABA99EB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthChecks.ClickHouse.Tests", "test\HealthChecks.ClickHouse.Tests\HealthChecks.ClickHouse.Tests.csproj", "{2FB5CB9F-F870-48DE-BD1D-306AE86A67CA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -868,6 +872,14 @@ Global
{D49CF52C-9D21-4D98-8A15-A2B259E9C003}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D49CF52C-9D21-4D98-8A15-A2B259E9C003}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D49CF52C-9D21-4D98-8A15-A2B259E9C003}.Release|Any CPU.Build.0 = Release|Any CPU
{96E2B0A3-02BD-456B-8888-4D96DABA99EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96E2B0A3-02BD-456B-8888-4D96DABA99EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96E2B0A3-02BD-456B-8888-4D96DABA99EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96E2B0A3-02BD-456B-8888-4D96DABA99EB}.Release|Any CPU.Build.0 = Release|Any CPU
{2FB5CB9F-F870-48DE-BD1D-306AE86A67CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2FB5CB9F-F870-48DE-BD1D-306AE86A67CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2FB5CB9F-F870-48DE-BD1D-306AE86A67CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2FB5CB9F-F870-48DE-BD1D-306AE86A67CA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1011,6 +1023,8 @@ Global
{3B812989-2C4E-4FCE-B3A0-EF9C00A9B3A5} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE}
{17913EAF-3B12-495B-80EA-9EB975FBE6BA} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4}
{D49CF52C-9D21-4D98-8A15-A2B259E9C003} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE}
{96E2B0A3-02BD-456B-8888-4D96DABA99EB} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4}
{2FB5CB9F-F870-48DE-BD1D-306AE86A67CA} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2B8C62A1-11B6-469F-874C-A02443256568}
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ HealthChecks packages include health checks for:
| Azure Key Vault | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.AzureKeyVault)](https://www.nuget.org/packages/AspNetCore.HealthChecks.AzureKeyVault) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.AzureKeyVault)](https://www.nuget.org/packages/AspNetCore.HealthChecks.AzureKeyVault) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/azure)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/azure)
| Azure Search | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.AzureSearch)](https://www.nuget.org/packages/AspNetCore.HealthChecks.AzureSearch) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.AzureSearch)](https://www.nuget.org/packages/AspNetCore.HealthChecks.AzureSearch) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/azure)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/azure)
| Azure Service Bus | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.AzureServiceBus)](https://www.nuget.org/packages/AspNetCore.HealthChecks.AzureServiceBus) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.AzureServiceBus)](https://www.nuget.org/packages/AspNetCore.HealthChecks.AzureServiceBus) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/azure)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/azure) | Queue and Topics |
| ClickHouse | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.ClickHouse)](https://www.nuget.org/packages/AspNetCore.HealthChecks.ClickHouse) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.ClickHouse)](https://www.nuget.org/packages/AspNetCore.HealthChecks.ClickHouse) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/clickhouse)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/clickhouse)
| Consul | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.Consul)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Consul) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.Consul)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Consul) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/consul)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/consul)
| CosmosDb | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.CosmosDb)](https://www.nuget.org/packages/AspNetCore.HealthChecks.CosmosDb) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.CosmosDb)](https://www.nuget.org/packages/AspNetCore.HealthChecks.CosmosDb) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/cosmosdb)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/cosmosdb) | CosmosDb and Azure Table
| Dapr | [![Nuget](https://img.shields.io/nuget/dt/AspNetCore.HealthChecks.Dapr)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Dapr) | [![Nuget](https://img.shields.io/nuget/v/AspNetCore.HealthChecks.Dapr)](https://www.nuget.org/packages/AspNetCore.HealthChecks.Dapr) | [![view](https://img.shields.io/github/issues/Xabaril/AspNetCore.Diagnostics.HealthChecks/dapr)](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/dapr)
Expand Down Expand Up @@ -141,6 +142,7 @@ Install-Package AspNetCore.HealthChecks.AzureKeyVault
Install-Package AspNetCore.HealthChecks.AzureSearch
Install-Package AspNetCore.HealthChecks.AzureServiceBus
Install-Package AspNetCore.HealthChecks.AzureStorage
Install-Package AspNetCore.HealthChecks.ClickHouse
Install-Package AspNetCore.HealthChecks.Consul
Install-Package AspNetCore.HealthChecks.CosmosDb
Install-Package AspNetCore.HealthChecks.Dapr
Expand Down Expand Up @@ -699,4 +701,4 @@ answering [questions](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthCh
2. Follow the code guidelines and conventions.
3. New features are not only code, tests and documentation are also mandatory.
4. PRs with [`Ups for grabs`](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/Ups%20for%20grabs)
and [help wanted](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/help%20wanted) tags are good candidates to contribute.
and [help wanted](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/labels/help%20wanted) tags are good candidates to contribute.
1 change: 1 addition & 0 deletions build/versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<HealthCheckAzureStorageBlobs>8.0.1</HealthCheckAzureStorageBlobs>
<HealthCheckAzureStorageFilesShares>8.0.1</HealthCheckAzureStorageFilesShares>
<HealthCheckAzureStorageQueues>8.0.1</HealthCheckAzureStorageQueues>
<HealthCheckClickHouse>8.0.1</HealthCheckClickHouse>
<HealthCheckCloudFirestore>8.0.1</HealthCheckCloudFirestore>
<HealthCheckConsul>8.0.1</HealthCheckConsul>
<HealthCheckCosmosDb>8.0.1</HealthCheckCosmosDb>
Expand Down
13 changes: 11 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ services:
volumes:
- ./build/docker-services/solrcore:/var/solr/data/solrcore
- ./build/docker-services/solrcoredown:/var/solr/data/solrcoredown
clickhouse:
image: clickhouse/clickhouse-server:24-alpine
environment:
- CLICKHOUSE_DB=${CLICKHOUSE_USER}
- CLICKHOUSE_USER=${CLICKHOUSE_USER}
- CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD}
- CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT="1"
ports:
- ${CLICKHOUSE_PORT}:8123
postgres:
image: postgres
environment:
Expand Down Expand Up @@ -165,7 +174,7 @@ services:
image: postgres
ports:
- "8010:5432"
environment:
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=Password12!
nats:
Expand All @@ -180,7 +189,7 @@ services:
ports:
- "8086:8086"
environment:
DOCKER_INFLUXDB_INIT_MODE: setup
DOCKER_INFLUXDB_INIT_MODE: setup
DOCKER_INFLUXDB_INIT_USERNAME: ci_user
DOCKER_INFLUXDB_INIT_PASSWORD: password
DOCKER_INFLUXDB_INIT_ORG: influxdata
Expand Down
43 changes: 43 additions & 0 deletions src/HealthChecks.ClickHouse/ClickHouseHealthCheck.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Diagnostics;
using ClickHouse.Client.ADO;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace HealthChecks.ClickHouse;

/// <summary>
/// A health check for ClickHouse databases.
/// </summary>
public class ClickHouseHealthCheck : IHealthCheck
{
private readonly ClickHouseHealthCheckOptions _options;

public ClickHouseHealthCheck(ClickHouseHealthCheckOptions options)
{
Debug.Assert(options.ConnectionString is not null);
Guard.ThrowIfNull(options.CommandText, true);
_options = options;
}

/// <inheritdoc />
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
try
{
await using var connection = new ClickHouseConnection(_options.ConnectionString);
_options.Configure?.Invoke(connection);
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);

using var command = connection.CreateCommand();
command.CommandText = _options.CommandText;
var result = await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);

return _options.HealthCheckResultBuilder == null
? HealthCheckResult.Healthy()
: _options.HealthCheckResultBuilder(result);
}
catch (Exception ex)
{
return new HealthCheckResult(context.Registration.FailureStatus, description: ex.Message, exception: ex);
}
}
}
49 changes: 49 additions & 0 deletions src/HealthChecks.ClickHouse/ClickHouseHealthCheckOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using ClickHouse.Client.ADO;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace HealthChecks.ClickHouse;

/// <summary>
/// Options for <see cref="ClickHouseHealthCheck"/>.
/// </summary>
public class ClickHouseHealthCheckOptions
{
internal ClickHouseHealthCheckOptions()
{
// This ctor is internal on purpose: those who want to use ClickHouseHealthCheckOptions
// need to specify either ConnectionString or DataSource when creating it.
// Making the ConnectionString and DataSource setters internal
// allows us to ensure that the customers don't try to mix both concepts.
// By encapsulating all of that, we ensure that all instances of this type are valid.
}

/// <summary>
/// Creates an instance of <see cref="ClickHouseHealthCheckOptions"/>.
/// </summary>
/// <param name="connectionString">The ClickHouse connection string to be used.</param>
public ClickHouseHealthCheckOptions(string connectionString)
{
ConnectionString = Guard.ThrowIfNull(connectionString, throwOnEmptyString: true);
}

/// <summary>
/// The ClickHouse connection string to be used.
/// </summary>
public string? ConnectionString { get; internal set; }

/// <summary>
/// The query to be executed.
/// </summary>
public string CommandText { get; set; } = ClickHouseHealthCheckBuilderExtensions.HEALTH_QUERY;

/// <summary>
/// An optional action executed before the connection is opened in the health check.
/// </summary>
public Action<ClickHouseConnection>? Configure { get; set; }

/// <summary>
/// An optional delegate to build health check result.
/// </summary>
public Func<object?, HealthCheckResult>? HealthCheckResultBuilder { get; set; }
}
Loading

0 comments on commit b7411b3

Please sign in to comment.